Hi Timo,

As http://wiki2.dovecot.org/Authentication/MasterUsers states, currently
the first way for master users to log in as other users only supports PLAIN SASL
mechanism, and because DIGEST-MD5 uses user name to calculate MD5 digest,
the second way can't support DIGEST-MD5.

I enhance the code to support DIGEST-MD5 too for the first way, please review the attached patch against dovecot-2.0 HG tip. The patch also contains a little
fix to "nonce-count" string, RFC 2831 shows it should be "nc".

I tested it on Debian Wheezy, it seems OK. Below are my verification steps.

(Debian packaged 2.0.15 + http://hg.dovecot.org/dovecot-2.0/rev/bed15faedfd4 + attached patch)

$ doveconf -n
# 2.0.15: /etc/dovecot/dovecot.conf
# OS: Linux 3.1.0-1-686-pae i686 Debian wheezy/sid
auth_default_realm = corp.example.com
auth_krb5_keytab = /etc/dovecot.keytab
auth_master_user_separator = *
auth_mechanisms = gssapi digest-md5 cram-md5
auth_realms = corp.example.com
auth_username_format = %n
first_valid_gid = 1000
first_valid_uid = 1000
mail_location = mdbox:/srv/mail/%u/Mail
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave
passdb {
  args = /etc/dovecot/master-users
  driver = passwd-file
  master = yes
}
passdb {
  driver = pam
}
plugin {
  sieve = /srv/mail/%u/.dovecot.sieve
  sieve_dir = /srv/mail/%u/sieve
}
protocols = " imap lmtp sieve"
service auth {
  unix_listener auth-client {
    group = Debian-exim
    mode = 0660
  }
}
ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem
userdb {
  args = home=/srv/mail/%u
  driver = passwd
}
protocol lmtp {
  mail_plugins = " sieve"
}
protocol lda {
  mail_plugins = " sieve"
}

$ grep webmail2 /etc/dovecot/master-users
webmail2:{DIGEST-MD5}458af98b24dce5db79f852d146d5a5ca

$ gsasl -m DIGEST-MD5 --imap imap.corp.example.com -z dieken -a webmail2 -p 123456 -r corp.example.com
Trying `gold.corp.example.com'...
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS LOGINDISABLED AUTH=GSSAPI AUTH=DIGEST-MD5 AUTH=CRAM-MD5] Dovecot ready.
. CAPABILITY
* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS LOGINDISABLED AUTH=GSSAPI AUTH=DIGEST-MD5 AUTH=CRAM-MD5
. OK Pre-login capabilities listed, post-login capabilities have more.
. STARTTLS
. OK Begin TLS negotiation now.
. CAPABILITY
* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=GSSAPI AUTH=DIGEST-MD5 AUTH=CRAM-MD5
. OK Pre-login capabilities listed, post-login capabilities have more.
. AUTHENTICATE DIGEST-MD5
+ cmVhbG09ImNvcnAuZXhhbXBsZS5jb20iLG5vbmNlPSI2Y0tvRWpoRkREQVpsRHM4Q05QTUx3PT0iLHFvcD0iYXV0aCIsY2hhcnNldD0idXRmLTgiLGFsZ29yaXRobT0ibWQ1LXNlc3Mi
Enter quality of protection (optional, e.g. 'qop-int'):
dXNlcm5hbWU9IndlYm1haWwyIiwgcmVhbG09ImNvcnAuZXhhbXBsZS5jb20iLCBub25jZT0iNmNLb0VqaEZEREFabERzOENOUE1Mdz09IiwgY25vbmNlPSJIUUZKQy9VbnFSb3lGb3orTWpOY2hnPT0iLCBuYz0wMDAwMDAwMSwgcW9wPWF1dGgsIGRpZ2VzdC11cmk9ImltYXAvaW1hcC5jb3JwLmV4YW1wbGUuY29tIiwgcmVzcG9uc2U9NjU0MTQ0NzM5MTFhNjNlMjE4ZDJmZjc0NmNjZjk0MjUsIGNoYXJzZXQ9dXRmLTgsIGF1dGh6aWQ9ImRpZWtlbiI=
+ cnNwYXV0aD04ZTNiZmZhMmNhOWM4YzczODU3Zjc2OWZiOGRlMTU3MQ==

* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS
Client authentication finished (server trusted)...
Enter application data (EOF to finish):
Session finished...
. LOGOUT
. OK Logged in
* BYE Logging out

$ sudo tail -f 30 /var/log/mail.log
....
Jan 14 20:35:30 gold dovecot: auth: Debug: client in: AUTH#0111#011DIGEST-MD5#011service=imap#011secured#011lip=127.0.1.1#011rip=127.0.0.1#011lport=143#011rport=54455 Jan 14 20:35:30 gold dovecot: auth: Debug: client out: CONT#0111#011cmVhbG09ImNvcnAuZXhhbXBsZS5jb20iLG5vbmNlPSJsQzM0dlQ3QkxUOHdlc2VOOWIybzhnPT0iLHFvcD0iYXV0aCIsY2hhcnNldD0idXRmLTgiLGFsZ29yaXRobT0ibWQ1LXNlc3Mi Jan 14 20:35:32 gold dovecot: auth: Debug: client in: CONT#0111#011dXNlcm5hbWU9IndlYm1haWwyIiwgcmVhbG09ImNvcnAuZXhhbXBsZS5jb20iLCBub25jZT0ibEMzNHZUN0JMVDh3ZXNlTjliMm84Zz09IiwgY25vbmNlPSJQOTFta2VHZjFFS2kzQVgxMWVVT3FnPT0iLCBuYz0wMDAwMDAwMSwgcW9wPWF1dGgsIGRpZ2VzdC11cmk9ImltYXAvaW1hcC5jb3JwLmV4YW1wbGUuY29tIiwgcmVzcG9uc2U9OTllNzM2MDc0ZWE3YjE2NTE4NGQ3ZGVjY2E5ZGExNTgsIGNoYXJzZXQ9dXRmLTgsIGF1dGh6aWQ9ImRpZWtlbiI= Jan 14 20:35:32 gold dovecot: auth: Debug: auth(webmail2,127.0.0.1,master): Master user lookup for login: dieken Jan 14 20:35:32 gold dovecot: auth: Debug: passwd-file(webmail2,127.0.0.1,master): lookup: user=webmail2 file=/etc/dovecot/master-users Jan 14 20:35:32 gold dovecot: auth: passdb(webmail2,127.0.0.1,master): Master user logging in as dieken Jan 14 20:35:32 gold dovecot: auth: Debug: password(dieken,127.0.0.1): Credentials: 458af98b24dce5db79f852d146d5a5ca Jan 14 20:35:32 gold dovecot: auth: Debug: client out: CONT#0111#011cnNwYXV0aD04YmU5ZjFmN2UyMTRlMjI3MmY2YjEwMDU0YmYwNmMwZg==
Jan 14 20:35:32 gold dovecot: auth: Debug: client in: CONT#0111#011
Jan 14 20:35:32 gold dovecot: auth: Debug: client out: OK#0111#011user=dieken Jan 14 20:35:32 gold dovecot: auth: Debug: master in: REQUEST#0112451832833#01115973#0111#011b7ff18971fd6967b00e2ea0ed2ef6278
Jan 14 20:35:32 gold dovecot: auth: Debug: passwd(dieken,127.0.0.1): lookup
Jan 14 20:35:32 gold dovecot: auth: Debug: master out: USER#0112451832833#011dieken#011home=/srv/mail/dieken#011system_groups_user=dieken#011uid=1000#011gid=1000#011master_user=webmail2 Jan 14 20:35:32 gold dovecot: imap-login: Login: user=<dieken>, method=DIGEST-MD5, rip=127.0.0.1, lip=127.0.1.1, mpid=15974, TLS Jan 14 20:35:32 gold dovecot: imap: Debug: Added userdb setting: plugin/master_user=webmail2 Jan 14 20:35:32 gold dovecot: imap(dieken): Debug: Effective uid=1000, gid=1000, home=/srv/mail/dieken Jan 14 20:35:32 gold dovecot: imap(dieken): Debug: fs: root=/srv/mail/dieken/Mail, index=, control=, inbox=, alt= Jan 14 20:35:32 gold dovecot: imap(dieken): Debug: Namespace : Using permissions from /srv/mail/dieken/Mail: mode=0700 gid=-1 Jan 14 20:35:34 gold dovecot: imap(dieken): Disconnected: Logged out bytes=8/329 Jan 14 20:35:34 gold dovecot: imap-login: Warning: SSL alert: where=0x4008, ret=256: warning close notify [127.0.0.1] Jan 14 21:04:50 gold dovecot: imap(dieken): Disconnected: Logged out bytes=131/533 Jan 14 21:33:59 gold dovecot: imap-login: Login: user=<dieken>, method=DIGEST-MD5, rip=127.0.0.1, lip=127.0.1.1, mpid=16114, TLS Jan 14 21:34:03 gold dovecot: imap(dieken): Disconnected: Logged out bytes=8/329 Jan 14 21:36:56 gold dovecot: imap-login: Disconnected (no auth attempts): rip=127.0.0.1, lip=127.0.1.1 Jan 14 21:36:56 gold dovecot: imap-login: Disconnected (no auth attempts): rip=127.0.0.1, lip=127.0.1.1 Jan 14 21:36:58 gold dovecot: imap-login: Login: user=<dieken>, method=DIGEST-MD5, rip=127.0.0.1, lip=127.0.1.1, mpid=16135, TLS Jan 14 21:37:00 gold dovecot: imap(dieken): Disconnected: Logged out bytes=10/377

Regards,
Yubao Liu

diff -r 8438f66433a6 src/auth/mech-digest-md5.c
--- a/src/auth/mech-digest-md5.c	Tue Jan 10 00:34:09 2012 +0200
+++ b/src/auth/mech-digest-md5.c	Sat Jan 14 21:47:02 2012 +0800
@@ -46,6 +46,7 @@
 	char *nonce_count;
 	char *qop_value;
 	char *digest_uri; /* may be NULL */
+	char *authzid; /* may be NULL, authorization ID */
 	unsigned char response[32];
 	unsigned long maxbuf;
 	unsigned int nonce_found:1;
@@ -133,7 +134,12 @@
 		     { nonce-value, ":" nc-value, ":",
 		       cnonce-value, ":", qop-value, ":", HEX(H(A2)) }))
 
-	   and since we don't support authzid yet:
+	   and if authzid is not empty:
+
+	   A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
+		":", nonce-value, ":", cnonce-value, ":", authzid }
+
+	   else:
 
 	   A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
 		":", nonce-value, ":", cnonce-value }
@@ -155,6 +161,10 @@
 	md5_update(&ctx, request->nonce, strlen(request->nonce));
 	md5_update(&ctx, ":", 1);
 	md5_update(&ctx, request->cnonce, strlen(request->cnonce));
+	if (request->authzid != NULL) {
+		md5_update(&ctx, ":", 1);
+		md5_update(&ctx, request->authzid, strlen(request->authzid));
+	}
 	md5_final(&ctx, digest);
 	a1_hex = binary_to_hex(digest, 16);
 
@@ -324,7 +334,7 @@
 		return TRUE;
 	}
 
-	if (strcmp(key, "nonce-count") == 0) {
+	if (strcmp(key, "nc") == 0) {
 		if (request->nonce_count != NULL) {
 			*error = "nonce-count must not exist more than once";
 			return FALSE;
@@ -417,8 +427,18 @@
 	}
 
 	if (strcmp(key, "authzid") == 0) {
-		/* not supported, abort */
-		return FALSE;
+		if (request->authzid != NULL) {
+		    *error = "authzid must not exist more than once";
+		    return FALSE;
+		}
+
+		if (*value == '\0') {
+		    *error = "empty authzid";
+		    return FALSE;
+		}
+
+		request->authzid = p_strdup(request->pool, value);
+		return TRUE;
 	}
 
 	/* unknown key, ignore */
@@ -544,7 +564,11 @@
 			username = request->username;
 		}
 
-		if (auth_request_set_username(auth_request, username, &error)) {
+		if (auth_request_set_username(auth_request, username, &error) &&
+				(request->authzid == NULL ||
+				 auth_request_set_login_username(auth_request,
+								 request->authzid,
+								 &error))) {
 			auth_request_lookup_credentials(auth_request,
 					"DIGEST-MD5", credentials_callback);
 			return;

Reply via email to