00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ldapconnection.h"
00022 #include "ldapdefs.h"
00023 #include "kldap_config.h"
00024
00025 #include <stdlib.h>
00026 #include <klocale.h>
00027 #include <kdebug.h>
00028
00029 #ifdef SASL2_FOUND
00030 #include <sasl/sasl.h>
00031 static sasl_callback_t callbacks[] = {
00032 { SASL_CB_ECHOPROMPT, NULL, NULL },
00033 { SASL_CB_NOECHOPROMPT, NULL, NULL },
00034 { SASL_CB_GETREALM, NULL, NULL },
00035 { SASL_CB_USER, NULL, NULL },
00036 { SASL_CB_AUTHNAME, NULL, NULL },
00037 { SASL_CB_PASS, NULL, NULL },
00038 { SASL_CB_CANON_USER, NULL, NULL },
00039 { SASL_CB_LIST_END, NULL, NULL }
00040 };
00041
00042 static bool ldapoperation_sasl_initialized = false;
00043 #endif
00044
00045 #ifdef LDAP_FOUND
00046 #include <lber.h>
00047 #include <ldap.h>
00048
00049 #ifndef LDAP_OPT_SUCCESS
00050 #define LDAP_OPT_SUCCESS 0
00051 #endif
00052
00053 #endif
00054
00055 using namespace KLDAP;
00056
00057 class LdapConnection::LdapConnectionPrivate
00058 {
00059 public:
00060 LdapConnectionPrivate();
00061 LdapServer mServer;
00062 QString mConnectionError;
00063
00064 #ifdef LDAP_FOUND
00065 LDAP *mLDAP;
00066 #else
00067 void *mLDAP;
00068 #endif
00069 #ifdef SASL2_FOUND
00070 sasl_conn_t *mSASLconn;
00071 #else
00072 void *mSASLconn;
00073 #endif
00074
00075 };
00076
00077 LdapConnection::LdapConnectionPrivate::LdapConnectionPrivate()
00078 {
00079 mSASLconn = 0;
00080 #ifdef SASL2_FOUND
00081 if ( !ldapoperation_sasl_initialized ) {
00082 sasl_client_init(NULL);
00083 ldapoperation_sasl_initialized = true;
00084 }
00085 #endif
00086 }
00087
00088 LdapConnection::LdapConnection()
00089 : d( new LdapConnectionPrivate )
00090 {
00091 d->mLDAP = 0;
00092 }
00093
00094 LdapConnection::LdapConnection( const LdapUrl &url )
00095 : d( new LdapConnectionPrivate )
00096 {
00097 d->mLDAP = 0;
00098 setUrl( url );
00099 }
00100
00101 LdapConnection::LdapConnection( const LdapServer &server )
00102 : d( new LdapConnectionPrivate )
00103 {
00104 d->mLDAP = 0;
00105 setServer( server );
00106 }
00107
00108 LdapConnection::~LdapConnection()
00109 {
00110 close();
00111 delete d;
00112 }
00113
00114 void LdapConnection::setUrl( const LdapUrl &url )
00115 {
00116 d->mServer.setUrl( url );
00117 }
00118
00119 void LdapConnection::setServer( const LdapServer &server )
00120 {
00121 d->mServer = server;
00122 }
00123
00124 const LdapServer &LdapConnection::server() const
00125 {
00126 return d->mServer;
00127 }
00128
00129 void *LdapConnection::handle() const
00130 {
00131 return (void *)d->mLDAP;
00132 }
00133
00134 void *LdapConnection::saslHandle() const
00135 {
00136 return (void *)d->mSASLconn;
00137 }
00138
00139 QString LdapConnection::errorString( int code )
00140 {
00141
00142 #ifdef LDAP_FOUND
00143 return QString::fromUtf8( ldap_err2string( code ) );
00144 switch ( code ) {
00145 case LDAP_OPERATIONS_ERROR:
00146 return i18n( "LDAP Operations error" );
00147
00148
00149 }
00150 #else
00151 return i18n( "No LDAP Support..." );
00152 #endif
00153 }
00154
00155 QString LdapConnection::saslErrorString() const
00156 {
00157 #ifdef SASL2_FOUND
00158 const char *str;
00159 str = sasl_errdetail( d->mSASLconn );
00160 return QString::fromLocal8Bit( str );
00161 #else
00162 return i18n( "SASL support is not available. Please recompile libkldap with the "
00163 "Cyrus-SASL (or compatible) client libraries, or complain to your "
00164 "distribution packagers." );
00165 #endif
00166 }
00167
00168 QString LdapConnection::connectionError() const
00169 {
00170 return d->mConnectionError;
00171 }
00172
00173 #ifdef LDAP_FOUND
00174 int LdapConnection::getOption( int option, void *value ) const
00175 {
00176 Q_ASSERT( d->mLDAP );
00177 return ldap_get_option( d->mLDAP, option, value );
00178 }
00179
00180 int LdapConnection::setOption( int option, void *value )
00181 {
00182 Q_ASSERT( d->mLDAP );
00183 return ldap_set_option( d->mLDAP, option, value );
00184 }
00185
00186 int LdapConnection::ldapErrorCode() const
00187 {
00188 Q_ASSERT( d->mLDAP );
00189 int err;
00190 ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err );
00191 return err;
00192 }
00193
00194 QString LdapConnection::ldapErrorString() const
00195 {
00196 Q_ASSERT( d->mLDAP );
00197 char *errmsg;
00198 ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg );
00199 QString msg = QString::fromLocal8Bit( errmsg );
00200 free( errmsg );
00201 return msg;
00202 }
00203
00204 bool LdapConnection::setSizeLimit( int sizelimit )
00205 {
00206 Q_ASSERT( d->mLDAP );
00207 kDebug() << "sizelimit:" << sizelimit;
00208 if ( setOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
00209 return false;
00210 }
00211 return true;
00212 }
00213
00214 int LdapConnection::sizeLimit() const
00215 {
00216 Q_ASSERT( d->mLDAP );
00217 int sizelimit;
00218 if ( getOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
00219 return -1;
00220 }
00221 return sizelimit;
00222 }
00223
00224 bool LdapConnection::setTimeLimit( int timelimit )
00225 {
00226 Q_ASSERT( d->mLDAP );
00227 kDebug() << "timelimit:" << timelimit;
00228 if ( setOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
00229 return false;
00230 }
00231 return true;
00232 }
00233
00234 int LdapConnection::timeLimit() const
00235 {
00236 Q_ASSERT( d->mLDAP );
00237 int timelimit;
00238 if ( getOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
00239 return -1;
00240 }
00241 return timelimit;
00242 }
00243
00244 int LdapConnection::connect()
00245 {
00246 int ret;
00247 QString url;
00248 if ( d->mLDAP ) {
00249 close();
00250 }
00251
00252 int version = d->mServer.version();
00253 int timeout = d->mServer.timeout();
00254
00255 url = d->mServer.security() == LdapServer::SSL ? "ldaps" : "ldap";
00256 url += "://";
00257 url += d->mServer.host();
00258 url += ':';
00259 url += QString::number( d->mServer.port() );
00260 kDebug() << "ldap url:" << url;
00261 #ifdef HAVE_LDAP_INITIALIZE
00262 ret = ldap_initialize( &d->mLDAP, url.toLatin1() );
00263 #else
00264 d->mLDAP = ldap_init( d->mServer.host().toLatin1().data(), d->mServer.port() );
00265 if ( d->mLDAP == 0 ) {
00266 ret = -1;
00267 }
00268 #endif
00269 if ( ret != LDAP_SUCCESS ) {
00270 d->mConnectionError = i18n( "An error occurred during the connection initialization phase." );
00271 return ret;
00272 }
00273
00274 kDebug() << "setting version to:" << version;
00275 if ( setOption( LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS ) {
00276 ret = ldapErrorCode();
00277 d->mConnectionError = i18n( "Cannot set protocol version to %1.", version );
00278 close();
00279 return ret;
00280 }
00281
00282 #if defined(LDAP_OPT_TIMEOUT)
00283 kDebug() << "setting timeout to:" << timeout;
00284
00285 if ( timeout ) {
00286 if ( setOption( LDAP_OPT_TIMEOUT, &timeout ) != LDAP_OPT_SUCCESS ) {
00287 ret = ldapErrorCode();
00288 d->mConnectionError = i18np( "Cannot set timeout to %1 second.",
00289 "Cannot set timeout to %1 seconds.",
00290 timeout );
00291 close();
00292 return ret;
00293 }
00294 }
00295 #endif
00296
00297
00298 kDebug() << "setting security to:" << d->mServer.security();
00299 if ( d->mServer.security() == LdapServer::TLS ) {
00300 kDebug() << "start TLS";
00301 #ifdef HAVE_LDAP_START_TLS_S
00302 if ( ( ret = ldap_start_tls_s( d->mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) {
00303 d->mConnectionError = ldapErrorString();
00304 close();
00305 return ret;
00306 }
00307 #else
00308 close();
00309 d->mConnectionError = i18n( "TLS support not available in the LDAP client libraries." );
00310 return -1;
00311 #endif
00312 }
00313
00314 kDebug() << "setting sizelimit to:" << d->mServer.sizeLimit();
00315 if ( d->mServer.sizeLimit() ) {
00316 if ( !setSizeLimit( d->mServer.sizeLimit() ) ) {
00317 ret = ldapErrorCode();
00318 close();
00319 d->mConnectionError = i18n( "Cannot set size limit." );
00320 return ret;
00321 }
00322 }
00323
00324 kDebug() << "setting timelimit to:" << d->mServer.timeLimit();
00325 if ( d->mServer.timeLimit() ) {
00326 if ( !setTimeLimit( d->mServer.timeLimit() ) ) {
00327 ret = ldapErrorCode();
00328 close();
00329 d->mConnectionError = i18n( "Cannot set time limit." );
00330 return ret;
00331 }
00332 }
00333
00334 #ifdef SASL2_FOUND
00335 kDebug() << "initializing SASL client";
00336 int saslresult = sasl_client_new( "ldap", d->mServer.host().toLatin1(),
00337 0, 0, callbacks, 0, &d->mSASLconn );
00338 if ( saslresult != SASL_OK ) {
00339 d->mConnectionError = i18n( "Cannot initialize the SASL client." );
00340 return KLDAP_SASL_ERROR;
00341 }
00342 #endif
00343
00344 return 0;
00345 }
00346
00347 void LdapConnection::close()
00348 {
00349 if ( d->mLDAP ) {
00350 #ifdef HAVE_LDAP_UNBIND_EXT
00351 ldap_unbind_ext( d->mLDAP, 0, 0 );
00352 #else
00353 ldap_unbind( d->mLDAP );
00354 #endif
00355 }
00356 d->mLDAP = 0;
00357 #ifdef SASL2_FOUND
00358 if ( d->mSASLconn ) {
00359 sasl_dispose( &d->mSASLconn );
00360 d->mSASLconn = 0;
00361 }
00362 #endif
00363 kDebug() << "connection closed!";
00364 }
00365 #else //LDAP_FOUND
00366
00367 int LdapConnection::getOption( int option, void *value ) const
00368 {
00369 kError() << "No LDAP support...";
00370 return -1;
00371 }
00372
00373 int LdapConnection::setOption( int option, void *value )
00374 {
00375 kError() << "No LDAP support...";
00376 return -1;
00377 }
00378
00379 int LdapConnection::ldapErrorCode() const
00380 {
00381 kError() << "No LDAP support...";
00382 return -1;
00383 }
00384
00385 QString LdapConnection::ldapErrorString() const
00386 {
00387 kError() << "No LDAP support...";
00388 return QString();
00389 }
00390
00391 bool LdapConnection::setSizeLimit( int sizelimit )
00392 {
00393 kError() << "No LDAP support...";
00394 return false;
00395 }
00396
00397 int LdapConnection::sizeLimit() const
00398 {
00399 kError() << "No LDAP support...";
00400 return -1;
00401 }
00402
00403 bool LdapConnection::setTimeLimit( int timelimit )
00404 {
00405 kError() << "No LDAP support...";
00406 return false;
00407 }
00408
00409 int LdapConnection::timeLimit() const
00410 {
00411 kError() << "No LDAP support...";
00412 return -1;
00413 }
00414
00415 int LdapConnection::connect( )
00416 {
00417 d->mConnectionError =
00418 i18n( "LDAP support not compiled in. Please recompile libkldap with the "
00419 "OpenLDAP (or compatible) client libraries, or complain to your "
00420 "distribution packagers." );
00421 kError() << "No LDAP support...";
00422 return -1;
00423 }
00424
00425 void LdapConnection::close()
00426 {
00427 kError() << "No LDAP support...";
00428 }
00429
00430 #endif