歡迎您光臨本站 註冊首頁

建個LDAP的API樓

←手機掃碼閱讀     火星人 @ 2014-03-04 , reply:0

建個LDAP的API樓

最近一直在看LDAP的api代碼,希望同樣研究api的人都來一起交流一下經驗,把這裡作為大家專門討論api和庫護端開發的專屬地!
作為一個初學ldap的晚輩,我先拋磚引玉吧,寫一些基本的api介面說明,主要來自於rfc1823(已經很老的版本了,但是作為初學ldap的api還是很有用的,都說了,是拋磚引玉嘛,不要苛求太高a :-) )
1.        Ldap的使用
使用的ldap的SDK是openldap-2.3.34版本。
1.1一個應用調用LDAP  API一般有以下四步:
1.1.1 打開一個到LDAP 伺服器的聯接。
ldap_open() 或者ldap_init() 函數調用返回一個聯接句柄,允許立即建立多聯接。
1.1.2 認證LDAP伺服器和/或X.500 DSA。
函數ldap_bind()友好地支持各種認證方式。
1.1.3 執行其它LDAP操作並獲得其值。
ldap_search()及其同類函數返回的值能被ldap_result2error(),  ldap_first_entry(),  ldap_next_entry()等函數解析。
1.1.4 關閉聯接。
ldap_unbind()函數調用關閉此聯接。
1.2        操作能同步或非同步執行。
同步調用的函數以_s結尾。例如,調用ldap_search_s()實現同步查詢,調用ldap_search()實現非同步查詢。所有同步操作返回一個操作結果的指示(例如,操作成功返回LDAP_SUCCESS,操作失敗返回錯誤代碼)。非同步操作返回操作初始化信息id。id能被用於隨後的ldap_result()函數調用,以獲得操作的結果。通過調用ldap_abandon()可以丟棄非同步操作。
結果和錯誤被返回到一個稱作LDAPMessage的不透明結構中。LDAP操作為這一結構提供語法分析,逐步分析返回的目錄項或屬性等。此外,LDAP操作還解釋出現的錯誤。

2. 已經不用的ldap介面
一下這些介面已經不再使用,但是系統仍然向下支持,如果開發新的客戶端程序,盡量使用新的介面(左邊是舊的介面,右邊是新的介面):
ldap_ssl_start()          ldap_ssl_client_init() 和 ldap_ssl_init()
ldap_open()             ldap_init()
ldap_bind()             ldap_simple_bind()
ldap_bind_s()           ldap_simple_bind_s()
ldap_modrdn()          ldap_rename()
ldap_modrdn_s()       ldap_rename_s()
ldap_result2error()       ldap_parse_result()
ldap_perror()           ldap_parse_result()
此外還有一些介面在不斷更新中,具體的可以參見ldap.h頭文件中的定義。

[ 本帖最後由 lhm0000 於 2007-11-16 09:53 編輯 ]
《解決方案》

3. 調用ldap介面進行操作
    以下介紹一些我所使用過的ldap  c語言介面:
3.1        打開連接
打開連接的操作將返回一個指向LDAP結構的指針。
3.1.1 LDAP 結構:
        typedef struct ldap{
                /*……隱含參數……*/
                int        ld_deref;
                int  ld_timelimit;
                int        ld_sizelimit;
                int        ld_errno;
                int        ld_matched;
                int        ld_error;
                /*……隱含參數……*/
        }LDAP;
其中有三個域決定了查詢操作的執行,它們分別是:
ld_sizelimit  限制查詢結果的數目。為0時表示沒有限制。
ld_timelimit  限制查詢的時間。為0表示沒有限制。
ld_deref    其值為以下任意一個LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING,               LDAP_DEREF_FINDING, 或LDAP_DEREF_ALWAYS,指明查詢時別名將怎樣被綁定。 值為LDAP_DEREF_SEARCHING表示在查詢時將不允許別名,但對base指定的條目將不受此限制;值為LDAP_DEREF_FINDING時情況剛好與LDAP_DEREF_SEARCHING相反。
ld_matched  用於LDAP_NO_SUCH_OBJECT錯誤值返回時,該參數限制了匹配的DN的範圍;
ld_error    該參數保存了LDAP伺服器發送出的出錯信息;
ld_errno    LDAP出錯代碼指出了操作的結果。其值為錯誤代碼中的任意一個(參見3.12.1 錯誤代碼)。
3.1.2 介面介紹
LDAP        *ldap_init( LDAP_CONST char *hostname, int port );
ldap_init() 返回一個聯結句柄, 即一個指向LDAP結構的指針。為隨後的綁定到目錄伺服器提供參數值。如果打開操作失敗,返回NULL。
參數:
hostname                需要聯接的LDAP伺服器的一個分離空間的主機名列表或者是代表伺服器IP地址的分離的字元串。有序列表中的主機都處於準備被聯接狀態,直到其中有一個被成功聯接上為止。
port                        含用於聯接的TCP埠號。預設的LDAP埠能夠從常量LDAP_PORT中獲得。
3.1.3 其他介面
        LDAP        *ldap_open( LDAP_COSNST char *hostname, int portno ); /* deprecated */
int                ldap_create( LDAP **ldp );
int                ldap_initialize( LDAP **ldp, LDAP_CONST char *url );       
3.2 綁定到目錄
        使用ldap_bind()及同類函數綁定到目錄:
3.2.1 介面介紹
        通用認證方式:
        int ldap_bind( LDAP *ld, char *dn, char *cred, int method );
   int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method );
        簡單認證方式:
    int ldap_simple_bind( LDAP *ld, char *dn, char *passwd );
    int ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd );
ldap提供了各種綁定方式,甚至不止於此,但其功能都差不多,區別是各種不同的綁定方法分別基於各種不同的認證方式上。
參數:
   ld         連接句柄;
   dn        進行綁定操作的用戶dn,who;
   cred       認證的證件,往往就是指密碼;
   method  使用的值是LDAP_AUTH_SIMPLE,LDAP_AUTH_KRBV41,或LDAP_AUTH_ LDAPKRBV42中的一種,包含用於認證的方式。
   passwd  為ldap_simple_bind()系列專有,用於與目錄項中的userPassword屬性值作比較。  
   這裡有關於bind調用的三種類型,提供簡單的認證,kerberos 認證,以及普通事務。由於第四版本的Kerberos認證使用了通用的ldap_bind() ,忽略了證書部分,因此系統假定存在有效的認證依據,並且能被用於恢復特定的服務依據。
與該事務一致的版本的名字以_s結尾。這些事務返回bind操作的結果。如果操作成功,返回LDAP_SUCCESS,否則返回錯誤代碼。下一節將列出可能出現的錯誤句柄的更多信息並且對這些信息加以解釋。
    與以上事務一致的版本將返回初始化bind操作的信息id。隨後調用ldap_result(),用於獲取bind操作的結果。如果出錯,返回-1,並在LDAP結構中設置ld_errno域。
注意,在bind操作成功之前,其它的所有操作都不能成功,其後的bind調用可用於同一聯接之上的重複認證。
3.2.2其他介面
int ldap_sasl_bind(  LDAP                *ld,
         LDAP_CONST char        *dn,
        LDAP_CONST char        *mechanism,
        struct berval            *cred,
        LDAPControl                **sctrls,
        LDAPControl                **cctrls,
        int                                *msgidp );
int ldap_sasl_bind_s(  LDAP        *ld,
        LDAP_CONST char        *dn,
        LDAP_CONST char        *mechanism,
        struct berval                *cred,
        LDAPControl                    **sctrls,
        LDAPControl                    **cctrls,
        int                                    *msgidp );
3.3 解除綁定,關閉連接
        ldap_unbind()  用於解除與目錄的綁定並關閉連接。
int ldap_unbind( LDAP *ld );
int ldap_unbind_s(LDAP *ld );
   參數:
   ld   連接句柄。
   ldap_unbind()  工作在同步模式,解除與目錄的綁定,關掉連接,並在返回前釋放ld結
構。ldap_unbind()返回LDAP_SUCCESS (如果請求未被送往LDAP伺服器,則返回一個LDAP
錯誤代碼)。在調用完ldap_unbind()之後,ld連接句柄失效。
   說明:ldap_unbind()和ldap_unbind_s()實際上都是同步的操作,在這裡只是兩種不同的名字,沒有區別。
《解決方案》

新的查詢介面加入了一些控制信息,作為本地的查詢輸入NULL即可,這樣功能就和老版本一樣了。其中用ldap_search_ext()代替ldap_search(),用ldap_search_exi_s()可代替ldap_search_s()和ldap_search_st()。
3.4 ldap的查詢操作
對ldap進行查詢,如果是非同步操作,將返回一個操作結果的id值,該值可以被ldap_result()函數獲得。如果是同步操作,將返回一個LDAP_SUCCESS或者一個錯誤代碼。查詢到的信息被保存到一個LDAPMessage結構的參數中。
3.4.1 進行查詢的介面
ldap_search() 及同類函數用於查詢LDAP目錄,返回匹配的目錄項的請求值。這裡有三種形式:
struct timeval {
    long    tv_sec;
    long    tv_usec;
};
介面介紹:
int ldap_search(
     LDAP    *ld,
     char    *base,
     int     scope,
    char    *filter,
     char    *attrs[],
     int     attrsonly);
int ldap_search_s(
     LDAP            *ld,
     char            *base,
     int             scope,
     char            *filter,
     char            *attrs[],
     int             attrsonly,
     LDAPMessage     **res);
int ldap_search_st(
     LDAP            *ld,
     char            *base,
     int             scope,
     char            *filter,
     char            *attrs[],
     int             attrsonly,
     struct timeval  *timeout,
     LDAPMessage     **res);
參數:
ld        連接句柄;
base      最基本的 dn 條件值;
scope     為LDAP_SCOPE_BASE,
       LDAP_SCOPE_ONELEVEL,
或LDAP_SCOPE_SUBTREE,
表示查詢的範圍。
filter      匹配的字元串,在RFC 1558 中有詳細的描述。
attrs      為NULL時表示返回所有匹配的條目。非空導致所有可用屬性將被恢復。
attrsonly  布爾值。如果為0則返回屬性類型以及屬性值;非0則只返回屬性類型。
timeout   當調用ldap_search_st()時,它將指出本地查詢的時延值。
res       當同步調用時,該參數將包含函數調用結束時的一個返回值。
ldap_search()進行的是非同步查詢。它返回初始化查詢的id值。該值被隨後調用的ldap_result()函數獲得,對其進行語法分析,並進行相應的描述。如果操作失敗,返回-1;並且,LDAP結構中的ld_errno域將被重設。
通過調用ldap_search_s()或ldap_search_st()進行同步查詢。進程將保持一致,除了ldap_search_st()函數的額外參數將指定查詢的時延。兩個函數都將直接返回查詢的結果:LDAP_SUCCESS或者錯誤代碼。查詢到的條目的返回值將保存在res參數里。該參數對於調用者來說是不透明的。條目、屬性、值等將通過下面介紹的函數獲得。保存在參數res中的結果當不再被使用時,將通過調用ldap_msgfree()函數進行釋放,這在後面會有詳細介紹。
說明:
LDAP 不支持直接的讀操作。實際上,查詢操作中的操作範圍:LDAP_SCOPE_BASE,匹配條件:"(objectclass=*)"都利用到了讀操作。參數attrs包含了返回的屬性列表。
LDAP 不直接支持列表操作。實際上,查詢操作中的操作範圍:LDAP_SCOPE_ ONELEVEL,匹配條件:"(objectclass=*)"也利用到了列表操作。參數attrs包含了返回的所有子條目的屬性列表。
3.4.2 其他介面:
在ldap.h文件中,聲明了新的查詢介面:
int  ldap_search_ext (
        LDAP                        *ld,
        LDAP_CONST char        *base,
        int                                scope,
        LDAP_CONST char        *filter,
        char                            **attrs,
        int                                attrsonly,
        LDAPControl                **serverctrls,
        LDAPControl                **clientctrls,
        struct timeval            *timeout,
        int                                sizelimit,
        int                                *msgidp );
int  ldap_search_ext_s (
        LDAP                        *ld,
        LDAP_CONST char        *base,
        int                                scope,
        LDAP_CONST char        *filter,
        char                            **attrs,
        int                                attrsonly,
        LDAPControl                **serverctrls,
        LDAPControl                **clientctrls,
        struct timeval            *timeout,
        int                                sizelimit,
        LDAPMessage        **res );
《解決方案》

新的查詢介面加入了一些控制信息,作為本地的查詢輸入NULL即可,這樣功能就和老版本一樣了。其中用ldap_search_ext()代替ldap_search(),用ldap_search_exi_s()可代替ldap_search_s()和ldap_search_st()。
3.5 查詢結果的處理
下面的函數調用用於分析由ldap_search()及其友員函數返回的結果。這些返回值存放在一個不透明的結構中,只能通過調用下面這些函數來獲得。這些函數可用於處理返回的條目、條目屬性、獲得條目名稱,以及獲得條目中給定屬性的屬性值。
3.5.1 獲得查詢條目
函數ldap_first_entry()和ldap_next_entry()用於處理查詢到的條目結果。   ldap_count_entries() 用於計算返回的條目個數。
介面介紹:
LDAPMesage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
LDAPMesage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
int ldap_count_entries( LDAP *ld, LDAPMessage *res );
參數:
   ld     連接句柄;
  res    查詢結果,由同步查詢進程或函數ldap_result()獲得;
   entry  函數調用ldap_first_entry()或ldap_next_entry()的返回值;
   當沒有條目存在時ldap_first_entry()和ldap_next_entry()將返回NULL。當函數在運行過程中出錯時也會返回NULL,但此時ld連接句柄中的ld_errno域將記錄該錯誤信息。
ldap_count_entries() 返回在條目鏈中條目的個數。該函數也可被用於計算在函數調用ldap_first_entry()或ldap_next_entry()中符合條件的條目的個數。
3.5.2 獲得查詢的屬性
    函數ldap_first_attribute() 和ldap_next_attribute()用於對由某個條目返回的屬性結果的處理。
介面介紹:
char *ldap_first_attribute(
     LDAP            *ld,
     LDAPMessage     *entry,
     BerElement        **ptr);
char *ldap_next_attribute(
     LDAP            *ld,
     LDAPMessage     *entry,
     BerElement        *ptr);
參數:
ld     連接句柄;
entry  需處理的屬性結果所在的條目,即ldap_first_entry()或ldap_next_entry()的返回值;
ptr    在函數ldap_first_attribute()中,用於保存當前條目所在位置的地址指針。函數ldap_next_attribute()所用到的指針為先前調用ldap_first_attribute()獲得的返回值。
當達到最後一個屬性時,函數ldap_first_attribute()和ldap_next_attribute()將返回NULL,由於這個原因,ld句柄中的ld_errno 域將被設置為error。
兩個進程都將返回一個指向包含當前屬性名的聯接緩衝的指針。這將被當作靜態數據對待。ldap_first_attribute()將定位並返回一個指向BerElement類型的名為ptr的指針,以保存當前位置的路徑。該指針將被後面的調用ldap_next_attribute() 所引用,以獲得下一個條目的屬性結果。
返回的屬性名將被ldap_get_values()極其成員函數利用,以獲得相關的屬性值。
3.5.3 獲得屬性值
ldap_get_values()和ldap_get_values_len()用於獲得條目的屬性值。ldap_count_values()和ldap_count_values_len()用於計算返回值的個數。ldap_value_free()和ldap_value_free_len()用於釋放返回的屬性值。
typedef struct berval {
       unsigned long   bv_len;
      char           *bv_val;
};
介面介紹
char **ldap_get_values(
      LDAP            *ld,
      LDAPMessage     *entry,
      char              *attr);
struct berval **ldap_get_values_len(
      LDAP            *ld,
      LDAPMessage     *entry,
      char              *attr);
int ldap_count_values( char **vals );
int ldap_count_values_len( struct berval **vals );
int ldap_value_free( char **vals );
int ldap_value_free_len( struct berval **vals );
參數:
ld     連接句柄;
entry  屬性所屬的條目,即ldap_first_entry()或ldap_next_entry()的返回值;
attr   返回值的屬性,即ldap_first_attribute()或ldap_next_attribute()或一個字元串調用的返回值(例如,"mail");
vals   先前調用ldap_get_values()或ldap_get_values_len()的返回值。兩種不同形式的調用都是有條件的。第一重形式只適用於非二進位的字元串類型數據;第二種_len形式適用於任何形式的數據。
注意,返回的值當不再使用時,應調用函數ldap_value_free()或ldap_value_free_len()進行釋放。
3.5.4 目錄項DN的處理
    ldap_get_dn() 用於獲得條目的dn 。
    ldap_explode_dn() 用於將 dn 中的各欄位切開。
ldap_dn2ufn()  用於將dn 的名字轉換成較易讀取的名字。
介面介紹:
char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
char **ldap_explode_dn( char *dn, int notypes );
char *ldap_dn2ufn( char *dn );
    參數:
   ld       連接句柄;
   entry    為ldap_first_entry()或ldap_next_entry()返回的搜尋代號;
   dn      可由ldap_get_dn()的返回值得到;
   notypes  布爾型參數,如果非零表明dn的組成部分將只包含屬性值,而不包含屬性名。(例如,"cn=Babs"將變為"Babs")。
    ldap_get_dn() 當dn分析錯誤時返回NULL,為ld連接句柄設置ld_errno以指明錯誤。它返回一個指向預分配空間的指針,當此空間不再被使用時,調用free() 進行空間釋放。這些DN的返回格式在RFC 1779中有所描述。
    ldap_explode_dn() 返回一個指針數組,該數組包含提供給DN的RDN部分。並通過notypes參數標識是否包含類型。當不再使用該數組返回值時,可調用ldap_value_free()進行資源釋放。
ldap_dn2ufn() 將DN轉換成較易讀取的名字(User Friendly Name),描述參見RFC 1781。UFN將返回值到預分配的空間,當此空間不再使用時,可調用free() 函數釋放。
3.6 比較操作
函數ldap_compare() 和 ldap_compare_s()負責比較條目中是否具有某一屬性值的操作。
新版本使用ldap_compare_ext() 和 ldap_compare_ext_s()負則比較條目的操作。
3.6.1 介面介紹
int ldap_compare( LDAP *ld, const char *dn, const char *attr, const char *value );
int ldap_compare_s( LDAP *ld, const char *dn,  const char *attr, const char *value );
參數
    ld        聯接句柄;
   dn       要比較的條目名;
   attr      要比較的屬性類型;
        value         要比較的屬性值;
返回操作結果的message id,如果是非同步的操作,調用ldap_resault()和ldap_result2error()函數處理結果信息。如果是同步操作,操作成功后可能返回下面的幾個值:
LDAP_COMPARE_TRUE    表示操作成功,找到了匹配的屬性值
LDAP_COMPARE_FALSE    表示操作成功,條目中沒有指定的屬性值
其他的錯誤信息,可以參考 3.13.1 錯誤代碼
3.6.2 其他介面
int ldap_compare_ext(
LDAP *ld, const char *dn,
     const char *attr, struct berval *bvalue,
     LDAPControl **serverctrls, LDAPControl **clientctrls,
     int *msgidp );
int ldap_compare_ext_s(
LDAP *ld, const char *dn,
     const char *attr, struct berval *bvalue,
     LDAPControl **serverctrls, LDAPControl **clientctrls );
     新的介面加入了一些伺服器端和客戶端的控制信息,如果是在本地應用可以設為NULL,這樣功能就和老版本一樣了。
《解決方案》

5555.... 發帖間隔不滿30秒。。。怎麼能誣陷偶在灌水捏?5555.。。。不管,現在繼續。。。

3.7 修改條目
函數ldap_modify() 和 ldap_modify_s()用於修改存在的LDAP條目。
新版本使用ldap_modify_ext()和ldap_modify_ext_s來修改LDAP的條目。
typedef struct ldapmod {
#define LDAP_MOD_OP                        (0x0007)
#define LDAP_MOD_ADD                (0x0000)
#define LDAP_MOD_DELETE                (0x0001)
#define LDAP_MOD_REPLACE        (0x0002)
#define LDAP_MOD_INCREMENT        (0x0003) /* OpenLDAP extension */
#define LDAP_MOD_BVALUES        (0x0080)
       int             mod_op;
       char           *mod_type;
       union {
          char         **modv_strvals;
          struct berval  **modv_bvals;
       } mod_vals;
} LDAPMod;
#define mod_values      mod_vals.modv_strvals
#define mod_bvalues     mod_vals.modv_bvals
3.7.1 介面
int ldap_modify( LDAP *ld, char *dn, LDAPMod *mods[] );
int ldap_modify_s( LDAP *ld, char *dn, LDAPMod *mods[] );
參數:
    ld       聯接句柄;
   dn       要修改的條目名;
   mods     屬性修改操作模式;

LDAPMod結構域包含以下信息:
  mod_op   操作類型。其值可能為:LDAP_MOD_ADD, LDAP_MOD_DELETE,或 LDAP_MOD_REPLACE。該域同時指定了mod_vals單元值的類型。如果為LDAP_MOD_BVALUES 則選擇了mod_bvalues模式。否則,mod_values定義的模式才有效。
mod_type  修改的屬性類型;
mod_vals  值為:add, delete,或replace。mod_values與mod_bvalues不能共用。只有在mods_op中指定為LDAP_MOD_BVALUES時才能在這裡設為mod_bvalues值。 mod_values為包含字元串的非空數組,字元串可為NULL。mod_bvalues為包含berval結構的非空數組,用於包含二進位類型的值,例如圖片。
    LDAP_MOD_ADD模式用於在條目中創建新的屬性。LDAP_MOD_DELETE模式用於刪除條目中不再需要的屬性。如果是刪除操作,那麼mod_vals域的值將設為NULL。   
LDAP_MOD_REPLACE模式中,屬性值將設置為列表中定義的值。所有模式的運行順序都遵循它們排列的先後順序。
   ldap_modify_s()返回修改操作的LDAP出錯代碼。該代碼能被ldap_perror()及其友元函數
解析。
   ldap_modify() 返回初始化信息的id,出錯時返回-1。操作結果通過調用ldap_result()獲得。
3.7.2 其他介面
int ldap_modify_ext (
        LDAP                        *ld,
        LDAP_CONST char        *dn,
        LDAPMod                        **mods,
        LDAPControl                **serverctrls,
        LDAPControl                **clientctrls,
        int                         *msgidp );
int ldap_modify_ext_s (
        LDAP                        *ld,
        LDAP_CONST char        *dn,
        LDAPMod                        **mods,
        LDAPControl                **serverctrls,
        LDAPControl                **clientctrls );
新的介面加入了一些伺服器端和客戶端的控制信息,如果是在本地應用可以設為NULL,這樣功能就和老版本一樣了。
3.8 修改條目的RDN
使用ldap_rename() 和 ldap_rename_s 可以改變條目的名稱。
3.8.1 介面介紹
int ldap_rename(
       LDAP            *ld,
       const char      *dn,
       const char      *newrdn,
       const char      *newparent,
       int             deleteoldrdn,
       LDAPControl     **serverctrls,
       LDAPControl     **clientctrls,
       int             *msgidp);
int ldap_rename_s(
       LDAP            *ld,
       const char      *dn,
       const char      *newrdn,
       const char      *newparent,
       int             deleteoldrdn,
       LDAPControl     **serverctrls,
       LDAPControl     **clientctrls)
參數:
ld                        連接句柄;
        dn                        將改變的條目名稱;
        newrdn                給條目新的條目名稱;
        newparent        指定新的上層條目,改變現在條目的根,如果設為NULL,則只改變條目的RDN。條目的根可以被指定,即使只是將它設為一個長度為零的字元串」」。如果使用的是LDAPv2版本,則此參數只能被設為NULL;
deleteoldrdn  一個布爾值,為0時則表示保留原來的rdn值並作為改名后的條目的一個屬性存在,否則就刪除原來的rdn;
serverctrls  和 clientctrls   分別指定一個伺服器端和客戶端的控制列表,如果只在本地應用可設為NULL,這時它的功能和老闆本的介面是一樣的。
3.8.2 其他介面
    以下這些介面已經不再使用。
        int ldap_modrdn(
                   LDAP    *ld,
                   char    *dn,
                   char    *newrdn,
                   int     deleteoldrdn
           );
    int ldap_modrdn_s(
                   LDAP    *ld,
                   char    *dn,
                   char    *newrdn,
                   int     deleteoldrdn
);
《解決方案》

又不滿30秒了,我忍。。。

3.9 增加一個條目
ldap_add()和ldap_add_s()用於增加LDAP目錄中的條目。
新版本的介面為ldap_add_ext() 和 ldap_add_ext_s()。
3.9.1介面介紹
int ldap_add( LDAP *ld, char *dn, LDAPMod *attrs[] );
int ldap_add_s( LDAP *ld, char *dn, LDAPMod *attrs[] );
   參數:
   ld      連接句柄;
   dn      新添加條目的名稱;
   attrs  條目的屬性,採用ldap_modify()中定義的LDAPMod結構。要求輸入mod_type與mod_vals域的值,mod_op域預設。除非遇到常量LDAP_MOD_BVALUES時, 需要用到相應的mod_bvalues替代mod_vals。
   注意,新添加條目的父條目必須已經存在。
如,要添加一個」cn=jessy,cn=Manager,dc=example,dc=com」,則在它的屬性」cn」中必須有一個值為」jessy」,用來作為條目的rdn。
   ldap_add_s()是同步操作,返回操作結果的LDAP錯誤代碼。
   ldap_add()為非同步操作,返回操作初始化的信息id。如果有誤返回-1。通過調用dap_result()
可以獲得操作的結果。
3.9.2 其他介面
int ldap_add_ext(
              LDAP        *ld,
              const char  *dn,
              LDAPMod     **attrs,
              LDAPControl **serverctrls,
              LDAPControl **clientctrls,
              int         *msgidp)
int ldap_add_ext_s(
LDAP      *ld,
              const char  *dn,
              LDAPMod     **attr,
              LDAPControl **serverctrls,
              LDAPControl **clientctrls)
新版本的操作加入了伺服器和客戶端的控制列表,如果只是在本地應用,可以設為NULL,則功能上和老版本的一樣。
3.10 刪除條目
    ldap_delete()和ldap_delete_s()用於刪除LDAP目錄中的條目。
    新版本的介面為ldap_add_ext() 和 ldap_add_ext_s()。
3.10.1 介面介紹
int ldap_delete( LDAP *ld, char *dn );
int ldap_delete_s( LDAP *ld, char *dn );
   參數:
   ld       連接句柄;
   dn       需要刪除的條目名稱。
   注意,被刪除的條目必須是「葉」條目(即,不含有子條目)。LDAP不支持刪除帶有子條目的結點。
   ldap_delete_s()  是同步操作,返回操作結果的LDAP錯誤代碼。
   ldap_delete()    是非同步操作,返回操作初始化的信息id。如果有誤返回-1。通過調用dap_result()可以獲得操作的結果。
3.10.2 其他介面
int ldap_delete_ext(
LDAP           *ld,
           const char     *dn,
           LDAPControl    **serverctrls,
           LDAPControl    **clientctrls,
           int            *msgidp)
int ldap_delete_ext_s(
LDAP           *ld,
           const char     *dn,
           LDAPControl    **serverctrls,
           LDAPControl    **clientctrls)
新版本的操作加入了伺服器和客戶端的控制列表,如果只是在本地應用,可以設為NULL,則功能上和老版本的一樣。
《解決方案》

3.11 取消操作
    ldap_abandon()用於取消非同步進行的操作。
    新版本的介面為ldap_abandon_ext()。
3.11.1 介面介紹:
int ldap_abandon( LDAP *ld, int msgid );
ldap_abandon()通過信息的id號——msgid取消操作。如果操作成功,返回0;否則,返回-1。在成功調用ldap_abandon()之後,給定信息id的操作結果將不會有返回值。
3.10.2 其他介面
int ldap_abandon_ext(
LDAP            *ld,
        int             msgid,
        LDAPControl     **serverctrls,
        LDAPControl     **clientctrls)
新版本的操作加入了伺服器和客戶端的控制列表,如果只是在本地應用,可以設為NULL,則功能上和老版本的一樣。
3.12 操作結果處理
ldap_result()用於獲得前面調用的非同步初始化操作的結果。ldap_msgfree()釋放由函數ldap_result()獲得的結果或同步查詢進程。
介面介紹
int ldap_result(
        LDAP            *ld,
        int             msgid,
        int             all,
        struct timeval  *timeout,
        LDAPMessage     **res);
int ldap_msgfree( LDAPMessage *res );
參數:
   ld       連接句柄;
   msgid   操作結果的信息id。如果希望返回所有的結果,則設為常量LDAP_RES_ANY;
all      一個布爾型參數,僅對查詢結果起作用。如果非0,表明在獲取了所有查詢結果后再一併返回;為0,表明查詢到一個結果就返回一個結果。
   timeout   等待結果返回的最短時間。為NULL表明沒有時間限制。為0表示輪詢操作。
   res       在ldap_result()中,該參數將保存操作的結果;在ldap_msgfree()中,該參數用於釋放從ldap_result()或ldap_search_s()或ldap_search_st()獲得的結果。
    若上面的操作成功,ldap_result()將通過res參數返回結果的類型。其類型為以下幾種:
    LDAP_RES_BIND
    LDAP_RES_SEARCH_ENTRY
    LDAP_RES_SEARCH_RESULT
    LDAP_RES_MODIFY
    LDAP_RES_ADD
    LDAP_RES_DELETE
    LDAP_RES_MODRDN
    LDAP_RES_COMPARE
    如果超出了時間限制,ldap_result()將返回0;如果出錯,將返回-1,同時將出錯信息記錄到ld_errno 域。
ldap_msgfree()釋放指向res結構的指針並返回釋放信息的類型。
3.13 錯誤處理
3.13.1 錯誤代碼
各種操作將返回以下代碼中的一個作為結果:
LDAP_SUCCESS
           LDAP_OPERATIONS_ERROR
           LDAP_PROTOCOL_ERROR
           LDAP_TIMELIMIT_EXCEEDED
           LDAP_SIZELIMIT_EXCEEDED
           LDAP_COMPARE_FALSE
           LDAP_COMPARE_TRUE
           LDAP_STRONG_AUTH_NOT_SUPPORTED
           LDAP_STRONG_AUTH_REQUIRED
           LDAP_NO_SUCH_ATTRIBUTE
           LDAP_UNDEFINED_TYPE
           LDAP_INAPPROPRIATE_MATCHING
           LDAP_CONSTRAINT_VIOLATION
           LDAP_TYPE_OR_VALUE_EXISTS
           LDAP_INVALID_SYNTAX
           LDAP_NO_SUCH_OBJECT
           LDAP_ALIAS_PROBLEM
           LDAP_INVALID_DN_SYNTAX
           LDAP_IS_LEAF
           LDAP_ALIAS_DEREF_PROBLEM
           LDAP_INAPPROPRIATE_AUTH
           LDAP_INVALID_CREDENTIALS
           LDAP_INSUFFICIENT_ACCESS
           LDAP_BUSY
           LDAP_UNAVAILABLE
           LDAP_UNWILLING_TO_PERFORM
           LDAP_LOOP_DETECT
           LDAP_NAMING_VIOLATION
           LDAP_OBJECT_CLASS_VIOLATION
           LDAP_NOT_ALLOWED_ON_NONLEAF
           LDAP_NOT_ALLOWED_ON_RDN
           LDAP_ALREADY_EXISTS
           LDAP_NO_OBJECT_CLASS_MODS
           LDAP_RESULTS_TOO_LARGE
           LDAP_OTHER
           LDAP_SERVER_DOWN
           LDAP_LOCAL_ERROR
           LDAP_ENCODING_ERROR
           LDAP_DECODING_ERROR
           LDAP_TIMEOUT
           LDAP_AUTH_UNKNOWN
           LDAP_FILTER_ERROR
           LDAP_USER_CANCELLED
           LDAP_PARAM_ERROR
           LDAP_NO_MEMORY
下面的函數調用用於解釋由其它LDAP API產生的出錯信息。
3.13.2 介面介紹
int ldap_result2error(
        LDAP            *ld,
        LDAPMessage     *res,
        int             freeit);
char *ldap_err2string( int err );
void ldap_perror( LDAP *ld, char *msg );
參數:
ld       連接句柄;
res      其它LDAP操作的返回值,即ldap_result()的返回值或其它同步API操作的結果;
freeit    布爾型參數,指明參數res是否被釋放(非0,釋放;0,不釋放);
err      LDAP出錯代碼,即ldap_result2error()的返回值或其它同步API操作的結果;
msg      在LDAP出錯信息之前顯示的信息。
   ldap_result2error()用於將從ldap_result()中獲得的LDAP結果,或同步API操作的結果轉換為數字類型的LDAP錯誤代碼。並且分析結果信息中的ld_matched and ld_error部分,將其放入連接句柄信息中。所有的同步操作進程在返回值之前調用ldap_result2error(),以確保各個域的正確設置。聯接結構中相關的域有:
ld_matched  用於LDAP_NO_SUCH_OBJECT錯誤值返回時,該參數限制了匹配的DN的範圍;
ld_error    該參數保存了LDAP伺服器發送出的出錯信息;
ld_errno    LDAP出錯代碼指出了操作的結果。其值為以下的任意一個:
    ldap_err2string()用於將數字型的LDAP出錯代碼(例如ldap_result2error()的返回值,或任意一同步API操作調用結果)轉換為描述該出錯信息的字元串。其返回一個指向靜態數據的指針。
    ldap_perror() 用於將ld_errno域中參數msg中包含的信息轉換為標準的錯誤信息。
《解決方案》

現寫到這裡吧,可以看到,大部分都是從rfc1823上抄下來的,呵呵,主要是想開個小樓,讓所有研究ldapapi的朋友都有一個集中的發言地,這樣方便大家的交流。隨著大家對ldap的研究越來越多,肯定會有更多的介面被用到,希望大家一起能把這裡的內容越來越豐富起來。開這個小樓,還有出於幾點考慮,一是目前ldap的權威資料都是英語的,大家都是高技術的人,這個英文水平嘛。。。嘿嘿,反正偶系不高地啦,二是,把想所有搞研究api的人集中起來,一起進步,雖說ldap也不算很難的技術,但要想一個人把它研究透也不是那麼簡單的,所以,眾人的智慧總是高於一個人的,在這裡每個人都可以發表一下自己的心得體會,以供別人作為積累,同時也可以學習別人的知識,直接把人家的經驗拿來用,拿來主義還是有好處的,呵呵,這樣大家都能共同提高,也算是為構建和諧社會貢獻一份力量嘛,呵呵。。。(最後拔高一下中心思想,大家表打我。。。)

[ 本帖最後由 lhm0000 於 2007-11-16 09:42 編輯 ]
《解決方案》

咋就沒人接著說捏?
沒有技術問題一起討論,扔倆臭雞蛋也行啊
《解決方案》

我前幾天在做ldap的開發,是把數字證書的發布到ldap中去,不過我們公司用的是netscape.ldap的api,是JAVA版的,對你的比較感興趣

[火星人 ] 建個LDAP的API樓已經有754次圍觀

http://coctec.com/docs/service/show-post-33231.html