| /************************************************************** |
| * |
| * 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 <rtl/ustrbuf.hxx> |
| #include <rtl/strbuf.hxx> |
| |
| |
| 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<sal_Char *>(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 |
| |