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,
if (ret == 0) {
auth_request_log_info(request, subsystem,
"Password mismatch");
- if (request->auth->set->debug_passwords) {
- auth_request_log_debug(request, subsystem,
- "%s(%s) != '%s'", scheme,
- plain_password,
- crypted_password);
- }
+ if (request->auth->set->debug_passwords) T_BEGIN {
+ log_password_failure(request, plain_password,
+ crypted_password, scheme,
+ request->original_username,
+ subsystem);
+ } T_END;
}
return ret;
}
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)
/* 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);