Re: LDAP API
От: TepMuHyc  
Дата: 25.03.02 18:28
Оценка: 4 (1)
Здравствуйте 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;
}
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.