1. openldap簡介openldap是在TCP上實現(xiàn)目錄服務(wù)的系統(tǒng),一種源代碼開放的ldap版本。相對OSI的X.500服務(wù),它使用了較少的代價(10%?)實現(xiàn)了目錄服務(wù)大部分功能(90%?)。因為它基于TCP網(wǎng)絡(luò),且實現(xiàn)的功能沒有X.500規(guī)定那么復(fù)雜,所以成為“輕量級”的目錄服務(wù)。 目錄服務(wù)器可以想象為樹型結(jié)構(gòu)。一個結(jié)點元素稱為對象,一個對象可以擁有多個屬性(例如某人身兼數(shù)值),多個對象擁有相同屬性也是可能的(許多人屬于某個公司)。objectclass是對屬性類型的描述,多個objectclass可以構(gòu)成一個schema,用于約束加入目錄服務(wù)器的數(shù)據(jù)對象。 我們當前的測試基于RedHat Linux 9.0,openldap-2.0.27-8,后臺基于dbm數(shù)據(jù)庫(gdbm兼容dbm)。 我們可以把ldap構(gòu)筑的數(shù)據(jù)存儲系統(tǒng),理解為數(shù)據(jù)庫結(jié)構(gòu)中的層次模型。 ldap概念識別名dn:目錄中每個對象唯一名字,是這個對象之上的所有對象單一屬性加上自身附加屬性構(gòu)成; 相對識別名rdn:以目錄中某個結(jié)點作為根節(jié)點命名其下的對象; LDIF文件:LDAP數(shù)據(jù)交換格式。它是一個純文本文件,每個對象包括許多行,對象定義的第一行以dn開頭。它主要用于ldap服務(wù)器對數(shù)據(jù)的導(dǎo)入、導(dǎo)出、交換等。 安裝openldapl安裝系統(tǒng)時選擇安裝openldap 這是最簡單的方式。鍵入命令: service ldap start 如果系統(tǒng)提示沒有錯誤,則說明ldap服務(wù)器已經(jīng)正確啟動。我們目前使用這種方式。 l下載openldap代碼,編譯安裝 一般經(jīng)過如下步驟: 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版本2.2.24,會遇到許多問題: 其一是在配置(執(zhí)行configure腳本)時選擇后臺數(shù)據(jù)庫的問題,我們必須加入選項設(shè)置--disable-bdb屏蔽BDB數(shù)據(jù)庫(Berkeley DataBase); 其二是系統(tǒng)上原來安裝的Cyrus SASL版本過老,必須下載安裝新版本。openldap-2.2.24要求SASL版本在2.1.18以上。目前我們沒有繼續(xù)試驗源碼方式的安裝。 4. 配置服務(wù)器端需要配置/etc/openldap/slapd.conf文件。 加入某個schema文件,例如: include /etc/openldap/openldap.schema 加入數(shù)據(jù)庫支持: database ldbm 聲明本地節(jié)點后綴: 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= 指定數(shù)據(jù)庫文件存放位置: directory /var/lib/ldap 其他配置項直接使用系統(tǒng)配置即可。 需要介紹的是slappasswd命令,使用下面命令得到加密后的口令,拷貝到配置文件中: slappasswd -h {加密方法} New Password: Re-enter new password: {加密方法}密文 5. 訪問5.1. 啟動ldap服務(wù)器:手工方式啟動: # /usr/sbin/slapd –f /etc/openldap/slapd.conf –d 256 其中-f指出配置文件的路徑名,-d指出debug級別。如果打開調(diào)試選項,則slapd把調(diào)試信息輸出至stdout,如果不使用調(diào)試選項,slapd以后臺進程方式啟動。 以服務(wù)方式啟動: # service ldap start 5.2. 關(guān)閉ldap服務(wù)器手工關(guān)閉:使用kill命令殺死slapd進程。 以服務(wù)方式關(guān)閉: # service ldap stop 注意:我們可以使用手工方式啟動,然后用服務(wù)方式關(guān)閉;反之亦然。 5.3. 腳本方式訪問ldapl ldapadd: 用于對ldap目錄服務(wù)器添加數(shù)據(jù),格式為LDIF; 例子: $ ldapadd - D “cn=root,o=aitiso.com,c=cn” –x –w passwd –f test.ldif 若不給出ldif文件,命令執(zhí)行成功并不退出,而是等待用戶輸入下一條修改數(shù)據(jù)。輸入^D結(jié)束 選項說明: -D后給出的是登錄DN(此時為管理員DN); -x說明使用簡單認證(明碼); -w后給出密碼正文; -f后給出需要插入的數(shù)據(jù)文件。 l ldapmodify: 用于修改目錄中的對象; 例子: $ ldapmodify - D “cn=root,o=aitiso.com,c=cn” –x –w passwd 若不給出ldif文件,命令執(zhí)行成功并不退出,而是等待用戶輸入下一條修改數(shù)據(jù)。輸入^D結(jié)束 選項同上,說明: -a,表示新加入數(shù)據(jù),效果同ldapadd命令。這兩個命令底層都使用ldap_add()函數(shù)完成。 l ldapdelete: 用于刪除目錄中的對象; 例子: $ ldapdelete “ou=communications,o=ait.com,c=cn” –D”cn=root,o=aitiso.com,c=cn” –x –w root 選項同上,說明: 雙引號中給出的是需要刪除的結(jié)點。注意,當結(jié)點有非空子結(jié)點時(即當前要刪除結(jié)點不是葉子結(jié)點),刪除操作失敗。如果加上-r選項,則命令將遞歸刪除所有子結(jié)點,且不會提示任何確認信息。使用時需要特別小心。 l ldapmodrdn: 修改rdn; 例子: $ ldapmodrdn - D “cn=root,o=aitiso.com,c=cn” –x –w passwd 選項同上,說明: -r表示刪除原有rdn。 在命令行結(jié)束后,用戶需要輸入原有dn,然后輸入修改dn,最后輸入^D結(jié)束 l ldapsearch: 查找對象; 例子: $ ldapsearch –D “cn=root,o=aitiso.com,c=cn” –b “o=aitiso.com,c=cn” –x –w passwd ’objectClass=person’ 選項同上,說明: -b后給出搜索的起始結(jié)點DN(base DN),它必須給出,否則無法查詢出結(jié)果; 單引號(雙引號也可以)中給出的objectClass用于過濾輸出結(jié)果(即搜索條件),此處查找的對象類型僅限于person對象,也就是查找aitiso.com,c=cn結(jié)點下的所有人員記錄。 注意: 1.查詢中經(jīng)常使用的是簡單認證,應(yīng)給出-x選項,使用-w給出密碼(或者-W在命令行后輸入); 2. ldif文件中某些objectClass必須擁有一些屬性(查看schema),在寫ldif文件時應(yīng)注意; 3. 應(yīng)保證/etc/openldap/slapd.conf能夠被ldap組的成員讀寫,否則無法正確讀入配置信息; 5.4. ldap的C接口l 需要包含的頭文件: #include #include l 需要包含的庫文件: -lldap -llber l 初始化,打開ldap服務(wù)器的socket連接 LDAP * ldap_init(ldap_host, port) char *ldap_host; /*ldap主機名字*/ int port /*ldap監(jiān)聽的端口號*/ 返回值為LDAP結(jié)構(gòu)。 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服務(wù)器 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服務(wù)器之后,在訪問之前的認證過程。它需要傳入ldap初始化結(jié)構(gòu)ld,需要輸入DN作為連接訪問者who,輸入密碼cred作為認證信息,并設(shè)置認證方式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; 如果某步驟出現(xiàn)錯誤,可以使用ldap_error()捕獲錯誤代碼,并輸出信息; l 解除與LDAP服務(wù)器的綁定 int ldap_unbind(ld) LDAP *ld; 返回值可以使用ldap_error(3)讀取,輸出。 l 查詢ldap目錄服務(wù)器的數(shù)據(jù) 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. 設(shè)置起始點DN 2. 設(shè)置搜索深度(搜索范圍) 過濾結(jié)果: l 處理返回的結(jié)果數(shù)據(jù) int ldap_msgfree(LDAPMessage *msg); /*釋放結(jié)果*/ int ldap_count_entries(LDAP *ld,LDAPMessage *result); /**/ LDAPMessage *ldap_first_entry(LDAP *ld,LDAPMessage *result); /*獲取第一個數(shù)據(jù)結(jié)點*/ LDAPMessage *ldap_next_entry(LDAP *ld,LDAPMessage *result); /*獲取下一個結(jié)點*/ 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. 數(shù)據(jù)備份和恢復(fù)l 數(shù)據(jù)備份: 使用命令slapcat。缺省slapcat把數(shù)據(jù)輸出至標準輸出stdout,我們可以使用重定向,把輸出保存到某個ldif文件中。 例子: slapcat > back.ldif l 數(shù)據(jù)恢復(fù),需要先刪除數(shù)據(jù)庫(或其中所有數(shù)據(jù)): 使用ldapadd命令,ldapadd -w … -D … < back.ldif |
|