changeset 9523:b48a4af4248d HEAD

auth_debug_passwords: If password is correct but scheme is wrong, try to detect and log it.
author Timo Sirainen <tss@iki.fi>
date Thu, 31 Dec 2009 15:13:15 -0500
parents 029c3afcfbd0
children e2ea80e1c239
files src/auth/auth-request.c src/auth/password-scheme.c src/auth/password-scheme.h
diffstat 3 files changed, 64 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }
--- 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)
--- 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);