2
This file is part of libkldap.
3
Copyright (c) 2004-2006 Szombathelyi Gyƶrgy <gyurco@freemail.hu>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public License
16
along with this library; see the file COPYING.LIB. If not, write to
17
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
Boston, MA 02110-1301, USA.
21
#include "ldapconnection.h"
28
#include <kldap_config.h>
31
#include <sasl/sasl.h>
35
#define LDAP_DEPRECATED 1 //for ldap_simple_bind_s
40
using namespace KLDAP;
43
class LdapConnection::LdapConnectionPrivate
47
QString mConnectionError;
56
LdapConnection::LdapConnection()
57
: d( new LdapConnectionPrivate )
62
LdapConnection::LdapConnection( const LdapUrl &url )
63
: d( new LdapConnectionPrivate )
69
LdapConnection::LdapConnection( const LdapServer &server )
70
: d( new LdapConnectionPrivate )
76
LdapConnection::~LdapConnection()
82
void LdapConnection::setUrl( const LdapUrl &url )
84
d->mServer.setUrl( url );
87
void LdapConnection::setServer( const LdapServer &server )
92
void *LdapConnection::handle() const
94
return (void*) d->mLDAP;
97
QString LdapConnection::errorString( int code )
99
//No translated error messages yet
101
return QString::fromUtf8( ldap_err2string( code ) );
103
case LDAP_OPERATIONS_ERROR: return i18n("LDAP Operations error");
105
/* add the LDAP error codes */
108
return i18n("No LDAP Support...");
112
QString LdapConnection::connectionError() const
114
return d->mConnectionError;
118
int LdapConnection::getOption( int option, void *value ) const
120
Q_ASSERT( d->mLDAP );
121
return ldap_get_option( d->mLDAP, option, value );
124
int LdapConnection::setOption( int option, void *value )
126
Q_ASSERT( d->mLDAP );
127
return ldap_set_option( d->mLDAP, option, value );
130
int LdapConnection::ldapErrorCode() const
132
Q_ASSERT( d->mLDAP );
134
ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err );
138
QString LdapConnection::ldapErrorString() const
140
Q_ASSERT( d->mLDAP );
142
ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg );
143
QString msg = QString::fromLocal8Bit( errmsg );
148
bool LdapConnection::setSizeLimit( int sizelimit )
150
Q_ASSERT( d->mLDAP );
151
kDebug() << "sizelimit: " << sizelimit << endl;
152
if ( setOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
158
int LdapConnection::sizeLimit() const
160
Q_ASSERT( d->mLDAP );
162
if ( getOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
168
bool LdapConnection::setTimeLimit( int timelimit )
170
Q_ASSERT( d->mLDAP );
171
kDebug() << "timelimit: " << timelimit << endl;
172
if ( setOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
178
int LdapConnection::timeLimit() const
180
Q_ASSERT( d->mLDAP );
182
if ( getOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
188
static int kldap_sasl_interact( LDAP *, unsigned, void *defaults, void *in )
191
LdapConnection::SASL_Data *data = (LdapConnection::SASL_Data*) defaults;
192
sasl_interact_t *interact = ( sasl_interact_t * ) in;
195
for ( ; interact->id != SASL_CB_LIST_END; interact++ ) {
196
switch ( interact->id ) {
197
case SASL_CB_GETREALM:
198
data->creds.fields |= LdapConnection::SASL_Realm;
200
case SASL_CB_AUTHNAME:
201
data->creds.fields |= LdapConnection::SASL_Authname;
204
data->creds.fields |= LdapConnection::SASL_Password;
207
data->creds.fields |= LdapConnection::SASL_Authzid;
212
if ( (retval = data->proc( data->creds, data->data )) ) return retval;
217
while( interact->id != SASL_CB_LIST_END ) {
219
switch( interact->id ) {
220
case SASL_CB_GETREALM:
221
value = data->creds.realm;
222
kDebug() << "SASL_REALM=" << value << endl;
224
case SASL_CB_AUTHNAME:
225
value = data->creds.authname;
226
kDebug() << "SASL_AUTHNAME=" << value << endl;
229
value = data->creds.password;
230
kDebug() << "SASL_PASSWD=[hidden]" << endl;
233
value = data->creds.authzid;
234
kDebug() << "SASL_AUTHZID=" << value << endl;
238
if ( value.isEmpty() ) {
239
interact->result = NULL;
242
interact->result = strdup( value.toUtf8() );
243
interact->len = strlen( (const char *) interact->result );
250
int LdapConnection::connect()
254
if ( d->mLDAP ) close();
256
int version = d->mServer.version();
258
url = d->mServer.security() == LdapServer::SSL ? "ldaps" : "ldap";
260
url += d->mServer.host();
262
url += QString::number( d->mServer.port() );
263
kDebug() << "ldap url: " << url << endl;
264
ret = ldap_initialize( &d->mLDAP, url.toLatin1() );
265
if ( ret != LDAP_SUCCESS ) {
266
d->mConnectionError = i18n("An error occurred during the connection initialization phase.");
270
kDebug() << "setting version to: " << version << endl;
271
if ( (setOption( LDAP_OPT_PROTOCOL_VERSION, &version )) != LDAP_OPT_SUCCESS ) {
272
ret = ldapErrorCode();
273
d->mConnectionError = i18n("Cannot set protocol version to %1.").arg(version);
278
//FIXME: accessing to certificate handling would be good
279
kDebug() << "setting security to: " << d->mServer.security() << endl;
280
if ( d->mServer.security() == LdapServer::TLS ) {
281
kDebug() << "start TLS" << endl;
282
if ( ( ret = ldap_start_tls_s( d->mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) {
284
d->mConnectionError = i18n("Cannot start TLS.");
289
kDebug() << "setting sizelimit to: " << d->mServer.sizeLimit() << endl;
290
if ( d->mServer.sizeLimit() ) {
291
if ( !setSizeLimit( d->mServer.sizeLimit() ) ) {
292
ret = ldapErrorCode();
294
d->mConnectionError = i18n("Cannot set size limit.");
299
kDebug() << "setting timelimit to: " << d->mServer.timeLimit() << endl;
300
if ( d->mServer.timeLimit() ) {
301
if ( !setTimeLimit( d->mServer.timeLimit() ) ) {
302
ret = ldapErrorCode();
304
d->mConnectionError = i18n("Cannot set time limit.");
311
int LdapConnection::bind( SASL_Callback_Proc *saslproc, void *data )
315
if ( d->mServer.auth() == LdapServer::SASL ) {
317
QString mech = d->mServer.mech();
318
if ( mech.isEmpty() ) mech = "DIGEST-MD5";
321
sasldata.proc = saslproc;
322
sasldata.data = data;
323
sasldata.creds.fields = 0;
324
sasldata.creds.realm = d->mServer.realm();
325
sasldata.creds.authname = d->mServer.user();
326
sasldata.creds.authzid = d->mServer.bindDn();
327
sasldata.creds.password = d->mServer.password();
329
ret = ldap_sasl_interactive_bind_s( d->mLDAP, 0, mech.toLatin1(), 0, 0,
330
LDAP_SASL_INTERACTIVE, &kldap_sasl_interact, &sasldata );
335
QString bindname, pass;
336
if ( d->mServer.auth() == LdapServer::Simple ) {
337
bindname = d->mServer.bindDn();
338
pass = d->mServer.password();
340
kDebug() << "binding to server, bindname: " << bindname << " password: *****" << endl;
341
ret = ldap_simple_bind_s( d->mLDAP, bindname.toUtf8(), pass.toUtf8() );
346
void LdapConnection::close()
348
if ( d->mLDAP ) ldap_unbind_ext_s( d->mLDAP, 0, 0 );
350
kDebug() << "connection closed!" << endl;
354
int LdapConnection::getOption( int option, void *value ) const
356
kError() << "No LDAP support..." << endl;
360
int LdapConnection::setOption( int option, void *value )
362
kError() << "No LDAP support..." << endl;
366
int LdapConnection::ldapErrorCode() const
368
kError() << "No LDAP support..." << endl;
372
QString LdapConnection::ldapErrorString() const
374
kError() << "No LDAP support..." << endl;
378
bool LdapConnection::setSizeLimit( int sizelimit )
380
kError() << "No LDAP support..." << endl;
384
int LdapConnection::sizeLimit() const
386
kError() << "No LDAP support..." << endl;
390
bool LdapConnection::setTimeLimit( int timelimit )
392
kError() << "No LDAP support..." << endl;
396
int LdapConnection::timeLimit() const
398
kError() << "No LDAP support..." << endl;
402
int LdapConnection::connect( )
404
d->mConnectionError = i18n("LDAP support not compiled in. Please recompile libkldap with the OpenLDAP (or compatible) client libraries, or complain to your distribution packagers.");
405
kError() << "No LDAP support..." << endl;
409
int LdapConnection::bind( SASL_Callback_Proc *saslproc, void *data )
411
kError() << "No LDAP support..." << endl;
415
void LdapConnection::close()
417
kError() << "No LDAP support..." << endl;