]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
DIGEST-MD5: Fixed authentication with user@domain usernames.
authorTimo Sirainen <tss@iki.fi>
Sat, 21 Feb 2009 22:10:43 +0000 (17:10 -0500)
committerTimo Sirainen <tss@iki.fi>
Sat, 21 Feb 2009 22:10:43 +0000 (17:10 -0500)
--HG--
branch : HEAD

src/auth/auth-request.h
src/auth/mech-digest-md5.c
src/auth/passdb.c
src/auth/password-scheme.c

index 52dc278b159b4a3a2cb41b5bff151a880451cdc2..b02ff15a2ffa241efdd60d7f8ea79db2ee61fec9 100644 (file)
@@ -40,6 +40,8 @@ struct auth_request {
        /* 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 @@ struct auth_request {
        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;
index ca000b443e632d25eb82e0024cd14c257db476a1..a5176728b0a44e9991966e14355fe21e723c6041 100644 (file)
@@ -41,7 +41,6 @@ struct digest_auth_request {
        enum qop_option qop;
 
        /* received: */
-       char *realm; /* may be NULL */
        char *username;
        char *cnonce;
        char *nonce_count;
@@ -300,8 +299,9 @@ static bool auth_handle_response(struct digest_auth_request *request,
                                        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 @@ mech_digest_md5_auth_continue(struct auth_request *auth_request,
        }
 
        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,
index 794b55760e138215797ac2ea3c0f468a4b844c73..2c0e3503b4203fea7f0f457990c987dfe6c9dcab 100644 (file)
@@ -52,7 +52,7 @@ bool passdb_get_credentials(struct auth_request *auth_request,
                            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 @@ bool passdb_get_credentials(struct auth_request *auth_request,
 
                /* 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);
index 2dbb5dba847244d2154e32e00d3df3d5d8c1f2e7..21a6c11337db08acba54f9425bb02fd13ebb2e43 100644 (file)
@@ -517,13 +517,21 @@ digest_md5_generate(const char *plaintext, const char *user,
        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;