Mercurial > dovecot > core-2.2
changeset 12978:62945c9d6b47
auth: Don't log warnings/errors when guessing a password's scheme.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 23 May 2011 15:38:16 +0300 |
parents | 9490d57d2f7b |
children | 93c41a60f894 |
files | src/auth/password-scheme-otp.c src/auth/password-scheme.c src/auth/password-scheme.h |
diffstat | 3 files changed, 88 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/password-scheme-otp.c Mon May 23 15:37:43 2011 +0300 +++ b/src/auth/password-scheme-otp.c Mon May 23 15:38:16 2011 +0300 @@ -12,16 +12,14 @@ #include "randgen.h" #include "otp.h" -const char *password_generate_otp(const char *pw, const char *data, - unsigned int algo) +int password_generate_otp(const char *pw, const char *data, + unsigned int algo, const char **result_r) { struct otp_state state; if (data != NULL) { - if (otp_parse_dbentry(data, &state) != 0) { - i_warning("Invalid OTP data in passdb"); - return ""; - } + if (otp_parse_dbentry(data, &state) != 0) + return -1; } else { /* Generate new OTP credentials from plaintext */ unsigned char random_data[OTP_MAX_SEED_LEN / 2]; @@ -35,6 +33,6 @@ } otp_hash(state.algo, state.seed, pw, state.seq, state.hash); - - return otp_print_dbentry(&state); + *result_r = otp_print_dbentry(&state); + return 0; }
--- a/src/auth/password-scheme.c Mon May 23 15:37:43 2011 +0300 +++ b/src/auth/password-scheme.c Mon May 23 15:38:16 2011 +0300 @@ -74,7 +74,8 @@ } int password_verify(const char *plaintext, const char *user, const char *scheme, - const unsigned char *raw_password, size_t size) + const unsigned char *raw_password, size_t size, + const char **error_r) { const struct password_scheme *s; enum password_encoding encoding; @@ -82,17 +83,21 @@ size_t generated_size; s = password_scheme_lookup(scheme, &encoding); - if (s == NULL) + if (s == NULL) { + *error_r = "Unknown password scheme"; return -1; + } - if (s->password_verify != NULL) - return s->password_verify(plaintext, user, raw_password, size); + if (s->password_verify != NULL) { + return s->password_verify(plaintext, user, raw_password, size, + error_r); + } /* generic verification handler: generate the password and compare it to the one in database */ s->password_generate(plaintext, user, &generated, &generated_size); return size != generated_size ? 0 : - memcmp(generated, raw_password, size) == 0; + memcmp(generated, raw_password, size) == 0 ? 1 : 0; } const char *password_get_scheme(const char **password) @@ -272,6 +277,7 @@ unsigned int i, count; const unsigned char *raw_password; size_t raw_password_size; + const char *error; schemes = array_get(&password_schemes, &count); for (i = 0; i < count; i++) { @@ -280,31 +286,33 @@ continue; if (password_verify(plain_password, user, schemes[i]->name, - raw_password, raw_password_size) > 0) + raw_password, raw_password_size, + &error) > 0) return schemes[i]->name; } return NULL; } -bool crypt_verify(const char *plaintext, const char *user ATTR_UNUSED, - const unsigned char *raw_password, size_t size) +int crypt_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { const char *password, *crypted; if (size == 0) { /* the default mycrypt() handler would return match */ - return FALSE; + return 0; } password = t_strndup(raw_password, size); crypted = mycrypt(plaintext, password); if (crypted == NULL) { /* really shouldn't happen unless the system is broken */ - i_error("crypt() failed: %m"); - return FALSE; + *error_r = t_strdup_printf("crypt() failed: %m"); + return -1; } - return strcmp(crypted, password) == 0; + return strcmp(crypted, password) == 0 ? 1 : 0; } static void @@ -320,9 +328,9 @@ *size_r = strlen(password); } -static bool +static int md5_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size) + const unsigned char *raw_password, size_t size, const char **error_r) { const char *password, *str; const unsigned char *md5_password; @@ -332,27 +340,27 @@ if (strncmp(password, "$1$", 3) == 0) { /* MD5-CRYPT */ str = password_generate_md5_crypt(plaintext, password); - return strcmp(str, password) == 0; + return strcmp(str, password) == 0 ? 1 : 0; } else if (password_decode(password, "PLAIN-MD5", &md5_password, &md5_size) < 0) { - i_error("md5_verify(%s): Not a valid MD5-CRYPT or " - "PLAIN-MD5 password", user); - return FALSE; + *error_r = "Not a valid MD5-CRYPT or PLAIN-MD5 password"; + return -1; } else { return password_verify(plaintext, user, "PLAIN-MD5", - md5_password, md5_size) > 0; + md5_password, md5_size, error_r); } } -static bool +static int md5_crypt_verify(const char *plaintext, const char *user ATTR_UNUSED, - const unsigned char *raw_password, size_t size) + const unsigned char *raw_password, size_t size, + const char **error_r ATTR_UNUSED) { const char *password, *str; password = t_strndup(raw_password, size); str = password_generate_md5_crypt(plaintext, password); - return strcmp(str, password) == 0; + return strcmp(str, password) == 0 ? 1 : 0; } static void @@ -433,23 +441,24 @@ *size_r = SHA1_RESULTLEN + SSHA_SALT_LEN; } -static bool ssha_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size) +static int ssha_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { unsigned char sha1_digest[SHA1_RESULTLEN]; struct sha1_ctxt ctx; /* format: <SHA1 hash><salt> */ if (size <= SHA1_RESULTLEN) { - i_error("ssha_verify(%s): SSHA password too short", user); - return FALSE; + *error_r = "SSHA password is too short"; + return -1; } sha1_init(&ctx); sha1_loop(&ctx, plaintext, strlen(plaintext)); sha1_loop(&ctx, raw_password + SHA1_RESULTLEN, size - SHA1_RESULTLEN); sha1_result(&ctx, sha1_digest); - return memcmp(sha1_digest, raw_password, SHA1_RESULTLEN) == 0; + return memcmp(sha1_digest, raw_password, SHA1_RESULTLEN) == 0 ? 1 : 0; } static void @@ -473,16 +482,17 @@ *size_r = SHA256_RESULTLEN + SSHA256_SALT_LEN; } -static bool ssha256_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size) +static int ssha256_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { unsigned char sha256_digest[SHA256_RESULTLEN]; struct sha256_ctx ctx; /* format: <SHA256 hash><salt> */ if (size <= SHA256_RESULTLEN) { - i_error("ssha256_verify(%s): SSHA256 password too short", user); - return FALSE; + *error_r = "SSHA256 password is too short"; + return -1; } sha256_init(&ctx); @@ -490,7 +500,8 @@ sha256_loop(&ctx, raw_password + SHA256_RESULTLEN, size - SHA256_RESULTLEN); sha256_result(&ctx, sha256_digest); - return memcmp(sha256_digest, raw_password, SHA256_RESULTLEN) == 0; + return memcmp(sha256_digest, raw_password, + SHA256_RESULTLEN) == 0 ? 1 : 0; } static void @@ -514,16 +525,17 @@ *size_r = SHA512_RESULTLEN + SSHA512_SALT_LEN; } -static bool ssha512_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size) +static int ssha512_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { unsigned char sha512_digest[SHA512_RESULTLEN]; struct sha512_ctx ctx; /* format: <SHA512 hash><salt> */ if (size <= SHA512_RESULTLEN) { - i_error("ssha512_verify(%s): SSHA512 password too short", user); - return FALSE; + *error_r = "SSHA512 password is too short"; + return -1; } sha512_init(&ctx); @@ -531,7 +543,8 @@ sha512_loop(&ctx, raw_password + SHA512_RESULTLEN, size - SHA512_RESULTLEN); sha512_result(&ctx, sha512_digest); - return memcmp(sha512_digest, raw_password, SHA512_RESULTLEN) == 0; + return memcmp(sha512_digest, raw_password, + SHA512_RESULTLEN) == 0 ? 1 : 0; } static void @@ -555,23 +568,24 @@ *size_r = MD5_RESULTLEN + SMD5_SALT_LEN; } -static bool smd5_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size) +static int smd5_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { unsigned char md5_digest[MD5_RESULTLEN]; struct md5_context ctx; /* format: <MD5 hash><salt> */ if (size <= MD5_RESULTLEN) { - i_error("smd5_verify(%s): SMD5 password too short", user); - return FALSE; + *error_r = "SMD5 password is too short"; + return -1; } md5_init(&ctx); md5_update(&ctx, plaintext, strlen(plaintext)); md5_update(&ctx, raw_password + MD5_RESULTLEN, size - MD5_RESULTLEN); md5_final(&ctx, md5_digest); - return memcmp(md5_digest, raw_password, MD5_RESULTLEN) == 0; + return memcmp(md5_digest, raw_password, MD5_RESULTLEN) == 0 ? 1 : 0; } static void @@ -680,14 +694,19 @@ *size_r = NTLMSSP_HASH_SIZE; } -static bool otp_verify(const char *plaintext, const char *user ATTR_UNUSED, - const unsigned char *raw_password, size_t size) +static int otp_verify(const char *plaintext, const char *user ATTR_UNUSED, + const unsigned char *raw_password, size_t size, + const char **error_r) { - const char *password; + const char *password, *generated; password = t_strndup(raw_password, size); - return strcasecmp(password, - password_generate_otp(plaintext, password, -1)) == 0; + if (password_generate_otp(plaintext, password, -1, &generated) < 0) { + *error_r = "Invalid OTP data in passdb"; + return -1; + } + + return strcasecmp(password, generated) == 0 ? 1 : 0; } static void @@ -696,7 +715,8 @@ { const char *password; - password = password_generate_otp(plaintext, NULL, OTP_HASH_SHA1); + if (password_generate_otp(plaintext, NULL, OTP_HASH_SHA1, &password) < 0) + i_unreached(); *raw_password_r = (const unsigned char *)password; *size_r = strlen(password); } @@ -707,7 +727,8 @@ { const char *password; - password = password_generate_otp(plaintext, NULL, OTP_HASH_MD4); + if (password_generate_otp(plaintext, NULL, OTP_HASH_MD4, &password) < 0) + i_unreached(); *raw_password_r = (const unsigned char *)password; *size_r = strlen(password); }
--- a/src/auth/password-scheme.h Mon May 23 15:37:43 2011 +0300 +++ b/src/auth/password-scheme.h Mon May 23 15:38:16 2011 +0300 @@ -15,8 +15,9 @@ hex and base64 encoded passwords. */ unsigned int raw_password_len; - bool (*password_verify)(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size); + int (*password_verify)(const char *plaintext, const char *user, + const unsigned char *raw_password, size_t size, + const char **error_r); void (*password_generate)(const char *plaintext, const char *user, const unsigned char **raw_password_r, size_t *size_r); @@ -25,9 +26,11 @@ extern ARRAY_TYPE(password_scheme_p) password_schemes; -/* Returns 1 = matched, 0 = didn't match, -1 = unknown scheme */ +/* Returns 1 = matched, 0 = didn't match, -1 = unknown scheme or invalid + raw_password */ int password_verify(const char *plaintext, const char *user, const char *scheme, - const unsigned char *raw_password, size_t size); + const unsigned char *raw_password, size_t size, + const char **error_r); /* Extracts scheme from password, or returns NULL if it isn't found. If auth_request is given, it's used for debug logging. */ @@ -72,12 +75,13 @@ /* INTERNAL: */ const char *password_generate_salt(size_t len); const char *password_generate_md5_crypt(const char *pw, const char *salt); -const char *password_generate_otp(const char *pw, const char *state, - unsigned int algo); +int password_generate_otp(const char *pw, const char *state, + unsigned int algo, const char **result_r); void password_generate_rpa(const char *pw, unsigned char result[]); -bool crypt_verify(const char *plaintext, const char *user, - const unsigned char *raw_password, size_t size); +int crypt_verify(const char *plaintext, const char *user, + const unsigned char *raw_password, size_t size, + const char **error_r); /* check wich of the algorithms Blowfisch, SHA-256 and SHA-512 are supported by the used libc's/glibc's crypt() */