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