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 = i18n( "Cannot set timeout to %1 seconds.", timeout );
00289 close();
00290 return ret;
00291 }
00292 }
00293 #endif
00294
00295
00296 kDebug() << "setting security to:" << d->mServer.security();
00297 if ( d->mServer.security() == LdapServer::TLS ) {
00298 kDebug() << "start TLS";
00299 #ifdef HAVE_LDAP_START_TLS_S
00300 if ( ( ret = ldap_start_tls_s( d->mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) {
00301 d->mConnectionError = ldapErrorString();
00302 close();
00303 return ret;
00304 }
00305 #else
00306 close();
00307 d->mConnectionError = i18n( "TLS support not available in the LDAP client libraries." );
00308 return -1;
00309 #endif
00310 }
00311
00312 kDebug() << "setting sizelimit to:" << d->mServer.sizeLimit();
00313 if ( d->mServer.sizeLimit() ) {
00314 if ( !setSizeLimit( d->mServer.sizeLimit() ) ) {
00315 ret = ldapErrorCode();
00316 close();
00317 d->mConnectionError = i18n( "Cannot set size limit." );
00318 return ret;
00319 }
00320 }
00321
00322 kDebug() << "setting timelimit to:" << d->mServer.timeLimit();
00323 if ( d->mServer.timeLimit() ) {
00324 if ( !setTimeLimit( d->mServer.timeLimit() ) ) {
00325 ret = ldapErrorCode();
00326 close();
00327 d->mConnectionError = i18n( "Cannot set time limit." );
00328 return ret;
00329 }
00330 }
00331
00332 #ifdef SASL2_FOUND
00333 kDebug() << "initializing SASL client";
00334 int saslresult = sasl_client_new( "ldap", d->mServer.host().toLatin1(),
00335 0, 0, callbacks, 0, &d->mSASLconn );
00336 if ( saslresult != SASL_OK ) {
00337 d->mConnectionError = i18n( "Cannot initialize the SASL client." );
00338 return KLDAP_SASL_ERROR;
00339 }
00340 #endif
00341
00342 return 0;
00343 }
00344
00345 void LdapConnection::close()
00346 {
00347 if ( d->mLDAP ) {
00348 #ifdef HAVE_LDAP_UNBIND_EXT
00349 ldap_unbind_ext( d->mLDAP, 0, 0 );
00350 #else
00351 ldap_unbind( d->mLDAP );
00352 #endif
00353 }
00354 d->mLDAP = 0;
00355 #ifdef SASL2_FOUND
00356 if ( d->mSASLconn ) {
00357 sasl_dispose( &d->mSASLconn );
00358 d->mSASLconn = 0;
00359 }
00360 #endif
00361 kDebug() << "connection closed!";
00362 }
00363 #else //LDAP_FOUND
00364
00365 int LdapConnection::getOption( int option, void *value ) const
00366 {
00367 kError() << "No LDAP support...";
00368 return -1;
00369 }
00370
00371 int LdapConnection::setOption( int option, void *value )
00372 {
00373 kError() << "No LDAP support...";
00374 return -1;
00375 }
00376
00377 int LdapConnection::ldapErrorCode() const
00378 {
00379 kError() << "No LDAP support...";
00380 return -1;
00381 }
00382
00383 QString LdapConnection::ldapErrorString() const
00384 {
00385 kError() << "No LDAP support...";
00386 return QString();
00387 }
00388
00389 bool LdapConnection::setSizeLimit( int sizelimit )
00390 {
00391 kError() << "No LDAP support...";
00392 return false;
00393 }
00394
00395 int LdapConnection::sizeLimit() const
00396 {
00397 kError() << "No LDAP support...";
00398 return -1;
00399 }
00400
00401 bool LdapConnection::setTimeLimit( int timelimit )
00402 {
00403 kError() << "No LDAP support...";
00404 return false;
00405 }
00406
00407 int LdapConnection::timeLimit() const
00408 {
00409 kError() << "No LDAP support...";
00410 return -1;
00411 }
00412
00413 int LdapConnection::connect( )
00414 {
00415 d->mConnectionError =
00416 i18n( "LDAP support not compiled in. Please recompile libkldap with the "
00417 "OpenLDAP (or compatible) client libraries, or complain to your "
00418 "distribution packagers." );
00419 kError() << "No LDAP support...";
00420 return -1;
00421 }
00422
00423 void LdapConnection::close()
00424 {
00425 kError() << "No LDAP support...";
00426 }
00427
00428 #endif