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