From 472156a41b1348c714986c772759ad950fffbe75 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 27 Jan 2013 15:11:21 -0600 Subject: Rename kioslaves --- tdeioslave/ldap/CMakeLists.txt | 6 +- tdeioslave/ldap/Makefile.am | 10 +- tdeioslave/ldap/kio_ldap.cpp | 1154 ---------------------------------------- tdeioslave/ldap/kio_ldap.h | 65 --- tdeioslave/ldap/ldap.protocol | 2 +- tdeioslave/ldap/ldaps.protocol | 2 +- tdeioslave/ldap/tdeio_ldap.cpp | 1154 ++++++++++++++++++++++++++++++++++++++++ tdeioslave/ldap/tdeio_ldap.h | 65 +++ 8 files changed, 1229 insertions(+), 1229 deletions(-) delete mode 100644 tdeioslave/ldap/kio_ldap.cpp delete mode 100644 tdeioslave/ldap/kio_ldap.h create mode 100644 tdeioslave/ldap/tdeio_ldap.cpp create mode 100644 tdeioslave/ldap/tdeio_ldap.h (limited to 'tdeioslave/ldap') diff --git a/tdeioslave/ldap/CMakeLists.txt b/tdeioslave/ldap/CMakeLists.txt index ebf162205..d05048e0d 100644 --- a/tdeioslave/ldap/CMakeLists.txt +++ b/tdeioslave/ldap/CMakeLists.txt @@ -28,10 +28,10 @@ link_directories( install( FILES ldap.protocol ldaps.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) -##### kio_ldap (module) ######################### +##### tdeio_ldap (module) ######################### -tde_add_kpart( kio_ldap AUTOMOC - SOURCES kio_ldap.cpp +tde_add_kpart( tdeio_ldap AUTOMOC + SOURCES tdeio_ldap.cpp LINK kabc-shared ${LDAP_LIBRARIES} DESTINATION ${PLUGIN_INSTALL_DIR} ) diff --git a/tdeioslave/ldap/Makefile.am b/tdeioslave/ldap/Makefile.am index ca66e1b17..3f71b669b 100644 --- a/tdeioslave/ldap/Makefile.am +++ b/tdeioslave/ldap/Makefile.am @@ -7,13 +7,13 @@ LDADD = $(LIB_KIO) $(LDAP_LIBS) ####### Files -kde_module_LTLIBRARIES = kio_ldap.la +kde_module_LTLIBRARIES = tdeio_ldap.la -kio_ldap_la_SOURCES = kio_ldap.cpp -kio_ldap_la_LIBADD = $(LIB_KIO) $(LDAP_LIBS) $(LIB_KABC) -kio_ldap_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LDAP_RPATH) -module $(KDE_PLUGIN) +tdeio_ldap_la_SOURCES = tdeio_ldap.cpp +tdeio_ldap_la_LIBADD = $(LIB_KIO) $(LDAP_LIBS) $(LIB_KABC) +tdeio_ldap_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LDAP_RPATH) -module $(KDE_PLUGIN) -noinst_HEADERS = kio_ldap.h +noinst_HEADERS = tdeio_ldap.h kdelnk_DATA = ldap.protocol ldaps.protocol kdelnkdir = $(kde_servicesdir) diff --git a/tdeioslave/ldap/kio_ldap.cpp b/tdeioslave/ldap/kio_ldap.cpp deleted file mode 100644 index d4a29f1d4..000000000 --- a/tdeioslave/ldap/kio_ldap.cpp +++ /dev/null @@ -1,1154 +0,0 @@ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef HAVE_SASL_SASL_H //prefer libsasl2 -#include -#else -#ifdef HAVE_SASL_H -#include -#endif -#endif -#include - -#include "kio_ldap.h" - -using namespace TDEIO; -using namespace KABC; - -extern "C" { int KDE_EXPORT kdemain(int argc, char **argv); } - -/** - * The main program. - */ -int kdemain( int argc, char **argv ) -{ - TDEInstance instance( "kio_ldap" ); - - kdDebug(7125) << "Starting " << getpid() << endl; - - if ( argc != 4 ) { - kdError() << "Usage kio_ldap protocol pool app" << endl; - return -1; - } - - // let the protocol class do its work - LDAPProtocol slave( argv[1], argv[ 2 ], argv[ 3 ] ); - slave.dispatchLoop(); - - kdDebug( 7125 ) << "Done" << endl; - return 0; -} - -/** - * Initialize the ldap slave - */ -LDAPProtocol::LDAPProtocol( const TQCString &protocol, const TQCString &pool, - const TQCString &app ) : SlaveBase( protocol, pool, app ) -{ - mLDAP = 0; mTLS = 0; mVer = 3; mAuthSASL = false; - mRealm = ""; mBindName = ""; - mTimeLimit = mSizeLimit = 0; - kdDebug(7125) << "LDAPProtocol::LDAPProtocol (" << protocol << ")" << endl; -} - -LDAPProtocol::~LDAPProtocol() -{ - closeConnection(); -} - -void LDAPProtocol::LDAPErr( const KURL &url, int err ) -{ - - char *errmsg = 0; - if ( mLDAP ) { - if ( err == LDAP_SUCCESS ) ldap_get_option( mLDAP, LDAP_OPT_ERROR_NUMBER, &err ); - if ( err != LDAP_SUCCESS ) ldap_get_option( mLDAP, LDAP_OPT_ERROR_STRING, &errmsg ); - } - if ( err == LDAP_SUCCESS ) return; - kdDebug(7125) << "error code: " << err << " msg: " << ldap_err2string(err) << - " Additonal error message: '" << errmsg << "'" << endl; - TQString msg; - TQString extraMsg; - if ( errmsg ) { - if ( errmsg[0] ) - extraMsg = i18n("\nAdditional info: ") + TQString::fromUtf8( errmsg ); - free( errmsg ); - } - msg = url.prettyURL(); - if ( !extraMsg.isEmpty() ) msg += extraMsg; - - /* FIXME: No need to close on all errors */ - closeConnection(); - - switch (err) { -/* FIXME: is it worth mapping the following error codes to kio errors? - - LDAP_OPERATIONS_ERROR - LDAP_STRONG_AUTH_REQUIRED - LDAP_PROTOCOL_ERROR - LDAP_TIMELIMIT_EXCEEDED - LDAP_SIZELIMIT_EXCEEDED - LDAP_COMPARE_FALSE - LDAP_COMPARE_TRUE - LDAP_PARTIAL_RESULTS - LDAP_NO_SUCH_ATTRIBUTE - LDAP_UNDEFINED_TYPE - LDAP_INAPPROPRIATE_MATCHING - LDAP_CONSTRAINT_VIOLATION - LDAP_INVALID_SYNTAX - LDAP_NO_SUCH_OBJECT - LDAP_ALIAS_PROBLEM - LDAP_INVALID_DN_SYNTAX - LDAP_IS_LEAF - LDAP_ALIAS_DEREF_PROBLEM - LDAP_INAPPROPRIATE_AUTH - LDAP_BUSY - LDAP_UNAVAILABLE - LDAP_UNWILLING_TO_PERFORM - LDAP_LOOP_DETECT - LDAP_NAMING_VIOLATION - LDAP_OBJECT_CLASS_VIOLATION - LDAP_NOT_ALLOWED_ON_NONLEAF - LDAP_NOT_ALLOWED_ON_RDN - LDAP_NO_OBJECT_CLASS_MODS - LDAP_OTHER - LDAP_LOCAL_ERROR - LDAP_ENCODING_ERROR - LDAP_DECODING_ERROR - LDAP_FILTER_ERROR -*/ - case LDAP_AUTH_UNKNOWN: - case LDAP_INVALID_CREDENTIALS: - case LDAP_STRONG_AUTH_NOT_SUPPORTED: - error(ERR_COULD_NOT_AUTHENTICATE, msg); - break; - case LDAP_ALREADY_EXISTS: - error(ERR_FILE_ALREADY_EXIST, msg); - break; - case LDAP_INSUFFICIENT_ACCESS: - error(ERR_ACCESS_DENIED, msg); - break; - case LDAP_CONNECT_ERROR: - case LDAP_SERVER_DOWN: - error(ERR_COULD_NOT_CONNECT,msg); - break; - case LDAP_TIMEOUT: - error(ERR_SERVER_TIMEOUT,msg); - break; - case LDAP_PARAM_ERROR: - error(ERR_INTERNAL,msg); - break; - case LDAP_NO_MEMORY: - error(ERR_OUT_OF_MEMORY,msg); - break; - - default: - error( ERR_SLAVE_DEFINED, - i18n( "LDAP server returned the error: %1 %2\nThe LDAP URL was: %3" ). - arg( ldap_err2string(err)).arg( extraMsg ).arg( url.prettyURL() ) ); - } -} - -void LDAPProtocol::controlsFromMetaData( LDAPControl ***serverctrls, - LDAPControl ***clientctrls ) -{ - TQString oid; bool critical; TQByteArray value; - int i = 0; - while ( hasMetaData( TQString::fromLatin1("SERVER_CTRL%1").arg(i) ) ) { - TQCString val = metaData( TQString::fromLatin1("SERVER_CTRL%1").arg(i) ).utf8(); - LDIF::splitControl( val, oid, critical, value ); - kdDebug(7125) << "server ctrl #" << i << " value: " << val << - " oid: " << oid << " critical: " << critical << " value: " << - TQString(TQString::fromUtf8( value, value.size() )) << endl; - addControlOp( serverctrls, oid, value, critical ); - i++; - } - i = 0; - while ( hasMetaData( TQString::fromLatin1("CLIENT_CTRL%1").arg(i) ) ) { - TQCString val = metaData( TQString::fromLatin1("CLIENT_CTRL%1").arg(i) ).utf8(); - LDIF::splitControl( val, oid, critical, value ); - kdDebug(7125) << "client ctrl #" << i << " value: " << val << - " oid: " << oid << " critical: " << critical << " value: " << - TQString(TQString::fromUtf8( value, value.size() )) << endl; - addControlOp( clientctrls, oid, value, critical ); - i++; - } -} - -int LDAPProtocol::asyncSearch( LDAPUrl &usrc ) -{ - char **attrs = 0; - int msgid; - LDAPControl **serverctrls = 0, **clientctrls = 0; - - int count = usrc.attributes().count(); - if ( count > 0 ) { - attrs = static_cast( malloc((count+1) * sizeof(char*)) ); - for (int i=0; ibv_val; - unsigned long len = bvals[i]->bv_len; - tmp.setRawData( val, len ); - result += LDIF::assembleLine( TQString::fromUtf8( name ), tmp, 76 ) + '\n'; - tmp.resetRawData( val, len ); - } - ldap_value_free_len(bvals); - } - ldap_memfree( name ); - // next attribute - name = ldap_next_attribute(mLDAP, message, entry); - } - return result; -} - -void LDAPProtocol::addControlOp( LDAPControl ***pctrls, const TQString &oid, - const TQByteArray &value, bool critical ) -{ - LDAPControl **ctrls; - LDAPControl *ctrl = (LDAPControl *) malloc( sizeof( LDAPControl ) ); - - ctrls = *pctrls; - - kdDebug(7125) << "addControlOp: oid:'" << oid << "' val: '" << - TQString(TQString::fromUtf8(value, value.size())) << "'" << endl; - 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.utf8() ); - - 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; -} - -void LDAPProtocol::addModOp( LDAPMod ***pmods, int mod_type, const TQString &attr, - const TQByteArray &value ) -{ -// kdDebug(7125) << "type: " << mod_type << " attr: " << attr << -// " value: " << TQString::fromUtf8(value,value.size()) << -// " size: " << value.size() << endl; - 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.utf8(),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 ) { - kdError() << "addModOp: realloc" << endl; - 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.utf8() ); - - *pmods = mods; - - int vallen = value.size(); - if ( vallen == 0 ) return; - BerValue *berval; - berval = ( BerValue* ) malloc( sizeof( BerValue ) ); - berval -> bv_val = (char*) malloc( vallen ); - berval -> bv_len = vallen; - memcpy( berval -> bv_val, value.data(), vallen ); - - 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; - kdDebug(7125) << "addModOp: new bervalue struct " << endl; - } 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 ) { - kdError() << "addModOp: realloc" << endl; - return; - } - mods[ i ]->mod_vals.modv_bvals[ j ] = berval; - mods[ i ]->mod_vals.modv_bvals[ j+1 ] = 0; - kdDebug(7125) << j << ". new bervalue " << endl; - } -} - -void LDAPProtocol::LDAPEntry2UDSEntry( const TQString &dn, UDSEntry &entry, - const LDAPUrl &usrc, bool dir ) -{ - UDSAtom atom; - - int pos; - entry.clear(); - atom.m_uds = UDS_NAME; - atom.m_long = 0; - TQString name = dn; - if ( (pos = name.find(",")) > 0 ) - name = name.left( pos ); - if ( (pos = name.find("=")) > 0 ) - name.remove( 0, pos+1 ); - name.replace(' ', "_"); - if ( !dir ) name += ".ldif"; - atom.m_str = name; - entry.append( atom ); - - // the file type - atom.m_uds = UDS_FILE_TYPE; - atom.m_str = ""; - atom.m_long = dir ? S_IFDIR : S_IFREG; - entry.append( atom ); - - // the mimetype - if (!dir) { - atom.m_uds = UDS_MIME_TYPE; - atom.m_long = 0; - atom.m_str = "text/plain"; - entry.append( atom ); - } - - atom.m_uds = UDS_ACCESS; - atom.m_long = dir ? 0500 : 0400; - entry.append( atom ); - - // the url - atom.m_uds = UDS_URL; - atom.m_long = 0; - LDAPUrl url; - url=usrc; - - url.setPath("/"+dn); - url.setScope( dir ? LDAPUrl::One : LDAPUrl::Base ); - atom.m_str = url.prettyURL(); - entry.append( atom ); -} - -void LDAPProtocol::changeCheck( LDAPUrl &url ) -{ - bool critical; - bool tls = ( url.hasExtension( "x-tls" ) ); - int ver = 3; - if ( url.hasExtension( "x-ver" ) ) - ver = url.extension( "x-ver", critical).toInt(); - bool authSASL = url.hasExtension( "x-sasl" ); - TQString mech; - if ( url.hasExtension( "x-mech" ) ) - mech = url.extension( "x-mech", critical).upper(); - TQString realm; - if ( url.hasExtension( "x-realm" ) ) - mech = url.extension( "x-realm", critical).upper(); - TQString bindname; - if ( url.hasExtension( "bindname" ) ) - bindname = url.extension( "bindname", critical).upper(); - int timelimit = 0; - if ( url.hasExtension( "x-timelimit" ) ) - timelimit = url.extension( "x-timelimit", critical).toInt(); - int sizelimit = 0; - if ( url.hasExtension( "x-sizelimit" ) ) - sizelimit = url.extension( "x-sizelimit", critical).toInt(); - - if ( !authSASL && bindname.isEmpty() ) bindname = mUser; - - if ( tls != mTLS || ver != mVer || authSASL != mAuthSASL || mech != mMech || - mRealm != realm || mBindName != bindname || mTimeLimit != timelimit || - mSizeLimit != sizelimit ) { - closeConnection(); - mTLS = tls; - mVer = ver; - mAuthSASL = authSASL; - mMech = mech; - mRealm = realm; - mBindName = bindname; - mTimeLimit = timelimit; - mSizeLimit = sizelimit; - kdDebug(7125) << "parameters changed: tls = " << mTLS << - " version: " << mVer << "SASLauth: " << mAuthSASL << endl; - openConnection(); - if ( mAuthSASL ) { - url.setUser( mUser ); - } else { - url.setUser( mBindName ); - } - } else { - if ( !mLDAP ) openConnection(); - } -} - -void LDAPProtocol::setHost( const TQString& host, int port, - const TQString& user, const TQString& password ) -{ - - if( mHost != host || mPort != port || mUser != user || mPassword != password ) - closeConnection(); - - mHost = host; - if( port > 0 ) - mPort = port; - else { - struct servent *pse; - if ( (pse = getservbyname(mProtocol, "tcp")) == NULL ) - if ( mProtocol == "ldaps" ) - mPort = 636; - else - mPort = 389; - else - mPort = ntohs( pse->s_port ); - } - mUser = user; - mPassword = password; - - kdDebug(7125) << "setHost: " << host << " port: " << port << " user: " << - mUser << " pass: [protected]" << endl; -} - -static int kldap_sasl_interact( LDAP *, unsigned, void *slave, void *in ) -{ - return ((LDAPProtocol*) slave)->saslInteract( in ); -} - -void LDAPProtocol::fillAuthInfo( AuthInfo &info ) -{ - info.url.setProtocol( mProtocol ); - info.url.setHost( mHost ); - info.url.setPort( mPort ); - info.url.setUser( mUser ); - info.caption = i18n("LDAP Login"); - info.comment = TQString::fromLatin1( mProtocol ) + "://" + mHost + ":" + - TQString::number( mPort ); - info.commentLabel = i18n("site:"); - info.username = mAuthSASL ? mUser : mBindName; - info.password = mPassword; - info.keepPassword = true; -} - -int LDAPProtocol::saslInteract( void *in ) -{ -#if defined HAVE_SASL_H || defined HAVE_SASL_SASL_H - AuthInfo info; - fillAuthInfo( info ); - - sasl_interact_t *interact = ( sasl_interact_t * ) in; - - //some mechanisms do not require username && pass, so it doesn't need a popup - //window for getting this info - for ( ; interact->id != SASL_CB_LIST_END; interact++ ) { - if ( interact->id == SASL_CB_AUTHNAME || - interact->id == SASL_CB_PASS ) { - - if ( info.username.isEmpty() || info.password.isEmpty() ) { - - const bool cached = checkCachedAuthentication( info ); - - if ( ! ( ( mFirstAuth && cached ) || - ( mFirstAuth ? - openPassDlg( info ) : - openPassDlg( info, i18n("Invalid authorization information.") ) ) ) ) { - kdDebug(7125) << "Dialog cancelled!" << endl; - mCancel = true; - return LDAP_USER_CANCELLED; - } - mUser = info.username; - mPassword = info.password; - } - break; - } - } - - interact = ( sasl_interact_t * ) in; - TQString value; - - while( interact->id != SASL_CB_LIST_END ) { - value = ""; - switch( interact->id ) { - case SASL_CB_GETREALM: - value = mRealm; - kdDebug(7125) << "SASL_REALM=" << mRealm << endl; - break; - case SASL_CB_AUTHNAME: - value = mUser; - kdDebug(7125) << "SASL_AUTHNAME=" << mUser << endl; - break; - case SASL_CB_PASS: - value = mPassword; - kdDebug(7125) << "SASL_PASSWD=[hidden]" << endl; - break; - case SASL_CB_USER: - value = mBindName; - kdDebug(7125) << "SASL_AUTHZID=" << mBindName << endl; - break; - } - if ( value.isEmpty() ) { - interact->result = NULL; - interact->len = 0; - } else { - interact->result = strdup( value.utf8() ); - interact->len = strlen( (const char *) interact->result ); - } - interact++; - } - -#endif - return LDAP_SUCCESS; -} - -void LDAPProtocol::openConnection() -{ - if ( mLDAP ) return; - - int version,ret; - - version = ( mVer == 2 ) ? LDAP_VERSION2 : LDAP_VERSION3; - - KURL Url; - Url.setProtocol( mProtocol ); - Url.setHost( mHost ); - Url.setPort( mPort ); - - AuthInfo info; - fillAuthInfo( info ); -/////////////////////////////////////////////////////////////////////////// - kdDebug(7125) << "OpenConnection to " << mHost << ":" << mPort << endl; - - ret = ldap_initialize( &mLDAP, Url.htmlURL().utf8() ); - if ( ret != LDAP_SUCCESS ) { - LDAPErr( Url, ret ); - return; - } - - if ( (ldap_set_option( mLDAP, LDAP_OPT_PROTOCOL_VERSION, &version )) != - LDAP_OPT_SUCCESS ) { - - closeConnection(); - error( ERR_UNSUPPORTED_ACTION, - i18n("Cannot set LDAP protocol version %1").arg(version) ); - return; - } - - if ( mTLS ) { - kdDebug(7125) << "start TLS" << endl; - if ( ( ret = ldap_start_tls_s( mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) { - LDAPErr( Url ); - return; - } - } - - if ( mSizeLimit ) { - kdDebug(7125) << "sizelimit: " << mSizeLimit << endl; - if ( ldap_set_option( mLDAP, LDAP_OPT_SIZELIMIT, &mSizeLimit ) != LDAP_SUCCESS ) { - closeConnection(); - error( ERR_UNSUPPORTED_ACTION, - i18n("Cannot set size limit.")); - return; - } - } - - if ( mTimeLimit ) { - kdDebug(7125) << "timelimit: " << mTimeLimit << endl; - if ( ldap_set_option( mLDAP, LDAP_OPT_TIMELIMIT, &mTimeLimit ) != LDAP_SUCCESS ) { - closeConnection(); - error( ERR_UNSUPPORTED_ACTION, - i18n("Cannot set time limit.")); - return; - } - } - -#if !defined HAVE_SASL_H && !defined HAVE_SASL_SASL_H - if ( mAuthSASL ) { - closeConnection(); - error( ERR_SLAVE_DEFINED, - i18n("SASL authentication not compiled into the ldap ioslave.") ); - return; - } -#endif - - bool auth = false; - TQString mechanism = mMech.isEmpty() ? "DIGEST-MD5" : mMech; - mFirstAuth = true; mCancel = false; - - const bool cached = checkCachedAuthentication( info ); - - ret = LDAP_SUCCESS; - while (!auth) { - if ( !mAuthSASL && ( - ( mFirstAuth && - !( mBindName.isEmpty() && mPassword.isEmpty() ) && //For anonymous bind - ( mBindName.isEmpty() || mPassword.isEmpty() ) ) || !mFirstAuth ) ) - { - if ( ( mFirstAuth && cached ) || - ( mFirstAuth ? - openPassDlg( info ) : - openPassDlg( info, i18n("Invalid authorization information.") ) ) ) { - - mBindName = info.username; - mPassword = info.password; - } else { - kdDebug(7125) << "Dialog cancelled!" << endl; - error( ERR_USER_CANCELED, TQString::null ); - closeConnection(); - return; - } - } - kdDebug(7125) << "user: " << mUser << " bindname: " << mBindName << endl; - ret = -#if defined HAVE_SASL_H || defined HAVE_SASL_SASL_H - mAuthSASL ? - ldap_sasl_interactive_bind_s( mLDAP, NULL, mechanism.utf8(), - NULL, NULL, LDAP_SASL_INTERACTIVE, &kldap_sasl_interact, this ) : -#endif - ldap_simple_bind_s( mLDAP, mBindName.utf8(), mPassword.utf8() ); - - mFirstAuth = false; - if ( ret != LDAP_INVALID_CREDENTIALS && - ret != LDAP_INSUFFICIENT_ACCESS && - ret != LDAP_INAPPROPRIATE_AUTH ) { - kdDebug(7125) << "ldap_bind retval: " << ret << endl; - auth = true; - if ( ret != LDAP_SUCCESS ) { - if ( mCancel ) - error( ERR_USER_CANCELED, TQString::null ); - else - LDAPErr( Url ); - closeConnection(); - return; - } - } - } - - kdDebug(7125) << "connected!" << endl; - connected(); -} - -void LDAPProtocol::closeConnection() -{ - if (mLDAP) ldap_unbind(mLDAP); - mLDAP = 0; - kdDebug(7125) << "connection closed!" << endl; -} - -/** - * Get the information contained in the URL. - */ -void LDAPProtocol::get( const KURL &_url ) -{ - kdDebug(7125) << "get(" << _url << ")" << endl; - - LDAPUrl usrc(_url); - int ret, id; - LDAPMessage *msg,*entry; - - changeCheck( usrc ); - if ( !mLDAP ) { - finished(); - return; - } - - if ( (id = asyncSearch( usrc )) == -1 ) { - LDAPErr( _url ); - return; - } - - // tell the mimetype - mimeType("text/plain"); - // collect the result - TQCString result; - filesize_t processed_size = 0; - TQByteArray array; - - while( true ) { - ret = ldap_result( mLDAP, id, 0, NULL, &msg ); - if ( ret == -1 ) { - LDAPErr( _url ); - return; - } - kdDebug(7125) << " ldap_result: " << ret << endl; - if ( ret == LDAP_RES_SEARCH_RESULT ) break; - if ( ret != LDAP_RES_SEARCH_ENTRY ) continue; - - entry = ldap_first_entry( mLDAP, msg ); - while ( entry ) { - result = LDAPEntryAsLDIF(entry); - result += '\n'; - uint len = result.length(); - processed_size += len; - array.setRawData( result.data(), len ); - data(array); - processedSize( processed_size ); - array.resetRawData( result.data(), len ); - - entry = ldap_next_entry( mLDAP, entry ); - } - LDAPErr( _url ); - - ldap_msgfree(msg); - // tell the length - } - - totalSize(processed_size); - - array.resize(0); - // tell we are finished - data(array); - - // tell we are finished - finished(); -} - -/** - * Test if the url contains a directory or a file. - */ -void LDAPProtocol::stat( const KURL &_url ) -{ - kdDebug(7125) << "stat(" << _url << ")" << endl; - - TQStringList att,saveatt; - LDAPUrl usrc(_url); - LDAPMessage *msg; - int ret, id; - - changeCheck( usrc ); - if ( !mLDAP ) { - finished(); - return; - } - - // look how many entries match - saveatt = usrc.attributes(); - att.append( "dn" ); - usrc.setAttributes( att ); - if ( _url.query().isEmpty() ) usrc.setScope( LDAPUrl::One ); - - if ( (id = asyncSearch( usrc )) == -1 ) { - LDAPErr( _url ); - return; - } - - kdDebug(7125) << "stat() getting result" << endl; - do { - ret = ldap_result( mLDAP, id, 0, NULL, &msg ); - if ( ret == -1 ) { - LDAPErr( _url ); - return; - } - if ( ret == LDAP_RES_SEARCH_RESULT ) { - ldap_msgfree( msg ); - error( ERR_DOES_NOT_EXIST, _url.prettyURL() ); - return; - } - } while ( ret != LDAP_RES_SEARCH_ENTRY ); - - ldap_msgfree( msg ); - ldap_abandon( mLDAP, id ); - - usrc.setAttributes( saveatt ); - - UDSEntry uds; - bool critical; - LDAPEntry2UDSEntry( usrc.dn(), uds, usrc, usrc.extension("x-dir", critical) != "base" ); - - statEntry( uds ); - // we are done - finished(); -} - -/** - * Deletes one entry; - */ -void LDAPProtocol::del( const KURL &_url, bool ) -{ - kdDebug(7125) << "del(" << _url << ")" << endl; - - LDAPUrl usrc(_url); - int ret; - - changeCheck( usrc ); - if ( !mLDAP ) { - finished(); - return; - } - - kdDebug(7125) << " del: " << usrc.dn().utf8() << endl ; - - if ( (ret = ldap_delete_s( mLDAP,usrc.dn().utf8() )) != LDAP_SUCCESS ) { - LDAPErr( _url ); - return; - } - finished(); -} - -#define FREELDAPMEM { \ - ldap_mods_free( lmod, 1 ); \ - ldap_controls_free( serverctrls ); \ - ldap_controls_free( clientctrls ); \ - lmod = 0; serverctrls = 0; clientctrls = 0; \ - } - -void LDAPProtocol::put( const KURL &_url, int, bool overwrite, bool ) -{ - kdDebug(7125) << "put(" << _url << ")" << endl; - - LDAPUrl usrc(_url); - - changeCheck( usrc ); - if ( !mLDAP ) { - finished(); - return; - } - - LDAPMod **lmod = 0; - LDAPControl **serverctrls = 0, **clientctrls = 0; - TQByteArray buffer; - int result = 0; - LDIF::ParseVal ret; - LDIF ldif; - ret = LDIF::MoreData; - int ldaperr; - - - do { - if ( ret == LDIF::MoreData ) { - dataReq(); // Request for data - result = readData( buffer ); - ldif.setLDIF( buffer ); - } - if ( result < 0 ) { - //error - FREELDAPMEM; - return; - } - if ( result == 0 ) { - kdDebug(7125) << "EOF!" << endl; - ldif.endLDIF(); - } - do { - - ret = ldif.nextItem(); - kdDebug(7125) << "nextitem: " << ret << endl; - - switch ( ret ) { - case LDIF::None: - case LDIF::NewEntry: - case LDIF::MoreData: - break; - case LDIF::EndEntry: - ldaperr = LDAP_SUCCESS; - switch ( ldif.entryType() ) { - case LDIF::Entry_None: - error( ERR_INTERNAL, i18n("The LDIF parser failed.") ); - FREELDAPMEM; - return; - case LDIF::Entry_Del: - kdDebug(7125) << "kio_ldap_del" << endl; - controlsFromMetaData( &serverctrls, &clientctrls ); - ldaperr = ldap_delete_ext_s( mLDAP, ldif.dn().utf8(), - serverctrls, clientctrls ); - FREELDAPMEM; - break; - case LDIF::Entry_Modrdn: - kdDebug(7125) << "kio_ldap_modrdn olddn:" << ldif.dn() << - " newRdn: " << ldif.newRdn() << - " newSuperior: " << ldif.newSuperior() << - " deloldrdn: " << ldif.delOldRdn() << endl; - controlsFromMetaData( &serverctrls, &clientctrls ); - ldaperr = ldap_rename_s( mLDAP, ldif.dn().utf8(), ldif.newRdn().utf8(), - ldif.newSuperior().isEmpty() ? TQCString() : ldif.newSuperior().utf8(), - ldif.delOldRdn(), serverctrls, clientctrls ); - - FREELDAPMEM; - break; - case LDIF::Entry_Mod: - kdDebug(7125) << "kio_ldap_mod" << endl; - if ( lmod ) { - controlsFromMetaData( &serverctrls, &clientctrls ); - ldaperr = ldap_modify_ext_s( mLDAP, ldif.dn().utf8(), lmod, - serverctrls, clientctrls ); - FREELDAPMEM; - } - break; - case LDIF::Entry_Add: - kdDebug(7125) << "kio_ldap_add " << ldif.dn() << endl; - if ( lmod ) { - controlsFromMetaData( &serverctrls, &clientctrls ); - ldaperr = ldap_add_ext_s( mLDAP, ldif.dn().utf8(), lmod, - serverctrls, clientctrls ); - if ( ldaperr == LDAP_ALREADY_EXISTS && overwrite ) { - kdDebug(7125) << ldif.dn() << " already exists, delete first" << endl; - ldaperr = ldap_delete_s( mLDAP, ldif.dn().utf8() ); - if ( ldaperr == LDAP_SUCCESS ) - ldaperr = ldap_add_ext_s( mLDAP, ldif.dn().utf8(), lmod, - serverctrls, clientctrls ); - } - FREELDAPMEM; - } - break; - } - if ( ldaperr != LDAP_SUCCESS ) { - kdDebug(7125) << "put ldap error: " << ldap_err2string(ldaperr) << endl; - LDAPErr( _url ); - FREELDAPMEM; - return; - } - break; - case LDIF::Item: - switch ( ldif.entryType() ) { - case LDIF::Entry_Mod: { - int modtype = 0; - switch ( ldif.modType() ) { - case LDIF::Mod_None: - modtype = 0; - break; - case LDIF::Mod_Add: - modtype = LDAP_MOD_ADD; - break; - case LDIF::Mod_Replace: - modtype = LDAP_MOD_REPLACE; - break; - case LDIF::Mod_Del: - modtype = LDAP_MOD_DELETE; - break; - } - addModOp( &lmod, modtype, ldif.attr(), ldif.val() ); - break; - } - case LDIF::Entry_Add: - if ( ldif.val().size() > 0 ) - addModOp( &lmod, 0, ldif.attr(), ldif.val() ); - break; - default: - error( ERR_INTERNAL, i18n("The LDIF parser failed.") ); - FREELDAPMEM; - return; - } - break; - case LDIF::Control: - addControlOp( &serverctrls, ldif.oid(), ldif.val(), ldif.critical() ); - break; - case LDIF::Err: - error( ERR_SLAVE_DEFINED, - i18n( "Invalid LDIF file in line %1." ).arg( ldif.lineNo() ) ); - FREELDAPMEM; - return; - } - } while ( ret != LDIF::MoreData ); - } while ( result > 0 ); - - FREELDAPMEM; - finished(); -} - -/** - * List the contents of a directory. - */ -void LDAPProtocol::listDir( const KURL &_url ) -{ - int ret, ret2, id, id2; - unsigned long total=0; - char *dn; - TQStringList att,saveatt; - LDAPMessage *entry,*msg,*entry2,*msg2; - LDAPUrl usrc(_url),usrc2; - bool critical; - bool isSub = ( usrc.extension( "x-dir", critical ) == "sub" ); - - kdDebug(7125) << "listDir(" << _url << ")" << endl; - - changeCheck( usrc ); - if ( !mLDAP ) { - finished(); - return; - } - usrc2 = usrc; - - saveatt = usrc.attributes(); - // look up the entries - if ( isSub ) { - att.append("dn"); - usrc.setAttributes(att); - } - if ( _url.query().isEmpty() ) usrc.setScope( LDAPUrl::One ); - - if ( (id = asyncSearch( usrc )) == -1 ) { - LDAPErr( _url ); - return; - } - - usrc.setAttributes( "" ); - usrc.setExtension( "x-dir", "base" ); - // publish the results - UDSEntry uds; - - while( true ) { - ret = ldap_result( mLDAP, id, 0, NULL, &msg ); - if ( ret == -1 ) { - LDAPErr( _url ); - return; - } - if ( ret == LDAP_RES_SEARCH_RESULT ) break; - if ( ret != LDAP_RES_SEARCH_ENTRY ) continue; - kdDebug(7125) << " ldap_result: " << ret << endl; - - entry = ldap_first_entry( mLDAP, msg ); - while( entry ) { - - total++; - uds.clear(); - - dn = ldap_get_dn( mLDAP, entry ); - kdDebug(7125) << "dn: " << dn << endl; - LDAPEntry2UDSEntry( TQString::fromUtf8(dn), uds, usrc ); - listEntry( uds, false ); -// processedSize( total ); - kdDebug(7125) << " total: " << total << " " << usrc.prettyURL() << endl; - - // publish the sub-directories (if dirmode==sub) - if ( isSub ) { - usrc2.setDn( TQString::fromUtf8( dn ) ); - usrc2.setScope( LDAPUrl::One ); - usrc2.setAttributes( att ); - usrc2.setFilter( TQString::null ); - kdDebug(7125) << "search2 " << dn << endl; - if ( (id2 = asyncSearch( usrc2 )) != -1 ) { - while ( true ) { - kdDebug(7125) << " next result " << endl; - ret2 = ldap_result( mLDAP, id2, 0, NULL, &msg2 ); - if ( ret2 == -1 ) break; - if ( ret2 == LDAP_RES_SEARCH_RESULT ) { - ldap_msgfree( msg2 ); - break; - } - if ( ret2 == LDAP_RES_SEARCH_ENTRY ) { - entry2=ldap_first_entry( mLDAP, msg2 ); - if ( entry2 ) { - usrc2.setAttributes( saveatt ); - usrc2.setFilter( usrc.filter() ); - LDAPEntry2UDSEntry( TQString::fromUtf8( dn ), uds, usrc2, true ); - listEntry( uds, false ); - total++; - } - ldap_msgfree( msg2 ); - ldap_abandon( mLDAP, id2 ); - break; - } - } - } - } - free( dn ); - - entry = ldap_next_entry( mLDAP, entry ); - } - LDAPErr( _url ); - ldap_msgfree( msg ); - } - -// totalSize( total ); - - uds.clear(); - listEntry( uds, true ); - // we are done - finished(); -} diff --git a/tdeioslave/ldap/kio_ldap.h b/tdeioslave/ldap/kio_ldap.h deleted file mode 100644 index f3bd61fe5..000000000 --- a/tdeioslave/ldap/kio_ldap.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __LDAP_H__ -#define __LDAP_H__ - -#include -#include - -#include -#include - -#define LDAP_DEPRECATED 1 /* Needed for ldap_simple_bind_s with openldap >= 2.3.x */ -#include -#include -#include - -class LDAPProtocol : public TDEIO::SlaveBase -{ - public: - LDAPProtocol( const TQCString &protocol, const TQCString &pool, const TQCString &app ); - virtual ~LDAPProtocol(); - - virtual void setHost( const TQString& host, int port, - const TQString& user, const TQString& pass ); - - virtual void openConnection(); - virtual void closeConnection(); - - virtual void get( const KURL& url ); - virtual void stat( const KURL& url ); - virtual void listDir( const KURL& url ); - virtual void del( const KURL& url, bool isfile ); - virtual void put( const KURL& url, int permissions, bool overwrite, bool resume ); - - int saslInteract( void *in ); - - private: - - TQString mHost; - int mPort; - TQString mUser; - TQString mPassword; - LDAP *mLDAP; - int mVer, mSizeLimit, mTimeLimit; - bool mTLS; - bool mAuthSASL; - TQString mMech,mRealm,mBindName; - bool mCancel, mFirstAuth; - - void controlsFromMetaData( LDAPControl ***serverctrls, - LDAPControl ***clientctrls ); - void addControlOp( LDAPControl ***pctrls, const TQString &oid, - const TQByteArray &value, bool critical ); - void addModOp( LDAPMod ***pmods, int mod_type, - const TQString &attr, const TQByteArray &value ); - void LDAPEntry2UDSEntry( const TQString &dn, TDEIO::UDSEntry &entry, - const KABC::LDAPUrl &usrc, bool dir=false ); - int asyncSearch( KABC::LDAPUrl &usrc ); - - TQCString LDAPEntryAsLDIF( LDAPMessage *msg ); - void LDAPErr( const KURL &url, int err = LDAP_SUCCESS ); - void changeCheck( KABC::LDAPUrl &url ); - - void fillAuthInfo( TDEIO::AuthInfo &info ); -}; - -#endif diff --git a/tdeioslave/ldap/ldap.protocol b/tdeioslave/ldap/ldap.protocol index 3e1e77b4b..3082c6cb7 100644 --- a/tdeioslave/ldap/ldap.protocol +++ b/tdeioslave/ldap/ldap.protocol @@ -1,5 +1,5 @@ [Protocol] -exec=kio_ldap +exec=tdeio_ldap protocol=ldap input=none output=filesystem diff --git a/tdeioslave/ldap/ldaps.protocol b/tdeioslave/ldap/ldaps.protocol index 1dd927506..2bcb2234c 100644 --- a/tdeioslave/ldap/ldaps.protocol +++ b/tdeioslave/ldap/ldaps.protocol @@ -1,5 +1,5 @@ [Protocol] -exec=kio_ldap +exec=tdeio_ldap protocol=ldaps input=none output=filesystem diff --git a/tdeioslave/ldap/tdeio_ldap.cpp b/tdeioslave/ldap/tdeio_ldap.cpp new file mode 100644 index 000000000..2e22e6994 --- /dev/null +++ b/tdeioslave/ldap/tdeio_ldap.cpp @@ -0,0 +1,1154 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_SASL_SASL_H //prefer libsasl2 +#include +#else +#ifdef HAVE_SASL_H +#include +#endif +#endif +#include + +#include "tdeio_ldap.h" + +using namespace TDEIO; +using namespace KABC; + +extern "C" { int KDE_EXPORT kdemain(int argc, char **argv); } + +/** + * The main program. + */ +int kdemain( int argc, char **argv ) +{ + TDEInstance instance( "tdeio_ldap" ); + + kdDebug(7125) << "Starting " << getpid() << endl; + + if ( argc != 4 ) { + kdError() << "Usage tdeio_ldap protocol pool app" << endl; + return -1; + } + + // let the protocol class do its work + LDAPProtocol slave( argv[1], argv[ 2 ], argv[ 3 ] ); + slave.dispatchLoop(); + + kdDebug( 7125 ) << "Done" << endl; + return 0; +} + +/** + * Initialize the ldap slave + */ +LDAPProtocol::LDAPProtocol( const TQCString &protocol, const TQCString &pool, + const TQCString &app ) : SlaveBase( protocol, pool, app ) +{ + mLDAP = 0; mTLS = 0; mVer = 3; mAuthSASL = false; + mRealm = ""; mBindName = ""; + mTimeLimit = mSizeLimit = 0; + kdDebug(7125) << "LDAPProtocol::LDAPProtocol (" << protocol << ")" << endl; +} + +LDAPProtocol::~LDAPProtocol() +{ + closeConnection(); +} + +void LDAPProtocol::LDAPErr( const KURL &url, int err ) +{ + + char *errmsg = 0; + if ( mLDAP ) { + if ( err == LDAP_SUCCESS ) ldap_get_option( mLDAP, LDAP_OPT_ERROR_NUMBER, &err ); + if ( err != LDAP_SUCCESS ) ldap_get_option( mLDAP, LDAP_OPT_ERROR_STRING, &errmsg ); + } + if ( err == LDAP_SUCCESS ) return; + kdDebug(7125) << "error code: " << err << " msg: " << ldap_err2string(err) << + " Additonal error message: '" << errmsg << "'" << endl; + TQString msg; + TQString extraMsg; + if ( errmsg ) { + if ( errmsg[0] ) + extraMsg = i18n("\nAdditional info: ") + TQString::fromUtf8( errmsg ); + free( errmsg ); + } + msg = url.prettyURL(); + if ( !extraMsg.isEmpty() ) msg += extraMsg; + + /* FIXME: No need to close on all errors */ + closeConnection(); + + switch (err) { +/* FIXME: is it worth mapping the following error codes to tdeio errors? + + LDAP_OPERATIONS_ERROR + LDAP_STRONG_AUTH_REQUIRED + LDAP_PROTOCOL_ERROR + LDAP_TIMELIMIT_EXCEEDED + LDAP_SIZELIMIT_EXCEEDED + LDAP_COMPARE_FALSE + LDAP_COMPARE_TRUE + LDAP_PARTIAL_RESULTS + LDAP_NO_SUCH_ATTRIBUTE + LDAP_UNDEFINED_TYPE + LDAP_INAPPROPRIATE_MATCHING + LDAP_CONSTRAINT_VIOLATION + LDAP_INVALID_SYNTAX + LDAP_NO_SUCH_OBJECT + LDAP_ALIAS_PROBLEM + LDAP_INVALID_DN_SYNTAX + LDAP_IS_LEAF + LDAP_ALIAS_DEREF_PROBLEM + LDAP_INAPPROPRIATE_AUTH + LDAP_BUSY + LDAP_UNAVAILABLE + LDAP_UNWILLING_TO_PERFORM + LDAP_LOOP_DETECT + LDAP_NAMING_VIOLATION + LDAP_OBJECT_CLASS_VIOLATION + LDAP_NOT_ALLOWED_ON_NONLEAF + LDAP_NOT_ALLOWED_ON_RDN + LDAP_NO_OBJECT_CLASS_MODS + LDAP_OTHER + LDAP_LOCAL_ERROR + LDAP_ENCODING_ERROR + LDAP_DECODING_ERROR + LDAP_FILTER_ERROR +*/ + case LDAP_AUTH_UNKNOWN: + case LDAP_INVALID_CREDENTIALS: + case LDAP_STRONG_AUTH_NOT_SUPPORTED: + error(ERR_COULD_NOT_AUTHENTICATE, msg); + break; + case LDAP_ALREADY_EXISTS: + error(ERR_FILE_ALREADY_EXIST, msg); + break; + case LDAP_INSUFFICIENT_ACCESS: + error(ERR_ACCESS_DENIED, msg); + break; + case LDAP_CONNECT_ERROR: + case LDAP_SERVER_DOWN: + error(ERR_COULD_NOT_CONNECT,msg); + break; + case LDAP_TIMEOUT: + error(ERR_SERVER_TIMEOUT,msg); + break; + case LDAP_PARAM_ERROR: + error(ERR_INTERNAL,msg); + break; + case LDAP_NO_MEMORY: + error(ERR_OUT_OF_MEMORY,msg); + break; + + default: + error( ERR_SLAVE_DEFINED, + i18n( "LDAP server returned the error: %1 %2\nThe LDAP URL was: %3" ). + arg( ldap_err2string(err)).arg( extraMsg ).arg( url.prettyURL() ) ); + } +} + +void LDAPProtocol::controlsFromMetaData( LDAPControl ***serverctrls, + LDAPControl ***clientctrls ) +{ + TQString oid; bool critical; TQByteArray value; + int i = 0; + while ( hasMetaData( TQString::fromLatin1("SERVER_CTRL%1").arg(i) ) ) { + TQCString val = metaData( TQString::fromLatin1("SERVER_CTRL%1").arg(i) ).utf8(); + LDIF::splitControl( val, oid, critical, value ); + kdDebug(7125) << "server ctrl #" << i << " value: " << val << + " oid: " << oid << " critical: " << critical << " value: " << + TQString(TQString::fromUtf8( value, value.size() )) << endl; + addControlOp( serverctrls, oid, value, critical ); + i++; + } + i = 0; + while ( hasMetaData( TQString::fromLatin1("CLIENT_CTRL%1").arg(i) ) ) { + TQCString val = metaData( TQString::fromLatin1("CLIENT_CTRL%1").arg(i) ).utf8(); + LDIF::splitControl( val, oid, critical, value ); + kdDebug(7125) << "client ctrl #" << i << " value: " << val << + " oid: " << oid << " critical: " << critical << " value: " << + TQString(TQString::fromUtf8( value, value.size() )) << endl; + addControlOp( clientctrls, oid, value, critical ); + i++; + } +} + +int LDAPProtocol::asyncSearch( LDAPUrl &usrc ) +{ + char **attrs = 0; + int msgid; + LDAPControl **serverctrls = 0, **clientctrls = 0; + + int count = usrc.attributes().count(); + if ( count > 0 ) { + attrs = static_cast( malloc((count+1) * sizeof(char*)) ); + for (int i=0; ibv_val; + unsigned long len = bvals[i]->bv_len; + tmp.setRawData( val, len ); + result += LDIF::assembleLine( TQString::fromUtf8( name ), tmp, 76 ) + '\n'; + tmp.resetRawData( val, len ); + } + ldap_value_free_len(bvals); + } + ldap_memfree( name ); + // next attribute + name = ldap_next_attribute(mLDAP, message, entry); + } + return result; +} + +void LDAPProtocol::addControlOp( LDAPControl ***pctrls, const TQString &oid, + const TQByteArray &value, bool critical ) +{ + LDAPControl **ctrls; + LDAPControl *ctrl = (LDAPControl *) malloc( sizeof( LDAPControl ) ); + + ctrls = *pctrls; + + kdDebug(7125) << "addControlOp: oid:'" << oid << "' val: '" << + TQString(TQString::fromUtf8(value, value.size())) << "'" << endl; + 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.utf8() ); + + 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; +} + +void LDAPProtocol::addModOp( LDAPMod ***pmods, int mod_type, const TQString &attr, + const TQByteArray &value ) +{ +// kdDebug(7125) << "type: " << mod_type << " attr: " << attr << +// " value: " << TQString::fromUtf8(value,value.size()) << +// " size: " << value.size() << endl; + 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.utf8(),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 ) { + kdError() << "addModOp: realloc" << endl; + 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.utf8() ); + + *pmods = mods; + + int vallen = value.size(); + if ( vallen == 0 ) return; + BerValue *berval; + berval = ( BerValue* ) malloc( sizeof( BerValue ) ); + berval -> bv_val = (char*) malloc( vallen ); + berval -> bv_len = vallen; + memcpy( berval -> bv_val, value.data(), vallen ); + + 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; + kdDebug(7125) << "addModOp: new bervalue struct " << endl; + } 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 ) { + kdError() << "addModOp: realloc" << endl; + return; + } + mods[ i ]->mod_vals.modv_bvals[ j ] = berval; + mods[ i ]->mod_vals.modv_bvals[ j+1 ] = 0; + kdDebug(7125) << j << ". new bervalue " << endl; + } +} + +void LDAPProtocol::LDAPEntry2UDSEntry( const TQString &dn, UDSEntry &entry, + const LDAPUrl &usrc, bool dir ) +{ + UDSAtom atom; + + int pos; + entry.clear(); + atom.m_uds = UDS_NAME; + atom.m_long = 0; + TQString name = dn; + if ( (pos = name.find(",")) > 0 ) + name = name.left( pos ); + if ( (pos = name.find("=")) > 0 ) + name.remove( 0, pos+1 ); + name.replace(' ', "_"); + if ( !dir ) name += ".ldif"; + atom.m_str = name; + entry.append( atom ); + + // the file type + atom.m_uds = UDS_FILE_TYPE; + atom.m_str = ""; + atom.m_long = dir ? S_IFDIR : S_IFREG; + entry.append( atom ); + + // the mimetype + if (!dir) { + atom.m_uds = UDS_MIME_TYPE; + atom.m_long = 0; + atom.m_str = "text/plain"; + entry.append( atom ); + } + + atom.m_uds = UDS_ACCESS; + atom.m_long = dir ? 0500 : 0400; + entry.append( atom ); + + // the url + atom.m_uds = UDS_URL; + atom.m_long = 0; + LDAPUrl url; + url=usrc; + + url.setPath("/"+dn); + url.setScope( dir ? LDAPUrl::One : LDAPUrl::Base ); + atom.m_str = url.prettyURL(); + entry.append( atom ); +} + +void LDAPProtocol::changeCheck( LDAPUrl &url ) +{ + bool critical; + bool tls = ( url.hasExtension( "x-tls" ) ); + int ver = 3; + if ( url.hasExtension( "x-ver" ) ) + ver = url.extension( "x-ver", critical).toInt(); + bool authSASL = url.hasExtension( "x-sasl" ); + TQString mech; + if ( url.hasExtension( "x-mech" ) ) + mech = url.extension( "x-mech", critical).upper(); + TQString realm; + if ( url.hasExtension( "x-realm" ) ) + mech = url.extension( "x-realm", critical).upper(); + TQString bindname; + if ( url.hasExtension( "bindname" ) ) + bindname = url.extension( "bindname", critical).upper(); + int timelimit = 0; + if ( url.hasExtension( "x-timelimit" ) ) + timelimit = url.extension( "x-timelimit", critical).toInt(); + int sizelimit = 0; + if ( url.hasExtension( "x-sizelimit" ) ) + sizelimit = url.extension( "x-sizelimit", critical).toInt(); + + if ( !authSASL && bindname.isEmpty() ) bindname = mUser; + + if ( tls != mTLS || ver != mVer || authSASL != mAuthSASL || mech != mMech || + mRealm != realm || mBindName != bindname || mTimeLimit != timelimit || + mSizeLimit != sizelimit ) { + closeConnection(); + mTLS = tls; + mVer = ver; + mAuthSASL = authSASL; + mMech = mech; + mRealm = realm; + mBindName = bindname; + mTimeLimit = timelimit; + mSizeLimit = sizelimit; + kdDebug(7125) << "parameters changed: tls = " << mTLS << + " version: " << mVer << "SASLauth: " << mAuthSASL << endl; + openConnection(); + if ( mAuthSASL ) { + url.setUser( mUser ); + } else { + url.setUser( mBindName ); + } + } else { + if ( !mLDAP ) openConnection(); + } +} + +void LDAPProtocol::setHost( const TQString& host, int port, + const TQString& user, const TQString& password ) +{ + + if( mHost != host || mPort != port || mUser != user || mPassword != password ) + closeConnection(); + + mHost = host; + if( port > 0 ) + mPort = port; + else { + struct servent *pse; + if ( (pse = getservbyname(mProtocol, "tcp")) == NULL ) + if ( mProtocol == "ldaps" ) + mPort = 636; + else + mPort = 389; + else + mPort = ntohs( pse->s_port ); + } + mUser = user; + mPassword = password; + + kdDebug(7125) << "setHost: " << host << " port: " << port << " user: " << + mUser << " pass: [protected]" << endl; +} + +static int kldap_sasl_interact( LDAP *, unsigned, void *slave, void *in ) +{ + return ((LDAPProtocol*) slave)->saslInteract( in ); +} + +void LDAPProtocol::fillAuthInfo( AuthInfo &info ) +{ + info.url.setProtocol( mProtocol ); + info.url.setHost( mHost ); + info.url.setPort( mPort ); + info.url.setUser( mUser ); + info.caption = i18n("LDAP Login"); + info.comment = TQString::fromLatin1( mProtocol ) + "://" + mHost + ":" + + TQString::number( mPort ); + info.commentLabel = i18n("site:"); + info.username = mAuthSASL ? mUser : mBindName; + info.password = mPassword; + info.keepPassword = true; +} + +int LDAPProtocol::saslInteract( void *in ) +{ +#if defined HAVE_SASL_H || defined HAVE_SASL_SASL_H + AuthInfo info; + fillAuthInfo( info ); + + sasl_interact_t *interact = ( sasl_interact_t * ) in; + + //some mechanisms do not require username && pass, so it doesn't need a popup + //window for getting this info + for ( ; interact->id != SASL_CB_LIST_END; interact++ ) { + if ( interact->id == SASL_CB_AUTHNAME || + interact->id == SASL_CB_PASS ) { + + if ( info.username.isEmpty() || info.password.isEmpty() ) { + + const bool cached = checkCachedAuthentication( info ); + + if ( ! ( ( mFirstAuth && cached ) || + ( mFirstAuth ? + openPassDlg( info ) : + openPassDlg( info, i18n("Invalid authorization information.") ) ) ) ) { + kdDebug(7125) << "Dialog cancelled!" << endl; + mCancel = true; + return LDAP_USER_CANCELLED; + } + mUser = info.username; + mPassword = info.password; + } + break; + } + } + + interact = ( sasl_interact_t * ) in; + TQString value; + + while( interact->id != SASL_CB_LIST_END ) { + value = ""; + switch( interact->id ) { + case SASL_CB_GETREALM: + value = mRealm; + kdDebug(7125) << "SASL_REALM=" << mRealm << endl; + break; + case SASL_CB_AUTHNAME: + value = mUser; + kdDebug(7125) << "SASL_AUTHNAME=" << mUser << endl; + break; + case SASL_CB_PASS: + value = mPassword; + kdDebug(7125) << "SASL_PASSWD=[hidden]" << endl; + break; + case SASL_CB_USER: + value = mBindName; + kdDebug(7125) << "SASL_AUTHZID=" << mBindName << endl; + break; + } + if ( value.isEmpty() ) { + interact->result = NULL; + interact->len = 0; + } else { + interact->result = strdup( value.utf8() ); + interact->len = strlen( (const char *) interact->result ); + } + interact++; + } + +#endif + return LDAP_SUCCESS; +} + +void LDAPProtocol::openConnection() +{ + if ( mLDAP ) return; + + int version,ret; + + version = ( mVer == 2 ) ? LDAP_VERSION2 : LDAP_VERSION3; + + KURL Url; + Url.setProtocol( mProtocol ); + Url.setHost( mHost ); + Url.setPort( mPort ); + + AuthInfo info; + fillAuthInfo( info ); +/////////////////////////////////////////////////////////////////////////// + kdDebug(7125) << "OpenConnection to " << mHost << ":" << mPort << endl; + + ret = ldap_initialize( &mLDAP, Url.htmlURL().utf8() ); + if ( ret != LDAP_SUCCESS ) { + LDAPErr( Url, ret ); + return; + } + + if ( (ldap_set_option( mLDAP, LDAP_OPT_PROTOCOL_VERSION, &version )) != + LDAP_OPT_SUCCESS ) { + + closeConnection(); + error( ERR_UNSUPPORTED_ACTION, + i18n("Cannot set LDAP protocol version %1").arg(version) ); + return; + } + + if ( mTLS ) { + kdDebug(7125) << "start TLS" << endl; + if ( ( ret = ldap_start_tls_s( mLDAP, NULL, NULL ) ) != LDAP_SUCCESS ) { + LDAPErr( Url ); + return; + } + } + + if ( mSizeLimit ) { + kdDebug(7125) << "sizelimit: " << mSizeLimit << endl; + if ( ldap_set_option( mLDAP, LDAP_OPT_SIZELIMIT, &mSizeLimit ) != LDAP_SUCCESS ) { + closeConnection(); + error( ERR_UNSUPPORTED_ACTION, + i18n("Cannot set size limit.")); + return; + } + } + + if ( mTimeLimit ) { + kdDebug(7125) << "timelimit: " << mTimeLimit << endl; + if ( ldap_set_option( mLDAP, LDAP_OPT_TIMELIMIT, &mTimeLimit ) != LDAP_SUCCESS ) { + closeConnection(); + error( ERR_UNSUPPORTED_ACTION, + i18n("Cannot set time limit.")); + return; + } + } + +#if !defined HAVE_SASL_H && !defined HAVE_SASL_SASL_H + if ( mAuthSASL ) { + closeConnection(); + error( ERR_SLAVE_DEFINED, + i18n("SASL authentication not compiled into the ldap ioslave.") ); + return; + } +#endif + + bool auth = false; + TQString mechanism = mMech.isEmpty() ? "DIGEST-MD5" : mMech; + mFirstAuth = true; mCancel = false; + + const bool cached = checkCachedAuthentication( info ); + + ret = LDAP_SUCCESS; + while (!auth) { + if ( !mAuthSASL && ( + ( mFirstAuth && + !( mBindName.isEmpty() && mPassword.isEmpty() ) && //For anonymous bind + ( mBindName.isEmpty() || mPassword.isEmpty() ) ) || !mFirstAuth ) ) + { + if ( ( mFirstAuth && cached ) || + ( mFirstAuth ? + openPassDlg( info ) : + openPassDlg( info, i18n("Invalid authorization information.") ) ) ) { + + mBindName = info.username; + mPassword = info.password; + } else { + kdDebug(7125) << "Dialog cancelled!" << endl; + error( ERR_USER_CANCELED, TQString::null ); + closeConnection(); + return; + } + } + kdDebug(7125) << "user: " << mUser << " bindname: " << mBindName << endl; + ret = +#if defined HAVE_SASL_H || defined HAVE_SASL_SASL_H + mAuthSASL ? + ldap_sasl_interactive_bind_s( mLDAP, NULL, mechanism.utf8(), + NULL, NULL, LDAP_SASL_INTERACTIVE, &kldap_sasl_interact, this ) : +#endif + ldap_simple_bind_s( mLDAP, mBindName.utf8(), mPassword.utf8() ); + + mFirstAuth = false; + if ( ret != LDAP_INVALID_CREDENTIALS && + ret != LDAP_INSUFFICIENT_ACCESS && + ret != LDAP_INAPPROPRIATE_AUTH ) { + kdDebug(7125) << "ldap_bind retval: " << ret << endl; + auth = true; + if ( ret != LDAP_SUCCESS ) { + if ( mCancel ) + error( ERR_USER_CANCELED, TQString::null ); + else + LDAPErr( Url ); + closeConnection(); + return; + } + } + } + + kdDebug(7125) << "connected!" << endl; + connected(); +} + +void LDAPProtocol::closeConnection() +{ + if (mLDAP) ldap_unbind(mLDAP); + mLDAP = 0; + kdDebug(7125) << "connection closed!" << endl; +} + +/** + * Get the information contained in the URL. + */ +void LDAPProtocol::get( const KURL &_url ) +{ + kdDebug(7125) << "get(" << _url << ")" << endl; + + LDAPUrl usrc(_url); + int ret, id; + LDAPMessage *msg,*entry; + + changeCheck( usrc ); + if ( !mLDAP ) { + finished(); + return; + } + + if ( (id = asyncSearch( usrc )) == -1 ) { + LDAPErr( _url ); + return; + } + + // tell the mimetype + mimeType("text/plain"); + // collect the result + TQCString result; + filesize_t processed_size = 0; + TQByteArray array; + + while( true ) { + ret = ldap_result( mLDAP, id, 0, NULL, &msg ); + if ( ret == -1 ) { + LDAPErr( _url ); + return; + } + kdDebug(7125) << " ldap_result: " << ret << endl; + if ( ret == LDAP_RES_SEARCH_RESULT ) break; + if ( ret != LDAP_RES_SEARCH_ENTRY ) continue; + + entry = ldap_first_entry( mLDAP, msg ); + while ( entry ) { + result = LDAPEntryAsLDIF(entry); + result += '\n'; + uint len = result.length(); + processed_size += len; + array.setRawData( result.data(), len ); + data(array); + processedSize( processed_size ); + array.resetRawData( result.data(), len ); + + entry = ldap_next_entry( mLDAP, entry ); + } + LDAPErr( _url ); + + ldap_msgfree(msg); + // tell the length + } + + totalSize(processed_size); + + array.resize(0); + // tell we are finished + data(array); + + // tell we are finished + finished(); +} + +/** + * Test if the url contains a directory or a file. + */ +void LDAPProtocol::stat( const KURL &_url ) +{ + kdDebug(7125) << "stat(" << _url << ")" << endl; + + TQStringList att,saveatt; + LDAPUrl usrc(_url); + LDAPMessage *msg; + int ret, id; + + changeCheck( usrc ); + if ( !mLDAP ) { + finished(); + return; + } + + // look how many entries match + saveatt = usrc.attributes(); + att.append( "dn" ); + usrc.setAttributes( att ); + if ( _url.query().isEmpty() ) usrc.setScope( LDAPUrl::One ); + + if ( (id = asyncSearch( usrc )) == -1 ) { + LDAPErr( _url ); + return; + } + + kdDebug(7125) << "stat() getting result" << endl; + do { + ret = ldap_result( mLDAP, id, 0, NULL, &msg ); + if ( ret == -1 ) { + LDAPErr( _url ); + return; + } + if ( ret == LDAP_RES_SEARCH_RESULT ) { + ldap_msgfree( msg ); + error( ERR_DOES_NOT_EXIST, _url.prettyURL() ); + return; + } + } while ( ret != LDAP_RES_SEARCH_ENTRY ); + + ldap_msgfree( msg ); + ldap_abandon( mLDAP, id ); + + usrc.setAttributes( saveatt ); + + UDSEntry uds; + bool critical; + LDAPEntry2UDSEntry( usrc.dn(), uds, usrc, usrc.extension("x-dir", critical) != "base" ); + + statEntry( uds ); + // we are done + finished(); +} + +/** + * Deletes one entry; + */ +void LDAPProtocol::del( const KURL &_url, bool ) +{ + kdDebug(7125) << "del(" << _url << ")" << endl; + + LDAPUrl usrc(_url); + int ret; + + changeCheck( usrc ); + if ( !mLDAP ) { + finished(); + return; + } + + kdDebug(7125) << " del: " << usrc.dn().utf8() << endl ; + + if ( (ret = ldap_delete_s( mLDAP,usrc.dn().utf8() )) != LDAP_SUCCESS ) { + LDAPErr( _url ); + return; + } + finished(); +} + +#define FREELDAPMEM { \ + ldap_mods_free( lmod, 1 ); \ + ldap_controls_free( serverctrls ); \ + ldap_controls_free( clientctrls ); \ + lmod = 0; serverctrls = 0; clientctrls = 0; \ + } + +void LDAPProtocol::put( const KURL &_url, int, bool overwrite, bool ) +{ + kdDebug(7125) << "put(" << _url << ")" << endl; + + LDAPUrl usrc(_url); + + changeCheck( usrc ); + if ( !mLDAP ) { + finished(); + return; + } + + LDAPMod **lmod = 0; + LDAPControl **serverctrls = 0, **clientctrls = 0; + TQByteArray buffer; + int result = 0; + LDIF::ParseVal ret; + LDIF ldif; + ret = LDIF::MoreData; + int ldaperr; + + + do { + if ( ret == LDIF::MoreData ) { + dataReq(); // Request for data + result = readData( buffer ); + ldif.setLDIF( buffer ); + } + if ( result < 0 ) { + //error + FREELDAPMEM; + return; + } + if ( result == 0 ) { + kdDebug(7125) << "EOF!" << endl; + ldif.endLDIF(); + } + do { + + ret = ldif.nextItem(); + kdDebug(7125) << "nextitem: " << ret << endl; + + switch ( ret ) { + case LDIF::None: + case LDIF::NewEntry: + case LDIF::MoreData: + break; + case LDIF::EndEntry: + ldaperr = LDAP_SUCCESS; + switch ( ldif.entryType() ) { + case LDIF::Entry_None: + error( ERR_INTERNAL, i18n("The LDIF parser failed.") ); + FREELDAPMEM; + return; + case LDIF::Entry_Del: + kdDebug(7125) << "tdeio_ldap_del" << endl; + controlsFromMetaData( &serverctrls, &clientctrls ); + ldaperr = ldap_delete_ext_s( mLDAP, ldif.dn().utf8(), + serverctrls, clientctrls ); + FREELDAPMEM; + break; + case LDIF::Entry_Modrdn: + kdDebug(7125) << "tdeio_ldap_modrdn olddn:" << ldif.dn() << + " newRdn: " << ldif.newRdn() << + " newSuperior: " << ldif.newSuperior() << + " deloldrdn: " << ldif.delOldRdn() << endl; + controlsFromMetaData( &serverctrls, &clientctrls ); + ldaperr = ldap_rename_s( mLDAP, ldif.dn().utf8(), ldif.newRdn().utf8(), + ldif.newSuperior().isEmpty() ? TQCString() : ldif.newSuperior().utf8(), + ldif.delOldRdn(), serverctrls, clientctrls ); + + FREELDAPMEM; + break; + case LDIF::Entry_Mod: + kdDebug(7125) << "tdeio_ldap_mod" << endl; + if ( lmod ) { + controlsFromMetaData( &serverctrls, &clientctrls ); + ldaperr = ldap_modify_ext_s( mLDAP, ldif.dn().utf8(), lmod, + serverctrls, clientctrls ); + FREELDAPMEM; + } + break; + case LDIF::Entry_Add: + kdDebug(7125) << "tdeio_ldap_add " << ldif.dn() << endl; + if ( lmod ) { + controlsFromMetaData( &serverctrls, &clientctrls ); + ldaperr = ldap_add_ext_s( mLDAP, ldif.dn().utf8(), lmod, + serverctrls, clientctrls ); + if ( ldaperr == LDAP_ALREADY_EXISTS && overwrite ) { + kdDebug(7125) << ldif.dn() << " already exists, delete first" << endl; + ldaperr = ldap_delete_s( mLDAP, ldif.dn().utf8() ); + if ( ldaperr == LDAP_SUCCESS ) + ldaperr = ldap_add_ext_s( mLDAP, ldif.dn().utf8(), lmod, + serverctrls, clientctrls ); + } + FREELDAPMEM; + } + break; + } + if ( ldaperr != LDAP_SUCCESS ) { + kdDebug(7125) << "put ldap error: " << ldap_err2string(ldaperr) << endl; + LDAPErr( _url ); + FREELDAPMEM; + return; + } + break; + case LDIF::Item: + switch ( ldif.entryType() ) { + case LDIF::Entry_Mod: { + int modtype = 0; + switch ( ldif.modType() ) { + case LDIF::Mod_None: + modtype = 0; + break; + case LDIF::Mod_Add: + modtype = LDAP_MOD_ADD; + break; + case LDIF::Mod_Replace: + modtype = LDAP_MOD_REPLACE; + break; + case LDIF::Mod_Del: + modtype = LDAP_MOD_DELETE; + break; + } + addModOp( &lmod, modtype, ldif.attr(), ldif.val() ); + break; + } + case LDIF::Entry_Add: + if ( ldif.val().size() > 0 ) + addModOp( &lmod, 0, ldif.attr(), ldif.val() ); + break; + default: + error( ERR_INTERNAL, i18n("The LDIF parser failed.") ); + FREELDAPMEM; + return; + } + break; + case LDIF::Control: + addControlOp( &serverctrls, ldif.oid(), ldif.val(), ldif.critical() ); + break; + case LDIF::Err: + error( ERR_SLAVE_DEFINED, + i18n( "Invalid LDIF file in line %1." ).arg( ldif.lineNo() ) ); + FREELDAPMEM; + return; + } + } while ( ret != LDIF::MoreData ); + } while ( result > 0 ); + + FREELDAPMEM; + finished(); +} + +/** + * List the contents of a directory. + */ +void LDAPProtocol::listDir( const KURL &_url ) +{ + int ret, ret2, id, id2; + unsigned long total=0; + char *dn; + TQStringList att,saveatt; + LDAPMessage *entry,*msg,*entry2,*msg2; + LDAPUrl usrc(_url),usrc2; + bool critical; + bool isSub = ( usrc.extension( "x-dir", critical ) == "sub" ); + + kdDebug(7125) << "listDir(" << _url << ")" << endl; + + changeCheck( usrc ); + if ( !mLDAP ) { + finished(); + return; + } + usrc2 = usrc; + + saveatt = usrc.attributes(); + // look up the entries + if ( isSub ) { + att.append("dn"); + usrc.setAttributes(att); + } + if ( _url.query().isEmpty() ) usrc.setScope( LDAPUrl::One ); + + if ( (id = asyncSearch( usrc )) == -1 ) { + LDAPErr( _url ); + return; + } + + usrc.setAttributes( "" ); + usrc.setExtension( "x-dir", "base" ); + // publish the results + UDSEntry uds; + + while( true ) { + ret = ldap_result( mLDAP, id, 0, NULL, &msg ); + if ( ret == -1 ) { + LDAPErr( _url ); + return; + } + if ( ret == LDAP_RES_SEARCH_RESULT ) break; + if ( ret != LDAP_RES_SEARCH_ENTRY ) continue; + kdDebug(7125) << " ldap_result: " << ret << endl; + + entry = ldap_first_entry( mLDAP, msg ); + while( entry ) { + + total++; + uds.clear(); + + dn = ldap_get_dn( mLDAP, entry ); + kdDebug(7125) << "dn: " << dn << endl; + LDAPEntry2UDSEntry( TQString::fromUtf8(dn), uds, usrc ); + listEntry( uds, false ); +// processedSize( total ); + kdDebug(7125) << " total: " << total << " " << usrc.prettyURL() << endl; + + // publish the sub-directories (if dirmode==sub) + if ( isSub ) { + usrc2.setDn( TQString::fromUtf8( dn ) ); + usrc2.setScope( LDAPUrl::One ); + usrc2.setAttributes( att ); + usrc2.setFilter( TQString::null ); + kdDebug(7125) << "search2 " << dn << endl; + if ( (id2 = asyncSearch( usrc2 )) != -1 ) { + while ( true ) { + kdDebug(7125) << " next result " << endl; + ret2 = ldap_result( mLDAP, id2, 0, NULL, &msg2 ); + if ( ret2 == -1 ) break; + if ( ret2 == LDAP_RES_SEARCH_RESULT ) { + ldap_msgfree( msg2 ); + break; + } + if ( ret2 == LDAP_RES_SEARCH_ENTRY ) { + entry2=ldap_first_entry( mLDAP, msg2 ); + if ( entry2 ) { + usrc2.setAttributes( saveatt ); + usrc2.setFilter( usrc.filter() ); + LDAPEntry2UDSEntry( TQString::fromUtf8( dn ), uds, usrc2, true ); + listEntry( uds, false ); + total++; + } + ldap_msgfree( msg2 ); + ldap_abandon( mLDAP, id2 ); + break; + } + } + } + } + free( dn ); + + entry = ldap_next_entry( mLDAP, entry ); + } + LDAPErr( _url ); + ldap_msgfree( msg ); + } + +// totalSize( total ); + + uds.clear(); + listEntry( uds, true ); + // we are done + finished(); +} diff --git a/tdeioslave/ldap/tdeio_ldap.h b/tdeioslave/ldap/tdeio_ldap.h new file mode 100644 index 000000000..f3bd61fe5 --- /dev/null +++ b/tdeioslave/ldap/tdeio_ldap.h @@ -0,0 +1,65 @@ +#ifndef __LDAP_H__ +#define __LDAP_H__ + +#include +#include + +#include +#include + +#define LDAP_DEPRECATED 1 /* Needed for ldap_simple_bind_s with openldap >= 2.3.x */ +#include +#include +#include + +class LDAPProtocol : public TDEIO::SlaveBase +{ + public: + LDAPProtocol( const TQCString &protocol, const TQCString &pool, const TQCString &app ); + virtual ~LDAPProtocol(); + + virtual void setHost( const TQString& host, int port, + const TQString& user, const TQString& pass ); + + virtual void openConnection(); + virtual void closeConnection(); + + virtual void get( const KURL& url ); + virtual void stat( const KURL& url ); + virtual void listDir( const KURL& url ); + virtual void del( const KURL& url, bool isfile ); + virtual void put( const KURL& url, int permissions, bool overwrite, bool resume ); + + int saslInteract( void *in ); + + private: + + TQString mHost; + int mPort; + TQString mUser; + TQString mPassword; + LDAP *mLDAP; + int mVer, mSizeLimit, mTimeLimit; + bool mTLS; + bool mAuthSASL; + TQString mMech,mRealm,mBindName; + bool mCancel, mFirstAuth; + + void controlsFromMetaData( LDAPControl ***serverctrls, + LDAPControl ***clientctrls ); + void addControlOp( LDAPControl ***pctrls, const TQString &oid, + const TQByteArray &value, bool critical ); + void addModOp( LDAPMod ***pmods, int mod_type, + const TQString &attr, const TQByteArray &value ); + void LDAPEntry2UDSEntry( const TQString &dn, TDEIO::UDSEntry &entry, + const KABC::LDAPUrl &usrc, bool dir=false ); + int asyncSearch( KABC::LDAPUrl &usrc ); + + TQCString LDAPEntryAsLDIF( LDAPMessage *msg ); + void LDAPErr( const KURL &url, int err = LDAP_SUCCESS ); + void changeCheck( KABC::LDAPUrl &url ); + + void fillAuthInfo( TDEIO::AuthInfo &info ); +}; + +#endif -- cgit v1.2.1