]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: If password data isn't valid for specified scheme, give a better error message.
authorTimo Sirainen <tss@iki.fi>
Sat, 1 Oct 2011 13:48:17 +0000 (16:48 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 1 Oct 2011 13:48:17 +0000 (16:48 +0300)
src/auth/auth-request.c
src/auth/passdb.c
src/auth/password-scheme.c
src/auth/password-scheme.h

index 588637a9b46a8d70b10f4dbee8bccd5de16be9f7..7b653605d71fadb633ebfb56469f28b690d1d6ac 100644 (file)
@@ -1509,12 +1509,12 @@ int auth_request_password_verify(struct auth_request *request,
        }
 
        ret = password_decode(crypted_password, scheme,
-                             &raw_password, &raw_password_size);
+                             &raw_password, &raw_password_size, &error);
        if (ret <= 0) {
                if (ret < 0) {
                        auth_request_log_error(request, subsystem,
-                               "Password in passdb is not in expected scheme %s",
-                               scheme);
+                               "Password data is not valid for scheme %s: %s",
+                               scheme, error);
                } else {
                        auth_request_log_error(request, subsystem,
                                               "Unknown scheme %s", scheme);
index 08f7aa02161568458ffddead6ef8c2b848f33b92..19d0f03e9326b75721e4d23bc06aaa9f4f258164 100644 (file)
@@ -64,7 +64,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, *username;
+       const char *plaintext, *username, *error;
        int ret;
 
        if (auth_request->prefer_plain_credentials &&
@@ -74,12 +74,13 @@ bool passdb_get_credentials(struct auth_request *auth_request,
                wanted_scheme = "";
        }
 
-       ret = password_decode(input, input_scheme, credentials_r, size_r);
+       ret = password_decode(input, input_scheme,
+                             credentials_r, size_r, &error);
        if (ret <= 0) {
                if (ret < 0) {
                        auth_request_log_error(auth_request, "password",
-                               "Password in passdb is not in expected scheme %s",
-                               input_scheme);
+                               "Password data is not valid for scheme %s: %s",
+                               input_scheme, error);
                } else {
                        auth_request_log_error(auth_request, "password",
                                "Unknown scheme %s", input_scheme);
index 7d53f4bae98a8be41bfbd234e7c0a702cf2ee7af..5bb71e972a69b827be2aab29410ce3b0cbbb4b4a 100644 (file)
@@ -132,16 +132,22 @@ const char *password_get_scheme(const char **password)
 }
 
 int password_decode(const char *password, const char *scheme,
-                   const unsigned char **raw_password_r, size_t *size_r)
+                   const unsigned char **raw_password_r, size_t *size_r,
+                   const char **error_r)
 {
        const struct password_scheme *s;
        enum password_encoding encoding;
        buffer_t *buf;
        unsigned int len;
+       bool guessed_encoding;
+
+       *error_r = NULL;
 
        s = password_scheme_lookup(scheme, &encoding);
-       if (s == NULL)
+       if (s == NULL) {
+               *error_r = "Unknown scheme";
                return 0;
+       }
 
        len = strlen(password);
        if (encoding != PW_ENCODING_NONE && s->raw_password_len != 0 &&
@@ -150,8 +156,11 @@ int password_decode(const char *password, const char *scheme,
                   base64 and hex encodings. the only problem is distinguishing
                   2 character strings, but there shouldn't be any that short
                   raw_password_lens. */
-               encoding = len == s->raw_password_len * 2 ? PW_ENCODING_HEX :
-                       PW_ENCODING_BASE64;
+               encoding = len == s->raw_password_len * 2 ?
+                       PW_ENCODING_HEX : PW_ENCODING_BASE64;
+               guessed_encoding = TRUE;
+       } else {
+               guessed_encoding = FALSE;
        }
 
        switch (encoding) {
@@ -167,14 +176,20 @@ int password_decode(const char *password, const char *scheme,
                        *size_r = buf->used;
                        break;
                }
+               if (!guessed_encoding) {
+                       *error_r = "Input isn't valid HEX encoded data";
+                       return -1;
+               }
                /* fall through, just in case it was base64-encoded after
                   all. some input lengths produce matching hex and base64
                   encoded lengths. */
        case PW_ENCODING_BASE64:
                buf = buffer_create_dynamic(pool_datastack_create(),
                                            MAX_BASE64_DECODED_SIZE(len));
-               if (base64_decode(password, len, NULL, buf) < 0)
+               if (base64_decode(password, len, NULL, buf) < 0) {
+                       *error_r = "Input isn't valid base64 encoded data";
                        return -1;
+               }
 
                *raw_password_r = buf->data;
                *size_r = buf->used;
@@ -182,6 +197,9 @@ int password_decode(const char *password, const char *scheme,
        }
        if (s->raw_password_len != *size_r && s->raw_password_len != 0) {
                /* password has invalid length */
+               *error_r = t_strdup_printf(
+                       "Input length isn't valid (%u instead of %u)",
+                       (unsigned int)*size_r, s->raw_password_len);
                return -1;
        }
        return 1;
@@ -282,7 +300,8 @@ password_scheme_detect(const char *plain_password, const char *crypted_password,
        schemes = array_get(&password_schemes, &count);
        for (i = 0; i < count; i++) {
                if (password_decode(crypted_password, schemes[i]->name,
-                                   &raw_password, &raw_password_size) <= 0)
+                                   &raw_password, &raw_password_size,
+                                   &error) <= 0)
                        continue;
 
                if (password_verify(plain_password, user, schemes[i]->name,
@@ -332,7 +351,7 @@ static int
 md5_verify(const char *plaintext, const char *user,
           const unsigned char *raw_password, size_t size, const char **error_r)
 {
-       const char *password, *str;
+       const char *password, *str, *error;
        const unsigned char *md5_password;
        size_t md5_size;
 
@@ -342,7 +361,7 @@ md5_verify(const char *plaintext, const char *user,
                str = password_generate_md5_crypt(plaintext, password);
                return strcmp(str, password) == 0 ? 1 : 0;
        } else if (password_decode(password, "PLAIN-MD5",
-                                  &md5_password, &md5_size) < 0) {
+                                  &md5_password, &md5_size, &error) < 0) {
                *error_r = "Not a valid MD5-CRYPT or PLAIN-MD5 password";
                return -1;
        } else {
index bbf5abbd355309efc0b3de9b5a1a8e091b7085fa..7b67929ecfcef5212629785fe6065b9f8ed61387 100644 (file)
@@ -39,7 +39,8 @@ const char *password_get_scheme(const char **password);
 /* Decode encoded (base64/hex) password to raw form. Returns 1 if ok,
    0 if scheme is unknown, -1 if password is invalid. */
 int password_decode(const char *password, const char *scheme,
-                   const unsigned char **raw_password_r, size_t *size_r);
+                   const unsigned char **raw_password_r, size_t *size_r,
+                   const char **error_r);
 
 /* Create password with wanted scheme out of plaintext password and username.
    Potential base64/hex directives are ignored in scheme. Returns FALSE if