[Dovecot] PATCH: CRAM-MD5 for Dovecot

Joshua Goodall joshua at roughtrade.net
Tue Nov 11 00:53:35 EET 2003


On Mon, Nov 10, 2003 at 10:36:07PM +0200, Timo Sirainen wrote:
> Thanks. I thought CRAM-MD5 required plaintext password in server side,
> but looks like you store them in some MD5 hash. That's good :)

Well - sort of good.  Unfortunately, the HMAC-MD5 encoding used doesn't
salt the passwords as they're hashed.

Theft of the hash allows an attacker to authenticate as that user,
and also permits a dictionary attack.  These weaknessess partially
motivate DIGEST-MD5, of course, but it's still better than pure
cleartext.

The format is the same as that used by Courier IMAP.  Properly, it
should be called {HMAC-MD5}, so the attached patch makes that change
before this settles.

[snip]
> And I rather try to avoid using 64bit integers which you used there, so
> I changed them to just print 16 random digits.

:) I was trying to minimise the amount of entropy pulled from the PRNG.
(For the same amount of entropy, using ints produced a challenge space
of 2^128 integers vs roughly 2^53).

> It'd be nice to add CRAM-MD5 support to password_verify() too so that
> plaintext authentication could work with such passwords. But not that
> important.

done. tested with passwd-file. see attached.

> > Would you consider including this in the next release?
> 
> Committed to CVS, see if it still works after my changes? ;)

I had problems with RFC noncompliance of the challenge (missing "<",">"
and comedy challenge characters with %10 of signed chars).  fixed, see patch.

It Works For Me(tm).

I've also added a doco update, and claimed copyright of the HMAC routine :)

Joshua.

-- 
Joshua Goodall
joshua at roughtrade.net             "Your object hit ratio is weak, old man"
"If you cache me now, I will dump more core than you can possibly imagine"
-------------- next part --------------
Index: dovecot-example.conf
===================================================================
RCS file: /home/cvs/dovecot/dovecot-example.conf,v
retrieving revision 1.77
diff -u -r1.77 dovecot-example.conf
--- dovecot-example.conf	6 Sep 2003 17:25:33 -0000	1.77
+++ dovecot-example.conf	10 Nov 2003 22:41:07 -0000
@@ -386,7 +386,7 @@
 
 auth default {
   # Space separated list of wanted authentication mechanisms:
-  #   plain digest-md5 anonymous
+  #   plain digest-md5 cram-md5 anonymous
   mechanisms = plain
 
   # Where user database is kept:
Index: doc/auth.txt
===================================================================
RCS file: /home/cvs/dovecot/doc/auth.txt,v
retrieving revision 1.10
diff -u -r1.10 auth.txt
--- doc/auth.txt	25 Jun 2003 23:15:35 -0000	1.10
+++ doc/auth.txt	10 Nov 2003 22:41:07 -0000
@@ -8,6 +8,8 @@
  - DIGEST-MD5: Should be quite secure by itself. It also supports
    integrity protecting and crypting the rest of the communication, but
    we don't support those yet.
+ - CRAM-MD5: Protects the secret in transit from eavesdroppers.  Doesn't
+   provide any integrity guarantees.
  - ANONYMOUS: No authentication required. User will be logged in as the user
    specified by auth_anonymous_username setting (default "anonymous"). There's
    no special restrictions given for anonymous users so you have to make sure
@@ -46,6 +48,7 @@
 
  - PLAIN: Although not that good idea, it enables support for all current
    and future authentication mechanisms.
+ - HMAC-MD5: HMAC-MD5 context of password, for the CRAM-MD5 mechanism.
  - DIGEST-MD5: MD5 sum of "user:realm:password", as required by DIGEST-MD5
    mechanism.
 
Index: src/auth/mech-cram-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.2
diff -u -r1.2 mech-cram-md5.c
--- src/auth/mech-cram-md5.c	10 Nov 2003 21:44:54 -0000	1.2
+++ src/auth/mech-cram-md5.c	10 Nov 2003 22:41:10 -0000
@@ -32,7 +32,7 @@
 
 static const char *get_cram_challenge(void)
 {
-	char buf[17];
+	unsigned char buf[17];
 	size_t i;
 
 	hostpid_init();
@@ -42,7 +42,7 @@
 		buf[i] = (buf[i] % 10) + '0';
 	buf[sizeof(buf)-1] = '\0';
 
-	return t_strdup_printf("%s.%s@%s", buf, dec2str(ioloop_time),
+	return t_strdup_printf("<%s.%s@%s>", buf, dec2str(ioloop_time),
 			       my_hostname);
 }
 
Index: src/auth/passdb.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/passdb.c,v
retrieving revision 1.12
diff -u -r1.12 passdb.c
--- src/auth/passdb.c	10 Nov 2003 20:36:02 -0000	1.12
+++ src/auth/passdb.c	10 Nov 2003 22:41:10 -0000
@@ -25,7 +25,7 @@
 	case PASSDB_CREDENTIALS_CRYPT:
 		return "CRYPT";
 	case PASSDB_CREDENTIALS_CRAM_MD5:
-		return "CRAM-MD5";
+		return "HMAC-MD5";
 	case PASSDB_CREDENTIALS_DIGEST_MD5:
 		return "DIGEST-MD5";
 	}
Index: src/auth/password-scheme-cram-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/password-scheme-cram-md5.c,v
retrieving revision 1.1
diff -u -r1.1 password-scheme-cram-md5.c
--- src/auth/password-scheme-cram-md5.c	10 Nov 2003 20:36:02 -0000	1.1
+++ src/auth/password-scheme-cram-md5.c	10 Nov 2003 22:41:10 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Timo Sirainen */
+/* Copyright (C) 2003 Timo Sirainen / Joshua Goodall */
 
 #include "lib.h"
 #include "md5.h"
Index: src/auth/password-scheme.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/password-scheme.c,v
retrieving revision 1.4
diff -u -r1.4 password-scheme.c
--- src/auth/password-scheme.c	10 Nov 2003 20:36:02 -0000	1.4
+++ src/auth/password-scheme.c	10 Nov 2003 22:41:11 -0000
@@ -30,6 +30,11 @@
 	if (strcasecmp(scheme, "PLAIN") == 0)
 		return strcmp(password, plaintext) == 0;
 
+	if (strcasecmp(scheme, "HMAC-MD5") == 0) {
+		str = password_generate_cram_md5(plaintext);
+		return strcmp(str, password) == 0;
+	}
+
 	if (strcasecmp(scheme, "DIGEST-MD5") == 0) {
 		/* user:realm:passwd */
 		realm = strchr(user, '@');
@@ -110,7 +115,7 @@
 	if (strcasecmp(scheme, "PLAIN") == 0)
 		return plaintext;
 
-	if (strcasecmp(scheme, "CRAM-MD5") == 0)
+	if (strcasecmp(scheme, "HMAC-MD5") == 0)
 		return password_generate_cram_md5(plaintext);
 
 	if (strcasecmp(scheme, "DIGEST-MD5") == 0) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
URL: <http://dovecot.org/pipermail/dovecot/attachments/20031111/f5d2549a/attachment-0001.bin>


More information about the dovecot mailing list