changeset 3918:40a461d554e6 HEAD

Added auth_debug_passwords setting. If it's not enabled, hide all password strings from logs.
author Timo Sirainen <tss@iki.fi>
date Sun, 22 Jan 2006 13:33:27 +0200
parents ae292bd41926
children b967ffb7e3a6
files dovecot-example.conf src/auth/auth-client-connection.c src/auth/auth-request.c src/auth/auth-request.h src/auth/auth.c src/auth/auth.h src/auth/passdb-cache.c src/auth/passdb-ldap.c src/auth/passdb-passwd-file.c src/auth/passdb-sql.c src/auth/passdb-vpopmail.c src/master/auth-process.c src/master/master-settings.c src/master/master-settings.h
diffstat 14 files changed, 117 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Sun Jan 22 12:50:54 2006 +0200
+++ b/dovecot-example.conf	Sun Jan 22 13:33:27 2006 +0200
@@ -598,9 +598,13 @@
 #auth_verbose = no
 
 # Even more verbose logging for debugging purposes. Shows for example SQL
-# queries. WARNING: This also saves users' passwords in logs!
+# queries.
 #auth_debug = no
 
+# In case of password mismatches, log the passwords and used scheme so the
+# problem can be debugged. Requires auth_debug=yes to be set.
+#auth_debug_passwords = no
+
 # Maximum number of dovecot-auth worker processes. They're used to execute
 # blocking passdb and userdb queries (eg. MySQL and PAM). They're
 # automatically created and destroyed as needed.
--- a/src/auth/auth-client-connection.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/auth-client-connection.c	Sun Jan 22 13:33:27 2006 +0200
@@ -21,26 +21,38 @@
 static void auth_client_connection_unref(struct auth_client_connection **_conn);
 
 static void auth_client_input(void *context);
-static void auth_client_send(struct auth_client_connection *conn,
-			     const char *fmt, ...) __attr_format__(2, 3);
+
+static const char *reply_line_hide_pass(const char *line)
+{
+	const char *p, *p2;
+
+	/* hide proxy reply password */
+	p = strstr(line, "\tpass=");
+	if (p == NULL)
+		return line;
+	p += 6;
+
+	p2 = strchr(p, '\t');
+	return t_strconcat(t_strdup_until(line, p), "<hidden>", p2, NULL);
+}
 
 static void auth_client_send(struct auth_client_connection *conn,
-			     const char *fmt, ...)
+			     const char *cmd)
 {
-	va_list args;
 	string_t *str;
 
 	i_assert(conn->refcount > 1);
 
 	t_push();
-	va_start(args, fmt);
 	str = t_str_new(256);
-	str_vprintfa(str, fmt, args);
+	str_append(str, cmd);
+	str_append_c(str, '\n');
 
-	if (conn->auth->verbose_debug)
-		i_info("client out: %s", str_c(str));
+	if (conn->auth->verbose_debug) {
+		i_info("client out: %s", conn->auth->verbose_debug_passwords ?
+		       cmd : reply_line_hide_pass(cmd));
+	}
 
-	str_append_c(str, '\n');
 	(void)o_stream_send(conn->output, str_data(str), str_len(str));
 
 	if (o_stream_get_buffer_used_size(conn->output) >=
@@ -50,7 +62,6 @@
 		if (conn->io != NULL)
 			io_remove(&conn->io);
 	}
-	va_end(args);
 	t_pop();
 }
 
@@ -64,7 +75,7 @@
 		return;
 	}
 
-	auth_client_send(conn, "%s", reply);
+	auth_client_send(conn, reply);
 }
 
 static bool
@@ -128,22 +139,55 @@
 	return 1;
 }
 
+static const char *auth_line_hide_pass(const char *line)
+{
+	const char *p, *p2;
+
+	p = strstr(line, "\tresp=");
+	if (p == NULL)
+		return line;
+	p += 6;
+
+	p2 = strchr(p, '\t');
+	return t_strconcat(t_strdup_until(line, p), "<hidden>", p2, NULL);
+}
+
+static const char *cont_line_hide_pass(const char *line)
+{
+	const char *p;
+
+	p = strchr(line, '\t');
+	if (p == NULL)
+		return line;
+
+	return t_strconcat(t_strdup_until(line, p), "<hidden>", NULL);
+}
+
 static bool
 auth_client_handle_line(struct auth_client_connection *conn, const char *line)
 {
-	if (conn->auth->verbose_debug)
-		i_info("client in: %s", line);
-
 	if (strncmp(line, "AUTH\t", 5) == 0) {
+		if (conn->auth->verbose_debug) {
+			i_info("client in: %s",
+			       conn->auth->verbose_debug_passwords ? line :
+			       auth_line_hide_pass(line));
+		}
 		return auth_request_handler_auth_begin(conn->request_handler,
 						       line + 5);
 	}
 	if (strncmp(line, "CONT\t", 5) == 0) {
+		if (conn->auth->verbose_debug) {
+			i_info("client in: %s",
+			       conn->auth->verbose_debug_passwords ? line :
+			       cont_line_hide_pass(line));
+		}
 		return auth_request_handler_auth_continue(conn->request_handler,
 							  line + 5);
 	}
 
 	/* ignore unknown command */
+	if (conn->auth->verbose_debug)
+		i_info("client in (unknown command): %s", line);
 	return TRUE;
 }
 
--- a/src/auth/auth-request.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/auth-request.c	Sun Jan 22 13:33:27 2006 +0200
@@ -15,6 +15,7 @@
 #include "passdb-blocking.h"
 #include "userdb-blocking.h"
 #include "passdb-cache.h"
+#include "password-scheme.h"
 
 struct auth_request *
 auth_request_new(struct auth *auth, struct mech_module *mech,
@@ -576,6 +577,31 @@
 	auth_stream_reply_add(request->extra_fields, name, value);
 }
 
+int auth_request_password_verify(struct auth_request *request,
+				 const char *plain_password,
+				 const char *crypted_password,
+				 const char *scheme, const char *subsystem)
+{
+	int ret;
+
+	ret = password_verify(plain_password, crypted_password, scheme,
+			      request->user);
+	if (ret < 0) {
+		auth_request_log_error(request, subsystem,
+				       "Unknown password scheme %s", scheme);
+	} else 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);
+		}
+	}
+	return ret;
+}
+
 static const char *escape_none(const char *str)
 {
 	return str;
--- a/src/auth/auth-request.h	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/auth-request.h	Sun Jan 22 13:33:27 2006 +0200
@@ -101,6 +101,11 @@
 			    const char *name, const char *value,
 			    const char *default_scheme);
 
+int auth_request_password_verify(struct auth_request *request,
+				 const char *plain_password,
+				 const char *crypted_password,
+				 const char *scheme, const char *subsystem);
+
 const struct var_expand_table *
 auth_request_get_var_expand_table(const struct auth_request *auth_request,
 				  const char *(*escape_func)(const char *));
--- a/src/auth/auth.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/auth.c	Sun Jan 22 13:33:27 2006 +0200
@@ -28,6 +28,8 @@
 
 	auth->verbose = getenv("VERBOSE") != NULL;
 	auth->verbose_debug = getenv("VERBOSE_DEBUG") != NULL;
+	auth->verbose_debug_passwords =
+		getenv("VERBOSE_DEBUG_PASSWORDS") != NULL;
 
 	t_push();
 	for (i = 1; ; i++) {
--- a/src/auth/auth.h	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/auth.h	Sun Jan 22 13:33:27 2006 +0200
@@ -44,7 +44,7 @@
 	bool ssl_require_client_cert;
         bool ssl_username_from_cert;
 
-	bool verbose, verbose_debug;
+	bool verbose, verbose_debug, verbose_debug_passwords;
 };
 
 const string_t *auth_mechanisms_get_list(struct auth *auth);
--- a/src/auth/passdb-cache.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/passdb-cache.c	Sun Jan 22 13:33:27 2006 +0200
@@ -69,13 +69,8 @@
 	scheme = password_get_scheme(&cached_pw);
 	i_assert(scheme != NULL);
 
-	ret = password_verify(password, cached_pw, scheme, request->user);
-	if (ret < 0) {
-		auth_request_log_error(request, "cache",
-				       "Unknown password scheme %s", scheme);
-	} else if (ret == 0) {
-		auth_request_log_info(request, "cache", "Password mismatch");
-	}
+	ret = auth_request_password_verify(request, password, cached_pw,
+					   scheme, "cache");
 
 	*result_r = ret > 0 ? PASSDB_RESULT_OK :
 		PASSDB_RESULT_PASSWORD_MISMATCH;
--- a/src/auth/passdb-ldap.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/passdb-ldap.c	Sun Jan 22 13:33:27 2006 +0200
@@ -175,15 +175,9 @@
 		return;
 	}
 
-	ret = password_verify(auth_request->mech_password, password, scheme,
-			      auth_request->user);
-	if (ret < 0) {
-		auth_request_log_error(auth_request, "ldap",
-			"Unknown password scheme %s", scheme);
-	} else if (ret == 0) {
-		auth_request_log_info(auth_request, "ldap",
-				      "password mismatch");
-	}
+	ret = auth_request_password_verify(auth_request,
+					   auth_request->mech_password,
+					   password, scheme, "ldap");
 
 	ldap_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
 					    PASSDB_RESULT_PASSWORD_MISMATCH,
--- a/src/auth/passdb-passwd-file.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/passdb-passwd-file.c	Sun Jan 22 13:33:27 2006 +0200
@@ -45,20 +45,11 @@
 				       crypted_pass, scheme);
 	}
 
-	ret = password_verify(password, crypted_pass, scheme,
-			      request->user);
-	if (ret > 0)
-		callback(PASSDB_RESULT_OK, request);
-	else {
-		if (ret < 0) {
-			auth_request_log_error(request, "passwd-file",
-				"unknown password scheme %s", scheme);
-		} else {
-			auth_request_log_info(request, "passwd-file",
-					      "password mismatch");
-		}
-		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
-	}
+	ret = auth_request_password_verify(request, password, crypted_pass,
+					   scheme, "passwd-file");
+
+	callback(ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH,
+		 request);
 }
 
 static void
--- a/src/auth/passdb-sql.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/passdb-sql.c	Sun Jan 22 13:33:27 2006 +0200
@@ -111,14 +111,9 @@
 		return;
 	}
 
-	ret = password_verify(auth_request->mech_password, password,
-			      scheme, user);
-	if (ret < 0) {
-		auth_request_log_error(auth_request, "sql",
-				       "Unknown password scheme %s", scheme);
-	} else if (ret == 0) {
-		auth_request_log_info(auth_request, "sql", "Password mismatch");
-	}
+	ret = auth_request_password_verify(auth_request,
+					   auth_request->mech_password,
+					   password, scheme, "sql");
 
 	sql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
 					   PASSDB_RESULT_PASSWORD_MISMATCH,
--- a/src/auth/passdb-vpopmail.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/auth/passdb-vpopmail.c	Sun Jan 22 13:33:27 2006 +0200
@@ -50,7 +50,8 @@
 	if (scheme == NULL)
 		scheme = request->passdb->passdb->default_pass_scheme;
 
-	ret = password_verify(password, crypted_pass, scheme, request->user);
+	ret = auth_request_password_verify(request, password, crypted_pass,
+					   scheme, "vpopmail");
 
 	safe_memset(vpw->pw_passwd, 0, strlen(vpw->pw_passwd));
 	if (vpw->pw_clear_passwd != NULL) {
@@ -59,13 +60,6 @@
 	}
 
 	if (ret <= 0) {
-		if (ret < 0) {
-			auth_request_log_error(request, "vpopmail",
-				"Unknown password scheme %s", scheme);
-		} else {
-			auth_request_log_info(request, "vpopmail",
-					      "password mismatch");
-		}
 		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
 		return;
 	}
--- a/src/master/auth-process.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/master/auth-process.c	Sun Jan 22 13:33:27 2006 +0200
@@ -454,6 +454,8 @@
 		env_put("VERBOSE=1");
 	if (set->debug)
 		env_put("VERBOSE_DEBUG=1");
+	if (set->debug_passwords)
+		env_put("VERBOSE_DEBUG_PASSWORDS=1");
 	if (set->ssl_require_client_cert)
 		env_put("SSL_REQUIRE_CLIENT_CERT=1");
 	if (set->ssl_username_from_cert)
--- a/src/master/master-settings.c	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/master/master-settings.c	Sun Jan 22 13:33:27 2006 +0200
@@ -170,6 +170,7 @@
 
 	DEF(SET_BOOL, verbose),
 	DEF(SET_BOOL, debug),
+	DEF(SET_BOOL, debug_passwords),
 	DEF(SET_BOOL, ssl_require_client_cert),
 	DEF(SET_BOOL, ssl_username_from_cert),
 
@@ -375,6 +376,7 @@
 
 	MEMBER(verbose) FALSE,
 	MEMBER(debug) FALSE,
+	MEMBER(debug_passwords) FALSE,
 	MEMBER(ssl_require_client_cert) FALSE,
 	MEMBER(ssl_username_from_cert) FALSE,
 
--- a/src/master/master-settings.h	Sun Jan 22 12:50:54 2006 +0200
+++ b/src/master/master-settings.h	Sun Jan 22 13:33:27 2006 +0200
@@ -171,7 +171,7 @@
 	const char *anonymous_username;
 	const char *krb5_keytab;
 
-	bool verbose, debug;
+	bool verbose, debug, debug_passwords;
 	bool ssl_require_client_cert;
 	bool ssl_username_from_cert;