2023年6月21日发(作者:)

搜索目录

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.1 主题的内容。这个主题的权值为 2。

在本节中,学习:

使用 OpenLDAP 搜索工具的基本选项

使用 OpenLDAP 搜索工具的高级选项

优化 LDAP 的搜索查询

使用搜索过滤器和它们的语法

只有当需要某个条目时能够找到它,树中的数据才有用。LDAP 提供了强大的功能集,允许您从树中提取信息。

搜索的基础知识

要对树进行搜索,您需要四种信息:

1. 拥有树的服务器上的凭证

2. 搜索所基于的树上的区分名(Distinguished Nam,DN)

3. 搜索范围

4. 搜索过滤器

您已经在本系列 以前的教程 中了解了服务器凭证。凭证可以没有任何内容,这将导致匿名绑定;凭证也可以是条目的 DN 和密码。这意味着服务器认为这些凭证是有效的,并允许您搜索!

搜索所基于的 DN 称为基 DN。所有搜索结果将会是基 DN 或者它的子 DN。如果您的基 DN 是

ou=people,dc=ertw,dc=com,那么您会找到

cn=Sean Walberg,ou=people,dc=ertw,dc=com,但是不会找到

cn=Users,ou=Groups,dc=ertw,dc=com,因为它位于您试图搜索的基 DN 之外。

搜索范围决定了基 DN 下的哪个条目将被搜索到。由于性能方面的原因,或者由于只有基 DN 的某些 子

DN 包含所需的信息,您可能想要限定搜索范围。默认的搜索范围为下级(subordinate)(通常缩写为

sub),包括基 DN 及其所有子 DN。您可以使用基 范围只搜索基 DN。比如,当您想测试某个条目是否在在时就可以使用这种方式。如果搜索范围为一级,则只搜索基 DN 的直接子 DN,并不搜索基 DN 本身和任何孙子层的 DN。图 1 展示了一个树和可能包含在 3 个不同搜索范围中的条目。

图 1. 3 个不同的搜索范围

搜索功能中最强大(和最复杂)的部分是搜索过滤器。凭证、基 DN 和范围限定了哪些条目将会被搜索,查询 检查每个记录并返回满足条件的记录。

简单的搜索过滤器 搜索过滤器包含在括号中。括号中是一个

attribute=value 对。(objectClass=inetOrgPerson) 就是一个简单的搜索过滤器,它将找到全部带有

inetOrgPerson 的 objectClass 的条目。属性本身不是大小写敏感的,但是根据属性在模式中的定义方式,值可能是大小写敏感的,也可能不是。在第一篇教程 LPI

301 考试准备:

概念、体系结构与设计 中讲到过,模式定义属性及其特性。属性的一个特性就是,比较既可以是大小写敏感的,也可以不是。

子字符串搜索使用星号(*)操作符来执行。针对

(Sean*) 进行搜索可以匹配所有以

Sean 开始的内容。星号可以位于字符串的任意位置,例如,(* Walberg) 可用于查找任何以

Walberg 结束的内容,或者

S*Wa*berg 可用于查找任何以

S 开始、以

berg 结束、并且其中包含

Wa 的内容。您可以使用这一方法查找作者的姓名,即使您知道它的名字是 Sean、Shawn、Walberg 还是 Wahlberg。

星号操作符最普通的形式为

attribute=*,它检查指定的属性是否在在。要查找包含指定电子邮件地址的所有条目,您可以使用

(mail=*)。

AND、OR 和 NOT

您可以分别使用 “&” 和 “|” 操作符执行逻辑 AND 或 OR 操作。LDAP 搜索字符串将该操作符放置到条件之前,因此您将会看到如清单 1 所示的过滤器。

清单 1. 使用 AND 和 OR 的搜索过滤器示例

(|(objectClass=inetOrgPerson)(objectClass=posixAccount))

(&(objectClass=*)(cn=Sean*)(ou=Engineering))

(&(|(objectClass=inetOrgPerson)(objectClass=posixAccount))(cn=Sean*))

清单 1 中的第一个搜索字符串查找包含

inetOrgPerson 或

posixAccount 的 objectClass 的任何内容。注意,每个组件仍然包含在括号内,并且 OR 操作符(|)和它的两个搜索选项也包含在另一组括号内。

第二个搜索字符串与第一个很相似,但以 AND 操作开始,而不是 OR。这里,必须满足三种不 同的测试,并且它们都在和号之后的自己括号内。第一个子句,objectClass=*,匹配带有给定的 objectClass 的任何内容。当您希望匹配所有内容并被要求输入过滤器时,就可以使用这种对 objectClass 的搜索。第二条子句匹配以

Sean 开始的全部内容。

第三条搜索字符串展示了 AND 和 OR 的结合使用,查找带有

inetOrgPerson 或

posixAccount 的

objectClass,而且其公用名(common name)以

Sean 开始的任何内容。

逻辑 NOT 使用感叹号(!)执行,与 AND 和 OR 非常相似。逻辑 NOT 只有一个参数,因此感叹号后面只带有一组括号。清单 2 展示了一些有效和无效的 NOT 用法。

清单 2. 如何正确使用逻辑 NOT

(!cn=Sean) # invalid, the ! applies to a filter inside ()

(!(cn=Sean)) # valid

(!(cn=Sean)(ou=Engineering)) # invalid, only one filter can be

negated

(!(&cn=Sean*)(ou=Engineering))) # valid, negates the AND clause

在清单 2 的第四个例子中,AND 过滤器上应用了 NOT 操作。因此,此规则返回不满足两条 AND 子句的任何条目。处理复合过滤器的 NOT 操作时要特别小心,因为结果并不总是直观的。如果条目的公用名不是以

Sean 开始,清单 2 中的第四个例子将返回带

Engineering 的

ou 的条目。两种测试都必须通过将要排除的记录。

搜索范围

您经常需要搜索某一范围内的值。LDAP 提供了<= 和 >= 操作符来查询一个属性。请注意,操作符中包含了等号(=),因为没有 < 和 > 操作符 — 您还必须测试相等与否。

并非所有的整数属性都可以用范围操作符进行检查。当有疑问时,对模式进行检查,以确保属性通过

ORDERING 关键字执行了一个排序类型。回顾一下第一篇教程 LPI 301 考试准备:

概念、体系结构和设计,属性是在策略中定义的,定义的一部分包括服务器如何对属性进行排序。

搜索近似匹配

LDAP 目录通常用于存储名称,这导致了拼写问题。“Sean” 也可以是 “Shawn” 或者 “Shaun”。LDAP

提供了一个 “声音相似” 操作符 “~=”,它返回与搜索字符串声音相似的内容。例如,(cn~=Shaun) 返回其公用名中包含与 “Shaun” 发音相似的单词的内容。声音相似搜索暗含的意思是子字符串搜索,比如

(cn=~Shaun) 将返回

cn=Shawn Walberg 的结果。OpenLDAP 实现并不完美, 虽然,同样的搜索并不会返回 “Sean” 拼写的结果。

对 DN 进行搜索

到目前为止,所有例子都集中在搜索属性上,而不是搜索标识记录的区分名(DN)。甚至 DN 最左侧的组件 —— 相对 DN(RDN)—— 也可视为属性并且可以搜索,目前提供的搜索过滤器将不会考虑 DN 的其他部分。

对 DN 的搜索通过一个需要精确匹配的特殊查询过滤器来完成。其格式为

attribute:dn:=value,其中的的属性是您想要搜索的 DN 的组件,而值代表搜索字符串(不允许通配符)。例如,(ou:dn:=People)

将返回 DN 中包含

ou=People 的所有条目,包括容器对象本身。

更改匹配规则

默认情况下,大多数字符串(例如公用名)是大小写不敏感的。如果您想要覆盖匹配规则,您可以使用类似于 DN 搜索的形式。比如,(ou:caseexactmatch:=people) 搜索将匹配一个 “people” 的组织单元,但不是 “People”。一些普通的匹配规则有:

caseIgnoreMatch 匹配字符串,不区分大小写。在匹配时还会忽略前后的空格。

caseExactMatch 是一个字符串匹配,需要被搜索的两个字符串之间具有相似的大小写形式。

octetStringMatch 像一个字符串匹配, 但不会删除空格,而且要求精确的、逐字节匹配。

telephoneNumberMatch 搜索一个电话号码,它在 LDAP 中有自己的数据类型。

您也可以通过组合 DN 搜索和匹配规则搜索来改变 DN 搜索的匹配规则。例如,(ou:dn:caseexactmatch:=people) 搜索精确地包含字符串 “people” 的 DN。

DN 搜索和匹配规则搜索也称为可扩展搜索。他们都需要精确匹配,不允许使用通配符。

回页首

使用

ldapsearch

搜索树的命令行工具是

ldapsearch。此工具使您可以通过各种方式绑定目录,执行一个或多个搜索并以

LDIF 格式获取数据。

ldapsearch 的默认行为是:

尝试一个到服务器的 Simple Authentication and Security Layer (SASL) 身份验证。

连接到 ldap://localhost:389 上的服务器

使用

(objectClass=*) 作为搜索过滤器

从 /etc/openldap/ 中读取搜索基

执行子搜索;也就是说,包括搜索基及其所有孩子

返回所有的用户属性,忽略操作(内部使用)属性。

使用扩展的 LDAP Data Interchange Format (LDIF) 进行输出。

不对输出进行排序。

到服务器的身份验证

如果您没有使用 SASL,则需要使用

-x 参数进行简单的身份验证。-x 独立执行一个匿名绑定,匿名绑定不需要绑定 DN 或密码。保留其他设置的默认设置,ldapsearch -x 将会转储从

/etc/openldap/ 中指定的搜索基开始的整个树。清单 3 展示了简单的匿名搜索的用法。

清单 3. 一个简单的匿名搜索

$ ldapsearch -x

# extended LDIF

#

# LDAPv3

# base <> with scope subtree

# filter: (objectclass=*)

# requesting: ALL

#

# people,

dn: ou=people,dc=ertw,dc=com

ou: people

description: All people in organization

objectClass: organizationalUnit

... output truncated ...

清单 3 展示了简单匿名搜索返回的头部和第一个条目。前 7 行组成了 LDIF 风格的头部,被使用 # 符号注释掉了。前三行表明剩下的文本是经过扩展的 LDIF 并使用 LDAP version 3 进行检索。下一行表明未指定任何基 DN,而且使用了子树搜索。 文本的最后两行指定搜索过滤器,表明搜索全部内容,要求全部属性。

您可以使用

-LLL 选项删除输出中的所有注释。

头部后面就是每一个条目;每一个条目以描述该条目的头部开始,然后是以 DN 开始的属性列表,未进行排序。

如果需要使用用户名和密码登录,请使用

-D 和

-w 选项分别指定绑定的 DN 和密码,例如,ldapsearch

-x D cn=root,dc=ertw,dc=com -w mypassword 将对根 DN 用户名和密码执行一次简单的身份验证。您也可以把密码输入到提示符中,使用

-W 而不是

-w password,使屏幕上不显示您的密码。

您可以使用

-H 选项向远程 LDAP 服务器传递统一资源标识符(Uniform Resource Identifier,URI),从而连接到不同的服务器。比如使用

ldapsearch -x -H ldap://192.168.1.1/ 与

192.168.1.1 上的服务器进行连接。

执行搜索

把搜索过滤器附加到您的命令行后面,就可以执行搜索。也可以把过滤器包括在引号中,这样可以保护搜索字符串中特定的字符不被 Shell 解释。清单 4 显示了公用名上的简单搜索。

清单 4. 从命令行执行简单搜索

$ ldapsearch -LLL -x '(cn=Fred Smith)'

dn: cn=Fred Smith,ou=people,dc=ertw,dc=com

objectClass: inetOrgPerson

sn: Smith

cn: Fred Smith

mail: fred@

清单 4 中的搜索使用

-LLL 选项删除输出中的注释,使用

-x 选项执行简单的身份验证。最后的参数是查找 Fred Smith 的条目的搜索字符串。 注意,搜索包含在括号内,使用单引号可以保护括号不被解释为 subshell 调用,而且由于搜索字符串包含一个空格,将会导致 “Smith” 被解释为单独的参数,使用单引号可以避免这种情况。

清单 4 返回 Fred Smith 的所有属性。如果只需要一两个属性,那么获取记录的所有值将会浪费客户端和服务器的资源。把您想查看的属性添加到

ldapsearch 命令行后面,这样就可以只获取这些属性。清单

5 显示了只想得到 Fred 的电子邮件地址时的搜索结果。

清单 5. 请求 Fred Smith 的电子邮件地址

$ ldapsearch -LLL -x '(cn=Fred Smith)' mail

dn: cn=Fred Smith,ou=people,dc=ertw,dc=com

mail: fred@

mail 属性添加到了清单 4 中的命令行后面,结果是找到了区分名和请求的属性。

ldapsearch 在 /etc/openldap/ 中查找以

BASE 开始的行以确定搜索基,根据服务器上

defaultsearchbase 中的设置,查找将会失败。搜索基是树中搜索开始的位置。只有搜索基的子条目(以及搜索基本身)将被搜索到。使用

-b 参数可以指定不同的搜索基,比如,ldapsearch -x -b

ou=groups,dc=ertw,dc=com 可以从 树中搜索组容器。 改变数据的返回方式

LDAP可以存储二进制数据,比如图片。jpegPhoto 属性是在树中存储图片的标准方法。如果从命令行得到属性值,您会发现它是用 base64 进行编码的。参数

-t 用于把任何二进制属性存入临时文件中。清单 6 展示了如何使用这一参数。

清单 6. 把二进制属性存入文件系统

$ ldapsearch -LLL -x 'cn=joe*' jpegphoto | head

dn: cn=Joe Blow,ou=people,dc=ertw,dc=com

jpegPhoto::

/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQw

... output continues for 1300+ lines ...

$ ldapsearch -LLL -t -x '(cn=joe*)' jpegphoto

dn: cn=Joe Blow,ou=people,dc=ertw,dc=com

jpegPhoto:< file:///tmp/ldapsearch-jpegPhoto-VaIjkE

$ file /tmp/ldapsearch-jpegPhoto-VaIjkE

/tmp/ldapsearch-jpegPhoto-VaIjkE: JPEG image data, JFIF standard

1.01, comment:

"Created with The GIMP377"

清单 6 展示了搜索其名称以 “Joe” 开头的人的两种方法,并且只获取

jpegPhoto 属性。第一次尝试未使用

-t 参数,因此

jpegPhoto 的值以 base64 格式在控制台上显示。这种方法只限于在命令行中使用,因此第二次尝试在命令行中指定了

-t 参数。这次,jpegPhoto 的值为一个文件的 URI(您也可以用

-T

选项更改目录)。最后,对返回的文件进行检查,该文件确实是可以查看的图片的二进制版本。

默认情况下,ldapsearch 以从服务器接收到的顺序打印出结果。可以使用

-S 参数对输出进行排序,将想要排序的属性名传递给它。如果要对多个属性进行排序,用逗号(,)把它们分开。

LDAP 命令行工具

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.2 主题的内容。这个主题的权值为 4。

在本节中,学习如何:

使用 ldap* 工具访问和修改目录

使用 slap* 工具访问和修改目录

OpenLDAP 附带了多种工具,可用于操纵目录或管理服务器。您已经熟悉了

ldapsearch,有关它的内容在 前一节 中已经讲到。以

ldap 开头的命令用于树的用户,以

slap 开头的命令用于管理员用户。

树操纵工具

本节中的命令用于操纵树,可以更改或读取数据。ldapsearch 也属于这个类别。要使用这些命令,您需要通过服务器的验证。

ldapadd 和 ldapmodify 这两个命令用于添加或修改树中的条目。您可能还记得在本系列的第一篇教程 LPI 301 考试准备:

概念、体系结构和设计 中讨论过,LDAP Data Interchange Format (LDIF) 可用于在树中添加、更改或删除数据。清单 7 展示了一个用于添加条目的 LDIF 示例。

清单 7. 将一个条目添加到树的 LDIF

dn: cn=Sean Walberg,ou=people,dc=ertw,dc=com

objectclass: inetOrgPerson

cn: Sean Walberg

cn: Sean A. Walberg

sn: Walberg

homephone: 555-111-2222

清单 7 首先描述了条目的区分名。此条目将会包含在

ou=people,dc=ertw,dc=com 容器中,并且拥有

cn=Sean Walberg 的一个相对区分名,这个相对区分名是通过分离第一个属性/值对之后的区分名(DN)得到的。此条目拥有一个

inetOrgPerson 的

objectclass,它对于属于一个组织的任何人来说是一种很普通的类型。后面是公用名的两种变形,然后是姓,最后是家庭电话号码。

清单 7 中向树中添加了一个条目,而不是更改或删除条目。LDIF 文件可以指定

changetype 关键字,告诉读取程序要如何对数据进行修改。

ldapadd 命令用于处理 LDIF 文件。如果清单 7 被存储为 “”,则可以使用

ldapadd -x -D

cn=root,dc=ertw,dc=com -w mypass -f 向树添加条目。命令的

-x -D

cn=root,dc=ertw,dc=com -w mypass 部分与前面讨论的

ldapsearch 很相似,这是使用简单验证和全能的根 DN 登录到树的一种方法。本节中的所有

ldap 命令都使用相同的参数登录到树,因此您将会多次看这种形式。

ldapadd 被实现为一个到

ldapmodify 的符号链接,在调用时,ldapadd 被解释为

ldapmodify -a。参数

-a 告诉

ldapmodify 假定

add 的一个默认

changetype,用于为树添加新条目。作为

ldapmodify

调用时,假定默认的

changetype 为修改操作。

ldapadd(和

ldapmodify)是一种把大量数据载入服务器的有效方式,无需关闭服务器。LDIF 文件可以包含许多操作,与编写自定义代码来解析数据源并通过 LDAP 将其直接添加到树中相比,从您尝试导入的其他数据源生成 LDIF 通常会更简单。

ldapdelete

由其名称可以看出,ldapdelete 用于从树中删除条目。所有条目都通过自己的 DN 在树中惟一标识,因此,ldapdelete 根据 DN 来删除条目,而不是通过任何其他查询。

除了已经讨论的验证参数以外,ldapdelete 还可以通过它的 DN 列表从命令行或文件中执行删除。要从命令行删除,只需将 DN 附加到命令行上,比如

ldapdelete -x -D cn=root,dc=ertw,dc=com -w mypass

"cn=Sean Walberg,ou=people,dc=ertw,dc=com"。如果要删除多个条目,可以将这些 DN 放置在一个文件中,一个 DN 占一行,并使用

-f filename 把

ldapdelete 指向该文件。

注意,也可以通过 LDIF 或者

ldapadd/ldapmodify 命令删除条目。在很多情况下,使用

ldapdelete 命令更方便一些,但这并不是删除条目的惟一方法。

ldapmodrdn

ldapmodrdn 命令用于修改对象的相对区分名,也就是 DN 中的第一个属性/值对。这种方法可以有效地重命名树的当前分枝中的条目。与 LDIF

moddn changetype 命令不同,此命令只能对条目进行重命名,而不能把它移动到树的另一个位置。 此命令的用法很简单:提供验证凭证、条目的 DN 和新 RDN。清单 8 展示了如何把帐户由 “Joe Blow”

重命名为 “Joseph Blow”。

清单 8. 对条目进行重命名

$ ldapmodrdn -x -D cn=root,dc=ertw,dc=com -w dirtysecret

'cn=Joe Blow,ou=people,dc=ertw,dc=com' 'cn=Joseph Blow'

$ ldapsearch -LLL -x '(cn=Joseph Blow)'

dn: cn=Joseph Blow,ou=people,dc=ertw,dc=com

objectClass: inetOrgPerson

sn: Blow

cn: Joe Blow

cn: Joseph Blow

注意,旧的 RDN 仍然会作为一个属性出现,也就是

cn: Joe Blow。如果想要删除旧的 RDN,可以将

-r

添加到命令行。这与将

deleteoldrdn: 1 添加到 LDIF 代码的方法相同(这是 LDIF 的默认行为,而不是

ldapmodrdn)。

ldapcompare

ldapcompare 允许您将预订值与 LDAP 树中的某个位置存储的值进行比较。用一个例子可以说明其工作原理。

清单 9. 使用 ldapcompare

$ ldapcompare -x "cn=Sean Walberg,ou=people,dc=ertw,dc=com" userPassword:mypassword

TRUE

$ ldapcompare -x "cn=Sean Walberg,ou=people,dc=ertw,dc=com" userPassword:badpassword

FALSE

在清单 9 中,执行了

ldapcompare 命令。除了验证参数,最后两个参数是要检查的 DN 和要检查的属性和值。上面两个例子中的 DN 是 “cn=Sean Walberg” 的清单,检查的属性均为

userPassword 属性。给出正确的密码之后,

ldapcompare 会输出字符串

TRUE 和一个错误代码 6。如果给定的值与条目中的内容不匹配,则发送

FALSE 到控制台并返回错误代码 5。-z 选项可以阻止打印任何内容;调用程序通过错误代码判断检查是否成功。

即使清单 9 中的例子对密码进行了检查,但是也可以使用任何属性,包括

objectClass。如果属性有多个值,比如多个公用名或

objectClass,则只要有一个值匹配,比较结果就算成功。

ldapwhoami

ldapwhoami 允许您对 LDAP 服务器的身份验证进行测试,并确定在服务器上验证了哪个 DN。只需使用普通的验证参数调用

ldapwhoami,如清单 10 所示。

清单 10.

ldapwhoami 演示

$ ldapwhoami -x

anonymous Result: Success (0)

$ ldapwhoami -x -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com" -w

mypassword

dn:cn=Sean Walberg,ou=people,dc=ertw,dc=com

Result: Success (0)

$ ldapwhoami -x -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com" -w

badpass

ldap_bind: Invalid credentials (49)

清单 10 中的第一个例子展示了一个没有用户名或密码的绑定。Ldapwhoami 返回字符串

anonymous,表明使用了匿名绑定;还返回一个状态行,表明授权成功。第二个例子绑定了用户的 DN。返回的 DN 与经过验证的 DN 相同。最后一个例子试图使用无效的凭证进行绑定。得到的结果是该问题的解释。

Ldapwhoami 命令对服务器配置的故障诊断和手动验证密码都很有帮助。访问列表可能会影响到

ldapsearch,因此可以使用

ldapwhoami 命令,它可以帮助您确定问题在于凭证还是访问列表。

回页首

管理工具

slap 开始的命令适用于管理员,它在数据库文件上直接操作,而不是通过 DLAP 协议操作。同样地,您通常需要以根用户的身份使用这些命令,而且在一些情况下需要关闭服务器。

slapacl

Slapacl 工具允许管理员根据绑定 DN、条目和属性的各种组合测试访问列表。例如,您可以使用

slapacl

进行测试,以查看一个特定用户对其他用户的属性的访问权限。此命令必须由根用户运行,因为它需要直接读取数据库和配置文件,而不是使用 LDAP。

slapacl 命令的用法通过一个例子可以很好地说明。在清单 11 中,管理员进行了测试,查看在实现 ACL

之前和实现了一个提升了访问安全级别的 ACL 之后,一个用户对自己的密码的访问权限。

清单 11. 使用

slapacl 确定更改 ACL 的效果

# slapacl -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=sean walberg,ou=people,dc=ertw,dc=com"

userPassword: read(=rscxd)

... change ...

# slapacl -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=sean walberg,ou=people,dc=ertw,dc=com"

userPassword: =wx

# slapacl -D "cn=Joseph Blow,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=joseph blow,ou=people,dc=ertw,dc=com"

userPassword: =0

slapacl 命令需要两部分信息。第一部分是绑定 DN,也就是您要测试其访问权限的用户的 DN。第二部分是您要测试的条目的 DN。绑定 DN 通过

-D 指定,而目标 DN 由

-b 指定。您可以选择对单个属性进行测试,方法是将其包含在命令行末尾(就像清单 11 中

userPassword 示例一样)。如果没有指定一个属性,您将收到条目中每个属性的结果。

在清单 11 的第一个命令中,管理员测试

cn=Sean Walberg 条目,以查看他对自己的密码有何种访问权限。结果为读访问权限。在本系列的第三篇教程 LPI 301 考试准备:

配置 中讨论过,用户应该能够写入和验证自己的

userPassword 属性,但是不能读取。改变 ACL 后再执行一次测试,结果只具有写和验证的权限。最后再进行一次测试,查看 Joseph Blow 对 Sean Walberg

的密码有何种访问权限;结果为他没有任何权限。

Slapacl 是一种测试ACL 更改和调试 ACL 问题的有效方法。它非常有效,因为它直接从数据库和

中读取结果,因此对 的任何更改都将反映到

slapacl 的输出中,而且无需重新重启

slapd。

slapcat

Slapcat 把 LDAP 树中的内容以 LDIF 格式转储到标准输出中,如果您使用

-l filename ,也可以转储到文件中。您也可以使用

-s 选项提供开始 DN,或使用

-a 选项传递一个查询过滤器。

Slapcat 直接对数据库进行操作,并且可以在服务器正在运行时进行操作。该命令只支持 bdb 数据库类型。

slapadd

Slapadd 是一个批量导入工具,它直接对后端数据库进行操作,这意味着必须停止 slapd 才能使用这个工具。它的设计目的是与

slapcat 的输出一起使用。Slapadd 并不对输入数据进行有效性验证,因此该命令可能在树的分离的分枝上停止。如果一些容器对象未导入,就会发生这种情况。

slapadd 的输入是一个 LDIF 文件,比如由

slapcat 生成的文件。slapadd(8C) manpage 建议使用

ldapadd,因为在线变量提供了数据有效性验证。该 manpage 也说明了

slapcat 的输出不一定会以与

ldapadd 兼容的方式进行排序(容器对象可能会跟在输出的子对象之后,因此验证将失败)。在

slapcat

中使用任何过滤器都会造成重要数据的丢失。因此,slapadd 只应该用于

slapcat 生成的 LDIF,将

ldapadd 用于任何其他 LDIF。

在关闭 LDAP 服务器之后,您可以运行

slapadd 命令把 LDAP 输出转换为标准输入。如果想从一个文件中读取数据,请使用

-l 选项。slapcat 只支持 bdb 数据库类型。

slappasswd Slappasswd 用于生成经过哈希运算的密码,该密码然后会存储在在目录或 中。常用方法是将经过哈希运算的密码用于 中的根 DN 的账户,这样,查看配置文件的任何人都不能确定出密码。如果您不提供任何参数,Slappasswd 将提示输入要进行哈希运算的密码,如清单 12 所示。

清单 12. 使用

slappasswd 对密码进行哈希运算

$ slappasswd

New password:

Re-enter new password:

{SSHA}G8Ly2+t/HMHJ3OWWE7LN+GRmZJAweXoE

然后您可以将整个字符串复制到 文件中的

rootpw 行中。Slapd 识别密码的格式,并将

{SSHA} 理解为其后面跟的是一个 SHA1 哈希算法。读取 文件的任何人都不会知道根密码。

slappasswd 产生的哈希值也可以通过

ldapadd 和

ldapmodify 命令用于 LDIF 文件中,这将允许您存储您的密码的安全的单向哈希值,而不是不安全的纯文本或 base64 编码的版本。

slapindex

您可能还记得本系列第三篇教程 LPI 301 考试准备:

配置 中的

slapindex。使用

index 关键字在 文件中创建或修改了索引之后,您必须重建索引,否则

slapd 将返回错误的结果。要重建索引,请停止

slapd 命令并运行

slapindex命令。这将花费一些时间,具体取决于您的数据库中有多少条目,或者如手册页中所述,“此命令将会为用户提供品尝饮料的充足时间”。

slaptest

Slapdtest 将进行检查,查看您的 文件是否正确。这一点很有帮助,因为如果您使用错误的配置文件重新启动

slapd 命令,那么在修复了文件中的错误之前,启动都会失败。Slaptest 允许您在重启之前对配置文件进行检查。

使用

slaptest 命令时只需输入

slaptest 即可。如果 文件是正确的,您将看到

config

file testing succeeded 消息。否则,您将看到一个用于解释问题的错误。

Slaptest 也会检查操作所需的各种文件和目录是否存在。 在测试过程中,作者能够发现一些传递给

slaptest 的配置文件错误,这将导致

slapd 失败。

Whitepages

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.3 主题的内容。这个主题的权值为 1。

在本节中,学习如何:

计划 Whitepages 服务

配置 Whitepages 服务

配置客户端,从 Whitepages 服务中获取数据

Whitepages

服务 允许电子邮件客户端从 LDAP 数据库获取联系人信息。与普通属性名(比如

inetOrgPerson objectClass 提供的普通属性名)一起使用,您可以获得与电子邮件客户端的对大兼容性。例如,Microsoft Outlook 和 Evolution 都使用

mail 属性存储用户的电子邮件地址,而

givenName、displayName、cn、和

sn 属性用于存储各种形式的名称。

为 LDAP 目录配置电子邮件客户端 从理论上讲,支持 LDAP 的任何邮件客户端都可使用您的树。您需要在客户端中配置的下列信息:

LDAP 服务器的地址或主机名

要绑定的凭证,进行匿名绑定时不需要

要搜索的基 DN

搜索过滤器,比如 (mail=*),这将删除没有电子邮件地址的帐户(可选)

在电子邮件客户端中输入上述信息之后,就应该能够搜索联系人信息了。

为 LDAP 目录配置 Microsoft Outlook

要配置 Microsoft Outlook(在 Outlook 2003 上进行测试),请选择 Tools > Email Accounts。您将看到一个与图 2 相似的对话框。

图 2. 选择要添加的帐户类型

选择添加新目录的选项,以添加一个新目录,然后单击 Next。您将会看到图 3 中的对话框。 图 3. 选择将要添加的目录类型

选择添加新 LDAP 目录的选项,添加一个新的 LDAP 目录。然后单击 Next。您将看到图 4 中的对话框。

图 4. 指定 LDAP 服务器的细节

在图 4 所示的对话框中输入您的 LDAP 服务器的相关细节。展示的示例使用用户凭证绑定到树。您还可以使用匿名访问,只要您的服务器支持。

输入基本细节之后,单击 More Settings,将提示您输入更多信息,如图 5 所示。

图 5. 为 LDAP 服务器配置添加高级选项

图 5 显示了更多选项,最重要的一个选项是搜索基。输入搜索基之后单击 OK,然后将会返回到 Outlook

的主界面。

现在,只要提示您寻找用户,您就可以从 “Show Names From” 字段中选择服务器名称来使用 LDAP 数据库。

结束语

在本教程中,您了解了如何通过搜索和命令行工具使用目录。还了解了如何配置电子邮件客户端,使用目录存储联系人信息。

对 LDAP 树进行搜索要求您建立查询过滤器。表 3 列出了查询中用到的各种操作符。

表 3. LDAP 搜索操作符

操作符

=

*

&

|

!

说明

测试相等性

测试某一属性是否在在

子字符串搜索

逻辑 AND

逻辑 OR

逻辑 NOT

示例

(cn=Walberg)

(cn=*)

(sn=Walb*)

(&(condition1)(condition2))

(|(condition1)(condition2))

(!(mail=*)) ~=

<= and >=

“声音相似” 匹配

范围匹配

(cn~=Shawn)

(pagesPerMinute >= 20)

有许多工具可以使用目录,比如

ldapsearch 可用于搜索,ldapadd 和

ldapmodify 用于添加和修改数据。以

ldap 开始的工具通过 LDAP 协议操作,并要求使用凭证登录到服务器。以

slap 开始的工具适用于管理员,并且直接对数据库进行操作。

本教程和 301 系列 的前几篇教程主要介绍了如何管理管理和使用 LDAP 服务器。本系列的下一篇教程将会介绍各种应用,包括电子邮件服务器,并展示如何将 LDAP 作为数据源使用。

2023年6月21日发(作者:)

搜索目录

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.1 主题的内容。这个主题的权值为 2。

在本节中,学习:

使用 OpenLDAP 搜索工具的基本选项

使用 OpenLDAP 搜索工具的高级选项

优化 LDAP 的搜索查询

使用搜索过滤器和它们的语法

只有当需要某个条目时能够找到它,树中的数据才有用。LDAP 提供了强大的功能集,允许您从树中提取信息。

搜索的基础知识

要对树进行搜索,您需要四种信息:

1. 拥有树的服务器上的凭证

2. 搜索所基于的树上的区分名(Distinguished Nam,DN)

3. 搜索范围

4. 搜索过滤器

您已经在本系列 以前的教程 中了解了服务器凭证。凭证可以没有任何内容,这将导致匿名绑定;凭证也可以是条目的 DN 和密码。这意味着服务器认为这些凭证是有效的,并允许您搜索!

搜索所基于的 DN 称为基 DN。所有搜索结果将会是基 DN 或者它的子 DN。如果您的基 DN 是

ou=people,dc=ertw,dc=com,那么您会找到

cn=Sean Walberg,ou=people,dc=ertw,dc=com,但是不会找到

cn=Users,ou=Groups,dc=ertw,dc=com,因为它位于您试图搜索的基 DN 之外。

搜索范围决定了基 DN 下的哪个条目将被搜索到。由于性能方面的原因,或者由于只有基 DN 的某些 子

DN 包含所需的信息,您可能想要限定搜索范围。默认的搜索范围为下级(subordinate)(通常缩写为

sub),包括基 DN 及其所有子 DN。您可以使用基 范围只搜索基 DN。比如,当您想测试某个条目是否在在时就可以使用这种方式。如果搜索范围为一级,则只搜索基 DN 的直接子 DN,并不搜索基 DN 本身和任何孙子层的 DN。图 1 展示了一个树和可能包含在 3 个不同搜索范围中的条目。

图 1. 3 个不同的搜索范围

搜索功能中最强大(和最复杂)的部分是搜索过滤器。凭证、基 DN 和范围限定了哪些条目将会被搜索,查询 检查每个记录并返回满足条件的记录。

简单的搜索过滤器 搜索过滤器包含在括号中。括号中是一个

attribute=value 对。(objectClass=inetOrgPerson) 就是一个简单的搜索过滤器,它将找到全部带有

inetOrgPerson 的 objectClass 的条目。属性本身不是大小写敏感的,但是根据属性在模式中的定义方式,值可能是大小写敏感的,也可能不是。在第一篇教程 LPI

301 考试准备:

概念、体系结构与设计 中讲到过,模式定义属性及其特性。属性的一个特性就是,比较既可以是大小写敏感的,也可以不是。

子字符串搜索使用星号(*)操作符来执行。针对

(Sean*) 进行搜索可以匹配所有以

Sean 开始的内容。星号可以位于字符串的任意位置,例如,(* Walberg) 可用于查找任何以

Walberg 结束的内容,或者

S*Wa*berg 可用于查找任何以

S 开始、以

berg 结束、并且其中包含

Wa 的内容。您可以使用这一方法查找作者的姓名,即使您知道它的名字是 Sean、Shawn、Walberg 还是 Wahlberg。

星号操作符最普通的形式为

attribute=*,它检查指定的属性是否在在。要查找包含指定电子邮件地址的所有条目,您可以使用

(mail=*)。

AND、OR 和 NOT

您可以分别使用 “&” 和 “|” 操作符执行逻辑 AND 或 OR 操作。LDAP 搜索字符串将该操作符放置到条件之前,因此您将会看到如清单 1 所示的过滤器。

清单 1. 使用 AND 和 OR 的搜索过滤器示例

(|(objectClass=inetOrgPerson)(objectClass=posixAccount))

(&(objectClass=*)(cn=Sean*)(ou=Engineering))

(&(|(objectClass=inetOrgPerson)(objectClass=posixAccount))(cn=Sean*))

清单 1 中的第一个搜索字符串查找包含

inetOrgPerson 或

posixAccount 的 objectClass 的任何内容。注意,每个组件仍然包含在括号内,并且 OR 操作符(|)和它的两个搜索选项也包含在另一组括号内。

第二个搜索字符串与第一个很相似,但以 AND 操作开始,而不是 OR。这里,必须满足三种不 同的测试,并且它们都在和号之后的自己括号内。第一个子句,objectClass=*,匹配带有给定的 objectClass 的任何内容。当您希望匹配所有内容并被要求输入过滤器时,就可以使用这种对 objectClass 的搜索。第二条子句匹配以

Sean 开始的全部内容。

第三条搜索字符串展示了 AND 和 OR 的结合使用,查找带有

inetOrgPerson 或

posixAccount 的

objectClass,而且其公用名(common name)以

Sean 开始的任何内容。

逻辑 NOT 使用感叹号(!)执行,与 AND 和 OR 非常相似。逻辑 NOT 只有一个参数,因此感叹号后面只带有一组括号。清单 2 展示了一些有效和无效的 NOT 用法。

清单 2. 如何正确使用逻辑 NOT

(!cn=Sean) # invalid, the ! applies to a filter inside ()

(!(cn=Sean)) # valid

(!(cn=Sean)(ou=Engineering)) # invalid, only one filter can be

negated

(!(&cn=Sean*)(ou=Engineering))) # valid, negates the AND clause

在清单 2 的第四个例子中,AND 过滤器上应用了 NOT 操作。因此,此规则返回不满足两条 AND 子句的任何条目。处理复合过滤器的 NOT 操作时要特别小心,因为结果并不总是直观的。如果条目的公用名不是以

Sean 开始,清单 2 中的第四个例子将返回带

Engineering 的

ou 的条目。两种测试都必须通过将要排除的记录。

搜索范围

您经常需要搜索某一范围内的值。LDAP 提供了<= 和 >= 操作符来查询一个属性。请注意,操作符中包含了等号(=),因为没有 < 和 > 操作符 — 您还必须测试相等与否。

并非所有的整数属性都可以用范围操作符进行检查。当有疑问时,对模式进行检查,以确保属性通过

ORDERING 关键字执行了一个排序类型。回顾一下第一篇教程 LPI 301 考试准备:

概念、体系结构和设计,属性是在策略中定义的,定义的一部分包括服务器如何对属性进行排序。

搜索近似匹配

LDAP 目录通常用于存储名称,这导致了拼写问题。“Sean” 也可以是 “Shawn” 或者 “Shaun”。LDAP

提供了一个 “声音相似” 操作符 “~=”,它返回与搜索字符串声音相似的内容。例如,(cn~=Shaun) 返回其公用名中包含与 “Shaun” 发音相似的单词的内容。声音相似搜索暗含的意思是子字符串搜索,比如

(cn=~Shaun) 将返回

cn=Shawn Walberg 的结果。OpenLDAP 实现并不完美, 虽然,同样的搜索并不会返回 “Sean” 拼写的结果。

对 DN 进行搜索

到目前为止,所有例子都集中在搜索属性上,而不是搜索标识记录的区分名(DN)。甚至 DN 最左侧的组件 —— 相对 DN(RDN)—— 也可视为属性并且可以搜索,目前提供的搜索过滤器将不会考虑 DN 的其他部分。

对 DN 的搜索通过一个需要精确匹配的特殊查询过滤器来完成。其格式为

attribute:dn:=value,其中的的属性是您想要搜索的 DN 的组件,而值代表搜索字符串(不允许通配符)。例如,(ou:dn:=People)

将返回 DN 中包含

ou=People 的所有条目,包括容器对象本身。

更改匹配规则

默认情况下,大多数字符串(例如公用名)是大小写不敏感的。如果您想要覆盖匹配规则,您可以使用类似于 DN 搜索的形式。比如,(ou:caseexactmatch:=people) 搜索将匹配一个 “people” 的组织单元,但不是 “People”。一些普通的匹配规则有:

caseIgnoreMatch 匹配字符串,不区分大小写。在匹配时还会忽略前后的空格。

caseExactMatch 是一个字符串匹配,需要被搜索的两个字符串之间具有相似的大小写形式。

octetStringMatch 像一个字符串匹配, 但不会删除空格,而且要求精确的、逐字节匹配。

telephoneNumberMatch 搜索一个电话号码,它在 LDAP 中有自己的数据类型。

您也可以通过组合 DN 搜索和匹配规则搜索来改变 DN 搜索的匹配规则。例如,(ou:dn:caseexactmatch:=people) 搜索精确地包含字符串 “people” 的 DN。

DN 搜索和匹配规则搜索也称为可扩展搜索。他们都需要精确匹配,不允许使用通配符。

回页首

使用

ldapsearch

搜索树的命令行工具是

ldapsearch。此工具使您可以通过各种方式绑定目录,执行一个或多个搜索并以

LDIF 格式获取数据。

ldapsearch 的默认行为是:

尝试一个到服务器的 Simple Authentication and Security Layer (SASL) 身份验证。

连接到 ldap://localhost:389 上的服务器

使用

(objectClass=*) 作为搜索过滤器

从 /etc/openldap/ 中读取搜索基

执行子搜索;也就是说,包括搜索基及其所有孩子

返回所有的用户属性,忽略操作(内部使用)属性。

使用扩展的 LDAP Data Interchange Format (LDIF) 进行输出。

不对输出进行排序。

到服务器的身份验证

如果您没有使用 SASL,则需要使用

-x 参数进行简单的身份验证。-x 独立执行一个匿名绑定,匿名绑定不需要绑定 DN 或密码。保留其他设置的默认设置,ldapsearch -x 将会转储从

/etc/openldap/ 中指定的搜索基开始的整个树。清单 3 展示了简单的匿名搜索的用法。

清单 3. 一个简单的匿名搜索

$ ldapsearch -x

# extended LDIF

#

# LDAPv3

# base <> with scope subtree

# filter: (objectclass=*)

# requesting: ALL

#

# people,

dn: ou=people,dc=ertw,dc=com

ou: people

description: All people in organization

objectClass: organizationalUnit

... output truncated ...

清单 3 展示了简单匿名搜索返回的头部和第一个条目。前 7 行组成了 LDIF 风格的头部,被使用 # 符号注释掉了。前三行表明剩下的文本是经过扩展的 LDIF 并使用 LDAP version 3 进行检索。下一行表明未指定任何基 DN,而且使用了子树搜索。 文本的最后两行指定搜索过滤器,表明搜索全部内容,要求全部属性。

您可以使用

-LLL 选项删除输出中的所有注释。

头部后面就是每一个条目;每一个条目以描述该条目的头部开始,然后是以 DN 开始的属性列表,未进行排序。

如果需要使用用户名和密码登录,请使用

-D 和

-w 选项分别指定绑定的 DN 和密码,例如,ldapsearch

-x D cn=root,dc=ertw,dc=com -w mypassword 将对根 DN 用户名和密码执行一次简单的身份验证。您也可以把密码输入到提示符中,使用

-W 而不是

-w password,使屏幕上不显示您的密码。

您可以使用

-H 选项向远程 LDAP 服务器传递统一资源标识符(Uniform Resource Identifier,URI),从而连接到不同的服务器。比如使用

ldapsearch -x -H ldap://192.168.1.1/ 与

192.168.1.1 上的服务器进行连接。

执行搜索

把搜索过滤器附加到您的命令行后面,就可以执行搜索。也可以把过滤器包括在引号中,这样可以保护搜索字符串中特定的字符不被 Shell 解释。清单 4 显示了公用名上的简单搜索。

清单 4. 从命令行执行简单搜索

$ ldapsearch -LLL -x '(cn=Fred Smith)'

dn: cn=Fred Smith,ou=people,dc=ertw,dc=com

objectClass: inetOrgPerson

sn: Smith

cn: Fred Smith

mail: fred@

清单 4 中的搜索使用

-LLL 选项删除输出中的注释,使用

-x 选项执行简单的身份验证。最后的参数是查找 Fred Smith 的条目的搜索字符串。 注意,搜索包含在括号内,使用单引号可以保护括号不被解释为 subshell 调用,而且由于搜索字符串包含一个空格,将会导致 “Smith” 被解释为单独的参数,使用单引号可以避免这种情况。

清单 4 返回 Fred Smith 的所有属性。如果只需要一两个属性,那么获取记录的所有值将会浪费客户端和服务器的资源。把您想查看的属性添加到

ldapsearch 命令行后面,这样就可以只获取这些属性。清单

5 显示了只想得到 Fred 的电子邮件地址时的搜索结果。

清单 5. 请求 Fred Smith 的电子邮件地址

$ ldapsearch -LLL -x '(cn=Fred Smith)' mail

dn: cn=Fred Smith,ou=people,dc=ertw,dc=com

mail: fred@

mail 属性添加到了清单 4 中的命令行后面,结果是找到了区分名和请求的属性。

ldapsearch 在 /etc/openldap/ 中查找以

BASE 开始的行以确定搜索基,根据服务器上

defaultsearchbase 中的设置,查找将会失败。搜索基是树中搜索开始的位置。只有搜索基的子条目(以及搜索基本身)将被搜索到。使用

-b 参数可以指定不同的搜索基,比如,ldapsearch -x -b

ou=groups,dc=ertw,dc=com 可以从 树中搜索组容器。 改变数据的返回方式

LDAP可以存储二进制数据,比如图片。jpegPhoto 属性是在树中存储图片的标准方法。如果从命令行得到属性值,您会发现它是用 base64 进行编码的。参数

-t 用于把任何二进制属性存入临时文件中。清单 6 展示了如何使用这一参数。

清单 6. 把二进制属性存入文件系统

$ ldapsearch -LLL -x 'cn=joe*' jpegphoto | head

dn: cn=Joe Blow,ou=people,dc=ertw,dc=com

jpegPhoto::

/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQw

... output continues for 1300+ lines ...

$ ldapsearch -LLL -t -x '(cn=joe*)' jpegphoto

dn: cn=Joe Blow,ou=people,dc=ertw,dc=com

jpegPhoto:< file:///tmp/ldapsearch-jpegPhoto-VaIjkE

$ file /tmp/ldapsearch-jpegPhoto-VaIjkE

/tmp/ldapsearch-jpegPhoto-VaIjkE: JPEG image data, JFIF standard

1.01, comment:

"Created with The GIMP377"

清单 6 展示了搜索其名称以 “Joe” 开头的人的两种方法,并且只获取

jpegPhoto 属性。第一次尝试未使用

-t 参数,因此

jpegPhoto 的值以 base64 格式在控制台上显示。这种方法只限于在命令行中使用,因此第二次尝试在命令行中指定了

-t 参数。这次,jpegPhoto 的值为一个文件的 URI(您也可以用

-T

选项更改目录)。最后,对返回的文件进行检查,该文件确实是可以查看的图片的二进制版本。

默认情况下,ldapsearch 以从服务器接收到的顺序打印出结果。可以使用

-S 参数对输出进行排序,将想要排序的属性名传递给它。如果要对多个属性进行排序,用逗号(,)把它们分开。

LDAP 命令行工具

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.2 主题的内容。这个主题的权值为 4。

在本节中,学习如何:

使用 ldap* 工具访问和修改目录

使用 slap* 工具访问和修改目录

OpenLDAP 附带了多种工具,可用于操纵目录或管理服务器。您已经熟悉了

ldapsearch,有关它的内容在 前一节 中已经讲到。以

ldap 开头的命令用于树的用户,以

slap 开头的命令用于管理员用户。

树操纵工具

本节中的命令用于操纵树,可以更改或读取数据。ldapsearch 也属于这个类别。要使用这些命令,您需要通过服务器的验证。

ldapadd 和 ldapmodify 这两个命令用于添加或修改树中的条目。您可能还记得在本系列的第一篇教程 LPI 301 考试准备:

概念、体系结构和设计 中讨论过,LDAP Data Interchange Format (LDIF) 可用于在树中添加、更改或删除数据。清单 7 展示了一个用于添加条目的 LDIF 示例。

清单 7. 将一个条目添加到树的 LDIF

dn: cn=Sean Walberg,ou=people,dc=ertw,dc=com

objectclass: inetOrgPerson

cn: Sean Walberg

cn: Sean A. Walberg

sn: Walberg

homephone: 555-111-2222

清单 7 首先描述了条目的区分名。此条目将会包含在

ou=people,dc=ertw,dc=com 容器中,并且拥有

cn=Sean Walberg 的一个相对区分名,这个相对区分名是通过分离第一个属性/值对之后的区分名(DN)得到的。此条目拥有一个

inetOrgPerson 的

objectclass,它对于属于一个组织的任何人来说是一种很普通的类型。后面是公用名的两种变形,然后是姓,最后是家庭电话号码。

清单 7 中向树中添加了一个条目,而不是更改或删除条目。LDIF 文件可以指定

changetype 关键字,告诉读取程序要如何对数据进行修改。

ldapadd 命令用于处理 LDIF 文件。如果清单 7 被存储为 “”,则可以使用

ldapadd -x -D

cn=root,dc=ertw,dc=com -w mypass -f 向树添加条目。命令的

-x -D

cn=root,dc=ertw,dc=com -w mypass 部分与前面讨论的

ldapsearch 很相似,这是使用简单验证和全能的根 DN 登录到树的一种方法。本节中的所有

ldap 命令都使用相同的参数登录到树,因此您将会多次看这种形式。

ldapadd 被实现为一个到

ldapmodify 的符号链接,在调用时,ldapadd 被解释为

ldapmodify -a。参数

-a 告诉

ldapmodify 假定

add 的一个默认

changetype,用于为树添加新条目。作为

ldapmodify

调用时,假定默认的

changetype 为修改操作。

ldapadd(和

ldapmodify)是一种把大量数据载入服务器的有效方式,无需关闭服务器。LDIF 文件可以包含许多操作,与编写自定义代码来解析数据源并通过 LDAP 将其直接添加到树中相比,从您尝试导入的其他数据源生成 LDIF 通常会更简单。

ldapdelete

由其名称可以看出,ldapdelete 用于从树中删除条目。所有条目都通过自己的 DN 在树中惟一标识,因此,ldapdelete 根据 DN 来删除条目,而不是通过任何其他查询。

除了已经讨论的验证参数以外,ldapdelete 还可以通过它的 DN 列表从命令行或文件中执行删除。要从命令行删除,只需将 DN 附加到命令行上,比如

ldapdelete -x -D cn=root,dc=ertw,dc=com -w mypass

"cn=Sean Walberg,ou=people,dc=ertw,dc=com"。如果要删除多个条目,可以将这些 DN 放置在一个文件中,一个 DN 占一行,并使用

-f filename 把

ldapdelete 指向该文件。

注意,也可以通过 LDIF 或者

ldapadd/ldapmodify 命令删除条目。在很多情况下,使用

ldapdelete 命令更方便一些,但这并不是删除条目的惟一方法。

ldapmodrdn

ldapmodrdn 命令用于修改对象的相对区分名,也就是 DN 中的第一个属性/值对。这种方法可以有效地重命名树的当前分枝中的条目。与 LDIF

moddn changetype 命令不同,此命令只能对条目进行重命名,而不能把它移动到树的另一个位置。 此命令的用法很简单:提供验证凭证、条目的 DN 和新 RDN。清单 8 展示了如何把帐户由 “Joe Blow”

重命名为 “Joseph Blow”。

清单 8. 对条目进行重命名

$ ldapmodrdn -x -D cn=root,dc=ertw,dc=com -w dirtysecret

'cn=Joe Blow,ou=people,dc=ertw,dc=com' 'cn=Joseph Blow'

$ ldapsearch -LLL -x '(cn=Joseph Blow)'

dn: cn=Joseph Blow,ou=people,dc=ertw,dc=com

objectClass: inetOrgPerson

sn: Blow

cn: Joe Blow

cn: Joseph Blow

注意,旧的 RDN 仍然会作为一个属性出现,也就是

cn: Joe Blow。如果想要删除旧的 RDN,可以将

-r

添加到命令行。这与将

deleteoldrdn: 1 添加到 LDIF 代码的方法相同(这是 LDIF 的默认行为,而不是

ldapmodrdn)。

ldapcompare

ldapcompare 允许您将预订值与 LDAP 树中的某个位置存储的值进行比较。用一个例子可以说明其工作原理。

清单 9. 使用 ldapcompare

$ ldapcompare -x "cn=Sean Walberg,ou=people,dc=ertw,dc=com" userPassword:mypassword

TRUE

$ ldapcompare -x "cn=Sean Walberg,ou=people,dc=ertw,dc=com" userPassword:badpassword

FALSE

在清单 9 中,执行了

ldapcompare 命令。除了验证参数,最后两个参数是要检查的 DN 和要检查的属性和值。上面两个例子中的 DN 是 “cn=Sean Walberg” 的清单,检查的属性均为

userPassword 属性。给出正确的密码之后,

ldapcompare 会输出字符串

TRUE 和一个错误代码 6。如果给定的值与条目中的内容不匹配,则发送

FALSE 到控制台并返回错误代码 5。-z 选项可以阻止打印任何内容;调用程序通过错误代码判断检查是否成功。

即使清单 9 中的例子对密码进行了检查,但是也可以使用任何属性,包括

objectClass。如果属性有多个值,比如多个公用名或

objectClass,则只要有一个值匹配,比较结果就算成功。

ldapwhoami

ldapwhoami 允许您对 LDAP 服务器的身份验证进行测试,并确定在服务器上验证了哪个 DN。只需使用普通的验证参数调用

ldapwhoami,如清单 10 所示。

清单 10.

ldapwhoami 演示

$ ldapwhoami -x

anonymous Result: Success (0)

$ ldapwhoami -x -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com" -w

mypassword

dn:cn=Sean Walberg,ou=people,dc=ertw,dc=com

Result: Success (0)

$ ldapwhoami -x -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com" -w

badpass

ldap_bind: Invalid credentials (49)

清单 10 中的第一个例子展示了一个没有用户名或密码的绑定。Ldapwhoami 返回字符串

anonymous,表明使用了匿名绑定;还返回一个状态行,表明授权成功。第二个例子绑定了用户的 DN。返回的 DN 与经过验证的 DN 相同。最后一个例子试图使用无效的凭证进行绑定。得到的结果是该问题的解释。

Ldapwhoami 命令对服务器配置的故障诊断和手动验证密码都很有帮助。访问列表可能会影响到

ldapsearch,因此可以使用

ldapwhoami 命令,它可以帮助您确定问题在于凭证还是访问列表。

回页首

管理工具

slap 开始的命令适用于管理员,它在数据库文件上直接操作,而不是通过 DLAP 协议操作。同样地,您通常需要以根用户的身份使用这些命令,而且在一些情况下需要关闭服务器。

slapacl

Slapacl 工具允许管理员根据绑定 DN、条目和属性的各种组合测试访问列表。例如,您可以使用

slapacl

进行测试,以查看一个特定用户对其他用户的属性的访问权限。此命令必须由根用户运行,因为它需要直接读取数据库和配置文件,而不是使用 LDAP。

slapacl 命令的用法通过一个例子可以很好地说明。在清单 11 中,管理员进行了测试,查看在实现 ACL

之前和实现了一个提升了访问安全级别的 ACL 之后,一个用户对自己的密码的访问权限。

清单 11. 使用

slapacl 确定更改 ACL 的效果

# slapacl -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=sean walberg,ou=people,dc=ertw,dc=com"

userPassword: read(=rscxd)

... change ...

# slapacl -D "cn=Sean Walberg,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=sean walberg,ou=people,dc=ertw,dc=com"

userPassword: =wx

# slapacl -D "cn=Joseph Blow,ou=people,dc=ertw,dc=com"

-b "cn=Sean Walberg,ou=People,dc=ertw,dc=com"

userPassword

authcDN: "cn=joseph blow,ou=people,dc=ertw,dc=com"

userPassword: =0

slapacl 命令需要两部分信息。第一部分是绑定 DN,也就是您要测试其访问权限的用户的 DN。第二部分是您要测试的条目的 DN。绑定 DN 通过

-D 指定,而目标 DN 由

-b 指定。您可以选择对单个属性进行测试,方法是将其包含在命令行末尾(就像清单 11 中

userPassword 示例一样)。如果没有指定一个属性,您将收到条目中每个属性的结果。

在清单 11 的第一个命令中,管理员测试

cn=Sean Walberg 条目,以查看他对自己的密码有何种访问权限。结果为读访问权限。在本系列的第三篇教程 LPI 301 考试准备:

配置 中讨论过,用户应该能够写入和验证自己的

userPassword 属性,但是不能读取。改变 ACL 后再执行一次测试,结果只具有写和验证的权限。最后再进行一次测试,查看 Joseph Blow 对 Sean Walberg

的密码有何种访问权限;结果为他没有任何权限。

Slapacl 是一种测试ACL 更改和调试 ACL 问题的有效方法。它非常有效,因为它直接从数据库和

中读取结果,因此对 的任何更改都将反映到

slapacl 的输出中,而且无需重新重启

slapd。

slapcat

Slapcat 把 LDAP 树中的内容以 LDIF 格式转储到标准输出中,如果您使用

-l filename ,也可以转储到文件中。您也可以使用

-s 选项提供开始 DN,或使用

-a 选项传递一个查询过滤器。

Slapcat 直接对数据库进行操作,并且可以在服务器正在运行时进行操作。该命令只支持 bdb 数据库类型。

slapadd

Slapadd 是一个批量导入工具,它直接对后端数据库进行操作,这意味着必须停止 slapd 才能使用这个工具。它的设计目的是与

slapcat 的输出一起使用。Slapadd 并不对输入数据进行有效性验证,因此该命令可能在树的分离的分枝上停止。如果一些容器对象未导入,就会发生这种情况。

slapadd 的输入是一个 LDIF 文件,比如由

slapcat 生成的文件。slapadd(8C) manpage 建议使用

ldapadd,因为在线变量提供了数据有效性验证。该 manpage 也说明了

slapcat 的输出不一定会以与

ldapadd 兼容的方式进行排序(容器对象可能会跟在输出的子对象之后,因此验证将失败)。在

slapcat

中使用任何过滤器都会造成重要数据的丢失。因此,slapadd 只应该用于

slapcat 生成的 LDIF,将

ldapadd 用于任何其他 LDIF。

在关闭 LDAP 服务器之后,您可以运行

slapadd 命令把 LDAP 输出转换为标准输入。如果想从一个文件中读取数据,请使用

-l 选项。slapcat 只支持 bdb 数据库类型。

slappasswd Slappasswd 用于生成经过哈希运算的密码,该密码然后会存储在在目录或 中。常用方法是将经过哈希运算的密码用于 中的根 DN 的账户,这样,查看配置文件的任何人都不能确定出密码。如果您不提供任何参数,Slappasswd 将提示输入要进行哈希运算的密码,如清单 12 所示。

清单 12. 使用

slappasswd 对密码进行哈希运算

$ slappasswd

New password:

Re-enter new password:

{SSHA}G8Ly2+t/HMHJ3OWWE7LN+GRmZJAweXoE

然后您可以将整个字符串复制到 文件中的

rootpw 行中。Slapd 识别密码的格式,并将

{SSHA} 理解为其后面跟的是一个 SHA1 哈希算法。读取 文件的任何人都不会知道根密码。

slappasswd 产生的哈希值也可以通过

ldapadd 和

ldapmodify 命令用于 LDIF 文件中,这将允许您存储您的密码的安全的单向哈希值,而不是不安全的纯文本或 base64 编码的版本。

slapindex

您可能还记得本系列第三篇教程 LPI 301 考试准备:

配置 中的

slapindex。使用

index 关键字在 文件中创建或修改了索引之后,您必须重建索引,否则

slapd 将返回错误的结果。要重建索引,请停止

slapd 命令并运行

slapindex命令。这将花费一些时间,具体取决于您的数据库中有多少条目,或者如手册页中所述,“此命令将会为用户提供品尝饮料的充足时间”。

slaptest

Slapdtest 将进行检查,查看您的 文件是否正确。这一点很有帮助,因为如果您使用错误的配置文件重新启动

slapd 命令,那么在修复了文件中的错误之前,启动都会失败。Slaptest 允许您在重启之前对配置文件进行检查。

使用

slaptest 命令时只需输入

slaptest 即可。如果 文件是正确的,您将看到

config

file testing succeeded 消息。否则,您将看到一个用于解释问题的错误。

Slaptest 也会检查操作所需的各种文件和目录是否存在。 在测试过程中,作者能够发现一些传递给

slaptest 的配置文件错误,这将导致

slapd 失败。

Whitepages

本节讨论 Senior Level Linux Professional(LPIC-3)考试 301 的 304.3 主题的内容。这个主题的权值为 1。

在本节中,学习如何:

计划 Whitepages 服务

配置 Whitepages 服务

配置客户端,从 Whitepages 服务中获取数据

Whitepages

服务 允许电子邮件客户端从 LDAP 数据库获取联系人信息。与普通属性名(比如

inetOrgPerson objectClass 提供的普通属性名)一起使用,您可以获得与电子邮件客户端的对大兼容性。例如,Microsoft Outlook 和 Evolution 都使用

mail 属性存储用户的电子邮件地址,而

givenName、displayName、cn、和

sn 属性用于存储各种形式的名称。

为 LDAP 目录配置电子邮件客户端 从理论上讲,支持 LDAP 的任何邮件客户端都可使用您的树。您需要在客户端中配置的下列信息:

LDAP 服务器的地址或主机名

要绑定的凭证,进行匿名绑定时不需要

要搜索的基 DN

搜索过滤器,比如 (mail=*),这将删除没有电子邮件地址的帐户(可选)

在电子邮件客户端中输入上述信息之后,就应该能够搜索联系人信息了。

为 LDAP 目录配置 Microsoft Outlook

要配置 Microsoft Outlook(在 Outlook 2003 上进行测试),请选择 Tools > Email Accounts。您将看到一个与图 2 相似的对话框。

图 2. 选择要添加的帐户类型

选择添加新目录的选项,以添加一个新目录,然后单击 Next。您将会看到图 3 中的对话框。 图 3. 选择将要添加的目录类型

选择添加新 LDAP 目录的选项,添加一个新的 LDAP 目录。然后单击 Next。您将看到图 4 中的对话框。

图 4. 指定 LDAP 服务器的细节

在图 4 所示的对话框中输入您的 LDAP 服务器的相关细节。展示的示例使用用户凭证绑定到树。您还可以使用匿名访问,只要您的服务器支持。

输入基本细节之后,单击 More Settings,将提示您输入更多信息,如图 5 所示。

图 5. 为 LDAP 服务器配置添加高级选项

图 5 显示了更多选项,最重要的一个选项是搜索基。输入搜索基之后单击 OK,然后将会返回到 Outlook

的主界面。

现在,只要提示您寻找用户,您就可以从 “Show Names From” 字段中选择服务器名称来使用 LDAP 数据库。

结束语

在本教程中,您了解了如何通过搜索和命令行工具使用目录。还了解了如何配置电子邮件客户端,使用目录存储联系人信息。

对 LDAP 树进行搜索要求您建立查询过滤器。表 3 列出了查询中用到的各种操作符。

表 3. LDAP 搜索操作符

操作符

=

*

&

|

!

说明

测试相等性

测试某一属性是否在在

子字符串搜索

逻辑 AND

逻辑 OR

逻辑 NOT

示例

(cn=Walberg)

(cn=*)

(sn=Walb*)

(&(condition1)(condition2))

(|(condition1)(condition2))

(!(mail=*)) ~=

<= and >=

“声音相似” 匹配

范围匹配

(cn~=Shawn)

(pagesPerMinute >= 20)

有许多工具可以使用目录,比如

ldapsearch 可用于搜索,ldapadd 和

ldapmodify 用于添加和修改数据。以

ldap 开始的工具通过 LDAP 协议操作,并要求使用凭证登录到服务器。以

slap 开始的工具适用于管理员,并且直接对数据库进行操作。

本教程和 301 系列 的前几篇教程主要介绍了如何管理管理和使用 LDAP 服务器。本系列的下一篇教程将会介绍各种应用,包括电子邮件服务器,并展示如何将 LDAP 作为数据源使用。