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