参考:http://blog.163.com/nonnie@126/blog/static/57630308201091275449969/
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构筑的数据存储系统,理解为数据库结构中的层次模型。
识别名dn:目录中每个对象唯一名字,是这个对象之上的所有对象单一属性加上自身附加属性构成;
相对识别名rdn:以目录中某个结点作为根节点命名其下的对象;
LDIF文件:LDAP数据交换格式。它是一个纯文本文件,每个对象包括许多行,对象定义的第一行以dn开头。它主要用于ldap服务器对数据的导入、导出、交换等。
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以上。目前我们没有继续试验源码方式的安装。
服务器端需要配置/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:
{加密方法}密文
手工方式启动:
# /usr/sbin/slapd –f /etc/openldap/slapd.conf –d 256
其中-f指出配置文件的路径名,-d指出debug级别。如果打开调试选项,则slapd把调试信息输出至stdout,如果不使用调试选项,slapd以后台进程方式启动。
以服务方式启动:
# service ldap start
手工关闭:使用kill命令杀死slapd进程。
以服务方式关闭:
# service ldap stop
注意:我们可以使用手工方式启动,然后用服务方式关闭;反之亦然。
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组的成员读写,否则无法正确读入配置信息;
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);
#includeint ldap_get_option(LDAP * ld, int option, void *outvalue); int ldap_set_option(LDAP *ld, int option, const void *invalue);
l 数据备份:
使用命令 slapcat 。缺省 slapcat 把数据输出至标准输出 stdout ,我们可以使用重定向,把输出保存到某个 ldif 文件