畢竟用PHP操作LDAP有局限性,因為當我們用產生認證的函數產生認證以後不可能再用PHP去給LDAP增加條目,所以最近研究了一下C語言操作LDAP,希望能對大家有點借鑒意義,有錯誤的地方還請原諒。至於如何安裝,運行和測試LDAP伺服器請看http://www.infosecurity.org.cn/forum/read.php?fid=12&tid=47&fpage=1
畢竟用PHP操作LDAP有局限性,因為當我們用產生認證的函數產生認證以後不可能再用PHP去給LDAP增加條目,所以最近研究了一下C語言操作LDAP,希望能對大家有點借鑒意義,有錯誤的地方還請原諒。至於如何安裝,運行和測試LDAP伺服器請看http://www.infosecurity.org.cn/forum/read.php?fid=12&tid=47&fpage=1
一 初始化LDAP庫
#include
#include
ld=ldap_init(ldap_host,LDAP_PORT)
假如沒有進行連接埠修改的話,用預設的LDAP_PORT就可以了,在ldap.h中定義為389
二 綁定LDAP伺服器
if(ldap_bind_s(ld,user_dn,user_pw,authmethod)!=LDAP_SUCCESS)
authmethod是使用的驗證方法,一般為LDAP_AUTH_SIMPLE,至於user_dn,user_pw就是使用者和密碼拉
可以使用ldap_unbind_s(LDAP *ld)來關閉綁定。
三 執行查詢
ldap_search_s(LDAP ld,char *base_dn,int scope ,char *filter ,char *attrs_reqired[],int attributesonly,LDAPMessage **result)
base_dn是指向查詢開始處對象的指標,它可以作為數的頂端,或者某一個低的點
scope有三個,為
LDAP_SCOPE_BASE,只對基點dn指定的對象進行搜尋
LDAP_SCOPE_ONELEVEL,可以搜尋處理基點DN指向對象以及樹中低於基點對象一級的所有對象
LDAP_SCOPE_SUBTREE,可以搜尋樹中該對象及以下的所有對象
Filter是過濾器,這裡有詳細的解釋http://www.infosecurity.org.cn/forum/read.php?fid=12&tid=49&fpage=1
Attrs_required是一個應該返回的NULL的屬性終止數組,可以只返回幾個屬性(如就DN和UID),指定NULL時將返回所有屬性
Attributesonly設定為1,只返回屬性的類型,通常設定為0,返回屬性類型和值。
成功返回LDAP_SUCCESS,否則返回出錯代碼。
例子:ldap_search_s(ld,base_dn,LDAP_SCOPE_SUBTREE,NULL,NULL,0,&ldap_message_set)
稍後必須釋放LDAPMessage **result,int ldap_msgfree(LDAPMessage *msg)
查詢過後,我們就需要得到我們具體的感興趣的東西
ldap_count_entries(ld,ldap_message_set)擷取搜尋得到的條目個數
ldap_first_entry(ld,ldap_message_set)擷取第一條
ldap_next_entry(ld,ldap_one_message);擷取下一條
ldap_first_attribute(ld,ldap_one_message,&ber_element_ptr);擷取第一條目的屬性
values= ldap_get_values(ld,ldap_one_message,attribute)擷取該屬性的值
ldap_value_free(values);
ldap_next_attribute(ld,ldap_one_message,ber_element_ptr);擷取下一屬性
可能看這麼多函數有點眼花,那我們來看個例子:
res=ldap_search_s(ld,base_dn,LDAP_SCOPE_SUBTREE,NULL,NULL,0,&ldap_message_set);
if(res!=LDAP_SUCCESS)
{
ldap_perror(ld,"Failure of ldap_search_s");
exit(0);
}
printf("There were %d objects found/n",ldap_count_entries(ld,ldap_message_set));
//擷取第一個條目
ldap_one_message=ldap_first_entry(ld,ldap_message_set);
while(ldap_one_message)
{
char *dn_str;
//擷取條目的DN
dn_str=ldap_get_dn(ld,ldap_one_message);
printf("Found dn %s/n",dn_str);
free(dn_str);
//擷取條目的屬性
attribute=ldap_first_attribute(ld,ldap_one_message,&ber_element_ptr);
//擷取每個屬性的具體值
while(attribute!=NULL)
{
if((values=ldap_get_values(ld,ldap_one_message,attribute))!=NULL)
{
for(i=0;values!=NULL;i++)
{
printf("%s:%s/n",attribute,values);
}
ldap_value_free(values);
}
//繼續下一屬性
attribute=ldap_next_attribute(ld,ldap_one_message,ber_element_ptr);
}
//繼續下一條目
ldap_one_message=ldap_next_entry(ld,ldap_one_message);
printf("/n");
}
//釋放查詢資訊
(void)ldap_msgfree(ldap_message_set);
由上面的例子可以清楚的看出,可以查詢出所有的搜尋搜尋結果的屬性以及屬性值
四:增加條目
增加條目需要乾的事情就是構造一個LDAPMod結構,它包括對象單個屬性的構造塊
typedef struct ldapmod
{
int mod_op;
char *mod_type;
union
{
char **modv_strvals;
struct berval **modv_bvals;
}mod_vals;
struct ldapmod *mod_next;
}LDAPMod;
#define mod_values mod_vals,modv_strvals
#define mod_bvalues mod_vals.modv_bvals
可能你看起來很複雜,那我給你看個例子你就能找到中間的規律拉。
1, 添加一個國家的條目LDAPMod
char *c_vals[]={"cn",NULL};
LDAPMod c_attribute;
c_attribute.mod_op=LDAP_MOD_ADD;
c_attribute.mod_type="c";
c_attribute.mod_values=c_vals;
2, 你是不是覺得太簡單,那我們來個麻煩點的,認證的LDAPMod
struct berval cert_berval;
struct berval *cert_values[2];
char *cert_data;
FILE *fp;
struct stat st;
LDAPMod cert_attribute;
if ( stat( "guest.der", &st ) != 0 ) {
perror( "stat" );
return( 1 );
}
if ( ( fp = fopen( "guest.der", "rb" ) ) == NULL ) {
perror( "fopen" );
return( 1 );
}
if ( ( ( cert_data = ( char * )malloc( st.st_size ) ) == NULL ) ││
( fread ( cert_data, st.st_size, 1, fp ) != 1 ) ) {
perror( cert_data ? "fread" : "malloc" );
return( 1 );
}
fclose( fp );
cert_attribute.mod_op = LDAP_MOD_BVALUES;
cert_attribute.mod_type = "userCertificate;binary";
cert_berval.bv_len = st.st_size;
cert_berval.bv_val = cert_data;
cert_values[0] = &cert_berval;
cert_values[1] = NULL;
cert_attribute.mod_values =cert_values;
我們看完這兩個例子那你看出規律了吧,為非是把LDAPMod中的幾個變數賦值而已
下面我們把這些值給LDAP添加進去
char *objectClass_vals[]={"guestcertificate",NULL}; guestcertificate是我定義的objectClass
objectClass_attribute.mod_op=LDAP_MOD_ADD;
objectClass_attribute.mod_type="objectClass";
objectClass_attribute.mod_values=objectClass_vals;
new_dn="c=cn,dc=sage,dc=com";
LDAPMod *modst[4];
modst[0]=&c_attribute;
modst[1]=&objectClass_attribute;
modst[2]=NULL;
if(ldap_add_s(ld,new_dn,modst)!=LDAP_SUCCESS)
現在new_dn就添加好了,呵呵,是不是很簡單。
至於修改條目ldap_mod_s(LDAP *ld,char *new_dn,LDAPMOD *mods[])
刪除條目 ldap_delete_s(LDAP *ld,char *dn_to_delete)應該沒問題拉。
附件裡有我寫的一個往LDAP伺服器中添加認證的函數,寫的很亂,不太好意思。用C語言來操作LDAP最好就是添加條目了,可以從CISOCA中提煉一下,編寫一個只需要使用者輸入資訊就可以產生認證的函數,然後將產生的認證直接發往LDAP伺服器就可以了。我建議其實查詢的話就用PHP去查詢LDAP,因為查詢出來要顯示在瀏覽器上的,並且需要提供給使用者下載,用CGI去編介面那就太。。。。PHP還方便點。