Bug 146582 - [PATCH] SASL Authentication fails if another client of sasl is loaded
Summary: [PATCH] SASL Authentication fails if another client of sasl is loaded
Status: RESOLVED FIXED
Alias: None
Product: kio
Classification: Frameworks and Libraries
Component: smtp (show other bugs)
Version: unspecified
Platform: Ubuntu Linux
: NOR normal (vote)
Target Milestone: ---
Assignee: Allen Winter
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-06-09 13:35 UTC by Andreas Roth
Modified: 2007-07-24 15:18 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Fix callbacks for SMTP and POP3 kioslave (2.03 KB, patch)
2007-06-09 13:38 UTC, Andreas Roth
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Roth 2007-06-09 13:35:29 UTC
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.
Comment 1 Andreas Roth 2007-06-09 13:38:05 UTC
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.
Comment 2 Allen Winter 2007-06-13 18:18:06 UTC
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!)
Comment 3 Dirk Mueller 2007-07-10 12:41:49 UTC
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. 

Comment 4 Andreas Roth 2007-07-13 07:23:17 UTC
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.
Comment 5 Dirk Mueller 2007-07-16 11:31:39 UTC
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. 
Comment 6 Andreas Roth 2007-07-16 15:32:38 UTC
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.
Comment 7 Carsten Lohrke 2007-07-24 12:50:57 UTC
> 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?
Comment 8 Dirk Mueller 2007-07-24 13:23:55 UTC
http://websvn.kde.org/?view=rev&revision=688530
Comment 9 Carsten Lohrke 2007-07-24 15:18:13 UTC
Ah, thanks. I read it, as if you patched cyrus sasl as well.