/* Copyright (C) 2003 Frédéric Giudicelli (contact_nos@yahoo.com). All rights reserved. This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) This program is released under the GPL with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // ClientLDAP.cpp: implementation of the ClientLDAP class. // ////////////////////////////////////////////////////////////////////// #include "ClientLDAP.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #ifndef _WIN32 #define stricmp strcasecmp #define strupr(x) \ { \ size_t dtlen; \ for(dtlen=0; dtlen & Results, int MaxResults, int MaxTime) { LDAPMessage * pMsg; LDAPMessage * currMsg; mString strSearch; LDAP_RC_TYPE LdapRet; // Try to reconnect if(!m_Connection && !Reconnect()) { return false; } ldap_set_option(m_Connection, LDAP_OPT_SIZELIMIT, (void *)&MaxResults); ldap_set_option(m_Connection, LDAP_OPT_TIMELIMIT, (void *)&MaxTime); if(m_utf8) mString::Encode("ISO-8859-1", "UTF-8", SearchString, strSearch); else strSearch = SearchString; pMsg=NULL; if((LdapRet = ldap_search_s(m_Connection, (char*)m_ldap_base.c_str(), LDAP_SCOPE_SUBTREE, (char*)strSearch.c_str(), NULL, 0, &pMsg)) != LDAP_SUCCESS) { // Should we try to reconnect switch(LdapRet) { case LDAP_SERVER_DOWN: // Retry the search if(!Reconnect()) { return false; } ldap_set_option(m_Connection, LDAP_OPT_SIZELIMIT, (void *)&MaxResults); ldap_set_option(m_Connection, LDAP_OPT_TIMELIMIT, (void *)&MaxTime); if((LdapRet = ldap_search_s(m_Connection, (char*)m_ldap_base.c_str(), LDAP_SCOPE_SUBTREE, (char*)strSearch.c_str(), NULL, 0, &pMsg)) != LDAP_SUCCESS) { NEWPKIerr(PKI_ERROR_TXT, ERROR_LDAP); ERR_add_error_data(2, "ldap_search_s : ", ldap_err2string(LdapRet)); return false; } break; case LDAP_TIMELIMIT_EXCEEDED: case LDAP_SIZELIMIT_EXCEEDED: if(!pMsg || !ldap_count_entries(m_Connection, pMsg)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_LDAP); ERR_add_error_data(2, "ldap_search_s : ", ldap_err2string(LdapRet)); return false; } break; default: NEWPKIerr(PKI_ERROR_TXT, ERROR_LDAP); ERR_add_error_data(2, "ldap_search_s : ", ldap_err2string(LdapRet)); return false; } } for(currMsg = ldap_first_entry(m_Connection, pMsg); currMsg; currMsg = ldap_next_entry(m_Connection, currMsg)) { AddCurrentMessage(Results, currMsg); } ldap_msgfree(pMsg); return true; } void ClientLDAP::AddCurrentMessage(mVector & Results, LDAPMessage * currMsg) { LdapResult newResult; char * Name; char * attrName; char ** attrValue; BerElement* ptr; // The DN Name = ldap_get_dn(m_Connection, currMsg); if(!Name) { return; } if(m_utf8) mString::Encode("UTF-8", "ISO-8859-1", Name, newResult.get_rdn()); else newResult.set_rdn(Name); ldap_memfree(Name); // We add the attributes for( attrName = ldap_first_attribute(m_Connection, currMsg, &ptr); attrName; attrName = ldap_next_attribute(m_Connection, currMsg, ptr) ) { if(!strstr(attrName, ";binary")) { attrValue = ldap_get_values(m_Connection, currMsg, attrName); if(attrValue) { // Did we already find the attribute UID and is this one // the attribute UID ? if(!newResult.get_uid().size() && m_ldap_attr_name == attrName) { if(m_utf8) mString::Encode("UTF-8", "ISO-8859-1", *attrValue, newResult.get_uid()); else newResult.set_uid(*attrValue); } AddObject(newResult.get_objects(), attrName, *attrValue); ldap_value_free(attrValue); } } ldap_memfree(attrName); } Results.push_back(newResult); } bool ClientLDAP::Reconnect() { LDAP_RC_TYPE LdapRet; Disconnect(); m_Connection = ldap_init((char*)m_ldap_server.c_str(), m_ldap_port); if(!m_Connection) { NEWPKIerr(PKI_ERROR_TXT, ERROR_LDAP); ERR_add_error_data(2, "ldap_init : ", ldap_err2string(LDAP_LAST_ERROR)); return false; } if(m_ldap_username.size()) { LdapRet = ldap_bind_s(m_Connection, (char*)m_ldap_username.c_str(), (char*)m_ldap_password.c_str(), LDAP_AUTH_SIMPLE); } else { LdapRet = ldap_bind_s(m_Connection, NULL, NULL, LDAP_AUTH_SIMPLE); } if(LdapRet != LDAP_SUCCESS) { NEWPKIerr(PKI_ERROR_TXT, ERROR_LDAP); ERR_add_error_data(2, "ldap_bind_s : ", ldap_err2string(LdapRet)); Disconnect(); return false; } return true; } ClientLDAP::operator int() { if(!m_Connection) return 0; else return 1; } int ClientLDAP::GetNid(char *Obj) { int nid; if(stricmp(Obj, "mail")==0) return NID_pkcs9_emailAddress; nid = OBJ_txt2nid(Obj); if(nid == NID_undef) { strupr((char*)Obj); nid = OBJ_txt2nid(Obj); if(nid == NID_undef) { strlwr((char*)Obj); ((char*)Obj)[0] = toupper(Obj[0]); nid = OBJ_txt2nid(Obj); } } return nid; } void ClientLDAP::AddObject(mVector & Objects, char * Name, char * Value) { LdapObject newObject; int nid; nid = GetNid(Name); if(nid == NID_undef) return; Name = (char*)OBJ_nid2ln(nid); if(!Name) return; if(m_utf8) { mString::Encode("UTF-8", "ISO-8859-1", Name, newObject.get_name()); mString::Encode("UTF-8", "ISO-8859-1", Value, newObject.get_value()); } else { newObject.set_name(Name); newObject.set_value(Value); } if(ObjectAlreadyKnown(Objects, newObject.get_name(), newObject.get_value())) { return; } Objects.push_back(newObject); } bool ClientLDAP::ObjectAlreadyKnown(const mVector & Objects, const mString & Name, const mString & Value) { size_t i; for(i=0; i