Version: (using KDE KDE 3.5.7) Installed from: Ubuntu Packages OS: Linux This error occurs, if another module (kio slave) already loaded the libsasl library and initialized the library. In smtp.cc the function sasl_client_init is called with a set of callback functions. If another user of libsasl already called this function before and specified a different set of callbacks (or NULL), the second set of callbacks is ignored an the first set is used. In the kio_smtp the callbacks must be specified to work with SASL mechanism which require callbacks to get username and password. But if the callbacks aren't installed because someone before has specified another set of callbacks all SASL mechanism which require callbacks aren't working (which left me with only two mechanisms EXTERNAL and ANONYMOUS). As a result i could not send mail over my mail server, because the authentification does not work. I think this issue also occurs on every other kioslave which uses the libsasl for authentication.
Created attachment 20815 [details] Fix callbacks for SMTP and POP3 kioslave The patch fixes the SASL callbacks for the SMTP and POP3 kioslaves. It simply specifies the callbacks for every connection (in sasl_client_new) instead of using the callbacks specified through sasl_client_init.
SVN commit 674951 by winterz: Fix bug "SASL Authentication fails if another client of sasl is loaded" Patch by Andreas. Thanks! BUGS: 146582 M +21 -9 pop3/pop3.cc M +23 -10 smtp/command.cc --- branches/KDE/3.5/kdebase/kioslave/pop3/pop3.cc #674950:674951 @@ -87,6 +87,18 @@ { SASL_CB_CANON_USER, NULL, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; + +static sasl_callback_t client_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_GETOPT, NULL, NULL }, + { SASL_CB_CANON_USER, NULL, NULL }, + { SASL_CB_LIST_END, NULL, NULL } +}; #endif int kdemain(int argc, char **argv) @@ -451,7 +463,7 @@ return true; #else return false; -#endif +#endif } #define SASLERROR closeConnection(); \ @@ -474,7 +486,7 @@ result = sasl_client_new( "pop", m_sServer.latin1(), - 0, 0, NULL, 0, &conn ); + 0, 0, client_callbacks, 0, &conn ); if ( result != SASL_OK ) { POP3_DEBUG << "sasl_client_new failed with: " << result << endl; @@ -505,7 +517,7 @@ } do { - result = sasl_client_start(conn, sasl_list.join(" ").latin1(), + result = sasl_client_start(conn, sasl_list.join(" ").latin1(), &client_interact, &out, &outlen, &mechusing); if (result == SASL_INTERACT) @@ -521,9 +533,9 @@ sasl_dispose( &conn ); return -1; } - + POP3_DEBUG << "Preferred authentication method is " << mechusing << "." << endl; - + QByteArray challenge, tmp; QString firstCommand = "AUTH " + QString::fromLatin1( mechusing ); @@ -534,7 +546,7 @@ firstCommand += " "; firstCommand += QString::fromLatin1( tmp.data(), tmp.size() ); } - + challenge.resize( 2049 ); resp = command( firstCommand.latin1(), challenge.data(), 2049 ); while( resp == Cont ) { @@ -610,7 +622,7 @@ bool POP3Protocol::loginPASS( KIO::AuthInfo &ai ) { char buf[512]; - + if (m_sUser.isEmpty() || m_sPass.isEmpty()) { // Prompt for usernames if (!openPassDlg(ai)) { @@ -761,7 +773,7 @@ switch ( retval ) { case 0: return true; case -1: return false; - default: + default: m_try_apop = false; } } else if ( m_try_sasl ) { @@ -770,7 +782,7 @@ switch ( retval ) { case 0: return true; case -1: return false; - default: + default: m_try_sasl = false; } } else { --- branches/KDE/3.5/kdebase/kioslave/smtp/command.cc #674950:674951 @@ -47,6 +47,19 @@ namespace KioSMTP { +#ifdef HAVE_LIBSASL2 +static sasl_callback_t client_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 } +}; +#endif + // // Command (base class) // @@ -144,7 +157,7 @@ // // STARTTLS - rfc 3207 - // + // QCString StartTLSCommand::nextCommandLine( TransactionState * ) { mComplete = true; @@ -195,16 +208,16 @@ mAi( &ai ), mFirstTime( true ) { -#ifdef HAVE_LIBSASL2 +#ifdef HAVE_LIBSASL2 int result; mMechusing = 0; conn = 0; client_interact = 0; mOut = 0; mOutlen = 0; mOneStep = false; - + result = sasl_client_new( "smtp", aFQDN.latin1(), - 0, 0, NULL, 0, &conn ); + 0, 0, client_callbacks, 0, &conn ); if ( result != SASL_OK ) { SASLERROR return; @@ -232,13 +245,13 @@ AuthCommand::~AuthCommand() { -#ifdef HAVE_LIBSASL2 +#ifdef HAVE_LIBSASL2 if ( conn ) { kdDebug(7112) << "dispose sasl connection" << endl; sasl_dispose( &conn ); conn = 0; } -#endif +#endif } bool AuthCommand::saslInteract( void *in ) @@ -309,7 +322,7 @@ mUngetSASLResponse = 0; } else if ( mFirstTime ) { QString firstCommand = "AUTH " + QString::fromLatin1( mMechusing ); - + tmp.setRawData( mOut, mOutlen ); KCodecs::base64Encode( tmp, challenge ); tmp.resetRawData( mOut, mOutlen ); @@ -318,7 +331,7 @@ firstCommand += QString::fromLatin1( challenge.data(), challenge.size() ); } cmd = firstCommand.latin1(); - + if ( mOneStep ) mComplete = true; } else { // kdDebug(7112) << "SS: '" << mLastChallenge << "'" << endl; @@ -344,7 +357,7 @@ tmp.setRawData( mOut, mOutlen ); cmd = KCodecs::base64Encode( tmp ); tmp.resetRawData( mOut, mOutlen ); - + // kdDebug(7112) << "CC: '" << cmd << "'" << endl; mComplete = ( result == SASL_OK ); } @@ -424,7 +437,7 @@ ts->addRejectedRecipient( mAddr, r.errorMessage() ); return false; - } + } // // DATA (only initial processing!)
this patch seems to break kio_pop3 completely. which other kioslave was using libsasl? the description doesn't make sense to me, because kioslaves are loaded into the same process one after the other - there is only one existing at the same time, hence the problem can't happen as described.
Your right, each kio slave is loaded into a different process. But there are other libraries which are using libsasl. Most notable the libnss-ldap, which is loaded when LDAP authentication is enabled. On my machine the kio slaves, which are using libsasl, does not work for users who are authenticated using LDAP. The ldap library itself uses SASL authentication (or even only initialize the libsasl) with different callbacks and the callbacks from the next user (the kio slave) will be ignored. This patch moves the initialization of the callbacks from the global libsasl init to the connection specific initialization. In KDE there are four (AFAIK) kio slaves which are using libsasl: smtp, pop3, imap and sieve (the later two are in kdepim). If you need further details, feel free to ask.
I can not see where libnss-ldap is doing a sasl initialisation, but in any case your description is wrong: the ioslaves are not supposed to use the hooks at all, given that they use the iterative client API. There is however a bug in the sasl libs that the getopt hook is invoked anyway, which causes the crashes with your patch. anyway, all sorted out now.
libnss-ldap does not itself initialize the sasl library, but it uses the openldap libraries, which i suppose initialize the sasl library. I check on a fresh installed Kubuntu 7.04 machine, that when the kio slave tries to initialize the sasl library, another one already did this before. But this only happens for users with use ldap based accounts. If i try the same with a local account, the library was not initialized before the kio slaves tried.
> There is however a bug in the sasl libs that the getopt hook is invoked anyway, which causes the crashes with your patch. anyway, all sorted out now. Would you mind sharing the sasl patch, please?
http://websvn.kde.org/?view=rev&revision=688530
Ah, thanks. I read it, as if you patched cyrus sasl as well.