1*2a97ec55SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*2a97ec55SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*2a97ec55SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*2a97ec55SAndrew Rist * distributed with this work for additional information 6*2a97ec55SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*2a97ec55SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*2a97ec55SAndrew Rist * "License"); you may not use this file except in compliance 9*2a97ec55SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*2a97ec55SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*2a97ec55SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*2a97ec55SAndrew Rist * software distributed under the License is distributed on an 15*2a97ec55SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*2a97ec55SAndrew Rist * KIND, either express or implied. See the License for the 17*2a97ec55SAndrew Rist * specific language governing permissions and limitations 18*2a97ec55SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*2a97ec55SAndrew Rist *************************************************************/ 21*2a97ec55SAndrew Rist 22*2a97ec55SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_extensions.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "ldapaccess.hxx" 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 30cdf0e10cSrcweir #include <rtl/strbuf.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir 33cdf0e10cSrcweir namespace extensions { namespace config { namespace ldap { 34cdf0e10cSrcweir 35cdf0e10cSrcweir oslModule LdapConnection::s_Ldap_Module = NULL; 36cdf0e10cSrcweir t_ldap_unbind_s LdapConnection::s_p_unbind_s = NULL; 37cdf0e10cSrcweir t_ldap_simple_bind_s LdapConnection::s_p_simple_bind_s = NULL; 38cdf0e10cSrcweir t_ldap_set_option LdapConnection::s_p_set_option = NULL; 39cdf0e10cSrcweir t_ldap_err2string LdapConnection::s_p_err2string = NULL; 40cdf0e10cSrcweir t_ldap_init LdapConnection::s_p_init = NULL; 41cdf0e10cSrcweir t_ldap_msgfree LdapConnection::s_p_msgfree = NULL; 42cdf0e10cSrcweir t_ldap_get_dn LdapConnection::s_p_get_dn = NULL; 43cdf0e10cSrcweir t_ldap_first_entry LdapConnection::s_p_first_entry = NULL; 44cdf0e10cSrcweir t_ldap_first_attribute LdapConnection::s_p_first_attribute = NULL; 45cdf0e10cSrcweir t_ldap_next_attribute LdapConnection::s_p_next_attribute = NULL; 46cdf0e10cSrcweir t_ldap_search_s LdapConnection::s_p_search_s = NULL; 47cdf0e10cSrcweir t_ldap_value_free LdapConnection::s_p_value_free = NULL; 48cdf0e10cSrcweir t_ldap_get_values LdapConnection::s_p_get_values = NULL; 49cdf0e10cSrcweir t_ldap_memfree LdapConnection::s_p_memfree = NULL; 50cdf0e10cSrcweir //------------------------------------------------------------------------------ 51cdf0e10cSrcweir typedef int LdapErrCode; 52cdf0e10cSrcweir //------------------------------------------------------------------------------ 53cdf0e10cSrcweir struct LdapMessageHolder 54cdf0e10cSrcweir { 55cdf0e10cSrcweir LdapMessageHolder() : msg(0) {} 56cdf0e10cSrcweir ~LdapMessageHolder() 57cdf0e10cSrcweir { 58cdf0e10cSrcweir if (msg) 59cdf0e10cSrcweir (*LdapConnection::s_p_msgfree)(msg); 60cdf0e10cSrcweir } 61cdf0e10cSrcweir 62cdf0e10cSrcweir LDAPMessage * msg; 63cdf0e10cSrcweir 64cdf0e10cSrcweir private: 65cdf0e10cSrcweir LdapMessageHolder(LdapMessageHolder const&); 66cdf0e10cSrcweir void operator=(LdapMessageHolder const&); 67cdf0e10cSrcweir }; 68cdf0e10cSrcweir //------------------------------------------------------------------------------ 69cdf0e10cSrcweir LdapConnection::~LdapConnection() 70cdf0e10cSrcweir { 71cdf0e10cSrcweir if (isValid()) disconnect(); 72cdf0e10cSrcweir } 73cdf0e10cSrcweir //------------------------------------------------------------------------------ 74cdf0e10cSrcweir 75cdf0e10cSrcweir void LdapConnection::disconnect() 76cdf0e10cSrcweir { 77cdf0e10cSrcweir if (mConnection != NULL) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir (*s_p_unbind_s)(mConnection) ; 80cdf0e10cSrcweir mConnection = NULL; 81cdf0e10cSrcweir } 82cdf0e10cSrcweir } 83cdf0e10cSrcweir //------------------------------------------------------------------------------ 84cdf0e10cSrcweir 85cdf0e10cSrcweir static void checkLdapReturnCode(const sal_Char *aOperation, 86cdf0e10cSrcweir LdapErrCode aRetCode, 87cdf0e10cSrcweir LDAP * /*aConnection*/) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir if (aRetCode == LDAP_SUCCESS) { return ; } 90cdf0e10cSrcweir 91cdf0e10cSrcweir static const sal_Char *kNoSpecificMessage = "No additional information" ; 92cdf0e10cSrcweir rtl::OUStringBuffer message ; 93cdf0e10cSrcweir 94cdf0e10cSrcweir if (aOperation != NULL) 95cdf0e10cSrcweir { 96cdf0e10cSrcweir message.appendAscii(aOperation).appendAscii(": ") ; 97cdf0e10cSrcweir } 98cdf0e10cSrcweir message.appendAscii((*LdapConnection::s_p_err2string)(aRetCode)).appendAscii(" (") ; 99cdf0e10cSrcweir sal_Char *stub = NULL ; 100cdf0e10cSrcweir 101cdf0e10cSrcweir #ifndef LDAP_OPT_SIZELIMIT // for use with OpenLDAP 102cdf0e10cSrcweir (*s_p_get_lderrno)(aConnection, NULL, &stub) ; 103cdf0e10cSrcweir #endif 104cdf0e10cSrcweir if (stub != NULL) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir message.appendAscii(stub) ; 107cdf0e10cSrcweir // It would seem the message returned is actually 108cdf0e10cSrcweir // not a copy of a string but rather some static 109cdf0e10cSrcweir // string itself. At any rate freeing it seems to 110cdf0e10cSrcweir // cause some undue problems at least on Windows. 111cdf0e10cSrcweir // This call is thus disabled for the moment. 112cdf0e10cSrcweir //(*s_p_memfree)(stub) ; 113cdf0e10cSrcweir } 114cdf0e10cSrcweir else { message.appendAscii(kNoSpecificMessage) ; } 115cdf0e10cSrcweir message.appendAscii(")") ; 116cdf0e10cSrcweir throw ldap::LdapGenericException(message.makeStringAndClear(), 117cdf0e10cSrcweir NULL, aRetCode) ; 118cdf0e10cSrcweir } 119cdf0e10cSrcweir //------------------------------------------------------------------------------ 120cdf0e10cSrcweir void LdapConnection::connectSimple(const LdapDefinition& aDefinition) 121cdf0e10cSrcweir throw (ldap::LdapConnectionException, ldap::LdapGenericException) 122cdf0e10cSrcweir { 123cdf0e10cSrcweir OSL_ENSURE(!isValid(), "Recoonecting an LDAP connection that is already established"); 124cdf0e10cSrcweir if (isValid()) disconnect(); 125cdf0e10cSrcweir 126cdf0e10cSrcweir mLdapDefinition = aDefinition; 127cdf0e10cSrcweir connectSimple(); 128cdf0e10cSrcweir } 129cdf0e10cSrcweir //------------------------------------------------------------------------------ 130cdf0e10cSrcweir void LdapConnection::connectSimple() 131cdf0e10cSrcweir throw (ldap::LdapConnectionException, ldap::LdapGenericException) 132cdf0e10cSrcweir { 133cdf0e10cSrcweir if (!isValid()) 134cdf0e10cSrcweir { 135cdf0e10cSrcweir // Connect to the server 136cdf0e10cSrcweir initConnection() ; 137cdf0e10cSrcweir // Set Protocol V3 138cdf0e10cSrcweir int version = LDAP_VERSION3; 139cdf0e10cSrcweir (*s_p_set_option)(mConnection, 140cdf0e10cSrcweir LDAP_OPT_PROTOCOL_VERSION, 141cdf0e10cSrcweir &version); 142cdf0e10cSrcweir 143cdf0e10cSrcweir #ifdef LDAP_X_OPT_CONNECT_TIMEOUT // OpenLDAP doesn't support this and the func 144cdf0e10cSrcweir /* timeout is specified in milliseconds -> 4 seconds*/ 145cdf0e10cSrcweir int timeout = 4000; 146cdf0e10cSrcweir (*s_p_set_option)( mConnection, 147cdf0e10cSrcweir LDAP_X_OPT_CONNECT_TIMEOUT, 148cdf0e10cSrcweir &timeout ); 149cdf0e10cSrcweir #endif 150cdf0e10cSrcweir 151cdf0e10cSrcweir // Do the bind 152cdf0e10cSrcweir LdapErrCode retCode = (*s_p_simple_bind_s)(mConnection, 153cdf0e10cSrcweir mLdapDefinition.mAnonUser , 154cdf0e10cSrcweir mLdapDefinition.mAnonCredentials) ; 155cdf0e10cSrcweir 156cdf0e10cSrcweir checkLdapReturnCode("SimpleBind", retCode, mConnection) ; 157cdf0e10cSrcweir } 158cdf0e10cSrcweir } 159cdf0e10cSrcweir //------------------------------------------------------------------------------ 160cdf0e10cSrcweir void LdapConnection::initConnection() 161cdf0e10cSrcweir throw (ldap::LdapConnectionException) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir if (mLdapDefinition.mServer.getLength() == 0) 164cdf0e10cSrcweir { 165cdf0e10cSrcweir rtl::OUStringBuffer message ; 166cdf0e10cSrcweir 167cdf0e10cSrcweir message.appendAscii("Cannot initialise connection to LDAP: No server specified.") ; 168cdf0e10cSrcweir throw ldap::LdapConnectionException(message.makeStringAndClear(), NULL) ; 169cdf0e10cSrcweir } 170cdf0e10cSrcweir 171cdf0e10cSrcweir if (mLdapDefinition.mPort == 0) mLdapDefinition.mPort = LDAP_PORT; 172cdf0e10cSrcweir 173cdf0e10cSrcweir mConnection = (*s_p_init)(mLdapDefinition.mServer, 174cdf0e10cSrcweir mLdapDefinition.mPort) ; 175cdf0e10cSrcweir if (mConnection == NULL) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir rtl::OUStringBuffer message ; 178cdf0e10cSrcweir 179cdf0e10cSrcweir message.appendAscii("Cannot initialise connection to LDAP server ") ; 180cdf0e10cSrcweir message.appendAscii(mLdapDefinition.mServer) ; 181cdf0e10cSrcweir message.appendAscii(":") ; 182cdf0e10cSrcweir message.append(mLdapDefinition.mPort) ; 183cdf0e10cSrcweir throw ldap::LdapConnectionException(message.makeStringAndClear(), 184cdf0e10cSrcweir NULL) ; 185cdf0e10cSrcweir } 186cdf0e10cSrcweir } 187cdf0e10cSrcweir //------------------------------------------------------------------------------ 188cdf0e10cSrcweir void LdapConnection::getUserProfile( 189cdf0e10cSrcweir const rtl::OUString& aUser, LdapData * data) 190cdf0e10cSrcweir throw (lang::IllegalArgumentException, 191cdf0e10cSrcweir ldap::LdapConnectionException, ldap::LdapGenericException) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir OSL_ASSERT(data != 0); 194cdf0e10cSrcweir if (!isValid()) { connectSimple(); } 195cdf0e10cSrcweir 196cdf0e10cSrcweir rtl::OString aUserDn =findUserDn( rtl::OUStringToOString(aUser, RTL_TEXTENCODING_ASCII_US)); 197cdf0e10cSrcweir 198cdf0e10cSrcweir LdapMessageHolder result; 199cdf0e10cSrcweir LdapErrCode retCode = (*s_p_search_s)(mConnection, 200cdf0e10cSrcweir aUserDn, 201cdf0e10cSrcweir LDAP_SCOPE_BASE, 202cdf0e10cSrcweir "(objectclass=*)", 203cdf0e10cSrcweir 0, 204cdf0e10cSrcweir 0, // Attributes + values 205cdf0e10cSrcweir &result.msg) ; 206cdf0e10cSrcweir 207cdf0e10cSrcweir checkLdapReturnCode("getUserProfile", retCode,mConnection) ; 208cdf0e10cSrcweir 209cdf0e10cSrcweir void * ptr; 210cdf0e10cSrcweir char * attr = (*s_p_first_attribute)(mConnection, result.msg, &ptr); 211cdf0e10cSrcweir while (attr != 0) { 212cdf0e10cSrcweir char ** values = (*s_p_get_values)(mConnection, result.msg, attr); 213cdf0e10cSrcweir if (values != 0) { 214cdf0e10cSrcweir data->insert( 215cdf0e10cSrcweir LdapData::value_type( 216cdf0e10cSrcweir rtl::OStringToOUString(attr, RTL_TEXTENCODING_ASCII_US), 217cdf0e10cSrcweir rtl::OStringToOUString(*values, RTL_TEXTENCODING_UTF8))); 218cdf0e10cSrcweir (*s_p_value_free)(values); 219cdf0e10cSrcweir } 220cdf0e10cSrcweir attr = (*s_p_next_attribute)(mConnection, result.msg, ptr); 221cdf0e10cSrcweir } 222cdf0e10cSrcweir } 223cdf0e10cSrcweir //------------------------------------------------------------------------------ 224cdf0e10cSrcweir rtl::OString LdapConnection::findUserDn(const rtl::OString& aUser) 225cdf0e10cSrcweir throw (lang::IllegalArgumentException, 226cdf0e10cSrcweir ldap::LdapConnectionException, ldap::LdapGenericException) 227cdf0e10cSrcweir { 228cdf0e10cSrcweir if (!isValid()) { connectSimple(); } 229cdf0e10cSrcweir 230cdf0e10cSrcweir if (aUser.getLength() == 0) 231cdf0e10cSrcweir { 232cdf0e10cSrcweir throw lang::IllegalArgumentException( 233cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM 234cdf0e10cSrcweir ("LdapConnection::findUserDn -User id is empty")), 235cdf0e10cSrcweir NULL, 0) ; 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir 239cdf0e10cSrcweir 240cdf0e10cSrcweir rtl::OStringBuffer filter( "(&(objectclass=" ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir filter.append( mLdapDefinition.mUserObjectClass ).append(")(") ; 243cdf0e10cSrcweir filter.append( mLdapDefinition.mUserUniqueAttr ).append("=").append(aUser).append("))") ; 244cdf0e10cSrcweir 245cdf0e10cSrcweir LdapMessageHolder result; 246cdf0e10cSrcweir sal_Char * attributes [2]; 247cdf0e10cSrcweir attributes[0]= const_cast<sal_Char *>(LDAP_NO_ATTRS); 248cdf0e10cSrcweir attributes[1]= NULL; 249cdf0e10cSrcweir LdapErrCode retCode = (*s_p_search_s)(mConnection, 250cdf0e10cSrcweir mLdapDefinition.mBaseDN, 251cdf0e10cSrcweir LDAP_SCOPE_SUBTREE, 252cdf0e10cSrcweir filter.makeStringAndClear(), attributes, 0, &result.msg) ; 253cdf0e10cSrcweir 254cdf0e10cSrcweir checkLdapReturnCode("FindUserDn", retCode,mConnection) ; 255cdf0e10cSrcweir rtl::OString userDn ; 256cdf0e10cSrcweir LDAPMessage *entry = (*s_p_first_entry)(mConnection, result.msg) ; 257cdf0e10cSrcweir 258cdf0e10cSrcweir if (entry != NULL) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir sal_Char *charsDn = (*s_p_get_dn)(mConnection, entry) ; 261cdf0e10cSrcweir 262cdf0e10cSrcweir userDn = charsDn ; 263cdf0e10cSrcweir (*s_p_memfree)(charsDn) ; 264cdf0e10cSrcweir } 265cdf0e10cSrcweir else 266cdf0e10cSrcweir { 267cdf0e10cSrcweir OSL_ENSURE( false, "LdapConnection::findUserDn-could not get DN for User "); 268cdf0e10cSrcweir } 269cdf0e10cSrcweir 270cdf0e10cSrcweir return userDn ; 271cdf0e10cSrcweir } 272cdf0e10cSrcweir 273cdf0e10cSrcweir extern "C" { static void SAL_CALL thisModule() {} } 274cdf0e10cSrcweir void LdapConnection::loadModule() 275cdf0e10cSrcweir { 276cdf0e10cSrcweir if ( !s_Ldap_Module ) 277cdf0e10cSrcweir { 278cdf0e10cSrcweir #if defined(WNT) 279cdf0e10cSrcweir # define LIBLDAP "nsldap32v50.dll" 280cdf0e10cSrcweir #else 281cdf0e10cSrcweir # ifdef WITH_OPENLDAP 282cdf0e10cSrcweir # define xstr(s) str(s) 283cdf0e10cSrcweir # define str(s) #s 284cdf0e10cSrcweir # define LIBLDAP "libldap-" xstr(LDAP_VENDOR_VERSION_MAJOR) "." xstr(LDAP_VENDOR_VERSION_MINOR) ".so." xstr(LDAP_VENDOR_VERSION_MAJOR) 285cdf0e10cSrcweir # else 286cdf0e10cSrcweir # define LIBLDAP "libldap50.so" 287cdf0e10cSrcweir # endif 288cdf0e10cSrcweir #endif 289cdf0e10cSrcweir const ::rtl::OUString sModuleName(RTL_CONSTASCII_USTRINGPARAM(LIBLDAP)); 290cdf0e10cSrcweir 291cdf0e10cSrcweir // load the dbtools library 292cdf0e10cSrcweir s_Ldap_Module = osl_loadModuleRelative(&thisModule, sModuleName.pData, 0); 293cdf0e10cSrcweir if ( s_Ldap_Module != NULL ) 294cdf0e10cSrcweir { 295cdf0e10cSrcweir s_p_unbind_s = (t_ldap_unbind_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_unbind_s").pData)); 296cdf0e10cSrcweir s_p_simple_bind_s = (t_ldap_simple_bind_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_simple_bind_s").pData)); 297cdf0e10cSrcweir s_p_set_option = (t_ldap_set_option)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_set_option").pData)); 298cdf0e10cSrcweir s_p_err2string = (t_ldap_err2string)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_err2string").pData)); 299cdf0e10cSrcweir s_p_init = (t_ldap_init)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_init").pData)); 300cdf0e10cSrcweir s_p_msgfree = (t_ldap_msgfree)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_msgfree").pData)); 301cdf0e10cSrcweir s_p_get_dn = (t_ldap_get_dn)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_get_dn").pData)); 302cdf0e10cSrcweir s_p_first_entry = (t_ldap_first_entry)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_first_entry").pData)); 303cdf0e10cSrcweir s_p_first_attribute = (t_ldap_first_attribute)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_first_attribute").pData)); 304cdf0e10cSrcweir s_p_next_attribute = (t_ldap_next_attribute)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_next_attribute").pData)); 305cdf0e10cSrcweir s_p_search_s = (t_ldap_search_s)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_search_s").pData)); 306cdf0e10cSrcweir s_p_value_free = (t_ldap_value_free)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_value_free").pData)); 307cdf0e10cSrcweir s_p_get_values = (t_ldap_get_values)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_get_values").pData)); 308cdf0e10cSrcweir s_p_memfree = (t_ldap_memfree)(osl_getFunctionSymbol(s_Ldap_Module, ::rtl::OUString::createFromAscii("ldap_memfree").pData)); 309cdf0e10cSrcweir } 310cdf0e10cSrcweir } 311cdf0e10cSrcweir } 312cdf0e10cSrcweir 313cdf0e10cSrcweir //------------------------------------------------------------------------------ 314cdf0e10cSrcweir } } } // extensions.config.ldap 315cdf0e10cSrcweir 316