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