[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-pim
Subject: [Kde-pim] [PATCH] SASL authentication enhacement
From: Szombathelyi "György" <gyurco () freemail ! hu>
Date: 2004-08-29 15:06:18
Message-ID: 200408291706.18597.gyurco () freemail ! hu
[Download RAW message or body]
Hello!
I wrote a patch for kio_imap4. It uses the cyrus-sasl package for SASL
authentication instead of KSASL class. It has several advantages, including
Kerberos support, and also can use any cyrus-sasl plugins. I didn't use QCA
(Qt Cryptographic Architecture), because SASL in QCA has only a signal-slot
interface, which is not optimal for ioslaves.
The patch contains modifications for kio_imap4, and for the account
configuration dialog in KMail (I added the GSSAPI mechanism). If accepted, I
will add cyrus-sasl support to more ioslaves, namely SMTP, POP3 and SIEVE.
May I commit?
Bye,
Gyorgy
____________________________________________________________________
Miert fizetsz az internetert? Korlatlan, ingyenes internet hozzaferes a FreeStarttol.
Probald ki most! http://www.freestart.hu
["imap-sasl.diff" (text/x-diff)]
Index: kioslaves/imap4/Makefile.am
===================================================================
RCS file: /home/kde/kdepim/kioslaves/imap4/Makefile.am,v
retrieving revision 1.24
diff -u -p -u -r1.24 Makefile.am
--- kioslaves/imap4/Makefile.am 20 Aug 2004 15:44:37 -0000 1.24
+++ kioslaves/imap4/Makefile.am 29 Aug 2004 14:53:24 -0000
@@ -7,7 +7,7 @@ kde_module_LTLIBRARIES = kio_imap4.la
kio_imap4_la_SOURCES = imapcommand.cc imaplist.cc mailaddress.cc \
mimeheader.cc rfcdecoder.cc imap4.cc imapinfo.cc imapparser.cc mailheader.cc \
mimehdrline.cc mimeio.cc
-kio_imap4_la_LIBADD = -lkdesasl $(LIB_KIO)
+kio_imap4_la_LIBADD = -lkdesasl $(LIB_KIO) $(SASL2_LIBS)
kio_imap4_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -module $(KDE_PLUGIN)
noinst_HEADERS = imap4.h
Index: kioslaves/imap4/configure.in.in
===================================================================
RCS file: /home/kde/kdepim/kioslaves/imap4/configure.in.in,v
retrieving revision 1.1
diff -u -p -u -r1.1 configure.in.in
--- kioslaves/imap4/configure.in.in 13 Apr 2004 16:28:13 -0000 1.1
+++ kioslaves/imap4/configure.in.in 29 Aug 2004 14:53:24 -0000
@@ -1 +1,14 @@
KDE_CHECK_SSL
+
+sasl2_header="no"
+SASL2_LIBS=""
+
+AC_CHECK_HEADERS([sasl/sasl.h], sasl2_header="yes")
+if test "$sasl2_header" = "yes" ; then
+ AC_CHECK_LIB(sasl2, sasl_client_init, SASL2_LIBS="-lsasl2")
+fi
+
+if test "x$SASL2_LIBS" != "x" ; then
+ AC_DEFINE_UNQUOTED(HAVE_LIBSASL2, 1, [Define if you have cyrus-sasl2 libraries])
+fi
+AC_SUBST(SASL2_LIBS)
Index: kioslaves/imap4/imap4.cc
===================================================================
RCS file: /home/kde/kdepim/kioslaves/imap4/imap4.cc,v
retrieving revision 1.188
diff -u -p -u -r1.188 imap4.cc
--- kioslaves/imap4/imap4.cc 20 Aug 2004 15:44:37 -0000 1.188
+++ kioslaves/imap4/imap4.cc 29 Aug 2004 14:53:24 -0000
@@ -62,6 +62,12 @@
#include <sys/types.h>
#include <sys/wait.h>
+#ifdef HAVE_LIBSASL2
+extern "C" {
+#include <sasl/sasl.h>
+}
+#endif
+
#include <qbuffer.h>
#include <qdatetime.h>
#include <kprotocolmanager.h>
@@ -85,6 +91,20 @@ extern "C"
int kdemain (int argc, char **argv);
}
+#ifdef HAVE_LIBSASL2
+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_GETOPT, NULL, NULL },
+ { SASL_CB_CANON_USER, NULL, NULL },
+ { SASL_CB_LIST_END, NULL, NULL }
+};
+#endif
+
int
kdemain (int argc, char **argv)
{
@@ -97,6 +117,13 @@ kdemain (int argc, char **argv)
::exit (-1);
}
+#ifdef HAVE_LIBSASL2
+ if ( sasl_client_init( callbacks ) != SASL_OK ) {
+ fprintf(stderr, "SASL library initialization failed!\n");
+ ::exit (-1);
+ }
+#endif
+
//set debug handler
IMAP4Protocol *slave;
@@ -109,6 +136,10 @@ kdemain (int argc, char **argv)
slave->dispatchLoop ();
delete slave;
+#ifdef HAVE_LIBSASL2
+ sasl_done();
+#endif
+
return 0;
}
@@ -1631,6 +1662,7 @@ bool IMAP4Protocol::makeLogin ()
myAuth = metaData("auth");
myTLS = metaData("tls");
+ kdDebug(7116) << "myAuth: " << myAuth << endl;
imapCommand *cmd;
@@ -1727,9 +1759,13 @@ bool IMAP4Protocol::makeLogin ()
}
else
{
- if (!clientAuthenticate (myUser, myPass, myAuth, mySSL, resultInfo))
+#ifdef HAVE_LIBSASL2
+ if (!clientAuthenticate (myUser, myPass, myHost, myAuth, mySSL, resultInfo))
error(KIO::ERR_COULD_NOT_LOGIN, i18n("Unable to authenticate via %1.\n"
"The server replied:\n%2").arg(myAuth).arg(resultInfo));
+#else
+ error(KIO::ERR_COULD_NOT_LOGIN, i18n("SASL authentication is not compiled into kio_imap4."));
+#endif
}
}
Index: kioslaves/imap4/imapparser.cc
===================================================================
RCS file: /home/kde/kdepim/kioslaves/imap4/imapparser.cc,v
retrieving revision 1.87
diff -u -p -u -r1.87 imapparser.cc
--- kioslaves/imap4/imapparser.cc 12 Aug 2004 20:21:16 -0000 1.87
+++ kioslaves/imap4/imapparser.cc 29 Aug 2004 14:53:27 -0000
@@ -22,6 +22,10 @@
*
*********************************************************************/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include "rfcdecoder.h"
#include "imapparser.h"
@@ -37,6 +41,12 @@
#include <stdlib.h>
#include <unistd.h>
+#ifdef HAVE_LIBSASL2
+extern "C" {
+#include <sasl/sasl.h>
+}
+#endif
+
#include <qregexp.h>
#include <qbuffer.h>
#include <qstring.h>
@@ -45,7 +55,6 @@
#include <kdebug.h>
#include <kmdcodec.h>
#include <kurl.h>
-#include <kio/kdesasl.h>
imapParser::imapParser ()
{
@@ -136,42 +145,120 @@ imapParser::clientLogin (const QString &
return retVal;
}
+#ifdef HAVE_LIBSASL2
+static void sasl_interact( const QString &aUser, const QString &aPass, void *in )
+{
+ kdDebug(7116) << "sasl_interact" << endl;
+ sasl_interact_t *interact = ( sasl_interact_t * ) in;
+
+ while( interact->id != SASL_CB_LIST_END ) {
+ kdDebug(7116) << "SASL_INTERACT id: " << interact->id << endl;
+ switch( interact->id ) {
+ case SASL_CB_AUTHNAME:
+ kdDebug(7116) << "SASL_CB_AUTHNAME: '" << aUser << "'" << endl;
+ interact->result = strdup( aUser.utf8() );
+ interact->len = strlen( (const char *) interact->result );
+ break;
+ case SASL_CB_PASS:
+ kdDebug(7116) << "SASL_CB_PASS: [hidden] " << endl;
+ interact->result = strdup( aPass.utf8() );
+ interact->len = strlen( (const char *) interact->result );
+ break;
+ default:
+ interact->result = NULL; interact->len = 0;
+ break;
+ }
+ interact++;
+ }
+}
+#endif
bool
-imapParser::clientAuthenticate (const QString & aUser, const QString & aPass,
- const QString & aAuth, bool isSSL, QString & resultInfo)
+imapParser::clientAuthenticate (const QString & aUser, const QString & aPass,
+ const QString & aFQDN, const QString & aAuth, bool isSSL, QString & resultInfo)
{
- imapCommand *cmd;
bool retVal = false;
+#ifdef HAVE_LIBSASL2
+ int result;
+ sasl_conn_t *conn = NULL;
+ sasl_interact_t *client_interact = NULL;
+ const char *out = NULL;
+ uint outlen;
+ const char *mechusing = NULL;
+
+ kdDebug(7116) << "aAuth: " << aAuth << " FQDN: " << aFQDN << " isSSL: " << isSSL << endl;
// see if server supports this authenticator
if (!hasCapability ("AUTH=" + aAuth))
return false;
+// result = sasl_client_new( isSSL ? "imaps" : "imap",
+ result = sasl_client_new( "imap", /* FIXME: with cyrus-imapd, even imaps' digest-uri
+ must be 'imap'. I don't know if it's good or bad. */
+ aFQDN.latin1(),
+ 0, 0, NULL, 0, &conn );
+
+ if ( result != SASL_OK ) {
+ kdDebug(7116) << "sasl_client_new failed with: " << result << endl;
+ resultInfo = QString::fromUtf8( sasl_errdetail( conn ) );
+ return false;
+ }
+
+ do {
+ result = sasl_client_start(conn, aAuth.latin1(), &client_interact,
+ 0, &outlen, &mechusing);
+
+ if (result == SASL_INTERACT) sasl_interact( aUser, aPass, client_interact );
+ } while ( result == SASL_INTERACT );
+
+ if ( result != SASL_CONTINUE && result != SASL_OK ) {
+ kdDebug(7116) << "sasl_client_start failed with: " << result << endl;
+ resultInfo = QString::fromUtf8( sasl_errdetail( conn ) );
+ sasl_dispose( &conn );
+ return false;
+ }
+ imapCommand *cmd;
+
// then lets try it
cmd = sendCommand (new imapCommand ("AUTHENTICATE", aAuth));
- KDESasl sasl(aUser, aPass, isSSL ? "imaps" : "imap");
- sasl.setMethod(aAuth.latin1());
+
while (!cmd->isComplete ())
{
//read the next line
while (parseLoop() == 0);
- if (!continuation.isEmpty ())
+ if (!continuation.isEmpty())
{
- QByteArray challenge;
- challenge.duplicate(continuation.data() + 2, continuation.size() - 2);
- challenge.resize(challenge.size() - 2); // trim CRLF
-
- if (aAuth.upper () == "ANONYMOUS")
- {
- // we should present the challenge to the user and ask
- // him for a mail-address or what ever
- challenge = KCodecs::base64Encode(aUser.utf8());
- } else {
- challenge = sasl.getResponse(challenge);
- }
-
+ QByteArray challenge, tmp;
+// kdDebug(7116) << "S: " << QCString(continuation.data(),continuation.size()+1) << endl;
+ if ( continuation.size() > 4 ) {
+ tmp.setRawData( continuation.data() + 2, continuation.size() - 4 );
+ KCodecs::base64Decode( tmp, challenge );
+// kdDebug(7116) << "S-1: " << QCString(challenge.data(),challenge.size()+1) << endl;
+ tmp.resetRawData( continuation.data() + 2, continuation.size() - 4 );
+ }
+
+ do {
+ result = sasl_client_step(conn, challenge.isEmpty() ? 0 : challenge.data(),
+ challenge.size(),
+ &client_interact,
+ &out, &outlen);
+
+ if ( result == SASL_INTERACT ) sasl_interact( aUser, aPass, client_interact );
+ } while ( result == SASL_INTERACT );
+
+ if ( result != SASL_CONTINUE && result != SASL_OK ) {
+ kdDebug(7116) << "sasl_client_step failed with: " << result << endl;
+ resultInfo = QString::fromUtf8( sasl_errdetail( conn ) );
+ sasl_dispose( &conn );
+ return false;
+ }
+
+ tmp.setRawData( out, outlen );
+// kdDebug(7116) << "C-1: " << QCString(tmp.data(),tmp.size()+1) << endl;
+ KCodecs::base64Encode( tmp, challenge );
+ tmp.resetRawData( out, outlen );
+// kdDebug(7116) << "C: " << QCString(challenge.data(),challenge.size()+1) << endl;
parseWriteLine (challenge);
continuation.resize(0);
}
@@ -185,6 +272,8 @@ imapParser::clientAuthenticate (const QS
resultInfo = cmd->resultInfo();
completeQueue.removeRef (cmd);
+ sasl_dispose( &conn ); //we don't use sasl_en/decode(), so it's safe to dispose the connection.
+#endif //HAVE_LIBSASL2
return retVal;
}
Index: kioslaves/imap4/imapparser.h
===================================================================
RCS file: /home/kde/kdepim/kioslaves/imap4/imapparser.h,v
retrieving revision 1.37
diff -u -p -u -r1.37 imapparser.h
--- kioslaves/imap4/imapparser.h 21 Apr 2004 21:18:25 -0000 1.37
+++ kioslaves/imap4/imapparser.h 29 Aug 2004 14:53:27 -0000
@@ -232,7 +232,7 @@ public:
* @return success or failure
*/
bool clientAuthenticate (const QString & aUser, const QString & aPass,
- const QString & aAuth, bool isSSL, QString & resultInfo);
+ const QString & aFQDN, const QString & aAuth, bool isSSL, QString & resultInfo);
/**
* main loop for the parser
Index: kmail/accountdialog.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/accountdialog.cpp,v
retrieving revision 1.155
diff -u -p -u -r1.155 accountdialog.cpp
--- kmail/accountdialog.cpp 3 Aug 2004 21:27:21 -0000 1.155
+++ kmail/accountdialog.cpp 29 Aug 2004 14:53:36 -0000
@@ -954,6 +954,7 @@ void AccountDialog::makeImapAccountPage(
mImap.authGroup );
mImap.authCramMd5 = new QRadioButton( i18n("CRAM-MD&5"), mImap.authGroup );
mImap.authDigestMd5 = new QRadioButton( i18n("&DIGEST-MD5"), mImap.authGroup );
+ mImap.authGSSAPI = new QRadioButton( i18n("&GSSAPI"), mImap.authGroup );
mImap.authAnonymous = new QRadioButton( i18n("&Anonymous"), mImap.authGroup );
vlay->addWidget( mImap.authGroup );
@@ -1106,6 +1107,8 @@ void AccountDialog::setupSettings()
mImap.authCramMd5->setChecked( TRUE );
else if (ai.auth() == "DIGEST-MD5")
mImap.authDigestMd5->setChecked( TRUE );
+ else if (ai.auth() == "GSSAPI")
+ mImap.authGSSAPI->setChecked( TRUE );
else if (ai.auth() == "ANONYMOUS")
mImap.authAnonymous->setChecked( TRUE );
else if (ai.auth() == "PLAIN")
@@ -1156,6 +1159,8 @@ void AccountDialog::setupSettings()
mImap.authCramMd5->setChecked( TRUE );
else if (ai.auth() == "DIGEST-MD5")
mImap.authDigestMd5->setChecked( TRUE );
+ else if (ai.auth() == "GSSAPI")
+ mImap.authGSSAPI->setChecked( TRUE );
else if (ai.auth() == "ANONYMOUS")
mImap.authAnonymous->setChecked( TRUE );
else if (ai.auth() == "PLAIN")
@@ -1470,6 +1475,8 @@ unsigned int AccountDialog::imapCapabili
capa |= CRAM_MD5;
else if ( cur == "AUTH=DIGEST-MD5" )
capa |= Digest_MD5;
+ else if ( cur == "AUTH=GSSAPI" )
+ capa |= GSSAPI;
else if ( cur == "AUTH=ANONYMOUS" )
capa |= Anonymous;
else if ( cur == "STARTTLS" )
@@ -1508,6 +1515,7 @@ void AccountDialog::enableImapAuthMethod
mImap.authLogin->setEnabled( capa & Login );
mImap.authCramMd5->setEnabled( capa & CRAM_MD5 );
mImap.authDigestMd5->setEnabled( capa & Digest_MD5 );
+ mImap.authGSSAPI->setEnabled( capa & GSSAPI );
mImap.authAnonymous->setEnabled( capa & Anonymous );
}
@@ -1647,6 +1655,8 @@ void AccountDialog::saveSettings()
epa.setAuth("CRAM-MD5");
else if (mImap.authDigestMd5->isChecked())
epa.setAuth("DIGEST-MD5");
+ else if (mImap.authGSSAPI->isChecked())
+ epa.setAuth("GSSAPI");
else if (mImap.authAnonymous->isChecked())
epa.setAuth("ANONYMOUS");
else if (mImap.authLogin->isChecked())
@@ -1698,6 +1708,8 @@ void AccountDialog::saveSettings()
epa.setAuth("CRAM-MD5");
else if (mImap.authDigestMd5->isChecked())
epa.setAuth("DIGEST-MD5");
+ else if (mImap.authGSSAPI->isChecked())
+ epa.setAuth("GSSAPI");
else if (mImap.authAnonymous->isChecked())
epa.setAuth("ANONYMOUS");
else if (mImap.authLogin->isChecked())
Index: kmail/accountdialog.h
===================================================================
RCS file: /home/kde/kdepim/kmail/accountdialog.h,v
retrieving revision 1.46
diff -u -p -u -r1.46 accountdialog.h
--- kmail/accountdialog.h 23 May 2004 22:04:31 -0000 1.46
+++ kmail/accountdialog.h 29 Aug 2004 14:53:36 -0000
@@ -169,6 +169,7 @@ class AccountDialog : public KDialogBase
QRadioButton *authLogin;
QRadioButton *authCramMd5;
QRadioButton *authDigestMd5;
+ QRadioButton *authGSSAPI;
QRadioButton *authAnonymous;
QPushButton *checkCapabilities;
KMFolderComboBox *trashCombo;
@@ -237,6 +238,7 @@ class AccountDialog : public KDialogBase
UIDL = 256,
STLS = 512, // TLS for POP
STARTTLS = 512, // TLS for IMAP
+ GSSAPI = 1024,
AllCapa = 0xffffffff
};
unsigned int mCurCapa;
_______________________________________________
kde-pim mailing list
kde-pim@mail.kde.org
https://mail.kde.org/mailman/listinfo/kde-pim
kde-pim home page at http://pim.kde.org/
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic