上一篇介绍了windows下使用c++操作LDAP Server,实现了增删改的操作
LDAP的数据存储是以树形结构的方式进行存储,不是使用表格,所以无法使用SQL语句进行查询
LDAP提供自己的一套查询方式,实现对数据的快速查询
查询功能
首先看接口
ULONG LDAPAPI ldap_search_sW(
LDAP *ld,
_In_opt_ const PWSTR base,
ULONG scope,
_In_ const PWSTR filter,
_In_ PZPWSTR attrs,
ULONG attrsonly,
_Outptr_result_maybenull_ LDAPMessage **res
);
- ld,句柄
- base,要查询的基本条目dn
- scope,范围
- filter,过滤条件
- attrs,检索的属性列表
- attrsonly,设置为 1,只返回属性的类型,通常设定为 0,返回属性类型和值
- res,结果
条目DN
要查询的条目,提供一个基准
范围
ldap为树形结构,以基准条目开始,设定要查找的范围
-
LDAP_SCOPE_BASE,仅搜索基本条目
-
LDAP_SCOPE_ONELEVEL,搜索基本条目下第一级的所有条目,不包括基本条目
-
LDAP_SCOPE_SUBTREE,搜索基本条目和基本条目下的所有条目
过滤器
过滤器语法定义在RFC4515
filter = "(" filtercomp ")"
filtercomp = and / or / not / item
and = "&" filterlist
or = "|" filterlist
not = "!" filter
如:(&(objectclass=idaPerson)(cn=test)),同时满足objectclass=idaPerson和cn=test的项,(&(objectclass=idaPerson)(|(cn=test)(cn=zhaoqi)))满足objectclass=idaPerson和cn=test或者objectclass=idaPerson和cn= zhaoqi的项
过滤器语法的子集
Option | 说明 |
& | |
| | |
! | |
= | |
~= | |
>= | |
<= | |
=* | |
* | |
/ |
属性
根据以上三个条件后,可以检索出想要的条目,检索出的条目可能是一条或若干条
属性参数为列举要查询的属性,即从检索出的条目中取出想要的属性值
代码
// 搜索结果
LDAPMessage *res = NULL;
PWSTR base_dn = (PWSTR)L"c=cn";
PWSTR filter = (PWSTR)L"cn=test22";
//搜索结果
PWCHAR attrs[3];
attrs[0] = (PWCHAR)L"cn";
attrs[1] = (PWCHAR)L"uid";
// attrs[2] = (PWCHAR)L"loginShell";
// attrs[3] = (PWCHAR)L"uid";
attrs[2] = NULL;
rc = ldap_search_s(
ld, // 会话句柄
base_dn, // 指向查询开始处对象的指针,可以作为数的顶端,或者某一个低的点
LDAP_SCOPE_SUBTREE, // 范围
filter, // 过滤器
attrs, // 检索属性列表
0, // 设置为 1,只返回属性的类型,通常设定为 0,返回属性类型和值
&res); // [输出]搜索结果
if (rc != LDAP_SUCCESS) {
fprintf(stderr, "ldap_search_s: rc: %d\n", rc);
ldap_unbind_s(ld);
if (res != NULL)
ldap_msgfree(res);
return -1;
}
printf("ldap_search_s success\n");
// 获取返回的条目数
ULONG count = ldap_count_entries(ld, res);
printf("The number of entries is: %d\n", count);
LDAPMessage* pEntry = NULL;
PCHAR pEntryDN = NULL;
ULONG iCnt = 0;
const char* sMsg;
BerElement* pBer = NULL;
PWCHAR pAttribute = NULL;
PWCHAR* ppValue = NULL;
ULONG iValue = 0;
for( iCnt=0; iCnt < count; iCnt++ )
{
// Get the first/next entry.
if( !iCnt )
pEntry = ldap_first_entry(ld, res);
else
pEntry = ldap_next_entry(ld, pEntry);
// Output a status message.
sMsg = (!iCnt ? "ldap_first_entry" : "ldap_next_entry");
if( pEntry == NULL )
{
printf("%s failed with 0x%0lx \n", sMsg, LdapGetLastError());
ldap_unbind_s(ld);
ldap_msgfree(res);
return -1;
}
else
printf("%s succeeded\n",sMsg);
// Output the entry number.
printf("ENTRY NUMBER %i \n", iCnt);
// Get the first attribute name.
pAttribute = ldap_first_attribute(
ld, // Session handle
pEntry, // Current entry
&pBer); // [out] Current BerElement
// Output the attribute names for the current object
// and output values.
while(pAttribute != NULL)
{
// Output the attribute name.
printf(" ATTR: %ls",pAttribute);
// Get the string values.
ppValue = ldap_get_values(
ld, // Session Handle
pEntry, // Current entry
pAttribute); // Current attribute
// Print status if no values are returned (NULL ptr)
if(ppValue == NULL)
{
printf(": [NO ATTRIBUTE VALUE RETURNED]");
}
// Output the attribute values
else
{
iValue = ldap_count_values(ppValue);
if(!iValue)
{
printf(": [BAD VALUE LIST]");
}
else
{
// Output the first attribute value
printf(": %ls", *ppValue);
// Output more values if available
ULONG z;
for(z=1; z<iValue; z++)
{
printf(", %ls", ppValue[z]);
}
}
}
// Free memory.
if(ppValue != NULL)
ldap_value_free(ppValue);
ppValue = NULL;
ldap_memfree(pAttribute);
// Get next attribute name.
pAttribute = ldap_next_attribute(
ld, // Session Handle
pEntry, // Current entry
pBer); // Current BerElement
printf("\n");
}
if( pBer != NULL )
ber_free(pBer,0);
pBer = NULL;
}
//----------------------------------------------------------
// Normal cleanup and exit.
//----------------------------------------------------------
ldap_unbind(ld);
ldap_msgfree(res);
ldap_value_free(ppValue);
LDAP查询链接
LDAP支持以URL的方式供外部访问查询,类型http的URL,查询功能可类比于http的下载链接,在浏览器打开即可下载
LDAP URL相关规则定义在RFC4516
举个例子
这是一个查询证书吊销列表CRL的LDAP地址
ldap://ldap8.wosign.com/CN=crl0,OU=CRL,O=aa,C=CN?certificateRevocationList?base?objectclass=cRLDistributionPoint
其组成为
ldap://<host>/<base>?<attrs>?<scope>?<filter>
- host:ip+端口号或者域名
- base,attrs,scope,filter即对应查询条件
根据这条链接就可以取到该ldap服务下,条目CN=crl0,OU=CRL,O=aa,C=CN的certificateRevocationList属性值,即吊销列表值
windows下可使用certutil工具进行下载
certutil -URL ldap://ldap8.wosign.com/CN=crl0,OU=CRL,O=aa,C=CN?certificateRevocationList?base?objectclass=cRLDistributionPoint