00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kldap_config.h"
00022 #include "ldapconnection.h"
00023 #include "ldapdefs.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: return i18n("LDAP Operations error");
00146
00147
00148 }
00149 #else
00150 return i18n("No LDAP Support...");
00151 #endif
00152 }
00153
00154 QString LdapConnection::saslErrorString() const
00155 {
00156 #ifdef SASL2_FOUND
00157 const char *str;
00158 str = sasl_errdetail( d->mSASLconn );
00159 return QString::fromLocal8Bit( str );
00160 #else
00161 return i18n("SASL support is not available...Please recompile libkldap with the "
00162 "Cyrus-SASL (or compatible) client libraries, or complain to your "
00163 "distribution packagers.");
00164 #endif
00165 }
00166
00167 QString LdapConnection::connectionError() const
00168 {
00169 return d->mConnectionError;
00170 }
00171
00172 #ifdef LDAP_FOUND
00173 int LdapConnection::getOption( int option, void *value ) const
00174 {
00175 Q_ASSERT( d->mLDAP );
00176 return ldap_get_option( d->mLDAP, option, value );
00177 }
00178
00179 int LdapConnection::setOption( int option, void *value )
00180 {
00181 Q_ASSERT( d->mLDAP );
00182 return ldap_set_option( d->mLDAP, option, value );
00183 }
00184
00185 int LdapConnection::ldapErrorCode() const
00186 {
00187 Q_ASSERT( d->mLDAP );
00188 int err;
00189 ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err );
00190 return err;
00191 }
00192
00193 QString LdapConnection::ldapErrorString() const
00194 {
00195 Q_ASSERT( d->mLDAP );
00196 char *errmsg;
00197 ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg );
00198 QString msg = QString::fromLocal8Bit( errmsg );
00199 free( errmsg );
00200 return msg;
00201 }
00202
00203 bool LdapConnection::setSizeLimit( int sizelimit )
00204 {
00205 Q_ASSERT( d->mLDAP );
00206 kDebug(5322) << "sizelimit:" << sizelimit;
00207 if ( setOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
00208 return false;
00209 }
00210 return true;
00211 }
00212
00213 int LdapConnection::sizeLimit() const
00214 {
00215 Q_ASSERT( d->mLDAP );
00216 int sizelimit;
00217 if ( getOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
00218 return -1;
00219 }
00220 return sizelimit;
00221 }
00222
00223 bool LdapConnection::setTimeLimit( int timelimit )
00224 {
00225 Q_ASSERT( d->mLDAP );
00226 kDebug(5322) << "timelimit:" << timelimit;
00227 if ( setOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
00228 return false;
00229 }
00230 return true;
00231 }
00232
00233 int LdapConnection::timeLimit() const
00234 {
00235 Q_ASSERT( d->mLDAP );
00236 int timelimit;
00237 if ( getOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
00238 return -1;
00239 }
00240 return timelimit;
00241 }
00242
00243 int LdapConnection::connect()
00244 {
00245 int ret;
00246 QString url;
00247 if ( d->mLDAP ) {
00248 close();
00249 }
00250
00251 int version = d->mServer.version();
00252 int timeout = d->mServer.timeout();
00253
00254 url = d->mServer.security() == LdapServer::SSL ? "ldaps" : "ldap";
00255 url += "://";
00256 url += d->mServer.host();
00257 url += ':';
00258 url += QString::number( d->mServer.port() );
00259 kDebug(5322) << "ldap url:" << url;
00260 #ifdef HAVE_LDAP_INITIALIZE
00261 ret = ldap_initialize( &d->mLDAP, url.toLatin1() );
00262 #else
00263 d->mLDAP = ldap_init( d->mServer.host().toLatin1().data(), d->mServer.port() );
00264 if ( d->mLDAP == 0 ) {
00265 ret = -1;
00266 }
00267 #endif
00268 if ( ret != LDAP_SUCCESS ) {
00269 d->mConnectionError = i18n("An error occurred during the connection initialization phase.");
00270 return ret;
00271 }
00272
00273 kDebug(5322) << "setting version to:" << version;
00274 if ( setOption( LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS ) {
00275 ret = ldapErrorCode();
00276 d->mConnectionError = i18n("Cannot set protocol version to %1.", version );
00277 close();
00278 return ret;
00279 }
00280
00281 #if defined(LDAP_OPT_TIMEOUT)
00282 kDebug(5322) << "setting timeout to:" << timeout;
00283
00284 if ( timeout ) {
00285 if ( setOption( LDAP_OPT_TIMEOUT, &timeout ) != LDAP_OPT_SUCCESS ) {
00286 ret = ldapErrorCode();
00287 d->mConnectionError = i18n("Cannot set timeout to %1 seconds.", timeout );
00288 close();
00289 return ret;
00290 }
00291 }
00292 #endif
00293
00294
00295 kDebug(5322) << "setting security to:" << d->mServer.security();
00296 if ( d->mServer.security() == LdapServer::TLS ) {
00297 kDebug(5322) << "start TLS";
00298 #ifdef HAVE_LDAP_START_TLS_S
00299 if ( ( ret = ldap_start_tls_s( d->mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) {
00300 d->mConnectionError = ldapErrorString();
00301 close();
00302 return ret;
00303 }
00304 #else
00305 close();
00306 d->mConnectionError = i18n("TLS support not available in the LDAP client libraries.");
00307 return -1;
00308 #endif
00309 }
00310
00311 kDebug(5322) << "setting sizelimit to:" << d->mServer.sizeLimit();
00312 if ( d->mServer.sizeLimit() ) {
00313 if ( !setSizeLimit( d->mServer.sizeLimit() ) ) {
00314 ret = ldapErrorCode();
00315 close();
00316 d->mConnectionError = i18n("Cannot set size limit.");
00317 return ret;
00318 }
00319 }
00320
00321 kDebug(5322) << "setting timelimit to:" << d->mServer.timeLimit();
00322 if ( d->mServer.timeLimit() ) {
00323 if ( !setTimeLimit( d->mServer.timeLimit() ) ) {
00324 ret = ldapErrorCode();
00325 close();
00326 d->mConnectionError = i18n("Cannot set time limit.");
00327 return ret;
00328 }
00329 }
00330
00331 #ifdef SASL2_FOUND
00332 kDebug(5322) << "initializing SASL client";
00333 int saslresult = sasl_client_new( "ldap", d->mServer.host().toLatin1(),
00334 0, 0, callbacks, 0, &d->mSASLconn );
00335 if ( saslresult != SASL_OK ) {
00336 d->mConnectionError = i18n("Cannot initialize the SASL client.");
00337 return KLDAP_SASL_ERROR;
00338 }
00339 #endif
00340
00341 return 0;
00342 }
00343
00344 void LdapConnection::close()
00345 {
00346 if ( d->mLDAP ) {
00347 #ifdef HAVE_LDAP_UNBIND_EXT
00348 ldap_unbind_ext( d->mLDAP, 0, 0 );
00349 #else
00350 ldap_unbind( d->mLDAP );
00351 #endif
00352 }
00353 d->mLDAP = 0;
00354 #ifdef SASL2_FOUND
00355 if ( d->mSASLconn ) {
00356 sasl_dispose( &d->mSASLconn );
00357 d->mSASLconn = 0;
00358 }
00359 #endif
00360 kDebug(5322) << "connection closed!";
00361 }
00362 #else //LDAP_FOUND
00363
00364 int LdapConnection::getOption( int option, void *value ) const
00365 {
00366 kError() << "No LDAP support...";
00367 return -1;
00368 }
00369
00370 int LdapConnection::setOption( int option, void *value )
00371 {
00372 kError() << "No LDAP support...";
00373 return -1;
00374 }
00375
00376 int LdapConnection::ldapErrorCode() const
00377 {
00378 kError() << "No LDAP support...";
00379 return -1;
00380 }
00381
00382 QString LdapConnection::ldapErrorString() const
00383 {
00384 kError() << "No LDAP support...";
00385 return QString();
00386 }
00387
00388 bool LdapConnection::setSizeLimit( int sizelimit )
00389 {
00390 kError() << "No LDAP support...";
00391 return false;
00392 }
00393
00394 int LdapConnection::sizeLimit() const
00395 {
00396 kError() << "No LDAP support...";
00397 return -1;
00398 }
00399
00400 bool LdapConnection::setTimeLimit( int timelimit )
00401 {
00402 kError() << "No LDAP support...";
00403 return false;
00404 }
00405
00406 int LdapConnection::timeLimit() const
00407 {
00408 kError() << "No LDAP support...";
00409 return -1;
00410 }
00411
00412 int LdapConnection::connect( )
00413 {
00414 d->mConnectionError =
00415 i18n("LDAP support not compiled in. Please recompile libkldap with the "
00416 "OpenLDAP (or compatible) client libraries, or complain to your "
00417 "distribution packagers.");
00418 kError() << "No LDAP support...";
00419 return -1;
00420 }
00421
00422 void LdapConnection::close()
00423 {
00424 kError() << "No LDAP support...";
00425 }
00426
00427 #endif