changeset 2691:46f879c46b45 HEAD

auth_verbose now affects imap/pop3 login processes too. Every authentication attempt by client is logged. Also fixed replies in AUTHENTICATE/AUTH commands when it was aborted by client.
author Timo Sirainen <tss@iki.fi>
date Tue, 05 Oct 2004 19:00:18 +0300
parents 7b50711a168d
children 1065a557516b
files src/imap-login/client-authenticate.c src/imap-login/client.c src/imap-login/client.h src/login-common/common.h src/login-common/main.c src/master/login-process.c src/pop3-login/client-authenticate.c src/pop3-login/client.c src/pop3-login/client.h
diffstat 9 files changed, 140 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/imap-login/client-authenticate.c	Tue Oct 05 19:00:18 2004 +0300
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2004 Timo Sirainen */
 
 #include "common.h"
 #include "base64.h"
@@ -8,6 +8,7 @@
 #include "ostream.h"
 #include "safe-memset.h"
 #include "str.h"
+#include "str-sanitize.h"
 #include "imap-parser.h"
 #include "auth-client.h"
 #include "ssl-proxy.h"
@@ -16,6 +17,9 @@
 #include "auth-common.h"
 #include "master.h"
 
+/* Used only for string sanitization while verbose_auth is set. */
+#define MAX_MECH_NAME 64
+
 const char *client_authenticate_get_capabilities(int secured)
 {
 	const struct auth_mech_desc *mech;
@@ -50,6 +54,9 @@
 		client->common.auth_request = NULL;
 	}
 
+	if (msg != NULL && verbose_auth)
+		client_syslog(client, "Authentication failed: %s", msg);
+
 	client_send_tagline(client, msg != NULL ?
 			    t_strconcat("NO ", msg, NULL) :
 			    "NO Authentication failed.");
@@ -161,6 +168,10 @@
 	pass = IMAP_ARG_STR(&args[1]);
 
 	if (!client->secured && disable_plaintext_auth) {
+		if (verbose_auth) {
+			client_syslog(client, "Login failed: "
+				      "Plaintext authentication disabled");
+		}
 		client_send_line(client,
 			"* BAD [ALERT] Plaintext authentication is disabled, "
 			"but your client sent password in plaintext anyway. "
@@ -192,6 +203,8 @@
 		auth_client_request_new(auth_client, NULL, &info,
 					login_callback, client, &error);
 	if (client->common.auth_request == NULL) {
+		if (verbose_auth)
+			client_syslog(client, "Login failed: %s", error);
 		client_send_tagline(client, t_strconcat(
 			"NO Login failed: ", error, NULL));
 		client_unref(client);
@@ -215,6 +228,12 @@
 	struct imap_client *client = context;
 	const char *error;
 
+	if (!client->authenticating) {
+		/* client aborted */
+		i_assert(reply == NULL);
+		return;
+	}
+
 	switch (auth_callback(request, reply, data, &client->common,
 			      master_callback, &error)) {
 	case -1:
@@ -301,12 +320,22 @@
 
 	mech = auth_client_find_mech(auth_client, mech_name);
 	if (mech == NULL) {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: "
+				      "Unsupported mechanism",
+				      str_sanitize(mech_name, MAX_MECH_NAME));
+		}
 		client_send_tagline(client,
 				    "NO Unsupported authentication mechanism.");
 		return TRUE;
 	}
 
 	if (!client->secured && mech->plaintext && disable_plaintext_auth) {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: "
+				      "Plaintext authentication disabled",
+				      str_sanitize(mech_name, MAX_MECH_NAME));
+		}
 		client_send_tagline(client,
 				    "NO Plaintext authentication disabled.");
 		return TRUE;
@@ -333,6 +362,11 @@
 					   client_auth_input, client);
                 client->authenticating = TRUE;
 	} else {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: %s",
+				      str_sanitize(mech_name, MAX_MECH_NAME),
+				      error);
+		}
 		client_send_tagline(client, t_strconcat(
 			"NO Authentication failed: ", error, NULL));
 		client_unref(client);
--- a/src/imap-login/client.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/imap-login/client.c	Tue Oct 05 19:00:18 2004 +0300
@@ -434,7 +434,7 @@
 	client->destroyed = TRUE;
 
 	if (reason != NULL)
-		client_syslog(client, reason);
+		client_syslog(client, "%s", reason);
 
 	hash_remove(clients, client);
 
@@ -507,15 +507,20 @@
 	client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL));
 }
 
-void client_syslog(struct imap_client *client, const char *text)
+void client_syslog(struct imap_client *client, const char *format, ...)
 {
 	const char *addr;
+	va_list args;
 
 	addr = net_ip2addr(&client->common.ip);
 	if (addr == NULL)
 		addr = "??";
 
-	i_info("%s [%s]", text, addr);
+	t_push();
+	va_start(args, format);
+	i_info("%s [%s]", t_strdup_vprintf(format, args), addr);
+	va_end(args);
+	t_pop();
 }
 
 static void client_check_idle(struct imap_client *client)
--- a/src/imap-login/client.h	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/imap-login/client.h	Tue Oct 05 19:00:18 2004 +0300
@@ -33,7 +33,8 @@
 
 void client_send_line(struct imap_client *client, const char *line);
 void client_send_tagline(struct imap_client *client, const char *line);
-void client_syslog(struct imap_client *client, const char *text);
+void client_syslog(struct imap_client *client, const char *format, ...)
+	__attr_format__(2, 3);
 
 int client_read(struct imap_client *client);
 void client_input(void *context);
--- a/src/login-common/common.h	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/login-common/common.h	Tue Oct 05 19:00:18 2004 +0300
@@ -3,8 +3,8 @@
 
 #include "lib.h"
 
-extern int disable_plaintext_auth, process_per_connection, verbose_proctitle;
-extern int verbose_ssl, greeting_capability;
+extern int disable_plaintext_auth, process_per_connection, greeting_capability;
+extern int verbose_proctitle, verbose_ssl, verbose_auth;
 char *greeting;
 extern unsigned int max_logging_users;
 extern unsigned int login_process_uid;
--- a/src/login-common/main.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/login-common/main.c	Tue Oct 05 19:00:18 2004 +0300
@@ -17,8 +17,8 @@
 #include <unistd.h>
 #include <syslog.h>
 
-int disable_plaintext_auth, process_per_connection, verbose_proctitle;
-int verbose_ssl, greeting_capability;
+int disable_plaintext_auth, process_per_connection, greeting_capability;
+int verbose_proctitle, verbose_ssl, verbose_auth;
 char *greeting;
 unsigned int max_logging_users;
 unsigned int login_process_uid;
@@ -159,6 +159,7 @@
 	process_per_connection = getenv("PROCESS_PER_CONNECTION") != NULL;
 	verbose_proctitle = getenv("VERBOSE_PROCTITLE") != NULL;
         verbose_ssl = getenv("VERBOSE_SSL") != NULL;
+        verbose_auth = getenv("VERBOSE_AUTH") != NULL;
 
 	value = getenv("MAX_LOGGING_USERS");
 	max_logging_users = value == NULL ? 0 : strtoul(value, NULL, 10);
--- a/src/master/login-process.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/master/login-process.c	Tue Oct 05 19:00:18 2004 +0300
@@ -419,6 +419,8 @@
 		env_put("VERBOSE_PROCTITLE=1");
 	if (set->verbose_ssl)
 		env_put("VERBOSE_SSL=1");
+	if (set->server->auths->verbose)
+		env_put("VERBOSE_AUTH=1");
 
 	if (set->login_process_per_connection) {
 		env_put("PROCESS_PER_CONNECTION=1");
--- a/src/pop3-login/client-authenticate.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/pop3-login/client-authenticate.c	Tue Oct 05 19:00:18 2004 +0300
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2004 Timo Sirainen */
 
 #include "common.h"
 #include "base64.h"
@@ -9,6 +9,7 @@
 #include "ostream.h"
 #include "safe-memset.h"
 #include "str.h"
+#include "str-sanitize.h"
 #include "auth-client.h"
 #include "../pop3/capability.h"
 #include "ssl-proxy.h"
@@ -18,6 +19,9 @@
 #include "client-authenticate.h"
 #include "ssl-proxy.h"
 
+/* Used only for string sanitization while verbose_auth is set. */
+#define MAX_MECH_NAME 64
+
 int cmd_capa(struct pop3_client *client, const char *args __attr_unused__)
 {
 	const struct auth_mech_desc *mech;
@@ -51,11 +55,16 @@
 
 static void client_auth_abort(struct pop3_client *client, const char *msg)
 {
+	client->authenticating = FALSE;
+
 	if (client->common.auth_request != NULL) {
 		auth_client_request_abort(client->common.auth_request);
 		client->common.auth_request = NULL;
 	}
 
+	if (msg != NULL && verbose_auth)
+		client_syslog(client, "Authentication failed: %s", msg);
+
 	client_send_line(client, msg != NULL ? t_strconcat("-ERR ", msg, NULL) :
 			 "-ERR Authentication failed.");
 
@@ -111,19 +120,6 @@
 	t_pop();
 }
 
-static enum auth_client_request_new_flags
-client_get_auth_flags(struct pop3_client *client)
-{
-        enum auth_client_request_new_flags auth_flags = 0;
-
-	if (client->common.proxy != NULL &&
-	    ssl_proxy_has_valid_client_cert(client->common.proxy))
-		auth_flags |= AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT;
-	if (client->tls)
-		auth_flags |= AUTH_CLIENT_FLAG_SSL_ENABLED;
-	return auth_flags;
-}
-
 static void login_callback(struct auth_request *request,
 			   struct auth_client_request_reply *reply,
 			   const unsigned char *data, void *context)
@@ -142,14 +138,32 @@
 	default:
 		/* success, we should be able to log in. if we fail, just
 		   disconnect the client. */
+                client->authenticating = FALSE;
 		client_send_line(client, "+OK Logged in.");
 		client_unref(client);
 	}
 }
 
+static enum auth_client_request_new_flags
+client_get_auth_flags(struct pop3_client *client)
+{
+        enum auth_client_request_new_flags auth_flags = 0;
+
+	if (client->common.proxy != NULL &&
+	    ssl_proxy_has_valid_client_cert(client->common.proxy))
+		auth_flags |= AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT;
+	if (client->tls)
+		auth_flags |= AUTH_CLIENT_FLAG_SSL_ENABLED;
+	return auth_flags;
+}
+
 int cmd_user(struct pop3_client *client, const char *args)
 {
 	if (!client->secured && disable_plaintext_auth) {
+		if (verbose_auth) {
+			client_syslog(client, "Login failed: "
+				      "Plaintext authentication disabled");
+		}
 		client_send_line(client,
 				 "-ERR Plaintext authentication disabled.");
 		return TRUE;
@@ -190,23 +204,27 @@
 	info.initial_resp_size = str_len(plain_login);
 
 	client_ref(client);
+
 	client->common.auth_request =
 		auth_client_request_new(auth_client, NULL, &info,
 					login_callback, client, &error);
-
-	if (client->common.auth_request != NULL) {
-		/* don't read any input from client until login is finished */
-		if (client->common.io != NULL) {
-			io_remove(client->common.io);
-			client->common.io = NULL;
-		}
-		return TRUE;
-	} else {
+	if (client->common.auth_request == NULL) {
+		if (verbose_auth)
+			client_syslog(client, "Login failed: %s", error);
 		client_send_line(client,
 			t_strconcat("-ERR Login failed: ", error, NULL));
 		client_unref(client);
 		return TRUE;
 	}
+
+	/* don't read any input from client until login is finished */
+	if (client->common.io != NULL) {
+		io_remove(client->common.io);
+		client->common.io = NULL;
+	}
+
+	client->authenticating = TRUE;
+	return TRUE;
 }
 
 static void authenticate_callback(struct auth_request *request,
@@ -216,6 +234,12 @@
 	struct pop3_client *client = context;
 	const char *error;
 
+	if (!client->authenticating) {
+		/* client aborted */
+		i_assert(reply == NULL);
+		return;
+	}
+
 	switch (auth_callback(request, reply, data, &client->common,
 			      master_callback, &error)) {
 	case -1:
@@ -230,6 +254,7 @@
 	default:
 		/* success, we should be able to log in. if we fail, just
 		   disconnect the client. */
+                client->authenticating = FALSE;
 		client_send_line(client, "+OK Logged in.");
 		client_unref(client);
 	}
@@ -307,12 +332,22 @@
 
 	mech = auth_client_find_mech(auth_client, mech_name);
 	if (mech == NULL) {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: "
+				      "Unsupported mechanism",
+				      str_sanitize(mech_name, MAX_MECH_NAME));
+		}
 		client_send_line(client,
 				 "-ERR Unsupported authentication mechanism.");
 		return TRUE;
 	}
 
 	if (!client->secured && mech->plaintext && disable_plaintext_auth) {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: "
+				      "Plaintext authentication disabled",
+				      str_sanitize(mech_name, MAX_MECH_NAME));
+		}
 		client_send_line(client,
 				 "-ERR Plaintext authentication disabled.");
 		return TRUE;
@@ -346,7 +381,13 @@
 			io_remove(client->common.io);
 		client->common.io = io_add(client->common.fd, IO_READ,
 					   client_auth_input, client);
+                client->authenticating = TRUE;
 	} else {
+		if (verbose_auth) {
+			client_syslog(client, "Authenticate %s failed: %s",
+				      str_sanitize(mech_name, MAX_MECH_NAME),
+				      error);
+		}
 		client_send_line(client, t_strconcat(
 			"-ERR Authentication failed: ", error, NULL));
 		client_unref(client);
@@ -362,6 +403,8 @@
 	buffer_t *apop_data;
 
 	if (client->apop_challenge == NULL) {
+		if (verbose_auth)
+			client_syslog(client, "APOP failed: APOP not enabled");
 	        client_send_line(client, "-ERR APOP not enabled.");
 		return TRUE;
 	}
@@ -369,6 +412,10 @@
 	/* <username> <md5 sum in hex> */
 	p = strchr(args, ' ');
 	if (p == NULL || strlen(p+1) != 32) {
+		if (verbose_auth) {
+			client_syslog(client, "APOP failed: "
+				      "Invalid parameters");
+		}
 	        client_send_line(client, "-ERR Invalid parameters.");
 		return TRUE;
 	}
@@ -382,6 +429,10 @@
 	buffer_append_c(apop_data, '\0');
 
 	if (hex_to_binary(p+1, apop_data) <= 0) {
+		if (verbose_auth) {
+			client_syslog(client, "APOP failed: "
+				      "Invalid characters in MD5 response");
+		}
 		client_send_line(client,
 				 "-ERR Invalid characters in MD5 response.");
 		return TRUE;
@@ -409,6 +460,7 @@
 			io_remove(client->common.io);
 			client->common.io = NULL;
 		}
+                client->authenticating = TRUE;
 	} else if (error == NULL) {
 		/* the auth connection was lost. we have no choice
 		   but to fail the APOP logins completely since the
@@ -416,6 +468,8 @@
 		client_destroy(client, "APOP auth connection lost");
 		client_unref(client);
 	} else {
+		if (verbose_auth) 
+			client_syslog(client, "APOP failed: %s", error);
 		client_send_line(client,
 			t_strconcat("-ERR Login failed: ", error, NULL));
 		client_unref(client);
--- a/src/pop3-login/client.c	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/pop3-login/client.c	Tue Oct 05 19:00:18 2004 +0300
@@ -340,7 +340,7 @@
 	client->destroyed = TRUE;
 
 	if (reason != NULL)
-		client_syslog(client, reason);
+		client_syslog(client, "%s", reason);
 
 	hash_remove(clients, client);
 
@@ -405,15 +405,20 @@
 		client_destroy(client, "Transmit buffer full");
 }
 
-void client_syslog(struct pop3_client *client, const char *text)
+void client_syslog(struct pop3_client *client, const char *format, ...)
 {
 	const char *addr;
+	va_list args;
 
 	addr = net_ip2addr(&client->common.ip);
 	if (addr == NULL)
 		addr = "??";
 
-	i_info("%s [%s]", text, addr);
+	t_push();
+	va_start(args, format);
+	i_info("%s [%s]", t_strdup_vprintf(format, args), addr);
+	va_end(args);
+	t_pop();
 }
 
 static void client_check_idle(struct pop3_client *client)
--- a/src/pop3-login/client.h	Tue Oct 05 18:30:03 2004 +0300
+++ b/src/pop3-login/client.h	Tue Oct 05 19:00:18 2004 +0300
@@ -25,6 +25,7 @@
 
 	unsigned int tls:1;
 	unsigned int secured:1;
+	unsigned int authenticating:1;
 	unsigned int auth_connected:1;
 	unsigned int destroyed:1;
 };
@@ -32,7 +33,8 @@
 void client_destroy(struct pop3_client *client, const char *reason);
 
 void client_send_line(struct pop3_client *client, const char *line);
-void client_syslog(struct pop3_client *client, const char *text);
+void client_syslog(struct pop3_client *client, const char *format, ...)
+	__attr_format__(2, 3);
 
 int client_read(struct pop3_client *client);
 void client_input(void *context);