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;