changeset 8302:0db37acdc59f HEAD

Login process: Log auth failure reasons better in disconnect message. For example if client certs are required it now logs if the cert wasn't sent or if the cert was invalid.
author Timo Sirainen <tss@iki.fi>
date Sun, 19 Oct 2008 14:00:57 +0300
parents d46579bb7a3c
children d3b37327936e
files src/imap-login/client-authenticate.c src/imap-login/client.c src/login-common/client-common.c src/login-common/client-common.h src/login-common/common.h src/login-common/main.c src/login-common/ssl-proxy-openssl.c src/login-common/ssl-proxy.c src/login-common/ssl-proxy.h src/master/login-process.c src/pop3-login/client-authenticate.c src/pop3-login/client.c
diffstat 12 files changed, 56 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/imap-login/client-authenticate.c	Sun Oct 19 14:00:57 2008 +0300
@@ -322,6 +322,7 @@
 				      "Plaintext authentication disabled");
 		}
 		client->common.auth_tried_disabled_plaintext = TRUE;
+		client->common.auth_attempts++;
 		client_send_line(client,
 			"* BAD [ALERT] Plaintext authentication is disabled, "
 			"but your client sent password in plaintext anyway. "
--- a/src/imap-login/client.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/imap-login/client.c	Sun Oct 19 14:00:57 2008 +0300
@@ -256,12 +256,7 @@
 {
 	client_send_line(client, "* BYE Logging out");
 	client_send_tagline(client, "OK Logout completed.");
-	if (client->common.auth_tried_disabled_plaintext) {
-		client_destroy(client, "Aborted login "
-			"(tried to use disabled plaintext authentication)");
-	} else {
-		client_destroy(client, "Aborted login");
-	}
+	client_destroy(client, "Aborted login");
 	return 1;
 }
 
@@ -547,10 +542,9 @@
 	client->destroyed = TRUE;
 
 	if (!client->login_success && reason != NULL) {
-		reason = client->common.auth_attempts == 0 ?
-			t_strdup_printf("%s (no auth attempts)", reason) :
-			t_strdup_printf("%s (auth failed, %u attempts)",
-					reason, client->common.auth_attempts);
+		reason = t_strconcat(reason, " ",
+			client_get_extra_disconnect_reason(&client->common),
+			NULL);
 	}
 	if (reason != NULL)
 		client_syslog(&client->common, reason);
--- a/src/login-common/client-common.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/client-common.c	Sun Oct 19 14:00:57 2008 +0300
@@ -179,3 +179,25 @@
 	}
 	return FALSE;
 }
+
+const char *client_get_extra_disconnect_reason(struct client *client)
+{
+	if (ssl_require_client_cert && client->proxy != NULL) {
+		if (ssl_proxy_has_broken_client_cert(client->proxy))
+			return "(client sent an invalid cert)";
+		if (!ssl_proxy_has_valid_client_cert(client->proxy))
+			return "(client didn't send a cert)";
+	}
+
+	if (client->auth_attempts == 0)
+		return "(no auth attempts)";
+
+	/* some auth attempts without SSL/TLS */
+	if (client->auth_tried_disabled_plaintext)
+		return "(tried to use disabled plaintext auth)";
+	if (ssl_require_client_cert)
+		return "(cert required, client didn't start TLS)";
+
+	return t_strdup_printf("(auth failed, %u attempts)",
+			       client->auth_attempts);
+}
--- a/src/login-common/client-common.h	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/client-common.h	Sun Oct 19 14:00:57 2008 +0300
@@ -54,6 +54,7 @@
 unsigned int clients_get_count(void) ATTR_PURE;
 
 void client_syslog(struct client *client, const char *msg);
+const char *client_get_extra_disconnect_reason(struct client *client);
 bool client_is_trusted(struct client *client);
 
 void clients_notify_auth_connected(void);
--- a/src/login-common/common.h	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/common.h	Sun Oct 19 14:00:57 2008 +0300
@@ -15,6 +15,7 @@
 
 extern bool disable_plaintext_auth, process_per_connection;
 extern bool verbose_proctitle, verbose_ssl, verbose_auth;
+extern bool ssl_require_client_cert;
 extern const char *greeting, *log_format;
 extern const char *const *log_format_elements;
 extern const char *capability_string;
--- a/src/login-common/main.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/main.c	Sun Oct 19 14:00:57 2008 +0300
@@ -21,6 +21,7 @@
 
 bool disable_plaintext_auth, process_per_connection;
 bool verbose_proctitle, verbose_ssl, verbose_auth;
+bool ssl_require_client_cert;
 const char *greeting, *log_format;
 const char *const *log_format_elements;
 const char *trusted_networks;
@@ -317,6 +318,7 @@
 	verbose_proctitle = getenv("VERBOSE_PROCTITLE") != NULL;
         verbose_ssl = getenv("VERBOSE_SSL") != NULL;
         verbose_auth = getenv("VERBOSE_AUTH") != NULL;
+	ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
 
 	greeting = getenv("GREETING");
 	if (greeting == NULL)
--- a/src/login-common/ssl-proxy-openssl.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/ssl-proxy-openssl.c	Sun Oct 19 14:00:57 2008 +0300
@@ -517,6 +517,11 @@
 	return proxy->cert_received && !proxy->cert_broken;
 }
 
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy)
+{
+	return proxy->cert_received && proxy->cert_broken;
+}
+
 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy)
 {
 	X509 *x509;
--- a/src/login-common/ssl-proxy.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/ssl-proxy.c	Sun Oct 19 14:00:57 2008 +0300
@@ -21,6 +21,11 @@
 	return FALSE;
 }
 
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy ATTR_UNUSED)
+{
+	return FALSE;
+}
+
 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy ATTR_UNUSED)
 {
 	return NULL;
--- a/src/login-common/ssl-proxy.h	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/login-common/ssl-proxy.h	Sun Oct 19 14:00:57 2008 +0300
@@ -11,6 +11,7 @@
    the given fd must be simply forgotten. */
 int ssl_proxy_new(int fd, struct ip_addr *ip, struct ssl_proxy **proxy_r);
 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy) ATTR_PURE;
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy);
 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy);
 bool ssl_proxy_is_handshaked(const struct ssl_proxy *proxy) ATTR_PURE;
 const char *ssl_proxy_get_last_error(const struct ssl_proxy *proxy) ATTR_PURE;
--- a/src/master/login-process.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/master/login-process.c	Sun Oct 19 14:00:57 2008 +0300
@@ -530,6 +530,8 @@
 static void login_process_init_env(struct login_group *group, pid_t pid)
 {
 	struct settings *set = group->set;
+	const struct auth_settings *auth;
+	bool require_cert;
 
 	child_process_init_env();
 
@@ -579,6 +581,13 @@
 		env_put("VERBOSE_SSL=1");
 	if (set->server->auths->verbose)
 		env_put("VERBOSE_AUTH=1");
+	require_cert = TRUE;
+	for (auth = set->server->auths; auth != NULL; auth = auth->next) {
+		if (!auth->ssl_require_client_cert)
+			require_cert = FALSE;
+	}
+	if (require_cert)
+		env_put("SSL_REQUIRE_CLIENT_CERT=1");
 
 	if (set->login_process_per_connection) {
 		env_put("PROCESS_PER_CONNECTION=1");
--- a/src/pop3-login/client-authenticate.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/pop3-login/client-authenticate.c	Sun Oct 19 14:00:57 2008 +0300
@@ -276,6 +276,7 @@
 	}
 	client_send_line(client, "-ERR "AUTH_PLAINTEXT_DISABLED_MSG);
 	client->common.auth_tried_disabled_plaintext = TRUE;
+	client->common.auth_attempts++;
 	return FALSE;
 }
 
--- a/src/pop3-login/client.c	Sun Oct 19 13:32:01 2008 +0300
+++ b/src/pop3-login/client.c	Sun Oct 19 14:00:57 2008 +0300
@@ -143,12 +143,7 @@
 static bool cmd_quit(struct pop3_client *client)
 {
 	client_send_line(client, "+OK Logging out");
-	if (client->common.auth_tried_disabled_plaintext) {
-		client_destroy(client, "Aborted login "
-			"(tried to use disabled plaintext authentication)");
-	} else {
-		client_destroy(client, "Aborted login");
-	}
+	client_destroy(client, "Aborted login");
 	return TRUE;
 }
 
@@ -352,10 +347,9 @@
 	client->destroyed = TRUE;
 
 	if (!client->login_success && reason != NULL) {
-		reason = client->common.auth_attempts == 0 ?
-			t_strdup_printf("%s (no auth attempts)", reason) :
-			t_strdup_printf("%s (auth failed, %u attempts)",
-					reason, client->common.auth_attempts);
+		reason = t_strconcat(reason, " ",
+			client_get_extra_disconnect_reason(&client->common),
+			NULL);
 	}
 	if (reason != NULL)
 		client_syslog(&client->common, reason);