# HG changeset patch # User Timo Sirainen # Date 1262290395 18000 # Node ID b48a4af4248d221ffbf2495bf5ccd8b7228d9f56 # Parent 029c3afcfbd0b0297a619ca6cb60f00018005c3a auth_debug_passwords: If password is correct but scheme is wrong, try to detect and log it. diff -r 029c3afcfbd0 -r b48a4af4248d src/auth/auth-request.c --- a/src/auth/auth-request.c Tue Dec 29 17:19:16 2009 -0500 +++ b/src/auth/auth-request.c Thu Dec 31 15:13:15 2009 -0500 @@ -1272,6 +1272,33 @@ auth_stream_reply_remove(request->extra_fields, "destuser"); } +static void log_password_failure(struct auth_request *request, + const char *plain_password, + const char *crypted_password, + const char *scheme, const char *user, + const char *subsystem) +{ + static bool scheme_ok = FALSE; + string_t *str = t_str_new(256); + const char *working_scheme; + + str_printfa(str, "%s(%s) != '%s'", scheme, + plain_password, crypted_password); + + if (!scheme_ok) { + /* perhaps the scheme is wrong - see if we can find + a working one */ + working_scheme = password_scheme_detect(plain_password, + crypted_password, user); + if (working_scheme != NULL) { + str_printfa(str, ", try %s scheme instead", + working_scheme); + } + } + + auth_request_log_debug(request, subsystem, "%s", str_c(str)); +} + int auth_request_password_verify(struct auth_request *request, const char *plain_password, const char *crypted_password, @@ -1320,12 +1347,12 @@ if (ret == 0) { auth_request_log_info(request, subsystem, "Password mismatch"); - if (request->auth->verbose_debug_passwords) { - auth_request_log_debug(request, subsystem, - "%s(%s) != '%s'", scheme, - plain_password, - crypted_password); - } + if (request->auth->verbose_debug_passwords) T_BEGIN { + log_password_failure(request, plain_password, + crypted_password, scheme, + request->original_username, + subsystem); + } T_END; } return ret; } diff -r 029c3afcfbd0 -r b48a4af4248d src/auth/password-scheme.c --- a/src/auth/password-scheme.c Tue Dec 29 17:19:16 2009 -0500 +++ b/src/auth/password-scheme.c Thu Dec 31 15:13:15 2009 -0500 @@ -251,6 +251,31 @@ s1->password_generate == s2->password_generate; } +const char * +password_scheme_detect(const char *plain_password, const char *crypted_password, + const char *user) +{ + const struct password_scheme *const *schemes; + unsigned int i, count; + const unsigned char *raw_password; + size_t raw_password_size; + + if (strncmp(crypted_password, "$1$", 3) == 0) + return "MD5-CRYPT"; + + 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) + continue; + + if (password_verify(plain_password, user, schemes[i]->name, + raw_password, raw_password_size) > 0) + return schemes[i]->name; + } + return NULL; +} + static bool crypt_verify(const char *plaintext, const char *user ATTR_UNUSED, const unsigned char *raw_password, size_t size) diff -r 029c3afcfbd0 -r b48a4af4248d src/auth/password-scheme.h --- a/src/auth/password-scheme.h Tue Dec 29 17:19:16 2009 -0500 +++ b/src/auth/password-scheme.h Thu Dec 31 15:13:15 2009 -0500 @@ -53,6 +53,12 @@ /* Returns TRUE if schemes are equivalent. */ bool password_scheme_is_alias(const char *scheme1, const char *scheme2); +/* Try to detect in which scheme crypted password is. Returns the scheme name + or NULL if nothing was found. */ +const char * +password_scheme_detect(const char *plain_password, const char *crypted_password, + const char *user); + void password_scheme_register(const struct password_scheme *scheme); void password_scheme_unregister(const struct password_scheme *scheme);