kde-playground/kdepimlibs/kldap/ldapoperation.cpp

1322 lines
35 KiB
C++
Raw Normal View History

/*
This file is part of libkldap.
Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "ldapoperation.h"
#include "kldap_config.h"
#include <kdebug.h>
#include <QtCore/QTime>
#include <stdlib.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef SASL2_FOUND
#include <sasl/sasl.h>
#endif
#ifdef LDAP_FOUND
# ifndef HAVE_WINLDAP_H
# include <lber.h>
# include <ldap.h>
# else
# include <w32-ldap-help.h>
# endif // HAVE_WINLDAP_H
#endif // LDAP_FOUND
#include "ldapdefs.h"
using namespace KLDAP;
#ifdef LDAP_FOUND
static void extractControls( LdapControls &ctrls, LDAPControl **pctrls );
#endif // LDAP_FOUND
/*
Returns the difference between msecs and elapsed. If msecs is -1,
however, -1 is returned.
*/
static int kldap_timeout_value( int msecs, int elapsed )
{
if ( msecs == -1 ) {
return -1;
}
int timeout = msecs - elapsed;
return timeout < 0 ? 0 : timeout;
}
class LdapOperation::LdapOperationPrivate
{
public:
LdapOperationPrivate();
~LdapOperationPrivate();
#ifdef LDAP_FOUND
int processResult( int rescode, LDAPMessage *msg );
int bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async );
#endif
LdapControls mClientCtrls, mServerCtrls, mControls;
LdapObject mObject;
QByteArray mExtOid, mExtData;
QByteArray mServerCred;
QString mMatchedDn;
QList<QByteArray> mReferrals;
LdapConnection *mConnection;
};
LdapOperation::LdapOperation()
: d( new LdapOperationPrivate )
{
d->mConnection = 0;
}
LdapOperation::LdapOperation( LdapConnection &conn )
: d( new LdapOperationPrivate )
{
setConnection( conn );
}
LdapOperation::~LdapOperation()
{
delete d;
}
void LdapOperation::setConnection( LdapConnection &conn )
{
d->mConnection = &conn;
}
LdapConnection &LdapOperation::connection()
{
return *d->mConnection;
}
void LdapOperation::setClientControls( const LdapControls &ctrls )
{
d->mClientCtrls = ctrls;
}
void LdapOperation::setServerControls( const LdapControls &ctrls )
{
d->mServerCtrls = ctrls;
}
LdapControls LdapOperation::clientControls() const
{
return d->mClientCtrls;
}
LdapControls LdapOperation::serverControls() const
{
return d->mServerCtrls;
}
LdapObject LdapOperation::object() const
{
return d->mObject;
}
LdapControls LdapOperation::controls() const
{
return d->mControls;
}
QByteArray LdapOperation::extendedOid() const
{
return d->mExtOid;
}
QByteArray LdapOperation::extendedData() const
{
return d->mExtData;
}
QString LdapOperation::matchedDn() const
{
return d->mMatchedDn;
}
QList<QByteArray> LdapOperation::referrals() const
{
return d->mReferrals;
}
QByteArray LdapOperation::serverCred() const
{
return d->mServerCred;
}
LdapOperation::LdapOperationPrivate::LdapOperationPrivate()
{
}
LdapOperation::LdapOperationPrivate::~LdapOperationPrivate()
{
}
#ifdef LDAP_FOUND
#ifdef SASL2_FOUND
static int kldap_sasl_interact( sasl_interact_t *interact, LdapOperation::SASL_Data *data )
{
if ( data->proc ) {
for ( ; interact->id != SASL_CB_LIST_END; interact++ ) {
switch ( interact->id ) {
case SASL_CB_GETREALM:
data->creds.fields |= LdapOperation::SASL_Realm;
break;
case SASL_CB_AUTHNAME:
data->creds.fields |= LdapOperation::SASL_Authname;
break;
case SASL_CB_PASS:
data->creds.fields |= LdapOperation::SASL_Password;
break;
case SASL_CB_USER:
data->creds.fields |= LdapOperation::SASL_Authzid;
break;
}
}
int retval;
if ( ( retval = data->proc( data->creds, data->data ) ) ) {
return retval;
}
}
QString value;
while ( interact->id != SASL_CB_LIST_END ) {
value.clear();
switch ( interact->id ) {
case SASL_CB_GETREALM:
value = data->creds.realm;
kDebug() << "SASL_REALM=" << value;
break;
case SASL_CB_AUTHNAME:
value = data->creds.authname;
kDebug() << "SASL_AUTHNAME=" << value;
break;
case SASL_CB_PASS:
value = data->creds.password;
kDebug() << "SASL_PASSWD=[hidden]";
break;
case SASL_CB_USER:
value = data->creds.authzid;
kDebug() << "SASL_AUTHZID=" << value;
break;
}
if ( value.isEmpty() ) {
interact->result = NULL;
interact->len = 0;
} else {
interact->result = strdup( value.toUtf8() );
interact->len = strlen( (const char *)interact->result );
}
interact++;
}
return KLDAP_SUCCESS;
}
#endif
int LdapOperation::LdapOperationPrivate::bind( const QByteArray &creds,
SASL_Callback_Proc *saslproc,
void *data, bool async )
{
Q_ASSERT( mConnection );
LDAP *ld = (LDAP *) mConnection->handle();
LdapServer server;
server = mConnection->server();
int ret;
if ( server.auth() == LdapServer::SASL ) {
#if defined( SASL2_FOUND ) && !defined( HAVE_WINLDAP_H )
sasl_conn_t *saslconn = (sasl_conn_t *)mConnection->saslHandle();
sasl_interact_t *client_interact = NULL;
const char *out = NULL;
uint outlen;
const char *mechusing = NULL;
struct berval ccred, *scred;
int saslresult;
QByteArray sdata = creds;
QString mech = server.mech();
if ( mech.isEmpty() ) {
mech = QLatin1String("DIGEST-MD5");
}
SASL_Data sasldata;
sasldata.proc = saslproc;
sasldata.data = data;
sasldata.creds.fields = 0;
sasldata.creds.realm = server.realm();
sasldata.creds.authname = server.user();
sasldata.creds.authzid = server.bindDn();
sasldata.creds.password = server.password();
do {
if ( sdata.isEmpty() ) {
do {
saslresult = sasl_client_start( saslconn, mech.toLatin1(),
&client_interact, &out, &outlen, &mechusing );
if ( saslresult == SASL_INTERACT ) {
if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) {
return KLDAP_SASL_ERROR;
}
}
kDebug() << "sasl_client_start mech: "
<< mechusing << " outlen " << outlen
<< " result: " << saslresult;
} while ( saslresult == SASL_INTERACT );
if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) {
return KLDAP_SASL_ERROR;
}
} else {
kDebug() << "sasl_client_step";
do {
saslresult = sasl_client_step( saslconn, sdata.data(), sdata.size(),
&client_interact, &out, &outlen );
if ( saslresult == SASL_INTERACT ) {
if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) {
return KLDAP_SASL_ERROR;
}
}
} while ( saslresult == SASL_INTERACT );
kDebug() << "sasl_client_step result" << saslresult;
if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) {
return KLDAP_SASL_ERROR;
}
}
ccred.bv_val = (char*) out;
ccred.bv_len = outlen;
if ( async ) {
kDebug() << "ldap_sasl_bind";
int msgid;
ret =
ldap_sasl_bind( ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
&ccred, 0, 0, &msgid );
if ( ret == 0 ) {
ret = msgid;
}
kDebug() << "ldap_sasl_bind msgid" << ret;
} else {
kDebug() << "ldap_sasl_bind_s";
ret =
ldap_sasl_bind_s( ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
&ccred, 0, 0, &scred );
kDebug() << "ldap_sasl_bind_s ret" << ret;
if ( scred ) {
sdata = QByteArray( scred->bv_val, scred->bv_len );
} else {
sdata = QByteArray();
}
}
} while ( !async && ret == KLDAP_SASL_BIND_IN_PROGRESS );
#else
kError() << "SASL authentication is not available "
<< "(re-compile kldap with cyrus-sasl and OpenLDAP development).";
return KLDAP_SASL_ERROR;
#endif
} else { //simple auth
QByteArray bindname, pass;
struct berval ccred;
if ( server.auth() == LdapServer::Simple ) {
bindname = server.bindDn().toUtf8();
pass = server.password().toUtf8();
}
ccred.bv_val = pass.data();
ccred.bv_len = pass.size();
kDebug() << "binding to server, bindname: " << bindname << " password: *****";
if ( async ) {
kDebug() << "ldap_sasl_bind (simple)";
#ifndef HAVE_WINLDAP_H
int msgid = 0;
ret = ldap_sasl_bind( ld, bindname.data(), 0, &ccred, 0, 0, &msgid );
if ( ret == 0 ) {
ret = msgid;
}
#else
ret = ldap_simple_bind( ld, bindname.data(), pass.data() );
#endif
} else {
kDebug() << "ldap_sasl_bind_s (simple)";
#ifndef HAVE_WINLDAP_H
ret = ldap_sasl_bind_s( ld, bindname.data(), 0, &ccred, 0, 0, 0 );
#else
ret = ldap_simple_bind_s( ld, bindname.data(), pass.data() );
#endif
}
}
return ret;
}
int LdapOperation::LdapOperationPrivate::processResult( int rescode, LDAPMessage *msg )
{
//kDebug();
int retval;
LDAP *ld = (LDAP *) mConnection->handle();
kDebug() << "rescode: " << rescode;
switch ( rescode ) {
case RES_SEARCH_ENTRY:
{
//kDebug() << "Found search entry";
mObject.clear();
LdapAttrMap attrs;
char *name;
struct berval **bvals;
BerElement *entry;
char *dn = ldap_get_dn( ld, msg );
mObject.setDn( QString::fromUtf8( dn ) );
ldap_memfree( dn );
// iterate over the attributes
name = ldap_first_attribute( ld, msg, &entry );
while ( name != 0 ) {
// print the values
bvals = ldap_get_values_len( ld, msg, name );
LdapAttrValue values;
if ( bvals ) {
for ( int i = 0; bvals[i] != 0; i++ ) {
char *val = bvals[i]->bv_val;
unsigned long len = bvals[i]->bv_len;
values.append( QByteArray( val, len ) );
}
ldap_value_free_len( bvals );
}
attrs[ QString::fromLatin1( name ) ] = values;
ldap_memfree( name );
// next attribute
name = ldap_next_attribute( ld, msg, entry );
}
ber_free( entry, 0 );
mObject.setAttributes( attrs );
break;
}
case RES_SEARCH_REFERENCE:
// Will only get this if following references is disabled. ignore it
rescode = 0;
break;
case RES_EXTENDED:
{
char *retoid;
struct berval *retdata;
retval = ldap_parse_extended_result( ld, msg, &retoid, &retdata, 0 );
if ( retval != KLDAP_SUCCESS ) {
ldap_msgfree( msg );
return -1;
}
mExtOid = retoid ? QByteArray( retoid ) : QByteArray();
mExtData = retdata ? QByteArray( retdata->bv_val, retdata->bv_len ) : QByteArray();
ldap_memfree( retoid );
ber_bvfree( retdata );
break;
}
case RES_BIND:
{
struct berval *servercred = 0;
#ifndef HAVE_WINLDAP_H
// FIXME: Error handling Winldap does not have ldap_parse_sasl_bind_result
retval = ldap_parse_sasl_bind_result( ld, msg, &servercred, 0 );
#else
retval = KLDAP_SUCCESS;
#endif
if ( retval != KLDAP_SUCCESS && retval != KLDAP_SASL_BIND_IN_PROGRESS ) {
kDebug() << "RES_BIND error: " << retval;
ldap_msgfree( msg );
return -1;
}
kDebug() << "RES_BIND rescode" << rescode << "retval:" << retval;
if ( servercred ) {
mServerCred = QByteArray( servercred->bv_val, servercred->bv_len );
ber_bvfree( servercred );
} else {
mServerCred = QByteArray();
}
break;
}
default:
{
LDAPControl **serverctrls = 0;
char *matcheddn = 0, *errmsg = 0;
char **referralsp;
int errcodep;
retval =
ldap_parse_result( ld, msg, &errcodep, &matcheddn, &errmsg, &referralsp,
&serverctrls, 0 );
kDebug() << "rescode" << rescode << "retval:" << retval
<< "matcheddn:" << matcheddn << "errcode:"
<< errcodep << "errmsg:" << errmsg;
if ( retval != KLDAP_SUCCESS ) {
ldap_msgfree( msg );
return -1;
}
mControls.clear();
if ( serverctrls ) {
extractControls( mControls, serverctrls );
ldap_controls_free( serverctrls );
}
mReferrals.clear();
if ( referralsp ) {
char **tmp = referralsp;
while ( *tmp ) {
mReferrals.append( QByteArray( *tmp ) );
ldap_memfree( *tmp );
tmp++;
}
ldap_memfree( (char *) referralsp );
}
mMatchedDn.clear();
if ( matcheddn ) {
mMatchedDn = QString::fromUtf8( matcheddn );
ldap_memfree( matcheddn );
}
if ( errmsg ) {
ldap_memfree( errmsg );
}
}
}
ldap_msgfree( msg );
return rescode;
}
static void addModOp( LDAPMod ***pmods, int mod_type, const QString &attr,
const QByteArray *value = 0 )
{
// kDebug() << "type:" << mod_type << "attr:" << attr <<
// "value:" << QString::fromUtf8(value,value.size()) <<
// "size:" << value.size();
LDAPMod **mods;
mods = *pmods;
uint i = 0;
if ( mods == 0 ) {
mods = (LDAPMod **)malloc( 2 * sizeof( LDAPMod * ) );
mods[ 0 ] = (LDAPMod *)malloc( sizeof( LDAPMod ) );
mods[ 1 ] = 0;
memset( mods[ 0 ], 0, sizeof( LDAPMod ) );
} else {
while ( mods[ i ] != 0 &&
( strcmp( attr.toUtf8(), mods[i]->mod_type ) != 0 ||
( mods[ i ]->mod_op & ~LDAP_MOD_BVALUES ) != mod_type ) ) i++;
if ( mods[ i ] == 0 ) {
mods = (LDAPMod **)realloc( mods, ( i + 2 ) * sizeof( LDAPMod * ) );
if ( mods == 0 ) {
kError() << "addModOp: realloc";
return;
}
mods[ i + 1 ] = 0;
mods[ i ] = (LDAPMod *) malloc( sizeof( LDAPMod ) );
memset( mods[ i ], 0, sizeof( LDAPMod ) );
}
}
mods[ i ]->mod_op = mod_type | LDAP_MOD_BVALUES;
if ( mods[ i ]->mod_type == 0 ) {
mods[ i ]->mod_type = strdup( attr.toUtf8() );
}
*pmods = mods;
if ( value == 0 ) {
return;
}
int vallen = value->size();
BerValue *berval;
berval = (BerValue *) malloc( sizeof( BerValue ) );
berval -> bv_len = vallen;
if ( vallen > 0 ) {
berval -> bv_val = (char *) malloc( vallen );
memcpy( berval -> bv_val, value->data(), vallen );
} else {
berval -> bv_val = 0;
}
if ( mods[ i ] -> mod_vals.modv_bvals == 0 ) {
mods[ i ]->mod_vals.modv_bvals =
(BerValue **) malloc( sizeof( BerValue * ) * 2 );
mods[ i ]->mod_vals.modv_bvals[ 0 ] = berval;
mods[ i ]->mod_vals.modv_bvals[ 1 ] = 0;
// kDebug() << "new bervalue struct" << attr << value;
} else {
uint j = 0;
while ( mods[ i ]->mod_vals.modv_bvals[ j ] != 0 ) {
j++;
}
mods[ i ]->mod_vals.modv_bvals =
(BerValue **)realloc( mods[ i ]->mod_vals.modv_bvals,
( j + 2 ) * sizeof( BerValue * ) );
if ( mods[ i ]->mod_vals.modv_bvals == 0 ) {
kError() << "addModOp: realloc";
free( berval );
return;
}
mods[ i ]->mod_vals.modv_bvals[ j ] = berval;
mods[ i ]->mod_vals.modv_bvals[ j+1 ] = 0;
kDebug() << j << ". new bervalue";
}
}
static void addControlOp( LDAPControl ***pctrls, const QString &oid,
const QByteArray &value, bool critical )
{
LDAPControl **ctrls;
LDAPControl *ctrl = (LDAPControl *) malloc( sizeof( LDAPControl ) );
ctrls = *pctrls;
kDebug() << "oid:'" << oid << "' val: '" << value << "'";
int vallen = value.size();
ctrl->ldctl_value.bv_len = vallen;
if ( vallen ) {
ctrl->ldctl_value.bv_val = (char *) malloc( vallen );
memcpy( ctrl->ldctl_value.bv_val, value.data(), vallen );
} else {
ctrl->ldctl_value.bv_val = 0;
}
ctrl->ldctl_iscritical = critical;
ctrl->ldctl_oid = strdup( oid.toUtf8() );
uint i = 0;
if ( ctrls == 0 ) {
ctrls = (LDAPControl **)malloc ( 2 * sizeof( LDAPControl * ) );
ctrls[ 0 ] = 0;
ctrls[ 1 ] = 0;
} else {
while ( ctrls[ i ] != 0 ) {
i++;
}
ctrls[ i + 1 ] = 0;
ctrls =
(LDAPControl **)realloc( ctrls, ( i + 2 ) * sizeof( LDAPControl * ) );
}
ctrls[ i ] = ctrl;
*pctrls = ctrls;
}
static void createControls( LDAPControl ***pctrls, const LdapControls &ctrls )
{
for ( int i = 0; i< ctrls.count(); ++i ) {
addControlOp( pctrls, ctrls[i].oid(), ctrls[i].value(), ctrls[i].critical() );
}
}
static void extractControls( LdapControls &ctrls, LDAPControl **pctrls )
{
LDAPControl *ctrl;
LdapControl control;
int i = 0;
while ( pctrls[i] ) {
ctrl = pctrls[ i ];
control.setOid( QString::fromUtf8( ctrl->ldctl_oid ) );
control.setValue( QByteArray( ctrl->ldctl_value.bv_val,
ctrl->ldctl_value.bv_len ) );
control.setCritical( ctrl->ldctl_iscritical );
ctrls.append( control );
i++;
}
}
int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data )
{
return d->bind( creds, saslproc, data, true );
}
int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data )
{
return d->bind( QByteArray(), saslproc, data, false );
}
int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
const QString &filter, const QStringList &attributes )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
char **attrs = 0;
int msgid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int count = attributes.count();
if ( count > 0 ) {
attrs = static_cast<char**>( malloc( ( count + 1 ) * sizeof( char * ) ) );
for ( int i=0; i<count; i++ ) {
attrs[i] = strdup( attributes.at( i ).toUtf8() );
}
attrs[count] = 0;
}
int lscope = LDAP_SCOPE_BASE;
switch ( scope ) {
case LdapUrl::Base:
lscope = LDAP_SCOPE_BASE;
break;
case LdapUrl::One:
lscope = LDAP_SCOPE_ONELEVEL;
break;
case LdapUrl::Sub:
lscope = LDAP_SCOPE_SUBTREE;
break;
}
kDebug() << "asyncSearch() base=\"" << base.toString()
<< "\" scope=" << (int)scope
<< "filter=\"" << filter
<< "\" attrs=" << attributes;
int retval =
ldap_search_ext( ld, base.toString().toUtf8().data(), lscope,
filter.isEmpty() ? QByteArray( "objectClass=*" ).data() :
filter.toUtf8().data(),
attrs, 0, serverctrls, clientctrls, 0,
d->mConnection->sizeLimit(), &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
// free the attributes list again
if ( count > 0 ) {
for ( int i=0; i<count; i++ ) {
free( attrs[i] );
}
free( attrs );
}
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::add( const LdapObject &object )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( LdapAttrMap::ConstIterator it = object.attributes().begin();
it != object.attributes().end(); ++it ) {
QString attr = it.key();
for ( LdapAttrValue::ConstIterator it2 = ( *it ).begin(); it2 != (*it).end(); ++it2 ) {
addModOp( &lmod, 0, attr, &( *it2 ) );
}
}
int retval =
ldap_add_ext( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
clientctrls, &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::add_s( const LdapObject &object )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( LdapAttrMap::ConstIterator it = object.attributes().begin();
it != object.attributes().end(); ++it ) {
QString attr = it.key();
for ( LdapAttrValue::ConstIterator it2 = ( *it ).begin(); it2 != (*it).end(); ++it2 ) {
addModOp( &lmod, 0, attr, &( *it2 ) );
}
}
int retval =
ldap_add_ext_s( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
return retval;
}
int LdapOperation::add( const LdapDN &dn, const ModOps &ops )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( int i = 0; i < ops.count(); ++i ) {
for ( int j = 0; j < ops[i].values.count(); ++j ) {
addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] );
}
}
int retval =
ldap_add_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls,
clientctrls, &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( int i = 0; i < ops.count(); ++i ) {
for ( int j = 0; j < ops[i].values.count(); ++j ) {
addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] );
}
}
kDebug() << dn.toString();
int retval =
ldap_add_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls,
clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
return retval;
}
int LdapOperation::rename( const LdapDN &dn, const QString &newRdn,
const QString &newSuperior, bool deleteold )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int retval = ldap_rename( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(),
deleteold, serverctrls, clientctrls, &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn,
const QString &newSuperior, bool deleteold )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int retval = ldap_rename_s( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(),
deleteold, serverctrls, clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
return retval;
}
int LdapOperation::del( const LdapDN &dn )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int retval =
ldap_delete_ext( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls, &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::del_s( const LdapDN &dn )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int retval = ldap_delete_ext_s( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
return retval;
}
int LdapOperation::modify( const LdapDN &dn, const ModOps &ops )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *)d->mConnection->handle();
int msgid;
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( int i = 0; i < ops.count(); ++i ) {
int mtype = 0;
switch ( ops[i].type ) {
case Mod_None:
mtype = 0;
break;
case Mod_Add:
mtype = LDAP_MOD_ADD;
break;
case Mod_Replace:
mtype = LDAP_MOD_REPLACE;
break;
case Mod_Del:
mtype = LDAP_MOD_DELETE;
break;
}
addModOp( &lmod, mtype, ops[i].attr, 0 );
for ( int j = 0; j < ops[i].values.count(); ++j ) {
addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] );
}
}
int retval =
ldap_modify_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPMod **lmod = 0;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
for ( int i = 0; i < ops.count(); ++i ) {
int mtype = 0;
switch ( ops[i].type ) {
case Mod_None:
mtype = 0;
break;
case Mod_Add:
mtype = LDAP_MOD_ADD;
break;
case Mod_Replace:
mtype = LDAP_MOD_REPLACE;
break;
case Mod_Del:
mtype = LDAP_MOD_DELETE;
break;
}
addModOp( &lmod, mtype, ops[i].attr, 0 );
for ( int j = 0; j < ops[i].values.count(); ++j ) {
addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] );
}
}
int retval =
ldap_modify_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
ldap_mods_free( lmod, 1 );
return retval;
}
int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int vallen = value.size();
BerValue *berval;
berval = (BerValue *) malloc( sizeof( BerValue ) );
berval -> bv_val = (char *) malloc( vallen );
berval -> bv_len = vallen;
memcpy( berval -> bv_val, value.data(), vallen );
int retval = ldap_compare_ext( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
serverctrls, clientctrls, &msgid );
ber_bvfree( berval );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
}
int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int vallen = value.size();
BerValue *berval;
berval = (BerValue *) malloc( sizeof( BerValue ) );
berval -> bv_val = (char *) malloc( vallen );
berval -> bv_len = vallen;
memcpy( berval -> bv_val, value.data(), vallen );
int retval = ldap_compare_ext_s( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
serverctrls, clientctrls );
ber_bvfree( berval );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
return retval;
}
int LdapOperation::exop( const QString &oid, const QByteArray &data )
{
Q_ASSERT( d->mConnection );
#if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
LDAP *ld = (LDAP *) d->mConnection->handle();
int msgid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int vallen = data.size();
BerValue *berval;
berval = (BerValue *) malloc( sizeof( BerValue ) );
berval -> bv_val = (char *) malloc( vallen );
berval -> bv_len = vallen;
memcpy( berval -> bv_val, data.data(), vallen );
int retval = ldap_extended_operation( ld, oid.toUtf8().data(), berval,
serverctrls, clientctrls, &msgid );
ber_bvfree( berval );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
if ( retval == 0 ) {
retval = msgid;
}
return retval;
#else
kError() << "Your LDAP client libraries don't support extended operations.";
return -1;
#endif
}
int LdapOperation::exop_s( const QString &oid, const QByteArray &data )
{
#if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
BerValue *retdata;
char *retoid;
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int vallen = data.size();
BerValue *berval;
berval = (BerValue *) malloc( sizeof( BerValue ) );
berval -> bv_val = (char *) malloc( vallen );
berval -> bv_len = vallen;
memcpy( berval -> bv_val, data.data(), vallen );
int retval = ldap_extended_operation_s( ld, oid.toUtf8().data(), berval,
serverctrls, clientctrls, &retoid, &retdata );
ber_bvfree( berval );
ber_bvfree( retdata );
free( retoid );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
return retval;
#else
kError() << "Your LDAP client libraries don't support extended operations.";
return -1;
#endif
}
int LdapOperation::abandon( int id )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPControl **serverctrls = 0, **clientctrls = 0;
createControls( &serverctrls, d->mServerCtrls );
createControls( &serverctrls, d->mClientCtrls );
int retval = ldap_abandon_ext( ld, id, serverctrls, clientctrls );
ldap_controls_free( serverctrls );
ldap_controls_free( clientctrls );
return retval;
}
int LdapOperation::waitForResult( int id, int msecs )
{
Q_ASSERT( d->mConnection );
LDAP *ld = (LDAP *) d->mConnection->handle();
LDAPMessage *msg;
int rescode;
QTime stopWatch;
stopWatch.start();
int attempt( 1 );
int timeout( 0 );
do {
// Calculate the timeout value to use and assign it to a timeval structure
// see man select (2) for details
timeout = kldap_timeout_value( msecs, stopWatch.elapsed() );
kDebug() << "(" << id << "," << msecs
<< "): Waiting" << timeout
<< "msecs for result. Attempt #" << attempt++;
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = ( timeout % 1000 ) * 1000;
// Wait for a result
rescode = ldap_result( ld, id, 0, timeout < 0 ? 0 : &tv, &msg );
if ( rescode == -1 ) {
return -1;
}
// Act on the return code
if ( rescode != 0 ) {
// Some kind of result is available for processing
return d->processResult( rescode, msg );
}
} while ( msecs == -1 || stopWatch.elapsed() < msecs );
return 0; //timeout
}
#else
int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
const QString &filter, const QStringList &attributes )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::add( const LdapObject &object )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::add_s( const LdapObject &object )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::add( const LdapDN &dn, const ModOps &ops )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::rename( const LdapDN &dn, const QString &newRdn,
const QString &newSuperior, bool deleteold )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn,
const QString &newSuperior, bool deleteold )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::del( const LdapDN &dn )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::del_s( const LdapDN &dn )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::modify( const LdapDN &dn, const ModOps &ops )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::exop( const QString &oid, const QByteArray &data )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::exop_s( const QString &oid, const QByteArray &data )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::waitForResult( int id, int msecs )
{
kError() << "LDAP support not compiled";
return -1;
}
int LdapOperation::abandon( int id )
{
kError() << "LDAP support not compiled";
return -1;
}
#endif