1.     openldap简介

openldap是在TCP上实现目录服务的系统,一种源代码开放的ldap版本。相对OSI的X.500服务,它使用了较少的代价(10%?)实现了目录服务大部分功能(90%?)。因为它基于TCP网络,且实现的功能没有X.500规定那么复杂,所以成为“轻量级”的目录服务。

目录服务器可以想象为树型结构。一个结点元素称为对象,一个对象可以拥有多个属性(例如某人身兼数值),多个对象拥有相同属性也是可能的(许多人属于某个公司)。objectclass是对属性类型的描述,多个objectclass可以构成一个schema,用于约束加入目录服务器的数据对象。

我们当前的测试基于RedHat Linux 9.0,openldap-2.0.27-8,后台基于dbm数据库(gdbm兼容dbm)。

我们可以把ldap构筑的数据存储系统,理解为数据库结构中的层次模型。

ldap概念

识别名dn目录中每个对象唯一名字,是这个对象之上的所有对象单一属性加上自身附加属性构成;

相对识别名rdn以目录中某个结点作为根节点命名其下的对象;

LDIF文件:LDAP数据交换格式。它是一个纯文本文件,每个对象包括许多行,对象定义的第一行以dn开头。它主要用于ldap服务器对数据的导入、导出、交换等。

安装openldap

l安装系统时选择安装openldap

这是最简单的方式。键入命令:

service ldap start

如果系统提示没有错误,则说明ldap服务器已经正确启动。我们目前使用这种方式。

l下载openldap代码,编译安装

一般经过如下步骤:

1.     # tar xzvf openldap-version.tgz

2.     # cd openldap-version

3.     # [env setting]./configure  [OPTIONS]

4.     # make depend

5.     # make

6.     # make test

7.     # make install

详细资料可以查看openldap的INSTALL文件,也可以查看在线手册http://www.openldap.org

如果安装最新的openldap版本2.2.24,会遇到许多问题:

其一是在配置(执行configure脚本)时选择后台数据库的问题,我们必须加入选项设置–disable-bdb屏蔽BDB数据库(Berkeley DataBase);

其二是系统上原来安装的Cyrus SASL版本过老,必须下载安装新版本。openldap-2.2.24要求SASL版本在2.1.18以上。目前我们没有继续试验源码方式的安装。

4.     配置

服务器端需要配置/etc/openldap/slapd.conf文件。

加入某个schema文件,例如:

include    /etc/openldap/openldap.schema

加入数据库支持:

database        ldbm

声明本地节点后缀:

suffix      “o=aitiso.com,c=cn”

管理员识别名:

rootdn     “cn=root,o=aitiso.com,c=cn”

管理员密码:

rootpw    secret

# rootpw        {CRYPT}B7fF/KIqexnDs

# rootpw        {MD5}iWPLuV9TDL/GdW1ZRcX3vA==

# rootpw        {SMD5}tMQdIbEBsjG9JJTiDgk5A7wnu/o=

# rootpw        {SHA}GQoNhXp4y6KsQMbOZBVaaoSzqsU=

指定数据库文件存放位置:

directory /var/lib/ldap

其他配置项直接使用系统配置即可。

需要介绍的是slappasswd命令,使用下面命令得到加密后的口令,拷贝到配置文件中:

slappasswd -h {加密方法}

New Password:

Re-enter new password:

{加密方法}密文

5.     访问5.1.   启动ldap服务器:

手工方式启动:

# /usr/sbin/slapd –f /etc/openldap/slapd.conf –d 256

其中-f指出配置文件的路径名,-d指出debug级别。如果打开调试选项,则slapd把调试信息输出至stdout,如果不使用调试选项,slapd以后台进程方式启动。

以服务方式启动:

# service ldap start

5.2.  关闭ldap服务器

手工关闭:使用kill命令杀死slapd进程。

以服务方式关闭:

# service ldap stop

注意:我们可以使用手工方式启动,然后用服务方式关闭;反之亦然。

5.3.   脚本方式访问ldap

l ldapadd:       用于对ldap目录服务器添加数据,格式为LDIF;

例子:

$     ldapadd – D “cn=root,o=aitiso.com,c=cn” –x –w passwd –f test.ldif

若不给出ldif文件,命令执行成功并不退出,而是等待用户输入下一条修改数据。输入^D结束

选项说明:

-D后给出的是登录DN(此时为管理员DN);

-x说明使用简单认证(明码);

-w后给出密码正文;

-f后给出需要插入的数据文件。

l ldapmodify:  用于修改目录中的对象;

例子:

$     ldapmodify – D “cn=root,o=aitiso.com,c=cn” –x –w passwd

若不给出ldif文件,命令执行成功并不退出,而是等待用户输入下一条修改数据。输入^D结束

选项同上,说明:

-a,表示新加入数据,效果同ldapadd命令。这两个命令底层都使用ldap_add()函数完成。

l ldapdelete:    用于删除目录中的对象;

例子:

$     ldapdelete “ou=communications,o=ait.com,c=cn” –D”cn=root,o=aitiso.com,c=cn” –x –w root

选项同上,说明:

双引号中给出的是需要删除的结点。注意,当结点有非空子结点时(即当前要删除结点不是叶子结点),删除操作失败。如果加上-r选项,则命令将递归删除所有子结点,且不会提示任何确认信息。使用时需要特别小心。

l ldapmodrdn: 修改rdn;

例子:

$     ldapmodrdn  – D “cn=root,o=aitiso.com,c=cn” –x –w passwd

选项同上,说明:

-r表示删除原有rdn。

在命令行结束后,用户需要输入原有dn,然后输入修改dn,最后输入^D结束

l ldapsearch:   查找对象;

例子:

$     ldapsearch –D “cn=root,o=aitiso.com,c=cn” –b “o=aitiso.com,c=cn” –x  –w passwd ’objectClass=person’

选项同上,说明:

-b后给出搜索的起始结点DN(base DN),它必须给出,否则无法查询出结果;

单引号(双引号也可以)中给出的objectClass用于过滤输出结果(即搜索条件),此处查找的对象类型仅限于person对象,也就是查找aitiso.com,c=cn结点下的所有人员记录。

注意:

1.查询中经常使用的是简单认证,应给出-x选项,使用-w给出密码(或者-W在命令行后输入);

2. ldif文件中某些objectClass必须拥有一些属性(查看schema),在写ldif文件时应注意;

3.  应保证/etc/openldap/slapd.conf能够被ldap组的成员读写,否则无法正确读入配置信息;

5.4.   ldap的C接口

l 需要包含的头文件:

#include

#include

l 需要包含的库文件:

-lldap -llber

l 初始化,打开ldap服务器的socket连接

LDAP * ldap_init(ldap_host, port)

char *ldap_host;            /*ldap主机名字*/

int    port                      /*ldap监听的端口号*/

返回值为LDAP结构。

typedef struct ldap {

/* … other stuff you should not mess with … */

char      ld_lberoptions;

int       ld_deref;

#define LDAP_DEREF_NEVER 0

#define LDAP_DEREF_SEARCHING  1

#define LDAP_DEREF_FINDING    2

#define LDAP_DEREF_ALWAYS     3

int       ld_timelimit;

int       ld_sizelimit;

#define LDAP_NO_LIMIT         0

int       ld_errno;

char      *ld_error;

char      *ld_matched;

int       ld_refhoplimit;

unsigned long  ld_options;

#define LDAP_OPT_REFERRALS      0x00000002   /* set by default */

#define LDAP_OPT_RESTART 0x00000004

/* … other stuff you should not mess with … */

} LDAP;

l 绑定LDAP服务器

int ldap_bind(ld, who, cred, method)

LDAP *ld;

char *who, *cred;

int method;

int ldap_bind_s(ld, who, cred, method)

LDAP *ld;

char *who, *cred;

int method;

这是打开ldap服务器之后,在访问之前的认证过程。它需要传入ldap初始化结构ld,需要输入DN作为连接访问者who,输入密码cred作为认证信息,并设置认证方式method。

返回值可以使用ldap_error(3)读取,输出。

l 错误输出:ldap_error(3)

struct ldaperror {

int e_code;

char *e_reason;

};

struct ldaperror ldap_errlist[];

char *ldap_err2string(err)

int err;

void ldap_perror(ld, s)

LDAP *ld;

char *s;

int ldap_result2error(ld, res, freeit)

LDAP *ld;

LDAPMessage *res;

int freeit;

如果某步骤出现错误,可以使用ldap_error()捕获错误代码,并输出信息;

l 解除与LDAP服务器的绑定

int ldap_unbind(ld)

LDAP *ld;

返回值可以使用ldap_error(3)读取,输出。

l 查询ldap目录服务器的数据

int ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res)

LDAP *ld;

char *base;

int scope;

char *filter, *attrs[]

int attrsonly;

LDAPMessage **res;

选择范围:

1. 设置起始点DN

2. 设置搜索深度(搜索范围)

过滤结果:

l 处理返回的结果数据

int ldap_msgfree(LDAPMessage *msg);      /*释放结果*/

int ldap_count_entries(LDAP *ld,LDAPMessage *result);   /**/

LDAPMessage *ldap_first_entry(LDAP *ld,LDAPMessage *result);  /*获取第一个数据结点*/

LDAPMessage *ldap_next_entry(LDAP *ld,LDAPMessage *result);  /*获取下一个结点*/

l 获取实际属性和值

char *ldap_first_attribute(LDAP *ld,LDAPMessage *entry,BerElement **ber_element);

char *ldap_next_attribute(LDAP *ld,LDAPMessage *entry,BerElement **ber_element);

char *ldap_get_dn(LDAP *ld, LDAPMessage *entry);

char **ldap_get_value(LDAP *ld,LDAPMessage *entry,char *attribute);

void ldap_value_free(char**value);

6.    数据备份和恢复

l 数据备份:

使用命令slapcat。缺省slapcat把数据输出至标准输出stdout,我们可以使用重定向,把输出保存到某个ldif文件中。

例子:

slapcat > back.ldif

l 数据恢复,需要先删除数据库(或其中所有数据):

使用ldapadd命令,ldapadd -w … -D … < back.ldif