KLDAP Library
ldapoperation.cpp
00001 /* 00002 This file is part of libkldap. 00003 Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "ldapoperation.h" 00022 #include "kldap_config.h" 00023 00024 #include <kdebug.h> 00025 00026 #include <QtCore/QTime> 00027 00028 #include <stdlib.h> 00029 #ifdef HAVE_SYS_TIME_H 00030 #include <sys/time.h> 00031 #endif 00032 00033 #ifdef SASL2_FOUND 00034 #include <sasl/sasl.h> 00035 #endif 00036 00037 #ifdef LDAP_FOUND 00038 # ifndef HAVE_WINLDAP_H 00039 # include <lber.h> 00040 # include <ldap.h> 00041 # else 00042 # include <w32-ldap-help.h> 00043 # endif // HAVE_WINLDAP_H 00044 #endif // LDAP_FOUND 00045 00046 #include "ldapdefs.h" 00047 00048 using namespace KLDAP; 00049 00050 #ifdef LDAP_FOUND 00051 static void extractControls( LdapControls &ctrls, LDAPControl **pctrls ); 00052 #endif // LDAP_FOUND 00053 00054 /* 00055 Returns the difference between msecs and elapsed. If msecs is -1, 00056 however, -1 is returned. 00057 */ 00058 static int kldap_timeout_value( int msecs, int elapsed ) 00059 { 00060 if ( msecs == -1 ) { 00061 return -1; 00062 } 00063 00064 int timeout = msecs - elapsed; 00065 return timeout < 0 ? 0 : timeout; 00066 } 00067 00068 class LdapOperation::LdapOperationPrivate 00069 { 00070 public: 00071 LdapOperationPrivate(); 00072 ~LdapOperationPrivate(); 00073 #ifdef LDAP_FOUND 00074 int processResult( int rescode, LDAPMessage *msg ); 00075 int bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async ); 00076 #endif 00077 LdapControls mClientCtrls, mServerCtrls, mControls; 00078 LdapObject mObject; 00079 QByteArray mExtOid, mExtData; 00080 QByteArray mServerCred; 00081 QString mMatchedDn; 00082 QList<QByteArray> mReferrals; 00083 00084 LdapConnection *mConnection; 00085 }; 00086 00087 LdapOperation::LdapOperation() 00088 : d( new LdapOperationPrivate ) 00089 { 00090 d->mConnection = 0; 00091 } 00092 00093 LdapOperation::LdapOperation( LdapConnection &conn ) 00094 : d( new LdapOperationPrivate ) 00095 { 00096 setConnection( conn ); 00097 } 00098 00099 LdapOperation::~LdapOperation() 00100 { 00101 delete d; 00102 } 00103 00104 void LdapOperation::setConnection( LdapConnection &conn ) 00105 { 00106 d->mConnection = &conn; 00107 } 00108 00109 LdapConnection &LdapOperation::connection() 00110 { 00111 return *d->mConnection; 00112 } 00113 00114 void LdapOperation::setClientControls( const LdapControls &ctrls ) 00115 { 00116 d->mClientCtrls = ctrls; 00117 } 00118 00119 void LdapOperation::setServerControls( const LdapControls &ctrls ) 00120 { 00121 d->mServerCtrls = ctrls; 00122 } 00123 00124 LdapControls LdapOperation::clientControls() const 00125 { 00126 return d->mClientCtrls; 00127 } 00128 00129 LdapControls LdapOperation::serverControls() const 00130 { 00131 return d->mServerCtrls; 00132 } 00133 00134 LdapObject LdapOperation::object() const 00135 { 00136 return d->mObject; 00137 } 00138 00139 LdapControls LdapOperation::controls() const 00140 { 00141 return d->mControls; 00142 } 00143 00144 QByteArray LdapOperation::extendedOid() const 00145 { 00146 return d->mExtOid; 00147 } 00148 00149 QByteArray LdapOperation::extendedData() const 00150 { 00151 return d->mExtData; 00152 } 00153 00154 QString LdapOperation::matchedDn() const 00155 { 00156 return d->mMatchedDn; 00157 } 00158 00159 QList<QByteArray> LdapOperation::referrals() const 00160 { 00161 return d->mReferrals; 00162 } 00163 00164 QByteArray LdapOperation::serverCred() const 00165 { 00166 return d->mServerCred; 00167 } 00168 00169 LdapOperation::LdapOperationPrivate::LdapOperationPrivate() 00170 { 00171 } 00172 00173 LdapOperation::LdapOperationPrivate::~LdapOperationPrivate() 00174 { 00175 } 00176 00177 #ifdef LDAP_FOUND 00178 00179 #ifdef SASL2_FOUND 00180 static int kldap_sasl_interact( sasl_interact_t *interact, LdapOperation::SASL_Data *data ) 00181 { 00182 if ( data->proc ) { 00183 for ( ; interact->id != SASL_CB_LIST_END; interact++ ) { 00184 switch ( interact->id ) { 00185 case SASL_CB_GETREALM: 00186 data->creds.fields |= LdapOperation::SASL_Realm; 00187 break; 00188 case SASL_CB_AUTHNAME: 00189 data->creds.fields |= LdapOperation::SASL_Authname; 00190 break; 00191 case SASL_CB_PASS: 00192 data->creds.fields |= LdapOperation::SASL_Password; 00193 break; 00194 case SASL_CB_USER: 00195 data->creds.fields |= LdapOperation::SASL_Authzid; 00196 break; 00197 } 00198 } 00199 int retval; 00200 if ( ( retval = data->proc( data->creds, data->data ) ) ) { 00201 return retval; 00202 } 00203 } 00204 00205 QString value; 00206 00207 while ( interact->id != SASL_CB_LIST_END ) { 00208 value.clear(); 00209 switch( interact->id ) { 00210 case SASL_CB_GETREALM: 00211 value = data->creds.realm; 00212 kDebug() << "SASL_REALM=" << value; 00213 break; 00214 case SASL_CB_AUTHNAME: 00215 value = data->creds.authname; 00216 kDebug() << "SASL_AUTHNAME=" << value; 00217 break; 00218 case SASL_CB_PASS: 00219 value = data->creds.password; 00220 kDebug() << "SASL_PASSWD=[hidden]"; 00221 break; 00222 case SASL_CB_USER: 00223 value = data->creds.authzid; 00224 kDebug() << "SASL_AUTHZID=" << value; 00225 break; 00226 } 00227 if ( value.isEmpty() ) { 00228 interact->result = NULL; 00229 interact->len = 0; 00230 } else { 00231 interact->result = strdup( value.toUtf8() ); 00232 interact->len = strlen( (const char *)interact->result ); 00233 } 00234 interact++; 00235 } 00236 return KLDAP_SUCCESS; 00237 } 00238 #endif 00239 00240 int LdapOperation::LdapOperationPrivate::bind( const QByteArray &creds, 00241 SASL_Callback_Proc *saslproc, 00242 void *data, bool async ) 00243 { 00244 Q_ASSERT( mConnection ); 00245 LDAP *ld = (LDAP*) mConnection->handle(); 00246 LdapServer server; 00247 server = mConnection->server(); 00248 00249 int ret; 00250 00251 if ( server.auth() == LdapServer::SASL ) { 00252 #if defined( SASL2_FOUND ) && !defined( HAVE_WINLDAP_H ) 00253 sasl_conn_t *saslconn = (sasl_conn_t *)mConnection->saslHandle(); 00254 sasl_interact_t *client_interact = NULL; 00255 const char *out = NULL; 00256 uint outlen; 00257 const char *mechusing = NULL; 00258 struct berval ccred, *scred; 00259 int saslresult; 00260 QByteArray sdata = creds; 00261 00262 QString mech = server.mech(); 00263 if ( mech.isEmpty() ) { 00264 mech = "DIGEST-MD5"; 00265 } 00266 00267 SASL_Data sasldata; 00268 sasldata.proc = saslproc; 00269 sasldata.data = data; 00270 sasldata.creds.fields = 0; 00271 sasldata.creds.realm = server.realm(); 00272 sasldata.creds.authname = server.user(); 00273 sasldata.creds.authzid = server.bindDn(); 00274 sasldata.creds.password = server.password(); 00275 00276 do { 00277 if ( sdata.isEmpty() ) { 00278 do { 00279 saslresult = sasl_client_start( saslconn, mech.toLatin1(), 00280 &client_interact, &out, &outlen, &mechusing ); 00281 00282 if ( saslresult == SASL_INTERACT ) { 00283 if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) { 00284 return KLDAP_SASL_ERROR; 00285 } 00286 } 00287 kDebug() << "sasl_client_start mech: " 00288 << mechusing << " outlen " << outlen 00289 << " result: " << saslresult; 00290 } while ( saslresult == SASL_INTERACT ); 00291 if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) { 00292 return KLDAP_SASL_ERROR; 00293 } 00294 00295 } else { 00296 kDebug() << "sasl_client_step"; 00297 do { 00298 saslresult = sasl_client_step( saslconn, sdata.data(), sdata.size(), 00299 &client_interact, &out, &outlen ); 00300 if ( saslresult == SASL_INTERACT ) { 00301 if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) { 00302 return KLDAP_SASL_ERROR; 00303 } 00304 } 00305 } while ( saslresult == SASL_INTERACT ); 00306 kDebug() << "sasl_client_step result" << saslresult; 00307 if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) { 00308 return KLDAP_SASL_ERROR; 00309 } 00310 } 00311 00312 ccred.bv_val = (char*) out; 00313 ccred.bv_len = outlen; 00314 00315 if ( async ) { 00316 kDebug() << "ldap_sasl_bind"; 00317 int msgid; 00318 ret = 00319 ldap_sasl_bind( ld, server.bindDn().toUtf8().data(), mech.toLatin1(), 00320 &ccred, 0, 0, &msgid ); 00321 if ( ret == 0 ) { 00322 ret = msgid; 00323 } 00324 kDebug() << "ldap_sasl_bind msgid" << ret; 00325 } else { 00326 kDebug() << "ldap_sasl_bind_s"; 00327 ret = 00328 ldap_sasl_bind_s( ld, server.bindDn().toUtf8().data(), mech.toLatin1(), 00329 &ccred, 0, 0, &scred ); 00330 kDebug() << "ldap_sasl_bind_s ret" << ret; 00331 if ( scred ) { 00332 sdata = QByteArray( scred->bv_val, scred->bv_len ); 00333 } else { 00334 sdata = QByteArray(); 00335 } 00336 } 00337 } while ( !async && ret == KLDAP_SASL_BIND_IN_PROGRESS ); 00338 #else 00339 kError() << "SASL authentication is not available " 00340 << "(re-compile kldap with cyrus-sasl and OpenLDAP development)."; 00341 return KLDAP_SASL_ERROR; 00342 #endif 00343 } else { //simple auth 00344 QByteArray bindname, pass; 00345 struct berval ccred; 00346 if ( server.auth() == LdapServer::Simple ) { 00347 bindname = server.bindDn().toUtf8(); 00348 pass = server.password().toUtf8(); 00349 } 00350 ccred.bv_val = pass.data(); 00351 ccred.bv_len = pass.size(); 00352 kDebug() << "binding to server, bindname: " << bindname << " password: *****"; 00353 00354 if ( async ) { 00355 kDebug() << "ldap_sasl_bind (simple)"; 00356 #ifndef HAVE_WINLDAP_H 00357 int msgid = 0; 00358 ret = ldap_sasl_bind( ld, bindname.data(), 0, &ccred, 0, 0, &msgid ); 00359 if ( ret == 0 ) { 00360 ret = msgid; 00361 } 00362 #else 00363 ret = ldap_simple_bind( ld, bindname.data(), pass.data() ); 00364 #endif 00365 } else { 00366 kDebug() << "ldap_sasl_bind_s (simple)"; 00367 #ifndef HAVE_WINLDAP_H 00368 ret = ldap_sasl_bind_s( ld, bindname.data(), 0, &ccred, 0, 0, 0 ); 00369 #else 00370 ret = ldap_simple_bind_s( ld, bindname.data(), pass.data() ); 00371 #endif 00372 } 00373 } 00374 return ret; 00375 } 00376 00377 int LdapOperation::LdapOperationPrivate::processResult( int rescode, LDAPMessage *msg ) 00378 { 00379 //kDebug(); 00380 int retval; 00381 LDAP *ld = (LDAP*) mConnection->handle(); 00382 00383 kDebug() << "rescode: " << rescode; 00384 switch ( rescode ) { 00385 case RES_SEARCH_ENTRY: 00386 { 00387 //kDebug() << "Found search entry"; 00388 mObject.clear(); 00389 LdapAttrMap attrs; 00390 char *name; 00391 struct berval **bvals; 00392 BerElement *entry; 00393 00394 char *dn = ldap_get_dn( ld, msg ); 00395 mObject.setDn( QString::fromUtf8( dn ) ); 00396 ldap_memfree( dn ); 00397 00398 // iterate over the attributes 00399 name = ldap_first_attribute( ld, msg, &entry ); 00400 while ( name != 0 ) { 00401 // print the values 00402 bvals = ldap_get_values_len( ld, msg, name ); 00403 LdapAttrValue values; 00404 if ( bvals ) { 00405 for ( int i = 0; bvals[i] != 0; i++ ) { 00406 char *val = bvals[i]->bv_val; 00407 unsigned long len = bvals[i]->bv_len; 00408 values.append( QByteArray( val, len ) ); 00409 } 00410 ldap_value_free_len( bvals ); 00411 } 00412 attrs[ QString::fromLatin1( name ) ] = values; 00413 ldap_memfree( name ); 00414 00415 // next attribute 00416 name = ldap_next_attribute( ld, msg, entry ); 00417 } 00418 ber_free( entry, 0 ); 00419 mObject.setAttributes( attrs ); 00420 break; 00421 } 00422 case RES_SEARCH_REFERENCE: 00423 // Will only get this if following references is disabled. ignore it 00424 rescode = 0; 00425 break; 00426 case RES_EXTENDED: 00427 { 00428 char *retoid; 00429 struct berval *retdata; 00430 retval = ldap_parse_extended_result( ld, msg, &retoid, &retdata, 0 ); 00431 if ( retval != KLDAP_SUCCESS ) { 00432 ldap_msgfree( msg ); 00433 return -1; 00434 } 00435 mExtOid = retoid ? QByteArray( retoid ) : QByteArray(); 00436 mExtData = retdata ? QByteArray( retdata->bv_val, retdata->bv_len ) : QByteArray(); 00437 ldap_memfree( retoid ); 00438 ber_bvfree( retdata ); 00439 break; 00440 } 00441 case RES_BIND: 00442 { 00443 struct berval *servercred = 0; 00444 #ifndef HAVE_WINLDAP_H 00445 // FIXME: Error handling Winldap does not have ldap_parse_sasl_bind_result 00446 retval = ldap_parse_sasl_bind_result( ld, msg, &servercred, 0 ); 00447 #else 00448 retval = KLDAP_SUCCESS; 00449 #endif 00450 if ( retval != KLDAP_SUCCESS && retval != KLDAP_SASL_BIND_IN_PROGRESS ) { 00451 kDebug() << "RES_BIND error: " << retval; 00452 ldap_msgfree( msg ); 00453 return -1; 00454 } 00455 kDebug() << "RES_BIND rescode" << rescode << "retval:" << retval; 00456 if ( servercred ) { 00457 mServerCred = QByteArray( servercred->bv_val, servercred->bv_len ); 00458 ber_bvfree( servercred ); 00459 } else { 00460 mServerCred = QByteArray(); 00461 } 00462 break; 00463 } 00464 default: 00465 { 00466 LDAPControl **serverctrls = 0; 00467 char *matcheddn = 0, *errmsg = 0; 00468 char **referralsp; 00469 int errcodep; 00470 retval = 00471 ldap_parse_result( ld, msg, &errcodep, &matcheddn, &errmsg, &referralsp, 00472 &serverctrls, 0 ); 00473 kDebug() << "rescode" << rescode << "retval:" << retval 00474 << "matcheddn:" << matcheddn << "errcode:" 00475 << errcodep << "errmsg:" << errmsg; 00476 if ( retval != KLDAP_SUCCESS ) { 00477 ldap_msgfree( msg ); 00478 return -1; 00479 } 00480 mControls.clear(); 00481 if ( serverctrls ) { 00482 extractControls( mControls, serverctrls ); 00483 ldap_controls_free( serverctrls ); 00484 } 00485 mReferrals.clear(); 00486 if ( referralsp ) { 00487 char **tmp = referralsp; 00488 while ( *tmp ) { 00489 mReferrals.append( QByteArray( *tmp ) ); 00490 ldap_memfree( *tmp ); 00491 tmp++; 00492 } 00493 ldap_memfree( (char *) referralsp ); 00494 } 00495 mMatchedDn.clear(); 00496 if ( matcheddn ) { 00497 mMatchedDn = QString::fromUtf8( matcheddn ); 00498 ldap_memfree( matcheddn ); 00499 } 00500 if ( errmsg ) { 00501 ldap_memfree( errmsg ); 00502 } 00503 } 00504 } 00505 00506 ldap_msgfree( msg ); 00507 00508 return rescode; 00509 } 00510 00511 static void addModOp( LDAPMod ***pmods, int mod_type, const QString &attr, 00512 const QByteArray *value = 0 ) 00513 { 00514 // kDebug() << "type:" << mod_type << "attr:" << attr << 00515 // "value:" << QString::fromUtf8(value,value.size()) << 00516 // "size:" << value.size(); 00517 LDAPMod **mods; 00518 00519 mods = *pmods; 00520 00521 uint i = 0; 00522 00523 if ( mods == 0 ) { 00524 mods = (LDAPMod **)malloc( 2 * sizeof( LDAPMod * ) ); 00525 mods[ 0 ] = (LDAPMod *)malloc( sizeof( LDAPMod ) ); 00526 mods[ 1 ] = 0; 00527 memset( mods[ 0 ], 0, sizeof( LDAPMod ) ); 00528 } else { 00529 while ( mods[ i ] != 0 && 00530 ( strcmp( attr.toUtf8(), mods[i]->mod_type ) != 0 || 00531 ( mods[ i ]->mod_op & ~LDAP_MOD_BVALUES ) != mod_type ) ) i++; 00532 00533 if ( mods[ i ] == 0 ) { 00534 mods = (LDAPMod **)realloc( mods, ( i + 2 ) * sizeof( LDAPMod * ) ); 00535 if ( mods == 0 ) { 00536 kError() << "addModOp: realloc"; 00537 return; 00538 } 00539 mods[ i + 1 ] = 0; 00540 mods[ i ] = (LDAPMod *) malloc( sizeof( LDAPMod ) ); 00541 memset( mods[ i ], 0, sizeof( LDAPMod ) ); 00542 } 00543 } 00544 00545 mods[ i ]->mod_op = mod_type | LDAP_MOD_BVALUES; 00546 if ( mods[ i ]->mod_type == 0 ) { 00547 mods[ i ]->mod_type = strdup( attr.toUtf8() ); 00548 } 00549 00550 *pmods = mods; 00551 00552 if ( value == 0 ) { 00553 return; 00554 } 00555 00556 int vallen = value->size(); 00557 BerValue *berval; 00558 berval = (BerValue *) malloc( sizeof( BerValue ) ); 00559 berval -> bv_len = vallen; 00560 if ( vallen > 0 ) { 00561 berval -> bv_val = (char *) malloc( vallen ); 00562 memcpy( berval -> bv_val, value->data(), vallen ); 00563 } else { 00564 berval -> bv_val = 0; 00565 } 00566 00567 if ( mods[ i ] -> mod_vals.modv_bvals == 0 ) { 00568 mods[ i ]->mod_vals.modv_bvals = 00569 (BerValue **) malloc( sizeof( BerValue * ) * 2 ); 00570 mods[ i ]->mod_vals.modv_bvals[ 0 ] = berval; 00571 mods[ i ]->mod_vals.modv_bvals[ 1 ] = 0; 00572 // kDebug() << "new bervalue struct" << attr << value; 00573 } else { 00574 uint j = 0; 00575 while ( mods[ i ]->mod_vals.modv_bvals[ j ] != 0 ) { 00576 j++; 00577 } 00578 mods[ i ]->mod_vals.modv_bvals = 00579 (BerValue **)realloc( mods[ i ]->mod_vals.modv_bvals, 00580 ( j + 2 ) * sizeof( BerValue * ) ); 00581 if ( mods[ i ]->mod_vals.modv_bvals == 0 ) { 00582 kError() << "addModOp: realloc"; 00583 free( berval ); 00584 return; 00585 } 00586 mods[ i ]->mod_vals.modv_bvals[ j ] = berval; 00587 mods[ i ]->mod_vals.modv_bvals[ j+1 ] = 0; 00588 kDebug() << j << ". new bervalue"; 00589 } 00590 } 00591 00592 static void addControlOp( LDAPControl ***pctrls, const QString &oid, 00593 const QByteArray &value, bool critical ) 00594 { 00595 LDAPControl **ctrls; 00596 LDAPControl *ctrl = (LDAPControl *) malloc( sizeof( LDAPControl ) ); 00597 00598 ctrls = *pctrls; 00599 00600 kDebug() << "oid:'" << oid << "' val: '" << value << "'"; 00601 int vallen = value.size(); 00602 ctrl->ldctl_value.bv_len = vallen; 00603 if ( vallen ) { 00604 ctrl->ldctl_value.bv_val = (char *) malloc( vallen ); 00605 memcpy( ctrl->ldctl_value.bv_val, value.data(), vallen ); 00606 } else { 00607 ctrl->ldctl_value.bv_val = 0; 00608 } 00609 ctrl->ldctl_iscritical = critical; 00610 ctrl->ldctl_oid = strdup( oid.toUtf8() ); 00611 00612 uint i = 0; 00613 00614 if ( ctrls == 0 ) { 00615 ctrls = (LDAPControl **)malloc ( 2 * sizeof( LDAPControl * ) ); 00616 ctrls[ 0 ] = 0; 00617 ctrls[ 1 ] = 0; 00618 } else { 00619 while ( ctrls[ i ] != 0 ) { 00620 i++; 00621 } 00622 ctrls[ i + 1 ] = 0; 00623 ctrls = 00624 (LDAPControl **)realloc( ctrls, ( i + 2 ) * sizeof( LDAPControl * ) ); 00625 } 00626 ctrls[ i ] = ctrl; 00627 *pctrls = ctrls; 00628 } 00629 00630 static void createControls( LDAPControl ***pctrls, const LdapControls &ctrls ) 00631 { 00632 for ( int i = 0; i< ctrls.count(); ++i ) { 00633 addControlOp( pctrls, ctrls[i].oid(), ctrls[i].value(), ctrls[i].critical() ); 00634 } 00635 } 00636 00637 static void extractControls( LdapControls &ctrls, LDAPControl **pctrls ) 00638 { 00639 LDAPControl *ctrl; 00640 LdapControl control; 00641 int i = 0; 00642 00643 while ( pctrls[i] ) { 00644 ctrl = pctrls[ i ]; 00645 control.setOid( QString::fromUtf8( ctrl->ldctl_oid ) ); 00646 control.setValue( QByteArray( ctrl->ldctl_value.bv_val, 00647 ctrl->ldctl_value.bv_len ) ); 00648 control.setCritical( ctrl->ldctl_iscritical ); 00649 ctrls.append( control ); 00650 i++; 00651 } 00652 } 00653 00654 int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data ) 00655 { 00656 return d->bind( creds, saslproc, data, true ); 00657 } 00658 00659 int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data ) 00660 { 00661 return d->bind( QByteArray(), saslproc, data, false ); 00662 } 00663 00664 int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope, 00665 const QString &filter, const QStringList &attributes ) 00666 { 00667 Q_ASSERT( d->mConnection ); 00668 LDAP *ld = (LDAP*) d->mConnection->handle(); 00669 00670 char **attrs = 0; 00671 int msgid; 00672 00673 LDAPControl **serverctrls = 0, **clientctrls = 0; 00674 createControls( &serverctrls, d->mServerCtrls ); 00675 createControls( &serverctrls, d->mClientCtrls ); 00676 00677 int count = attributes.count(); 00678 if ( count > 0 ) { 00679 attrs = static_cast<char**>( malloc( ( count + 1 ) * sizeof( char * ) ) ); 00680 for ( int i=0; i<count; i++ ) { 00681 attrs[i] = strdup( attributes.at(i).toUtf8() ); 00682 } 00683 attrs[count] = 0; 00684 } 00685 00686 int lscope = LDAP_SCOPE_BASE; 00687 switch ( scope ) { 00688 case LdapUrl::Base: 00689 lscope = LDAP_SCOPE_BASE; 00690 break; 00691 case LdapUrl::One: 00692 lscope = LDAP_SCOPE_ONELEVEL; 00693 break; 00694 case LdapUrl::Sub: 00695 lscope = LDAP_SCOPE_SUBTREE; 00696 break; 00697 } 00698 00699 kDebug() << "asyncSearch() base=\"" << base.toString() 00700 << "\" scope=" << (int)scope 00701 << "filter=\"" << filter 00702 << "\" attrs=" << attributes; 00703 int retval = 00704 ldap_search_ext( ld, base.toString().toUtf8().data(), lscope, 00705 filter.isEmpty() ? QByteArray( "objectClass=*" ).data() : 00706 filter.toUtf8().data(), 00707 attrs, 0, serverctrls, clientctrls, 0, 00708 d->mConnection->sizeLimit(), &msgid ); 00709 00710 ldap_controls_free( serverctrls ); 00711 ldap_controls_free( clientctrls ); 00712 00713 // free the attributes list again 00714 if ( count > 0 ) { 00715 for ( int i=0; i<count; i++ ) { 00716 free( attrs[i] ); 00717 } 00718 free( attrs ); 00719 } 00720 00721 if ( retval == 0 ) { 00722 retval = msgid; 00723 } 00724 return retval; 00725 } 00726 00727 int LdapOperation::add( const LdapObject &object ) 00728 { 00729 Q_ASSERT( d->mConnection ); 00730 LDAP *ld = (LDAP*) d->mConnection->handle(); 00731 00732 int msgid; 00733 LDAPMod **lmod = 0; 00734 00735 LDAPControl **serverctrls = 0, **clientctrls = 0; 00736 createControls( &serverctrls, d->mServerCtrls ); 00737 createControls( &serverctrls, d->mClientCtrls ); 00738 00739 for ( LdapAttrMap::ConstIterator it = object.attributes().begin(); 00740 it != object.attributes().end(); ++it ) { 00741 QString attr = it.key(); 00742 for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) { 00743 addModOp( &lmod, 0, attr, &(*it2) ); 00744 } 00745 } 00746 00747 int retval = 00748 ldap_add_ext( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls, 00749 clientctrls, &msgid ); 00750 00751 ldap_controls_free( serverctrls ); 00752 ldap_controls_free( clientctrls ); 00753 ldap_mods_free( lmod, 1 ); 00754 if ( retval == 0 ) { 00755 retval = msgid; 00756 } 00757 return retval; 00758 } 00759 00760 int LdapOperation::add_s( const LdapObject &object ) 00761 { 00762 Q_ASSERT( d->mConnection ); 00763 LDAP *ld = (LDAP*) d->mConnection->handle(); 00764 00765 LDAPMod **lmod = 0; 00766 00767 LDAPControl **serverctrls = 0, **clientctrls = 0; 00768 createControls( &serverctrls, d->mServerCtrls ); 00769 createControls( &serverctrls, d->mClientCtrls ); 00770 00771 for ( LdapAttrMap::ConstIterator it = object.attributes().begin(); 00772 it != object.attributes().end(); ++it ) { 00773 QString attr = it.key(); 00774 for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) { 00775 addModOp( &lmod, 0, attr, &(*it2) ); 00776 } 00777 } 00778 00779 int retval = 00780 ldap_add_ext_s( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls, 00781 clientctrls ); 00782 00783 ldap_controls_free( serverctrls ); 00784 ldap_controls_free( clientctrls ); 00785 ldap_mods_free( lmod, 1 ); 00786 return retval; 00787 } 00788 00789 int LdapOperation::add( const LdapDN &dn, const ModOps &ops ) 00790 { 00791 Q_ASSERT( d->mConnection ); 00792 LDAP *ld = (LDAP*) d->mConnection->handle(); 00793 00794 int msgid; 00795 LDAPMod **lmod = 0; 00796 00797 LDAPControl **serverctrls = 0, **clientctrls = 0; 00798 createControls( &serverctrls, d->mServerCtrls ); 00799 createControls( &serverctrls, d->mClientCtrls ); 00800 00801 for ( int i = 0; i < ops.count(); ++i ) { 00802 for ( int j = 0; j < ops[i].values.count(); ++j ) { 00803 addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] ); 00804 } 00805 } 00806 00807 int retval = 00808 ldap_add_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls, 00809 clientctrls, &msgid ); 00810 00811 ldap_controls_free( serverctrls ); 00812 ldap_controls_free( clientctrls ); 00813 ldap_mods_free( lmod, 1 ); 00814 if ( retval == 0 ) { 00815 retval = msgid; 00816 } 00817 return retval; 00818 } 00819 00820 int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops ) 00821 { 00822 Q_ASSERT( d->mConnection ); 00823 LDAP *ld = (LDAP*) d->mConnection->handle(); 00824 00825 LDAPMod **lmod = 0; 00826 00827 LDAPControl **serverctrls = 0, **clientctrls = 0; 00828 createControls( &serverctrls, d->mServerCtrls ); 00829 createControls( &serverctrls, d->mClientCtrls ); 00830 00831 for ( int i = 0; i < ops.count(); ++i ) { 00832 for ( int j = 0; j < ops[i].values.count(); ++j ) { 00833 addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] ); 00834 } 00835 } 00836 kDebug() << dn.toString(); 00837 int retval = 00838 ldap_add_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls, 00839 clientctrls ); 00840 00841 ldap_controls_free( serverctrls ); 00842 ldap_controls_free( clientctrls ); 00843 ldap_mods_free( lmod, 1 ); 00844 return retval; 00845 } 00846 00847 int LdapOperation::rename( const LdapDN &dn, const QString &newRdn, 00848 const QString &newSuperior, bool deleteold ) 00849 { 00850 Q_ASSERT( d->mConnection ); 00851 LDAP *ld = (LDAP*) d->mConnection->handle(); 00852 00853 int msgid; 00854 00855 LDAPControl **serverctrls = 0, **clientctrls = 0; 00856 createControls( &serverctrls, d->mServerCtrls ); 00857 createControls( &serverctrls, d->mClientCtrls ); 00858 00859 int retval = ldap_rename( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(), 00860 newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(), 00861 deleteold, serverctrls, clientctrls, &msgid ); 00862 00863 ldap_controls_free( serverctrls ); 00864 ldap_controls_free( clientctrls ); 00865 00866 if ( retval == 0 ) { 00867 retval = msgid; 00868 } 00869 return retval; 00870 } 00871 00872 int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn, 00873 const QString &newSuperior, bool deleteold ) 00874 { 00875 Q_ASSERT( d->mConnection ); 00876 LDAP *ld = (LDAP*) d->mConnection->handle(); 00877 00878 LDAPControl **serverctrls = 0, **clientctrls = 0; 00879 createControls( &serverctrls, d->mServerCtrls ); 00880 createControls( &serverctrls, d->mClientCtrls ); 00881 00882 int retval = ldap_rename_s( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(), 00883 newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(), 00884 deleteold, serverctrls, clientctrls ); 00885 00886 ldap_controls_free( serverctrls ); 00887 ldap_controls_free( clientctrls ); 00888 00889 return retval; 00890 } 00891 00892 int LdapOperation::del( const LdapDN &dn ) 00893 { 00894 Q_ASSERT( d->mConnection ); 00895 LDAP *ld = (LDAP*) d->mConnection->handle(); 00896 00897 int msgid; 00898 00899 LDAPControl **serverctrls = 0, **clientctrls = 0; 00900 createControls( &serverctrls, d->mServerCtrls ); 00901 createControls( &serverctrls, d->mClientCtrls ); 00902 00903 int retval = 00904 ldap_delete_ext( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls, &msgid ); 00905 00906 ldap_controls_free( serverctrls ); 00907 ldap_controls_free( clientctrls ); 00908 00909 if ( retval == 0 ) { 00910 retval = msgid; 00911 } 00912 return retval; 00913 } 00914 00915 int LdapOperation::del_s( const LdapDN &dn ) 00916 { 00917 Q_ASSERT( d->mConnection ); 00918 LDAP *ld = (LDAP*) d->mConnection->handle(); 00919 00920 LDAPControl **serverctrls = 0, **clientctrls = 0; 00921 createControls( &serverctrls, d->mServerCtrls ); 00922 createControls( &serverctrls, d->mClientCtrls ); 00923 00924 int retval = ldap_delete_ext_s( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls ); 00925 00926 ldap_controls_free( serverctrls ); 00927 ldap_controls_free( clientctrls ); 00928 00929 return retval; 00930 } 00931 00932 int LdapOperation::modify( const LdapDN &dn, const ModOps &ops ) 00933 { 00934 Q_ASSERT( d->mConnection ); 00935 LDAP *ld = (LDAP *)d->mConnection->handle(); 00936 00937 int msgid; 00938 LDAPMod **lmod = 0; 00939 00940 LDAPControl **serverctrls = 0, **clientctrls = 0; 00941 createControls( &serverctrls, d->mServerCtrls ); 00942 createControls( &serverctrls, d->mClientCtrls ); 00943 00944 for ( int i = 0; i < ops.count(); ++i ) { 00945 int mtype = 0; 00946 switch ( ops[i].type ) { 00947 case Mod_None: 00948 mtype = 0; 00949 break; 00950 case Mod_Add: 00951 mtype = LDAP_MOD_ADD; 00952 break; 00953 case Mod_Replace: 00954 mtype = LDAP_MOD_REPLACE; 00955 break; 00956 case Mod_Del: 00957 mtype = LDAP_MOD_DELETE; 00958 break; 00959 } 00960 addModOp( &lmod, mtype, ops[i].attr, 0 ); 00961 for ( int j = 0; j < ops[i].values.count(); ++j ) { 00962 addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] ); 00963 } 00964 } 00965 00966 int retval = 00967 ldap_modify_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid ); 00968 00969 ldap_controls_free( serverctrls ); 00970 ldap_controls_free( clientctrls ); 00971 ldap_mods_free( lmod, 1 ); 00972 if ( retval == 0 ) { 00973 retval = msgid; 00974 } 00975 return retval; 00976 } 00977 00978 int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops ) 00979 { 00980 Q_ASSERT( d->mConnection ); 00981 LDAP *ld = (LDAP*) d->mConnection->handle(); 00982 00983 LDAPMod **lmod = 0; 00984 00985 LDAPControl **serverctrls = 0, **clientctrls = 0; 00986 createControls( &serverctrls, d->mServerCtrls ); 00987 createControls( &serverctrls, d->mClientCtrls ); 00988 00989 for ( int i = 0; i < ops.count(); ++i ) { 00990 int mtype = 0; 00991 switch ( ops[i].type ) { 00992 case Mod_None: 00993 mtype = 0; 00994 break; 00995 case Mod_Add: 00996 mtype = LDAP_MOD_ADD; 00997 break; 00998 case Mod_Replace: 00999 mtype = LDAP_MOD_REPLACE; 01000 break; 01001 case Mod_Del: 01002 mtype = LDAP_MOD_DELETE; 01003 break; 01004 } 01005 addModOp( &lmod, mtype, ops[i].attr, 0 ); 01006 for ( int j = 0; j < ops[i].values.count(); ++j ) { 01007 addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] ); 01008 } 01009 } 01010 01011 int retval = 01012 ldap_modify_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls ); 01013 01014 ldap_controls_free( serverctrls ); 01015 ldap_controls_free( clientctrls ); 01016 ldap_mods_free( lmod, 1 ); 01017 return retval; 01018 } 01019 01020 int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value ) 01021 { 01022 Q_ASSERT( d->mConnection ); 01023 LDAP *ld = (LDAP*) d->mConnection->handle(); 01024 int msgid; 01025 01026 LDAPControl **serverctrls = 0, **clientctrls = 0; 01027 createControls( &serverctrls, d->mServerCtrls ); 01028 createControls( &serverctrls, d->mClientCtrls ); 01029 01030 int vallen = value.size(); 01031 BerValue *berval; 01032 berval = (BerValue *) malloc( sizeof( BerValue ) ); 01033 berval -> bv_val = (char *) malloc( vallen ); 01034 berval -> bv_len = vallen; 01035 memcpy( berval -> bv_val, value.data(), vallen ); 01036 01037 int retval = ldap_compare_ext( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval, 01038 serverctrls, clientctrls, &msgid ); 01039 01040 ber_bvfree( berval ); 01041 ldap_controls_free( serverctrls ); 01042 ldap_controls_free( clientctrls ); 01043 01044 if ( retval == 0 ) { 01045 retval = msgid; 01046 } 01047 return retval; 01048 } 01049 01050 int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value ) 01051 { 01052 Q_ASSERT( d->mConnection ); 01053 LDAP *ld = (LDAP*) d->mConnection->handle(); 01054 01055 LDAPControl **serverctrls = 0, **clientctrls = 0; 01056 createControls( &serverctrls, d->mServerCtrls ); 01057 createControls( &serverctrls, d->mClientCtrls ); 01058 01059 int vallen = value.size(); 01060 BerValue *berval; 01061 berval = (BerValue *) malloc( sizeof( BerValue ) ); 01062 berval -> bv_val = (char *) malloc( vallen ); 01063 berval -> bv_len = vallen; 01064 memcpy( berval -> bv_val, value.data(), vallen ); 01065 01066 int retval = ldap_compare_ext_s( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval, 01067 serverctrls, clientctrls ); 01068 01069 ber_bvfree( berval ); 01070 ldap_controls_free( serverctrls ); 01071 ldap_controls_free( clientctrls ); 01072 01073 return retval; 01074 } 01075 01076 int LdapOperation::exop( const QString &oid, const QByteArray &data ) 01077 { 01078 Q_ASSERT( d->mConnection ); 01079 #if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE) 01080 LDAP *ld = (LDAP*) d->mConnection->handle(); 01081 int msgid; 01082 01083 LDAPControl **serverctrls = 0, **clientctrls = 0; 01084 createControls( &serverctrls, d->mServerCtrls ); 01085 createControls( &serverctrls, d->mClientCtrls ); 01086 01087 int vallen = data.size(); 01088 BerValue *berval; 01089 berval = (BerValue *) malloc( sizeof( BerValue ) ); 01090 berval -> bv_val = (char *) malloc( vallen ); 01091 berval -> bv_len = vallen; 01092 memcpy( berval -> bv_val, data.data(), vallen ); 01093 01094 int retval = ldap_extended_operation( ld, oid.toUtf8().data(), berval, 01095 serverctrls, clientctrls, &msgid ); 01096 01097 ber_bvfree( berval ); 01098 ldap_controls_free( serverctrls ); 01099 ldap_controls_free( clientctrls ); 01100 01101 if ( retval == 0 ) { 01102 retval = msgid; 01103 } 01104 return retval; 01105 #else 01106 kError() << "Your LDAP client libraries don't support extended operations."; 01107 return -1; 01108 #endif 01109 } 01110 01111 int LdapOperation::exop_s( const QString &oid, const QByteArray &data ) 01112 { 01113 #if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE) 01114 Q_ASSERT( d->mConnection ); 01115 LDAP *ld = (LDAP*) d->mConnection->handle(); 01116 BerValue *retdata; 01117 char *retoid; 01118 01119 LDAPControl **serverctrls = 0, **clientctrls = 0; 01120 createControls( &serverctrls, d->mServerCtrls ); 01121 createControls( &serverctrls, d->mClientCtrls ); 01122 01123 int vallen = data.size(); 01124 BerValue *berval; 01125 berval = (BerValue *) malloc( sizeof( BerValue ) ); 01126 berval -> bv_val = (char *) malloc( vallen ); 01127 berval -> bv_len = vallen; 01128 memcpy( berval -> bv_val, data.data(), vallen ); 01129 01130 int retval = ldap_extended_operation_s( ld, oid.toUtf8().data(), berval, 01131 serverctrls, clientctrls, &retoid, &retdata ); 01132 01133 ber_bvfree( berval ); 01134 ber_bvfree( retdata ); 01135 free( retoid ); 01136 ldap_controls_free( serverctrls ); 01137 ldap_controls_free( clientctrls ); 01138 01139 return retval; 01140 #else 01141 kError() << "Your LDAP client libraries don't support extended operations."; 01142 return -1; 01143 #endif 01144 } 01145 01146 int LdapOperation::abandon( int id ) 01147 { 01148 Q_ASSERT( d->mConnection ); 01149 LDAP *ld = (LDAP*) d->mConnection->handle(); 01150 01151 LDAPControl **serverctrls = 0, **clientctrls = 0; 01152 createControls( &serverctrls, d->mServerCtrls ); 01153 createControls( &serverctrls, d->mClientCtrls ); 01154 01155 int retval = ldap_abandon_ext( ld, id, serverctrls, clientctrls ); 01156 01157 ldap_controls_free( serverctrls ); 01158 ldap_controls_free( clientctrls ); 01159 01160 return retval; 01161 } 01162 01163 int LdapOperation::waitForResult( int id, int msecs ) 01164 { 01165 Q_ASSERT( d->mConnection ); 01166 LDAP *ld = (LDAP*) d->mConnection->handle(); 01167 01168 LDAPMessage *msg; 01169 int rescode; 01170 01171 QTime stopWatch; 01172 stopWatch.start(); 01173 int attempt( 1 ); 01174 int timeout( 0 ); 01175 01176 do { 01177 // Calculate the timeout value to use and assign it to a timeval structure 01178 // see man select (2) for details 01179 timeout = kldap_timeout_value( msecs, stopWatch.elapsed() ); 01180 kDebug() << "(" << id << "," << msecs 01181 << "): Waiting" << timeout 01182 << "msecs for result. Attempt #" << attempt++; 01183 struct timeval tv; 01184 tv.tv_sec = timeout / 1000; 01185 tv.tv_usec = ( timeout % 1000 ) * 1000; 01186 01187 // Wait for a result 01188 rescode = ldap_result( ld, id, 0, timeout < 0 ? 0 : &tv, &msg ); 01189 if ( rescode == -1 ) { 01190 return -1; 01191 } 01192 // Act on the return code 01193 if ( rescode != 0 ) { 01194 // Some kind of result is available for processing 01195 return d->processResult( rescode, msg ); 01196 } 01197 } while ( msecs == -1 || stopWatch.elapsed() < msecs ); 01198 01199 return 0; //timeout 01200 } 01201 01202 #else 01203 01204 int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data ) 01205 { 01206 kError() << "LDAP support not compiled"; 01207 return -1; 01208 } 01209 01210 int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data ) 01211 { 01212 kError() << "LDAP support not compiled"; 01213 return -1; 01214 } 01215 01216 int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope, 01217 const QString &filter, const QStringList &attributes ) 01218 { 01219 kError() << "LDAP support not compiled"; 01220 return -1; 01221 } 01222 01223 int LdapOperation::add( const LdapObject &object ) 01224 { 01225 kError() << "LDAP support not compiled"; 01226 return -1; 01227 } 01228 01229 int LdapOperation::add_s( const LdapObject &object ) 01230 { 01231 kError() << "LDAP support not compiled"; 01232 return -1; 01233 } 01234 01235 int LdapOperation::add( const LdapDN &dn, const ModOps &ops ) 01236 { 01237 kError() << "LDAP support not compiled"; 01238 return -1; 01239 } 01240 01241 int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops ) 01242 { 01243 kError() << "LDAP support not compiled"; 01244 return -1; 01245 } 01246 01247 int LdapOperation::rename( const LdapDN &dn, const QString &newRdn, 01248 const QString &newSuperior, bool deleteold ) 01249 { 01250 kError() << "LDAP support not compiled"; 01251 return -1; 01252 } 01253 01254 int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn, 01255 const QString &newSuperior, bool deleteold ) 01256 { 01257 kError() << "LDAP support not compiled"; 01258 return -1; 01259 } 01260 01261 int LdapOperation::del( const LdapDN &dn ) 01262 { 01263 kError() << "LDAP support not compiled"; 01264 return -1; 01265 } 01266 01267 int LdapOperation::del_s( const LdapDN &dn ) 01268 { 01269 kError() << "LDAP support not compiled"; 01270 return -1; 01271 } 01272 01273 int LdapOperation::modify( const LdapDN &dn, const ModOps &ops ) 01274 { 01275 kError() << "LDAP support not compiled"; 01276 return -1; 01277 } 01278 01279 int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops ) 01280 { 01281 kError() << "LDAP support not compiled"; 01282 return -1; 01283 } 01284 01285 int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value ) 01286 { 01287 kError() << "LDAP support not compiled"; 01288 return -1; 01289 } 01290 01291 int LdapOperation::exop( const QString &oid, const QByteArray &data ) 01292 { 01293 kError() << "LDAP support not compiled"; 01294 return -1; 01295 } 01296 01297 int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value ) 01298 { 01299 kError() << "LDAP support not compiled"; 01300 return -1; 01301 } 01302 01303 int LdapOperation::exop_s( const QString &oid, const QByteArray &data ) 01304 { 01305 kError() << "LDAP support not compiled"; 01306 return -1; 01307 } 01308 01309 int LdapOperation::waitForResult( int id, int msecs ) 01310 { 01311 kError() << "LDAP support not compiled"; 01312 return -1; 01313 } 01314 01315 int LdapOperation::abandon( int id ) 01316 { 01317 kError() << "LDAP support not compiled"; 01318 return -1; 01319 } 01320 01321 #endif
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:00:06 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:00:06 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.