[Goodies-commits] r4040 - in xfce4-mailwatch-plugin/trunk: . libmailwatch-core
Brian Tarricone
kelnos at xfce.org
Fri Mar 14 06:02:37 CET 2008
Author: kelnos
Date: 2008-03-14 05:02:37 +0000 (Fri, 14 Mar 2008)
New Revision: 4040
Modified:
xfce4-mailwatch-plugin/trunk/NEWS
xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c
xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c
xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c
xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h
Log:
add CRAM-MD5 authentication support for imap and pop3 (bug 3420)
Modified: xfce4-mailwatch-plugin/trunk/NEWS
===================================================================
--- xfce4-mailwatch-plugin/trunk/NEWS 2008-03-13 12:34:27 UTC (rev 4039)
+++ xfce4-mailwatch-plugin/trunk/NEWS 2008-03-14 05:02:37 UTC (rev 4040)
@@ -9,6 +9,7 @@
* Fix incorrect getaddrinfo() usage breaking use on NetBSD (bug 3767).
* Fix possible hang when reading IMAP responses when a selected folder
is later deleted or unsubscribed.
+ * Fix buffer size issues when reading IMAP folder contents (bug 2009).
Features:
* Update the new message counts for all mailboxes on startup, rather than
@@ -16,6 +17,8 @@
* Document the behavior of forcing a new messsage count update when the
user double-clicks the icon (patch from Maximilian Schleiss).
* Add experimental IPv6 support.
+ * Add an 'Update Now' menu item (bug 3908).
+ * Add CRAM-MD5 authentication support for POP3 and IMAP (bug 3420).
Version 1.0.1 (20 Apr 2006):
Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c 2008-03-13 12:34:27 UTC (rev 4039)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c 2008-03-14 05:02:37 UTC (rev 4040)
@@ -253,9 +253,61 @@
goto cleanuperr;
}
+#ifdef HAVE_SSL_SUPPORT
+ if(strstr(buf, "AUTH=CRAM-MD5")) {
+ /* the server supports CRAM-MD5; prefer that over LOGIN */
+ g_snprintf(buf, BUFSIZE, "%05d AUTHENTICATE CRAM-MD5\r\n",
+ ++imailbox->imap_tag);
+ bout = imap_send(imailbox, buf);
+ if(bout != strlen(buf))
+ goto cleanuperr;
+
+ bin = imap_recv(imailbox, buf, BUFSIZE);
+ DBG("response from AUTHENTICATE CRAM-MD5 (%d): %s\n", bin, bin>0?buf:"(nada)");
+ if(bin <= 0)
+ goto cleanuperr;
+
+ if(*buf == '+' && *(buf+1) == ' ' && *(buf+2)) {
+ gchar *p, *response_base64;
+
+ /* we got a challenge */
+ p = strstr(buf, "\r\n");
+ if(!p)
+ p = strstr(buf, "\n");
+ if(!p) {
+ DBG("cram-md5 challenge wasn't a full line?");
+ goto cleanuperr;
+ }
+ *p = 0;
+
+ response_base64 = xfce_mailwatch_cram_md5(username, password,
+ buf + 2);
+ if(!response_base64)
+ goto cleanuperr;
+ g_snprintf(buf, BUFSIZE, "%s\r\n", response_base64);
+ g_free(response_base64);
+ bout = imap_send(imailbox, buf);
+ DBG("sent CRAM-MD5 response: %s\n", buf);
+ if(bout != strlen(buf))
+ goto cleanuperr;
+
+ bin = imap_recv(imailbox, buf, BUFSIZE);
+ DBG("reponse from cram-md5 resp (%d): %s\n", bin, bin>0?buf:"(nada)");
+ if(bin <= 0)
+ goto cleanuperr;
+ if(!strstr(buf, "OK"))
+ goto cleanuperr;
+
+ /* auth successful */
+ TRACE("leaving (success)");
+ return TRUE;
+ }
+ }
+#endif
+
/* send the creds */
g_snprintf(buf, BUFSIZE, "%05d LOGIN \"%s\" \"%s\"\r\n",
- ++imailbox->imap_tag, username, password);
+ ++imailbox->imap_tag, username, password);
bout = imap_send(imailbox, buf);
DBG("sent login (%d)", bout);
if(bout != strlen(buf))
Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c 2008-03-13 12:34:27 UTC (rev 4039)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c 2008-03-14 05:02:37 UTC (rev 4040)
@@ -202,8 +202,76 @@
gint bin, bout;
gchar buf[BUFSIZE+1];
- TRACE("entering");
+#ifdef HAVE_SSL_SUPPORT
+ gint off;
+ gchar *p, *q;
+ /* see if CRAM-MD5 is supported */
+ g_strlcpy(buf, "CAPA\r\n", BUFSIZE);
+ bout = pop3_send(pmailbox, buf);
+ if(bout != strlen(buf))
+ goto cleanuperr;
+
+ off = 0;
+ do {
+ bin = pop3_recv(pmailbox, buf + off, BUFSIZE - off);
+ if(bin > 0)
+ off += bin;
+ } while(bin > 0 && !strstr(buf, ".\r\n"));
+ if(bin < 0)
+ goto cleanuperr;
+
+ if((p = strstr(buf, "SASL ")) && (q = strstr(p, "\r\n"))
+ && (p = strstr(p, "CRAM-MD5")) && p < q)
+ {
+ /* server supports CRAM-MD5 */
+ g_strlcpy(buf, "AUTH CRAM-MD5\r\n", BUFSIZE);
+ bout = pop3_send(pmailbox, buf);
+ if(bout != strlen(buf))
+ goto cleanuperr;
+
+ bin = pop3_recv(pmailbox, buf, BUFSIZE);
+ if(bin <= 0)
+ goto cleanuperr;
+ DBG("got cram-md5 challenge: %s\n", buf);
+
+ if(*buf == '+' && *(buf+1) == ' ' && *(buf+2)) {
+ gchar *response_base64;
+
+ p = strstr(buf, "\r\n");
+ if(!p)
+ p = strstr(buf, "\n");
+ if(!p) {
+ DBG("cram-md5 challenge wasn't a full line?");
+ goto cleanuperr;
+ }
+ *p = 0;
+
+ response_base64 = xfce_mailwatch_cram_md5(username, password,
+ buf + 2);
+ if(!response_base64)
+ goto cleanuperr;
+ g_strlcpy(buf, response_base64, BUFSIZE);
+ g_strlcat(buf, "\r\n", BUFSIZE);
+ g_free(response_base64);
+ bout = pop3_send(pmailbox, buf);
+ if(bout != strlen(buf))
+ goto cleanuperr;
+
+ bin = pop3_recv(pmailbox, buf, BUFSIZE);
+ if(bin <= 0)
+ goto cleanuperr;
+ DBG("got response to cram-md5 auth: %s", buf);
+ if(strncmp(buf, "+OK", 3))
+ goto cleanuperr;
+
+ TRACE("leaving (success)");
+
+ return TRUE;
+ }
+ }
+#endif
+
/* send the username */
g_snprintf(buf, BUFSIZE, "USER %s\r\n", username);
bout = pop3_send(pmailbox, buf);
@@ -240,7 +308,7 @@
return TRUE;
- cleanuperr:
+cleanuperr:
shutdown(pmailbox->sockfd, SHUT_RDWR);
close(pmailbox->sockfd);
Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c 2008-03-13 12:34:27 UTC (rev 4039)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c 2008-03-14 05:02:37 UTC (rev 4040)
@@ -498,7 +498,79 @@
#endif
}
+#ifdef HAVE_SSL_SUPPORT
+/* assumes |dest| is allocated 2x |src_len| */
+static void
+bin2hex(gchar *dest,
+ const guchar *src,
+ gsize src_len)
+{
+ static const gchar hexdigits[] = "0123456789abcdef";
+
+ if(!src_len)
+ return;
+
+ while(src_len-- > 0) {
+ *dest++ = hexdigits[(*src >> 4) & 0xf];
+ *dest++ = hexdigits[*src & 0xf];
+ src++;
+ }
+}
+
+gchar *
+xfce_mailwatch_cram_md5(const gchar *username,
+ const gchar *password,
+ const gchar *challenge_base64)
+{
+ gchar challenge[2048];
+ gsize len, username_len;
+ gcry_md_hd_t hmac_md5;
+ gchar *response, *response_base64 = NULL;
+
+ g_return_val_if_fail(username && *username && password && *password
+ && challenge_base64 && *challenge_base64, NULL);
+
+ len = xfce_mailwatch_base64_decode(challenge_base64, (guchar *)challenge,
+ sizeof(challenge) - 1);
+ if(len <= 0)
+ return NULL;
+ challenge[len] = 0;
+ DBG("challenge is \"%s\"\n", challenge);
+
+ if(gcry_md_open(&hmac_md5, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
+ return NULL;
+ gcry_md_setkey(hmac_md5, password, strlen(password));
+ gcry_md_write(hmac_md5, challenge, len);
+ gcry_md_final(hmac_md5);
+
+ username_len = strlen(username);
+ /* username + a space + MD5 in hex + null */
+ response = g_malloc0(username_len + 1
+ + gcry_md_get_algo_dlen(GCRY_MD_MD5)*2 + 1);
+ strcpy(response, username);
+ response[username_len] = ' ';
+ bin2hex(response + username_len + 1, gcry_md_read(hmac_md5, GCRY_MD_MD5),
+ gcry_md_get_algo_dlen(GCRY_MD_MD5));
+
+ gcry_md_close(hmac_md5);
+
+ DBG("response before base64: %s\n", response);
+ if(xfce_mailwatch_base64_encode((guchar *)response, strlen(response),
+ &response_base64) <= 0)
+ {
+ g_free(response_base64);
+ response_base64 = NULL;
+ }
+
+ g_free(response);
+
+ return response_base64;
+}
+
+#endif
+
+
/*
* The following Base64 code is provided under the following license:
*
@@ -534,13 +606,15 @@
* SUCH DAMAGE.
*
* Modified slightly by Brian Tarricone <bjt23 at cornell.edu> to use g_malloc()
- * and glib primitive types.
+ * and glib primitive types, and to add buffer overrun checking.
*/
static const gchar base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
gint
-xfce_mailwatch_base64_encode(const guint8 *data, gint size, gchar **str)
+xfce_mailwatch_base64_encode(const guint8 *data,
+ gsize size,
+ gchar **str)
{
gchar *s, *p;
gint i;
@@ -548,8 +622,6 @@
const guchar *q;
p = s = (gchar *)g_malloc(size*4/3+4);
- if (p == NULL)
- return -1;
q = (const guchar *)data;
i=0;
for(i = 0; i < size;){
@@ -577,6 +649,91 @@
return strlen(s);
}
+static
+int pos(gchar c)
+{
+ gchar *p;
+ for(p = (gchar *)base64; *p; p++)
+ if(*p == c)
+ return p - base64;
+ return -1;
+}
+
+gint
+xfce_mailwatch_base64_decode(const gchar *str,
+ guint8 *data,
+ gsize size)
+{
+ const char *p;
+ unsigned char *q;
+ int c;
+ int x;
+ int done = 0;
+
+ q=(unsigned char*)data;
+ for(p=str; *p && !done; p+=4){
+ x = pos(p[0]);
+ if(x >= 0)
+ c = x;
+ else{
+ done = 3;
+ break;
+ }
+ c*=64;
+
+ x = pos(p[1]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ c*=64;
+
+ if(p[2] == '=')
+ done++;
+ else{
+ x = pos(p[2]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ c*=64;
+
+ if(p[3] == '=')
+ done++;
+ else{
+ if(done)
+ return -1;
+ x = pos(p[3]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ if(done < 3) {
+ if(!size)
+ return -1;
+ *q++=(c&0x00ff0000)>>16;
+ --size;
+ }
+
+ if(done < 2) {
+ if(!size)
+ return -1;
+ *q++=(c&0x0000ff00)>>8;
+ --size;
+ }
+
+ if(done < 1) {
+ if(!size)
+ return -1;
+ *q++=(c&0x000000ff)>>0;
+ --size;
+ }
+ }
+ return q - (unsigned char*)data;
+}
+
/*****
* End Base64 code. Don't put other stuff under here.
*****/
Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h 2008-03-13 12:34:27 UTC (rev 4039)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h 2008-03-14 05:02:37 UTC (rev 4040)
@@ -88,10 +88,16 @@
GtkWidget *xfce_mailwatch_create_framebox(const gchar *title,
GtkWidget **frame_bin);
+gchar *xfce_mailwatch_cram_md5(const gchar *username,
+ const gchar *password,
+ const gchar *challenge_base64);
+
gint xfce_mailwatch_base64_encode(const guint8 *data,
- gint size,
+ gsize size,
gchar **str);
-
+gint xfce_mailwatch_base64_decode(const gchar *str,
+ guint8 *data,
+ gsize size);
G_END_DECLS
#endif
More information about the Goodies-commits
mailing list