aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1999-06-08 07:20:17 +0000
committerEric S. Raymond <esr@thyrsus.com>1999-06-08 07:20:17 +0000
commit6f232ed6b5343dea62abdbbd7d38b48858bee373 (patch)
tree8898d48f48c81a3ded8b0aeb73246af5b22d52e5
parent92397efcc624980fdf8467449b69d88d4acc4530 (diff)
downloadfetchmail-6f232ed6b5343dea62abdbbd7d38b48858bee373.tar.gz
fetchmail-6f232ed6b5343dea62abdbbd7d38b48858bee373.tar.bz2
fetchmail-6f232ed6b5343dea62abdbbd7d38b48858bee373.zip
CRAM-MD5 authentication support a la RFC2195.
svn path=/trunk/; revision=2485
-rw-r--r--NEWS1
-rw-r--r--design-notes.html6
-rw-r--r--fetchmail-features.html6
-rw-r--r--fetchmail.man2
-rw-r--r--imap.c136
5 files changed, 146 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index c14ae3cd..d5f0cc86 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ fetchmail-5.1.0 ():
* There is now a documented return code 13 for termination on fetchlimit.
* Added qpopper 2.53 warning to the FAQ and fetchmailconf.
* Fix fetchmailconf to handle window-manager destroy notifications.
+* Todd <tastas@home.com> Sabin's RFC2195 support for AUTH=CRAM-MD5 under IMAP.
There are 260 people on fetchmail-friends and 387 on fetchmail-announce.
diff --git a/design-notes.html b/design-notes.html
index cc193045..356a5b3b 100644
--- a/design-notes.html
+++ b/design-notes.html
@@ -10,7 +10,7 @@
<table width="100%" cellpadding=0><tr>
<td width="30%">Back to <a href="/~esr/index.html">Fetchmail Home Page</a>
<td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1999/05/16 18:24:08 $
+<td width="30%" align=right>$Date: 1999/06/08 07:20:17 $
</table>
<HR>
<H1 ALIGN=CENTER>Design Notes On Fetchmail</H1>
@@ -525,6 +525,8 @@ all shaped the design in one way or another.<P>
<DD> IMAP4 Compatibility With IMAP2bis
<DT><A HREF="ftp://ftp.isi.edu/in-notes/rfc2062.txt">RFC2062</A>
<DD> Internet Message Access Protocol - Obsolete Syntax
+<DT><A HREF="ftp://ftp.isi.edu/in-notes/rfc2195.txt">RFC2449</A>
+<DD> IMAP/POP AUTHorize Extension for Simple Challenge/Response
<DT><A HREF="ftp://ftp.isi.edu/in-notes/rfc2449.txt">RFC2449</A>
<DD> POP3 Extension Mechanism
</DL>
@@ -533,7 +535,7 @@ all shaped the design in one way or another.<P>
<table width="100%" cellpadding=0><tr>
<td width="30%">Back to <a href="index.html">Fetchmail Home Page</a>
<td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1999/05/16 18:24:08 $
+<td width="30%" align=right>$Date: 1999/06/08 07:20:17 $
</table>
<P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@snark.thyrsus.com&gt;</A></ADDRESS>
diff --git a/fetchmail-features.html b/fetchmail-features.html
index ab778a90..b607de57 100644
--- a/fetchmail-features.html
+++ b/fetchmail-features.html
@@ -10,7 +10,7 @@
<table width="100%" cellpadding=0><tr>
<td width="30%">Back to <a href="index.html">Fetchmail Home Page</a>
<td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1999/04/18 18:32:01 $
+<td width="30%" align=right>$Date: 1999/06/08 07:20:17 $
</table>
<HR>
@@ -19,6 +19,8 @@
<H2>Since 5.0:</H2>
<UL>
<LI>Expunge option can now be used to break POP3 retrieval into subsessions.
+
+<LI>Support for AUTH=CRAM-MD5 under IMAP, a la RFC2195.
</UL>
<H2>Since 4.0:</H2>
@@ -173,7 +175,7 @@ get-mail, gwpop, pimp-1.0, pop-perl5-1.2, popc, popmail-1.6 and upop.<P>
<table width="100%" cellpadding=0><tr>
<td width="30%">Back to <a href="index.html">Fetchmail Home Page</a>
<td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1999/04/18 18:32:01 $
+<td width="30%" align=right>$Date: 1999/06/08 07:20:17 $
</table>
<P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@snark.thyrsus.com&gt;</A></ADDRESS>
diff --git a/fetchmail.man b/fetchmail.man
index 62dd8df9..3896971c 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -1851,7 +1851,7 @@ IMAP2/IMAP2BIS:
RFC 1176, RFC 1732
.TP 5
IMAP4:
-RFC 1730, RFC 1731, RFC 1732, RFC 2060, RFC 2061
+RFC 1730, RFC 1731, RFC 1732, RFC 2060, RFC 2061, RFC 2195
.TP 5
ETRN:
RFC 1985
diff --git a/imap.c b/imap.c
index 1b62f65b..94e4da30 100644
--- a/imap.c
+++ b/imap.c
@@ -37,6 +37,8 @@
#include <gssapi/gssapi_generic.h>
#endif
+#include "md5.h"
+
#if OPIE
#include <opie.h>
#endif /* OPIE */
@@ -588,6 +590,127 @@ static int do_gssauth(int sock, char *hostname, char *username)
}
#endif /* GSSAPI */
+static void hmac_md5 (unsigned char *password, size_t pass_len,
+ unsigned char *challenge, size_t chal_len,
+ unsigned char *response, size_t resp_len)
+{
+ int i;
+ unsigned char ipad[64];
+ unsigned char opad[64];
+ unsigned char hash_passwd[16];
+
+ MD5_CTX ctx;
+
+ if (resp_len != 16)
+ return;
+
+ if (pass_len > sizeof (ipad))
+ {
+ MD5Init (&ctx);
+ MD5Update (&ctx, password, pass_len);
+ MD5Final (hash_passwd, &ctx);
+ password = hash_passwd; pass_len = sizeof (hash_passwd);
+ }
+
+ memset (ipad, 0, sizeof (ipad));
+ memset (opad, 0, sizeof (opad));
+ memcpy (ipad, password, pass_len);
+ memcpy (opad, password, pass_len);
+
+ for (i=0; i<64; i++) {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+ MD5Init (&ctx);
+ MD5Update (&ctx, ipad, sizeof (ipad));
+ MD5Update (&ctx, challenge, chal_len);
+ MD5Final (response, &ctx);
+
+ MD5Init (&ctx);
+ MD5Update (&ctx, opad, sizeof (opad));
+ MD5Update (&ctx, response, resp_len);
+ MD5Final (response, &ctx);
+}
+
+
+static int do_cram_md5 (int sock, struct query *ctl)
+/* authenticate as per RFC2195 */
+{
+ int result;
+ int len;
+ unsigned char buf1[1024];
+ unsigned char msg_id[768];
+ unsigned char response[16];
+ unsigned char reply[1024];
+
+ gen_send (sock, "AUTHENTICATE CRAM-MD5");
+
+ /* From RFC2195:
+ * The data encoded in the first ready response contains an
+ * presumptively arbitrary string of random digits, a timestamp, and the
+ * fully-qualified primary host name of the server. The syntax of the
+ * unencoded form must correspond to that of an RFC 822 'msg-id'
+ * [RFC822] as described in [POP3].
+ */
+
+ if (result = gen_recv (sock, buf1, sizeof (buf1))) {
+ return result;
+ }
+
+ len = from64tobits (msg_id, buf1);
+ if (len < 0) {
+ report (stderr, _("could not decode BASE64 challenge\n"));
+ return PS_AUTHFAIL;
+ } else if (len < sizeof (msg_id)) {
+ msg_id[len] = 0;
+ } else {
+ msg_id[sizeof (msg_id)-1] = 0;
+ }
+ if (outlevel >= O_DEBUG) {
+ report (stdout, "decoded as %s\n", msg_id);
+ }
+
+ /* The client makes note of the data and then responds with a string
+ * consisting of the user name, a space, and a 'digest'. The latter is
+ * computed by applying the keyed MD5 algorithm from [KEYED-MD5] where
+ * the key is a shared secret and the digested text is the timestamp
+ * (including angle-brackets).
+ */
+
+ hmac_md5 (ctl->password, strlen (ctl->password),
+ msg_id, strlen (msg_id),
+ response, sizeof (response));
+
+ snprintf (reply, sizeof (reply),
+ "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ ctl->remotename,
+ response[0], response[1], response[2], response[3],
+ response[4], response[5], response[6], response[7],
+ response[8], response[9], response[10], response[11],
+ response[12], response[13], response[14], response[15]);
+
+ if (outlevel >= O_DEBUG) {
+ report (stdout, "replying with %s\n", reply);
+ }
+
+ to64frombits (buf1, reply, strlen (reply));
+ if (outlevel >= O_MONITOR) {
+ report (stdout, "IMAP> %s\n", buf1);
+ }
+ SockWrite (sock, buf1, strlen (buf1));
+ SockWrite (sock, "\r\n", 2);
+
+ if (result = gen_recv (sock, buf1, sizeof (buf1)))
+ return result;
+
+ if (strstr (buf1, "OK")) {
+ return PS_SUCCESS;
+ } else {
+ return PS_AUTHFAIL;
+ }
+}
+
int imap_canonicalize(char *result, char *passwd)
/* encode an IMAP password as per RFC1730's quoting conventions */
{
@@ -695,6 +818,19 @@ int imap_getauth(int sock, struct query *ctl, char *greeting)
}
#endif /* KERBEROS_V4 */
+ if (strstr (capabilities, "AUTH=CRAM-MD5"))
+ {
+ if (outlevel >= O_DEBUG)
+ report (stdout, _("CRAM-MD5 authentication is supported\n"));
+ if ((ok = do_cram_md5 (sock, ctl)))
+ {
+ if (outlevel >= O_MONITOR)
+ report (stdout, "IMAP> *\n");
+ SockWrite (sock, "*\r\n", 3);
+ }
+ return ok;
+ }
+
#ifdef __UNUSED__ /* The Cyrus IMAP4rev1 server chokes on this */
/* this handles either AUTH=LOGIN or AUTH-LOGIN */
if ((imap_version >= IMAP4rev1) && (!strstr(capabilities, "LOGIN"))) {