/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_extensions.hxx" #include "ldapaccess.hxx" #include #include namespace extensions { namespace config { namespace ldap { oslModule LdapConnection::s_Ldap_Module = NULL; t_ldap_unbind_s LdapConnection::s_p_unbind_s = NULL; t_ldap_simple_bind_s LdapConnection::s_p_simple_bind_s = NULL; t_ldap_set_option LdapConnection::s_p_set_option = NULL; t_ldap_err2string LdapConnection::s_p_err2string = NULL; t_ldap_init LdapConnection::s_p_init = NULL; t_ldap_msgfree LdapConnection::s_p_msgfree = NULL; t_ldap_get_dn LdapConnection::s_p_get_dn = NULL; t_ldap_first_entry LdapConnection::s_p_first_entry = NULL; t_ldap_first_attribute LdapConnection::s_p_first_attribute = NULL; t_ldap_next_attribute LdapConnection::s_p_next_attribute = NULL; t_ldap_search_s LdapConnection::s_p_search_s = NULL; t_ldap_value_free LdapConnection::s_p_value_free = NULL; t_ldap_get_values LdapConnection::s_p_get_values = NULL; t_ldap_memfree LdapConnection::s_p_memfree = NULL; //------------------------------------------------------------------------------ typedef int LdapErrCode; //------------------------------------------------------------------------------ struct LdapMessageHolder { LdapMessageHolder() : msg(0) {} ~LdapMessageHolder() { if (msg) (*LdapConnection::s_p_msgfree)(msg); } LDAPMessage * msg; private: LdapMessageHolder(LdapMessageHolder const&); void operator=(LdapMessageHolder const&); }; //------------------------------------------------------------------------------ LdapConnection::~LdapConnection() { if (isValid()) disconnect(); } //------------------------------------------------------------------------------ void LdapConnection::disconnect() { if (mConnection != NULL) { (*s_p_unbind_s)(mConnection) ; mConnection = NULL; } } //------------------------------------------------------------------------------ static void checkLdapReturnCode(const sal_Char *aOperation, LdapErrCode aRetCode, LDAP * /*aConnection*/) { if (aRetCode == LDAP_SUCCESS) { return ; } static const sal_Char *kNoSpecificMessage = "No additional information" ; rtl::OUStringBuffer message ; if (aOperation != NULL) { message.appendAscii(aOperation).appendAscii(": ") ; } message.appendAscii((*LdapConnection::s_p_err2string)(aRetCode)).appendAscii(" (") ; sal_Char *stub = NULL ; #ifndef LDAP_OPT_SIZELIMIT // for use with OpenLDAP (*s_p_get_lderrno)(aConnection, NULL, &stub) ; #endif if (stub != NULL) { message.appendAscii(stub) ; // It would seem the message returned is actually // not a copy of a string but rather some static // string itself. At any rate freeing it seems to // cause some undue problems at least on Windows. // This call is thus disabled for the moment. //(*s_p_memfree)(stub) ; } else { message.appendAscii(kNoSpecificMessage) ; } message.appendAscii(")") ; throw ldap::LdapGenericException(message.makeStringAndClear(), NULL, aRetCode) ; } //------------------------------------------------------------------------------ void LdapConnection::connectSimple(const LdapDefinition& aDefinition) throw (ldap::LdapConnectionException, ldap::LdapGenericException) { OSL_ENSURE(!isValid(), "Recoonecting an LDAP connection that is already established"); if (isValid()) disconnect(); mLdapDefinition = aDefinition; connectSimple(); } //------------------------------------------------------------------------------ void LdapConnection::connectSimple() throw (ldap::LdapConnectionException, ldap::LdapGenericException) { if (!isValid()) { // Connect to the server initConnection() ; // Set Protocol V3 int version = LDAP_VERSION3; (*s_p_set_option)(mConnection, LDAP_OPT_PROTOCOL_VERSION, &version); #ifdef LDAP_X_OPT_CONNECT_TIMEOUT // OpenLDAP doesn't support this and the func /* timeout is specified in milliseconds -> 4 seconds*/ int timeout = 4000; (*s_p_set_option)( mConnection, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout ); #endif // Do the bind LdapErrCode retCode = (*s_p_simple_bind_s)(mConnection, mLdapDefinition.mAnonUser.getStr(), mLdapDefinition.mAnonCredentials.getStr()) ; checkLdapReturnCode("SimpleBind", retCode, mConnection) ; } } //------------------------------------------------------------------------------ void LdapConnection::initConnection() throw (ldap::LdapConnectionException) { if (mLdapDefinition.mServer.getLength() == 0) { rtl::OUStringBuffer message ; message.appendAscii("Cannot initialise connection to LDAP: No server specified.") ; throw ldap::LdapConnectionException(message.makeStringAndClear(), NULL) ; } if (mLdapDefinition.mPort == 0) mLdapDefinition.mPort = LDAP_PORT; mConnection = (*s_p_init)( mLdapDefinition.mServer.getStr(), mLdapDefinition.mPort) ; if (mConnection == NULL) { rtl::OUStringBuffer message ; message.appendAscii("Cannot initialise connection to LDAP server ") ; message.appendAscii( mLdapDefinition.mServer.getStr()); message.appendAscii(":") ; message.append(mLdapDefinition.mPort) ; throw ldap::LdapConnectionException(message.makeStringAndClear(), NULL) ; } } //------------------------------------------------------------------------------ void LdapConnection::getUserProfile( const rtl::OUString& aUser, LdapData * data) throw (lang::IllegalArgumentException, ldap::LdapConnectionException, ldap::LdapGenericException) { OSL_ASSERT(data != 0); if (!isValid()) { connectSimple(); } rtl::OString aUserDn =findUserDn( rtl::OUStringToOString(aUser, RTL_TEXTENCODING_ASCII_US)); LdapMessageHolder result; LdapErrCode retCode = (*s_p_search_s)(mConnection, aUserDn.getStr(), LDAP_SCOPE_BASE, "(objectclass=*)", 0, 0, // Attributes + values &result.msg) ; checkLdapReturnCode("getUserProfile", retCode,mConnection) ; void * ptr; char * attr = (*s_p_first_attribute)(mConnection, result.msg, &ptr); while (attr != 0) { char ** values = (*s_p_get_values)(mConnection, result.msg, attr); if (values != 0) { data->insert( LdapData::value_type( rtl::OStringToOUString(attr, RTL_TEXTENCODING_ASCII_US), rtl::OStringToOUString(*values, RTL_TEXTENCODING_UTF8))); (*s_p_value_free)(values); } attr = (*s_p_next_attribute)(mConnection, result.msg, ptr); } } //------------------------------------------------------------------------------ rtl::OString LdapConnection::findUserDn(const rtl::OString& aUser) throw (lang::IllegalArgumentException, ldap::LdapConnectionException, ldap::LdapGenericException) { if (!isValid()) { connectSimple(); } if (aUser.getLength() == 0) { throw lang::IllegalArgumentException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("LdapConnection::findUserDn -User id is empty")).getStr(), NULL, 0) ; } rtl::OStringBuffer filter( "(&(objectclass=" ); filter.append( mLdapDefinition.mUserObjectClass ).append(")(") ; filter.append( mLdapDefinition.mUserUniqueAttr ).append("=").append(aUser).append("))") ; LdapMessageHolder result; sal_Char * attributes [2]; attributes[0]= const_cast(LDAP_NO_ATTRS); attributes[1]= NULL; LdapErrCode retCode = (*s_p_search_s)(mConnection, mLdapDefinition.mBaseDN.getStr(), LDAP_SCOPE_SUBTREE, filter.getStr(), attributes, 0, &result.msg) ; checkLdapReturnCode("FindUserDn", retCode,mConnection) ; rtl::OString userDn ; LDAPMessage *entry = (*s_p_first_entry)(mConnection, result.msg) ; if (entry != NULL) { sal_Char *charsDn = (*s_p_get_dn)(mConnection, entry) ; userDn = charsDn ; (*s_p_memfree)(charsDn) ; } else { OSL_ENSURE( false, "LdapConnection::findUserDn-could not get DN for User "); } return userDn ; } extern "C" { static void SAL_CALL thisModule() {} } void LdapConnection::loadModule() { if ( !s_Ldap_Module ) { #if defined(WNT) # define LIBLDAP "nsldap32v50.dll" #else # ifdef WITH_OPENLDAP # define xstr(s) str(s) # define str(s) #s # define LIBLDAP "libldap-" xstr(LDAP_VENDOR_VERSION_MAJOR) "." xstr(LDAP_VENDOR_VERSION_MINOR) ".so." xstr(LDAP_VENDOR_VERSION_MAJOR) # else # define LIBLDAP "libldap50.so" # endif #endif const ::rtl::OUString sModuleName(RTL_CONSTASCII_USTRINGPARAM(LIBLDAP)); // load the dbtools library s_Ldap_Module = osl_loadModuleRelative(&thisModule, sModuleName.pData, 0); if ( s_Ldap_Module != NULL ) { s_p_unbind_s = (t_ldap_unbind_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_unbind_s").pData)); s_p_simple_bind_s = (t_ldap_simple_bind_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_simple_bind_s").pData)); s_p_set_option = (t_ldap_set_option)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_set_option").pData)); s_p_err2string = (t_ldap_err2string)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_err2string").pData)); s_p_init = (t_ldap_init)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_init").pData)); s_p_msgfree = (t_ldap_msgfree)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_msgfree").pData)); s_p_get_dn = (t_ldap_get_dn)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_get_dn").pData)); s_p_first_entry = (t_ldap_first_entry)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_first_entry").pData)); s_p_first_attribute = (t_ldap_first_attribute)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_first_attribute").pData)); s_p_next_attribute = (t_ldap_next_attribute)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_next_attribute").pData)); s_p_search_s = (t_ldap_search_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_search_s").pData)); s_p_value_free = (t_ldap_value_free)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_value_free").pData)); s_p_get_values = (t_ldap_get_values)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_get_values").pData)); s_p_memfree = (t_ldap_memfree)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_memfree").pData)); } } } //------------------------------------------------------------------------------ } } } // extensions.config.ldap