kde-playground/kdepimlibs/kldap/ldapconnection.cpp

437 lines
9.8 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 "ldapconnection.h"
#include "ldapdefs.h"
#include "kldap_config.h" // SASL2_FOUND, LDAP_FOUND
#include <stdlib.h>
#include <klocalizedstring.h>
#include <kdebug.h>
#ifdef SASL2_FOUND
#include <sasl/sasl.h>
static sasl_callback_t callbacks[] = {
{ SASL_CB_ECHOPROMPT, NULL, NULL },
{ SASL_CB_NOECHOPROMPT, NULL, NULL },
{ SASL_CB_GETREALM, NULL, NULL },
{ SASL_CB_USER, NULL, NULL },
{ SASL_CB_AUTHNAME, NULL, NULL },
{ SASL_CB_PASS, NULL, NULL },
{ SASL_CB_CANON_USER, NULL, NULL },
{ SASL_CB_LIST_END, NULL, NULL }
};
static bool ldapoperation_sasl_initialized = false;
#endif
#ifdef LDAP_FOUND
# ifndef HAVE_WINLDAP_H
# include <lber.h>
# include <ldap.h>
#else
# include <w32-ldap-help.h>
#endif // HAVE_WINLDAP_H
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS 0
#endif
#endif
using namespace KLDAP;
class LdapConnection::LdapConnectionPrivate
{
public:
LdapConnectionPrivate();
LdapServer mServer;
QString mConnectionError;
#ifdef LDAP_FOUND
LDAP *mLDAP;
#else
void *mLDAP;
#endif
#ifdef SASL2_FOUND
sasl_conn_t *mSASLconn;
#else
void *mSASLconn;
#endif
};
LdapConnection::LdapConnectionPrivate::LdapConnectionPrivate()
{
mSASLconn = 0;
#ifdef SASL2_FOUND
if ( !ldapoperation_sasl_initialized ) {
sasl_client_init( NULL );
ldapoperation_sasl_initialized = true;
}
#endif
}
LdapConnection::LdapConnection()
: d( new LdapConnectionPrivate )
{
d->mLDAP = 0;
}
LdapConnection::LdapConnection( const LdapUrl &url )
: d( new LdapConnectionPrivate )
{
d->mLDAP = 0;
setUrl( url );
}
LdapConnection::LdapConnection( const LdapServer &server )
: d( new LdapConnectionPrivate )
{
d->mLDAP = 0;
setServer( server );
}
LdapConnection::~LdapConnection()
{
close();
delete d;
}
void LdapConnection::setUrl( const LdapUrl &url )
{
d->mServer.setUrl( url );
}
void LdapConnection::setServer( const LdapServer &server )
{
d->mServer = server;
}
const LdapServer &LdapConnection::server() const
{
return d->mServer;
}
void *LdapConnection::handle() const
{
return (void *)d->mLDAP;
}
void *LdapConnection::saslHandle() const
{
return (void *)d->mSASLconn;
}
QString LdapConnection::errorString( int code )
{
//No translated error messages yet
#ifdef LDAP_FOUND
return QString::fromUtf8( ldap_err2string( code ) );
switch ( code ) {
case LDAP_OPERATIONS_ERROR:
return i18n( "LDAP Operations error" );
//FIXME:
/* add the LDAP error codes */
}
#else
return i18n( "No LDAP Support..." );
#endif
}
QString LdapConnection::saslErrorString() const
{
#ifdef SASL2_FOUND
const char *str;
str = sasl_errdetail( d->mSASLconn );
return QString::fromLocal8Bit( str );
#else
return i18n( "SASL support is not available. Please recompile libkldap with the "
"Cyrus-SASL (or compatible) client libraries, or complain to your "
"distribution packagers." );
#endif
}
QString LdapConnection::connectionError() const
{
return d->mConnectionError;
}
#ifdef LDAP_FOUND
int LdapConnection::getOption( int option, void *value ) const
{
Q_ASSERT( d->mLDAP );
return ldap_get_option( d->mLDAP, option, value );
}
int LdapConnection::setOption( int option, void *value )
{
Q_ASSERT( d->mLDAP );
return ldap_set_option( d->mLDAP, option, value );
}
int LdapConnection::ldapErrorCode() const
{
Q_ASSERT( d->mLDAP );
int err;
ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err );
return err;
}
QString LdapConnection::ldapErrorString() const
{
Q_ASSERT( d->mLDAP );
char *errmsg;
ldap_get_option( d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg );
QString msg = QString::fromLocal8Bit( errmsg );
free( errmsg );
return msg;
}
bool LdapConnection::setSizeLimit( int sizelimit )
{
Q_ASSERT( d->mLDAP );
kDebug() << "sizelimit:" << sizelimit;
if ( setOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
return false;
}
return true;
}
int LdapConnection::sizeLimit() const
{
Q_ASSERT( d->mLDAP );
int sizelimit;
if ( getOption( LDAP_OPT_SIZELIMIT, &sizelimit ) != LDAP_OPT_SUCCESS ) {
return -1;
}
return sizelimit;
}
bool LdapConnection::setTimeLimit( int timelimit )
{
Q_ASSERT( d->mLDAP );
kDebug() << "timelimit:" << timelimit;
if ( setOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
return false;
}
return true;
}
int LdapConnection::timeLimit() const
{
Q_ASSERT( d->mLDAP );
int timelimit;
if ( getOption( LDAP_OPT_TIMELIMIT, &timelimit ) != LDAP_OPT_SUCCESS ) {
return -1;
}
return timelimit;
}
int LdapConnection::connect()
{
int ret;
QString url;
if ( d->mLDAP ) {
close();
}
int version = d->mServer.version();
int timeout = d->mServer.timeout();
url = d->mServer.security() == LdapServer::SSL ? QLatin1String("ldaps") : QLatin1String("ldap");
url += QLatin1String("://");
url += d->mServer.host();
url += QLatin1Char(':');
url += QString::number( d->mServer.port() );
kDebug() << "ldap url:" << url;
#ifdef HAVE_LDAP_INITIALIZE
ret = ldap_initialize( &d->mLDAP, url.toLatin1() );
#else
d->mLDAP = ldap_init( d->mServer.host().toLatin1().data(), d->mServer.port() );
if ( d->mLDAP == 0 ) {
ret = -1;
} else {
ret = LDAP_SUCCESS;
}
#endif
if ( ret != LDAP_SUCCESS ) {
d->mConnectionError = i18n( "An error occurred during the connection initialization phase." );
return ret;
}
kDebug() << "setting version to:" << version;
if ( setOption( LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS ) {
ret = ldapErrorCode();
d->mConnectionError = i18n( "Cannot set protocol version to %1.", version );
close();
return ret;
}
#if defined(LDAP_OPT_TIMEOUT)
kDebug() << "setting timeout to:" << timeout;
if ( timeout ) {
if ( setOption( LDAP_OPT_TIMEOUT, &timeout ) != LDAP_OPT_SUCCESS ) {
ret = ldapErrorCode();
d->mConnectionError = i18np( "Cannot set timeout to %1 second.",
"Cannot set timeout to %1 seconds.",
timeout );
close();
return ret;
}
}
#endif
//FIXME: accessing to certificate handling would be good
kDebug() << "setting security to:" << d->mServer.security();
if ( d->mServer.security() == LdapServer::TLS ) {
kDebug() << "start TLS";
#ifdef HAVE_LDAP_START_TLS_S
if ( ( ret = ldap_start_tls_s( d->mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) {
d->mConnectionError = ldapErrorString();
close();
return ret;
}
#else
close();
d->mConnectionError = i18n( "TLS support not available in the LDAP client libraries." );
return -1;
#endif
}
kDebug() << "setting sizelimit to:" << d->mServer.sizeLimit();
if ( d->mServer.sizeLimit() ) {
if ( !setSizeLimit( d->mServer.sizeLimit() ) ) {
ret = ldapErrorCode();
close();
d->mConnectionError = i18n( "Cannot set size limit." );
return ret;
}
}
kDebug() << "setting timelimit to:" << d->mServer.timeLimit();
if ( d->mServer.timeLimit() ) {
if ( !setTimeLimit( d->mServer.timeLimit() ) ) {
ret = ldapErrorCode();
close();
d->mConnectionError = i18n( "Cannot set time limit." );
return ret;
}
}
#ifdef SASL2_FOUND
kDebug() << "initializing SASL client";
int saslresult = sasl_client_new( "ldap", d->mServer.host().toLatin1(),
0, 0, callbacks, 0, &d->mSASLconn );
if ( saslresult != SASL_OK ) {
d->mConnectionError = i18n( "Cannot initialize the SASL client." );
return KLDAP_SASL_ERROR;
}
#endif
return 0;
}
void LdapConnection::close()
{
if ( d->mLDAP ) {
#ifdef HAVE_LDAP_UNBIND_EXT
ldap_unbind_ext( d->mLDAP, 0, 0 );
#else
ldap_unbind( d->mLDAP );
#endif
}
d->mLDAP = 0;
#ifdef SASL2_FOUND
if ( d->mSASLconn ) {
sasl_dispose( &d->mSASLconn );
d->mSASLconn = 0;
}
#endif
kDebug() << "connection closed!";
}
#else //LDAP_FOUND
int LdapConnection::getOption( int option, void *value ) const
{
kError() << "No LDAP support...";
return -1;
}
int LdapConnection::setOption( int option, void *value )
{
kError() << "No LDAP support...";
return -1;
}
int LdapConnection::ldapErrorCode() const
{
kError() << "No LDAP support...";
return -1;
}
QString LdapConnection::ldapErrorString() const
{
kError() << "No LDAP support...";
return QString();
}
bool LdapConnection::setSizeLimit( int sizelimit )
{
kError() << "No LDAP support...";
return false;
}
int LdapConnection::sizeLimit() const
{
kError() << "No LDAP support...";
return -1;
}
bool LdapConnection::setTimeLimit( int timelimit )
{
kError() << "No LDAP support...";
return false;
}
int LdapConnection::timeLimit() const
{
kError() << "No LDAP support...";
return -1;
}
int LdapConnection::connect( )
{
d->mConnectionError =
i18n( "LDAP support not compiled in. Please recompile libkldap with the "
"OpenLDAP (or compatible) client libraries, or complain to your "
"distribution packagers." );
kError() << "No LDAP support...";
return -1;
}
void LdapConnection::close()
{
kError() << "No LDAP support...";
}
#endif