Здравствуйте James, Вы писали:
J>Привет всем,
J>нужно написать клиент Win LDAP для просмотра и аутентификации юзеров.
Смотри код ниже — эта штука вываливает все записи с сервера у которых
CommonName, surname или givenName начинаются со строки szLNameStart.
Код построен на синхронных функциях — т.к. асинхронные функции мастдай и извращение.
Захочется асинхронщины — запусти этот код в новой нитке или переделай под асинхронные фуннкции.
ЗЫ. На всякий случай, если ты еще не наступал на эти грабли....
Библиотека wldap32.lib из Visual Studio — ПЛОХАЯ. Хорошая есть в Platform SDK.
class CLdapDatabase {
//....
public:
CString m_sLdapHost;//<--имя LDAP сервера
CString m_sLdapUserDN;//<--DN юзера под которым ты коннектишься - для начала оставь пустым
CString m_sLdapPassword;//<--обьяснять надо ?
protected:
struct XEntry {
CString sFname;
CString sLname;
CString sTitle;
CString sDivision;
CString sLocation;
CString sOfficePhoneExt;
CString sMobilePhone;
CString sPagerPhone;
CString sHomePhone;
CString sWorkstationName;
CString sCity;
//--
CString sEmailAddress;
};
CArray<XEntry, XEntry&> m_aRequest;//<-- здесь будет лежать результат запроса.
};
//--------------------------------------------------------------------
#include <winldap.h>
bool CLdapDatabase::SuggestNames(LPCTSTR szLNameStart)
{
m_aRequest.RemoveAll();
if( szLNameBeginning == NULL )
return false;
LONG res;
LDAP *ld = NULL;
if( NULL == (ld = ldap_init((LPTSTR)(LPCTSTR)m_sLdapHost, LDAP_PORT)) )
return false;
int opt;
res = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &(opt=LDAP_VERSION3));
res = ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &(opt=LDAP_NO_LIMIT));
if( LDAP_SUCCESS != (res = ldap_connect(ld, NULL)) )
return false;
if( LDAP_SUCCESS != (res = ldap_bind_s(ld,
m_sLdapUserDN.IsEmpty()?NULL:(LPTSTR)(LPCTSTR)m_sLdapUserDN,
m_sLdapPassword.IsEmpty()?NULL:(LPTSTR)(LPCTSTR)m_sLdapPassword,
LDAP_AUTH_NTLM) ) )
{// NT logon didn't pay off - try simple one
if( LDAP_SUCCESS != (res = ldap_simple_bind_s(ld,
(LPTSTR)(LPCTSTR)m_sLdapUserDN, (LPTSTR)(LPCTSTR)m_sLdapPassword) ) )
return false;
}
LDAPMessage *srchRes;
CString sFilter;
sFilter.Format(_T("(&(!objectClass=groupOfNames)(|(sn=%s*)(cn=%s*)(givenName=%s*)))"),
szLNameBeginning,szLNameBeginning,szLNameBeginning);
const LPCTSTR pcszAttrList[] = {
_T("dn"),_T("givenName"),_T("sn"),_T("title"),_T("department"), _T("physicalDeliveryOfficeName"),
_T("telephoneNumber"),_T("mobile"),_T("pager"),_T("homephone"),_T("postalCode"),_T("mail"),_T("rfc822Mailbox"),
_T("Company"),
NULL
};
if( LDAP_SUCCESS != (res = ldap_search_s(ld, NULL, LDAP_SCOPE_SUBTREE,
(LPTSTR)(LPCTSTR)sFilter, (TCHAR**)pcszAttrList, 0, &srchRes)) )
{
ldap_unbind(ld);
return false;
}
/* -- Debug - dump LDAP query to file
раскоментарь это чтобы все данные вывалить в файл - здорово помогает
разобраться в этом мусоре
FILE *out = fopen("ldap.out", "w");
LDAPMessage *entry = ldap_first_entry(ld, srchRes);
while( out && entry )
{
fprintf(out, "\n#--------------------\n");
BerElement *attr;
TCHAR *pszAttr = ldap_first_attribute(ld, entry, &attr);
while( pszAttr ) {
TCHAR **ppszVals = ldap_get_values(ld, entry, pszAttr);
while( *ppszVals ) {
fprintf(out, "%s: %s\n", pszAttr, *ppszVals);
ppszVals++;
}
pszAttr = ldap_next_attribute(ld, entry, attr);
}
entry = ldap_next_entry(ld, entry);
}
fclose(out);
*/
#define GET_LDAP_VALUE(name, str) do{ ppszVals = ldap_get_values(ld, entry, name); if( ppszVals ) { str = *ppszVals; ldap_value_free(ppszVals); } } while(0)
LDAPMessage *entry = ldap_first_entry(ld, srchRes);
while( entry )
{
XEntry xe;
TCHAR **ppszVals;
GET_LDAP_VALUE(_T("givenName"), xe.sFname);
GET_LDAP_VALUE(_T("sn"), xe.sLname);
GET_LDAP_VALUE(_T("title"), xe.sTitle);
GET_LDAP_VALUE(_T("department"), xe.sDivision);
GET_LDAP_VALUE(_T("physicalDeliveryOfficeName"), xe.sLocation);
GET_LDAP_VALUE(_T("telephoneNumber"), xe.sOfficePhoneExt);
GET_LDAP_VALUE(_T("mobile"), xe.sMobilePhone);
GET_LDAP_VALUE(_T("pager"), xe.sPagerPhone);
GET_LDAP_VALUE(_T("homephone"), xe.sHomePhone);
GET_LDAP_VALUE(_T("postalCode"), xe.sWorkstationName);
GET_LDAP_VALUE(_T("mail"), xe.sEmailAddress);
GET_LDAP_VALUE(_T("rfc822Mailbox"), xe.sEmailAddress);
GET_LDAP_VALUE(_T("Company"), xe.sCity);
if( (!xe.sFname.IsEmpty()) || (!xe.sLname.IsEmpty()) )
{
//at least firstname or lastname should be filled -
//this is not true for distribution lists
m_aRequest.Add(xe);
}
entry = ldap_next_entry(ld, entry);
}
ldap_msgfree(srchRes);
ldap_unbind(ld);
return true;
}