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