本文系作者原创,转载请保留出处:
http://marion.cublog.cn
其中理解可能也有不当之处,欢迎各位指正。
为了让openldap支持ssl/tls和sasl,我们这次的安装将首先安装openssl0.98e和cyrus-sasl-2.0.22这两个软件包。
一、安装openssl0.98e
1.1 下载相关软件包至/usr/local/src目录
1.2 安装openssl
#cd /usr/local/src
#tar zxvf openssl-0.9.8e.tar.gz
#cd openssl-0.9.8e
#./config shared zlib
#make
#make test
#make install
mv /usr/bin/openssl /usr/bin/openssl.OFF
mv /usr/include/openssl /usr/include/openssl.OFF
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl /usr/include/openssl
1.3 配置库文件搜索路径
#echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
#ldconfig -v
1.4 查看openssl的版本号,以验正是否安装正确
#openssl version -a
OpenSSL 0.9.8e 17 Apr 2007
built on: Sat Mar 24 21:24:41 CST 2007
platform: linux-elf
options: bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) idea(int) blowfish(idx)
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT
-DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer
-Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DSHA1_ASM
-DMD5_ASM -DRMD160_ASM -DAES_ASM
OPENSSLDIR: "/usr/local/ssl"
二、安装cyrus-sasl-2.0.22
2.1 下载cyrus-sasl-2.1.22到/usr/local/src
2.2 编译安装
#tar zxvf cyrus-sasl-2.1.22.tar.gz
#cd cyrus-sasl-2.1.22
# ./configure --prefix=/usr/local/sasl2 --enable-login --with-openssl=/usr/local/ssl
#make
#make install
2.3配置库文件搜索路径
#echo "/usr/local/sasl2/lib" >> /etc/ld.so.conf
#echo "/usr/local/sasl2/lib/sasl2" >> /etc/ld.so.conf
#ldconfig -v
2.4 把Redhat9.0原有的sasl库文件改名或删除,并将相关符号链接指向新安装SASL的库文件
#cd /usr/lib
# mv libsasl2.a libsasl2.a.OFF
# mv libsasl2.la libsasl2.la.OFF
# mv libsasl2.so libsasl2.so.OFF
# mv libsasl2.so.2.0.10 libsasl2.so.2.0.10.OFF
# mv lIbsasl2.so.2 libsasl2.so.2.OFF
# ln -s /usr/local/sasl2/lib/* /usr/lib
# ln -s /usr/local/sasl2/lib/sasl2 /usr/lib/sasl2
#ln -s /usr/local/sasl2/lib/libsasl2.so.2.0.22 /usr/lib/libsasl2.so.2
#ln -s /usr/local/sasl2/lib/libsasl2.so /usr/lib/libsasl2.so
2.5 创建运行时需要的目录并调试启动
#mkdir -pv /var/state/saslauthd
# ./saslauthd -a pam shadow -d
saslauthd[3533] :main : num_procs : 5
saslauthd[3533] :main : mech_option: NULL
saslauthd[3533] :main : run_path : /var/state/saslauthd
saslauthd[3533] :main : auth_mech : pam
saslauthd[3533] :ipc_init : using accept lock file: /var/state/saslauthd/mux.accept
saslauthd[3533] :detach_tty : master pid is: 0
saslauthd[3533] :ipc_init : listening on socket: /var/state/saslauthd/mux
saslauthd[3533] :main : using process model
saslauthd[3534] :get_accept_lock : acquired accept lock (此处使用"ctrl+c"退出)
saslauthd[3533] :have_baby : forked child: 3534
saslauthd[3533] :have_baby : forked child: 3535
saslauthd[3533] :have_baby : forked child: 3536
saslauthd[3533] :have_baby : forked child: 3537
2.6 启动并测试验正
#/usr/local/sasl2/sbin/saslauthd -a pam shadow
#/usr/local/sasl2/sbin/testsaslauthd -u root -p root的密码
0: OK "Success."
三、安装BerkeleyDB
3.1 下载相关软件至/usr/local/src
3.2 编译安装
#tar zxvf db-4.5.20.tar.gz
#cd db-4.5.20/build_unix
#../dist/configure --prefix=/usr/local/BerkeleyDB
#make
#make install
四、安装openldap-2.3.32
4.1 下载相关软件至/usr/local/src
4.2 编译安装
#tar zxvf openldap-stable-20070110.tgz
#cd openldap-2.3.32
#env CPPFLAGS="-I/usr/local/BerkeleyDB/include
-I/usr/local/sasl2/include" LDFLAGS="-L/usr/local/BerkeleyDB/lib
-L/usr/local/sasl2/lib -L/usr/local/sasl2/lib/sasl2" ./configure
--prefix=/usr/local/openldap --sysconfdir=/etc/openldap --enable-passwd
--enable-wrappers --disable-ipv6 --enable-spasswd --enable-crypt
--enable-modules --enable-accesslog=yes
#make depend
#make
#make test
#make install
#cp /usr/local/openldap/var/openldap-data/DB_CONFIG.example /usr/local/openldap/var/openldap-data/DB_CONFIG
4.3 测试启动
# /usr/local/openldap/libexec/slapd -d 256
@(#) $OpenLDAP: slapd 2.3.32 (Apr 17 2007 00:44:16) $
ldomain:/usr/local/src/openldap-2.3.32/servers/slapd
Expect poor performance for suffix dc=my-domain,dc=com.
slapd starting
4.4 启动及关闭服务
启动
#/usr/local/openldap/libexec/slapd
查看监听的端口
# netstat -tunlp |grep :389
tcp 0 0 0.0.0.0:389 0.0.0.0:* LISTEN 10111/slapd
查看能否正常查询
# /usr/local/openldap/bin/ldapsearch -x -b '' -s base '(objectclass=*)' (此行为命令,以下为结果)
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: ALL
#
#
dn:
objectClass: top
objectClass: OpenLDAProotDSE
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
关闭
#kill -INT `cat /usr/local/openldap/var/run/slapd.pid`
五、主配置文件slapd.conf介绍
安全起见,slapd.conf文件应该只让运行此进程的用户可读写。下面是安装完毕后的一个slapd.conf示例。
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /etc/openldap/openldap/schema/core.schema
# Define global ACLs to disable default read access.
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral ldap://root.openldap.org
pidfile /usr/local/openldap/var/run/slapd.pid
argsfile /usr/local/openldap/var/run/slapd.args
# Load dynamic backend modules:
# modulepath /usr/local/openldap/libexec/openldap
# moduleload back_bdb.la
# moduleload back_ldap.la
# moduleload back_ldbm.la
# moduleload back_passwd.la
# moduleload back_shell.la
# Sample security restrictions
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64
# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
#############################################################
# BDB database definitions
#############################################################
database bdb
suffix "dc=my-domain,dc=org"
rootdn "cn=Manager,dc=mydomain,dc=org"
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw secret
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 reorgmended.
directory /usr/local/openldap/var/openldap-data
# Indices to maintain
index objectClass eq
接下来我们对上述部分进行一些介绍:
include /etc/openldap/openldap/schema/core.schema
此句是用来将目录所用到的schema文件包含进来;openldap一般默认带有几个schema,在我们的配置文件安装目录下的schema目录中存
放。本句中的core.schema是LDAP V3中必须的,它给出了LDAP
V3中最基本的attribute和objects的定义。其它的还有:corba.schema、dyngroup.schema、
java.schema nis.schema、openldap.schema、cosine.schema、
inetorgperson.schema、misc.schema、ppolicy.schema
pidfile /usr/local/openldap/var/run/slapd.pid
此句用来定义slapd进程运行时的pid文件,需要使用绝对路径。
argsfile /usr/local/openldap/var/run/slapd.args
此句用来定义包含当前正在运行的slapd进程所用到的命令行参数的文件,需要使用绝对路径。
# Load dynamic backend modules:
# modulepath /usr/local/openldap/libexec/openldap
# moduleload back_bdb.la
# moduleload back_ldap.la
# moduleload back_ldbm.la
# moduleload back_passwd.la
# moduleload back_shell.la
以上用来指定动态加载的后端模块。
# Sample security restrictions
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64
以上是安全相关的声明语句。常用到的参数有五类,除了Require和security外还有Allow、Disallow和password-hash等。
Require参数用来使管理员指定访问目录时必须遵循的规则和条件;这种指定可以是全局的,也可以仅用来限制对某个后端数据库的访问限制。
security参数用来让管理员指定加强安全性的一般规则。
# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
以上主要是用来定义访问控制列表。
#######################################################################
# BDB database definitions
#######################################################################
database bdb
定义使用的后端数据存储方式。其后可以跟的值有bdb、ldbm、passwd、config、dnssrv、ldif、perl、hdb和shell等。bdb指使用Berkley DB 4数据库。
suffix "dc=my-domain,dc=org"
定义suffix,以上部分可以改作你的域名中相关的部分,如"dc=example,dc=com"。
rootdn "cn=Manager,dc=mydomain,dc=org"
定义此目录的超级管理员帐号,类同于系统中的root。由于访问控制对此用户是不生效的,因此存在很大的安全隐患。建议安装配置及调试完成以后移除此帐号。
rootpw secret
定义超级管理员帐号的密码,这里使用的是明文存储(secret即是其密码)的方式。这是极不安全的,建议使用加密方式存储,可以使用的加密方式有:
CRYPT、MD5、SMD5、SHA和SSHA。产生加密密码散列的方法是使用slappasswd命令,用-h选项指明加密时使用的方式。示例如下:
# /usr/local/openldap/sbin/slappasswd -h {SSHA}
New password:
Re-enter new password:
{SSHA}k2H1GPM/95VfgsKg2jZv9hV+2GCH04hC
directory /usr/local/openldap/var/openldap-data
这一句用来指定目录相关数据的存放位置。此目录最好只能由运行slapd进程的用户所有,推荐权限为700
index objectClass eq
此句用来指定slapd索引时用到的attribute,eq指索引时的匹配规则。主要是用来优化查询的。常用到的匹配规则有:approx(模糊匹配,
approximate)、eq(精确匹配,equality)、pres(现值匹配,若某记录的此attribute没有值则不进行匹配,
presence)和sub (子串匹配,substring)。
具体应用的实现:建立起始目录项,并导入数据
6.1 先建立一个创建起始结点所用的ldif文件
#vi init.ldif
输入以下内容(可以根据自己的需要修改)
dn: dc=mydomain,dc=org #定义根结点
objectClass: top
objectClass: domain
objectClass: organization
dc: mydomain
o: mydomain.org
description: Mydomain.org ldap
dn: cn=Manager,dc=mydomain,dc=org #定义目录管理员
objectClass: organizationalRole
cn: Manager
description: Directory Manager
dn: ou=people,dc=mydomain,dc=org #定义一个OU
ou: people
objectClass: organizationalUnit
注意:ldif文件中,每一行中冒号后有一个空格,行尾一定不能有空格。切记!
6.2使用离线import命令导入到目录中,需要离线进行(要先关闭slapd进程)
#kill -INT `cat /usr/local/openldap/var/run/slapd.pid`
# /usr/local/openldap/sbin/slapadd -v -l ./init.ldif
bdb_db_open: Warning - No DB_CONFIG file found in directory /var/openldap/data-3: (2)
Expect poor performance for suffix dc=mydomain,dc=org.
added: "dc=mydomain,dc=org" (00000001)
added: "ou=people,dc=mydomain,dc=org" (00000002)
命令中:
-v选项表示启用verbose模式,即输出执行中的具体信息;
-l表示后面附加ldif文件。
其它常用的选项还有:
-d 指定debug向日志文件输出信息,后面跟日志级别
-f 指定要读取的配置文件
6.3 启动服务进程
#/usr/local/openldap/libexec/slapd
6.4 建立要导入的具体信息记录的ldif文件
#vi users.ldif
dn: cn=Tom Black,ou=people,dc=mydomain,dc=org 定义人员1
cn: Tom Black
sn: Black
mail:
telephoneNumber: 371-6338-3522
objectClass: inetOrgPerson
dn: cn=Jerry Smith,ou=people,dc=mydomain,dc=org 定义人员2
cn: Jerry Smith
sn: Smith
mail:
telephoneNumber: 371-6338-3521
objectClass: inetOrgPerson
6.5 导入ldif文件
# /usr/local/openldap/bin/ldapadd -D "cn=Manager,dc=mydomain,dc=org" -W -x -f users.ldif
Enter LDAP Password:
adding new entry "cn=Tom Black,ou=people,dc=mydomain,dc=org"
adding new entry "cn=Jerry Smith,ou=people,dc=mydomain,dc=org"
命令中:
-D选项表示指定绑定到LDAP的DN;
-W表示提示用户输入密码;
-x表示使用简单身份验正方式,默认的是使用sasl进行验正;
-f用来指定ldif文件;
七、配置文件中的高级功能使用方法
1. 开启日志功能
启用日志功能,需要在编译时指定--enable-debug 选项,默认是允许的。要打开slapd的日志功能,需要在slapd.conf中的全局配置段添加loglevel指令,并后跟一个十进制数字表示的日志级别,如下所示:
# Added logging parameters
loglevel 256
其日志级别如下所示:
-1 记录所有的信息
0 不记录debug
1 跟踪功能调用的信息
2 包处理的debug信息
4 丰富的debug信息
8 连接管理信息
16 包的收发信息
32 搜索过滤的处理过程
64 配置文件的处理过程
128 访问控制列表处理过程
256 连接、操作及其结果的统计数据
512 向客户端返回的结果的统计信息
1024 与shell后端的通信信息
2048 显示记录条目的分析信息
4096 数据库缓存处理信息
8192 数据库索引
16384 从服务器数据同步资源消耗处理信息
若要记录所有的debug日志,可以使用LOG_LEVEL4 syslogd系统日志来记录,这需要在slapd.conf中添加如下语句实现:
local4.debug /var/log/slapd.log
2. 为BDB后端数据库实例指定在内存中的缓存空间大小
在如下句子后
DBDirectory: /usr/local/openldap/var/openldap-data
后添加:
DBCachesize: 2000
3. 访问控制列表:
3.1 语法
access to
[by ]+
其中,access to指示启用访问控制,上句大致可以理解为:
access to <对什么目标进行控制>[by <作用于哪些访问者> <授予什么样的访问权限><采取什么样的匹配控制动作>]+
3.2 剖析
3.2.1 控制目标
这一域主要是实现对ACL应用对象的指定,对象可以是记录和属性。选择ACL目标记录的方法一般有两种:DN和filter,语法为:
::= * |
[dn[.]= | dn.=]
[filter=] [attrs=]
3.2.1.1 指定所有的记录
access to *
3.2.1.2 通过DN指定
语法如下:
to dn[.]=
::= regex | exact
to dn.=
::= base | one | subtree | children
第一种方法是使用正则表达式(dn.regex)或精确匹配(dn.style)的方式来匹配符合条件的记录(这个好像不像想象的那么简单,实现起来颇为费脑筋),例如:
access to dn="^.*,uid=([^,]+),ou=users,(.*)$"
第二种方法通过“区域”选择的方法进行目标记录的选取,对以指定的DN开始的目录树区域进行目标记录匹配。匹配区域的方式共有四种:
base 只匹配DN本身一条记录
one 匹配以给定DN为父目录的所有记录
subtree 匹配以给定DN为根目录的所有子树内的记录
children 匹配给定DN下的所有记录,但应该不包括以DN直接命名的那条记录(参见例子的解释)
例如:对于
0: dc=mydomain,dc=org
1: cn=root,dc=mydomain,dc=org
2: ou=users,dc=mydomain,dc=org
3: uid=samba,ou=users,dc=mydomain,dc=org
4: cn=Administator,uid=samba,ou=users,dc=mydomain,dc=org
5: uid=guest,ou=users,dc=mydomain,dc=org
规则 dn.base="ou=users,dc=mydomain,dc=org" 只会匹配记录2
规则 dn.one="ou=users,dc=mydomain,dc=org" 匹配记录3和记录5,记录4是记录3的子目录,故不算在内
规则 dn.subtree="ou=users,dc=mydomain,dc=org" 匹配记录2、3、4、5
规则 dn.children="ou=users,dc=mydomain,dc=org" 匹配记录3、4、5,因为记录0、1和2都是以DN直接命名的,故不匹配
3.2.1.3 通过filter匹配记录
通过filter指定过滤规则进行记录过虑,语法如下:
access to filter=
其中filter指定的为search的过滤规则,这类同于linux系统中grep的匹配方式。如:
access to filter=(objectClass=sambaSamAccount)
也可以结合使用DN和filter进行记录的匹配,例如:
access to dn.subtree="ou=users,dc=mydomain,dc=org" filter=(objectClass=posixAccount)
3.2.1.4 通过attrs选取匹配记录
语法:
attrs=
例如:
access to attrs=uid,uidNumber,gidNumber
也可以结合使用DN和attrs进行记录的匹配,例如:
access to dn.subtree="ou=users,dc=mydomain,dc=org" attrs=uid
3.2.2 被用来授权的访问者的指定
指定被授权的用户范围的方法大致有以下几种:
* 所有的访问者,包括匿名的用户
anonymous 非认证的匿名用户
users 认证的用户
self 目标记录的用户自身
dn[.]= 在指定目录内匹配正则表达式的用户
dn.= 指定DN内的用户
例如:
by dn.subtree="ou=users,dc=domain,dc=org"="^samba*"
3.2.3 被授予的权限
当选取好ACL作用的目标记录并选取好用户范围后,就该给这些用户授予他们应该得到的权限了。大致的权限(由低到高)有以下几类:
none 无权限,即拒绝访问
auth 访问bind(认证)设置的权限;前提是需要用户提交一个DN形式的用户名并能通过认证
compare 比较属性的权限;(例如:对照查看某用户的telephoneNumber值是不是158 8888 8888),但并不具有搜索的权限
search 利用过虑条件进行搜索的权限,但这并不一定具有可读取搜索结果的权限
read 读取搜索结果的权限
write 更改记录属性值的权限
可以在slapd.conf文件中通过defaultaccess指定默认的权限级别,如:
defaultaccess search
3.2.4 采取什么样的匹配控制动作
在进行记录的匹配时,如果有多条规则存在,那么在第一次匹配产生后是否还进行后续的匹配或采取其它的动作将取决于此项的设置;控制方式共有以下三种:
stop 这个是默认值,这表示在一次匹配产生后将不再进行下一个匹配,所有后续的匹配将会停止。
continue 无论匹配是否已经发生,继续进行直到所有的规则全部进行完匹配检查
break 一个匹配发生后,跳出当前的子句进行后一个子句的检查
3.2.5 一个例子
access to dn.chilren="ou=users,dc=mydomain,dc=org"
attrs=userPassword #指定“密码”属性
by self write #用户自己可更改
by * auth #所有访问者需要通过认证
by dn.children="ou=admins,dc=mydomain,dc=org" write #管理员组的用户可更改
待续……