changeset 8766:888f57b1bf9c HEAD

DIGEST-MD5: Fixed authentication with user@domain usernames.
author Timo Sirainen <tss@iki.fi>
date Sat, 21 Feb 2009 17:10:43 -0500
parents d69763bee853
children e82e0a6b9399
files src/auth/auth-request.h src/auth/mech-digest-md5.c src/auth/passdb.c src/auth/password-scheme.c
diffstat 4 files changed, 38 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-request.h	Sat Feb 21 14:59:33 2009 -0500
+++ b/src/auth/auth-request.h	Sat Feb 21 17:10:43 2009 -0500
@@ -40,6 +40,8 @@
 	/* the username after doing all internal translations, but before
 	   being changed by a db lookup */
 	const char *translated_username;
+	/* realm for the request, may be specified by some auth mechanisms */
+	const char *realm;
 	char *mech_password; /* set if verify_plain() is called */
 	char *passdb_password; /* set after password lookup if successful */
         /* extra_fields are returned in authentication reply. Fields prefixed
@@ -84,6 +86,7 @@
 	unsigned int passdb_internal_failure:1;
 	unsigned int userdb_internal_failure:1;
 	unsigned int delayed_failure:1;
+	unsigned int domain_is_realm:1;
 	unsigned int accept_input:1;
 	unsigned int no_failure_delay:1;
 	unsigned int no_login:1;
--- a/src/auth/mech-digest-md5.c	Sat Feb 21 14:59:33 2009 -0500
+++ b/src/auth/mech-digest-md5.c	Sat Feb 21 17:10:43 2009 -0500
@@ -41,7 +41,6 @@
 	enum qop_option qop;
 
 	/* received: */
-	char *realm; /* may be NULL */
 	char *username;
 	char *cnonce;
 	char *nonce_count;
@@ -300,8 +299,9 @@
 					str_sanitize(value, MAX_REALM_LEN));
 			return FALSE;
 		}
-		if (request->realm == NULL && *value != '\0')
-			request->realm = p_strdup(request->pool, value);
+		if (request->auth_request.realm == NULL && *value != '\0')
+			request->auth_request.realm =
+				p_strdup(request->pool, value);
 		return TRUE;
 	}
 
@@ -551,9 +551,14 @@
 	}
 
 	if (parse_digest_response(request, data, data_size, &error)) {
-		username = request->realm == NULL ? request->username :
-			t_strconcat(request->username, "@",
-				    request->realm, NULL);
+		if (auth_request->realm != NULL &&
+		    strchr(request->username, '@') == NULL) {
+			username = t_strconcat(request->username, "@",
+					       auth_request->realm, NULL);
+			auth_request->domain_is_realm = TRUE;
+		} else {
+			username = request->username;
+		}
 
 		if (auth_request_set_username(auth_request, username, &error)) {
 			auth_request_lookup_credentials(auth_request,
--- a/src/auth/passdb.c	Sat Feb 21 14:59:33 2009 -0500
+++ b/src/auth/passdb.c	Sat Feb 21 17:10:43 2009 -0500
@@ -52,7 +52,7 @@
 			    const unsigned char **credentials_r, size_t *size_r)
 {
 	const char *wanted_scheme = auth_request->credentials_scheme;
-	const char *plaintext;
+	const char *plaintext, *username;
 	int ret;
 
 	if (auth_request->prefer_plain_credentials &&
@@ -99,14 +99,19 @@
 
 		/* we can generate anything out of plaintext passwords */
 		plaintext = t_strndup(*credentials_r, *size_r);
+		username = auth_request->original_username;
+		if (!auth_request->domain_is_realm &&
+		    strchr(username, '@') != NULL) {
+			/* domain must not be used as realm. add the @realm. */
+			username = t_strconcat(username, "@",
+					       auth_request->realm, NULL);
+		}
 		if (auth_request->auth->verbose_debug_passwords) {
 			auth_request_log_info(auth_request, "password",
-				"Generating %s from user %s password %s",
-				wanted_scheme, auth_request->original_username,
-				plaintext);
+				"Generating %s from user '%s', password '%s'",
+				wanted_scheme, username, plaintext);
 		}
-		if (!password_generate(plaintext,
-				       auth_request->original_username,
+		if (!password_generate(plaintext, username,
 				       wanted_scheme, credentials_r, size_r)) {
 			auth_request_log_error(auth_request, "password",
 				"Requested unknown scheme %s", wanted_scheme);
--- a/src/auth/password-scheme.c	Sat Feb 21 14:59:33 2009 -0500
+++ b/src/auth/password-scheme.c	Sat Feb 21 17:10:43 2009 -0500
@@ -517,13 +517,21 @@
 	if (user == NULL)
 		i_fatal("digest_md5_generate(): username not given");
 
-	/* user:realm:passwd */
-	realm = strchr(user, '@');
-	if (realm != NULL) realm++; else realm = "";
 
+	/* assume user@realm format for username. If user@domain is wanted
+	   in the username, allow also user@domain@realm. */
+	realm = strrchr(user, '@');
+	if (realm != NULL) {
+		user = t_strdup_until(user, realm);
+		realm++;
+	} else {
+		user = realm;
+		realm = "";
+	}
+
+	/* user:realm:passwd */
 	digest = t_malloc(MD5_RESULTLEN);
-	str = t_strdup_printf("%s:%s:%s", t_strcut(user, '@'),
-			      realm, plaintext);
+	str = t_strdup_printf("%s:%s:%s", user, realm, plaintext);
 	md5_get_digest(str, strlen(str), digest);
 
 	*raw_password_r = digest;