Blame SOURCES/dovecot-2.2.36-cve_2019_3814part1of3.patch

c9ace8
From eb5ffe2641febe0fa5e9038f2e216c130e1e7519 Mon Sep 17 00:00:00 2001
c9ace8
From: Aki Tuomi <aki.tuomi@open-xchange.com>
c9ace8
Date: Mon, 21 Jan 2019 11:36:30 +0200
c9ace8
Subject: [PATCH] login-common: Ensure we get username from certificate
c9ace8
c9ace8
---
c9ace8
 src/login-common/sasl-server.c | 42 ++++++++++++++++++++++++++++++++--
c9ace8
 1 file changed, 40 insertions(+), 2 deletions(-)
c9ace8
c9ace8
diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c
c9ace8
index a833c9a6d4..9465da9657 100644
c9ace8
--- a/src/login-common/sasl-server.c
c9ace8
+++ b/src/login-common/sasl-server.c
c9ace8
@@ -321,6 +321,37 @@ authenticate_callback(struct auth_client_request *request,
c9ace8
 	}
c9ace8
 }
c9ace8
 
c9ace8
+static bool get_cert_username(struct client *client, const char **username_r,
c9ace8
+			      const char **error_r)
c9ace8
+{
c9ace8
+	/* no SSL */
c9ace8
+	if (client->ssl_proxy == NULL) {
c9ace8
+		*username_r = NULL;
c9ace8
+		return TRUE;
c9ace8
+	}
c9ace8
+
c9ace8
+	/* no client certificate */
c9ace8
+	if (!ssl_proxy_has_valid_client_cert(client->ssl_proxy)) {
c9ace8
+		*username_r = NULL;
c9ace8
+		return TRUE;
c9ace8
+	}
c9ace8
+
c9ace8
+	/* get peer name */
c9ace8
+	const char *username = ssl_proxy_get_peer_name(client->ssl_proxy);
c9ace8
+
c9ace8
+	/* if we wanted peer name, but it was not there, fail */
c9ace8
+	if (client->set->auth_ssl_username_from_cert &&
c9ace8
+	    (username == NULL || *username == '\0')) {
c9ace8
+		if (client->set->auth_ssl_require_client_cert) {
c9ace8
+			*error_r = "Missing username in certificate";
c9ace8
+			return FALSE;
c9ace8
+		}
c9ace8
+	}
c9ace8
+
c9ace8
+	*username_r = username;
c9ace8
+	return TRUE;
c9ace8
+}
c9ace8
+
c9ace8
 void sasl_server_auth_begin(struct client *client,
c9ace8
 			    const char *service, const char *mech_name,
c9ace8
 			    const char *initial_resp_base64,
c9ace8
@@ -359,8 +390,15 @@ void sasl_server_auth_begin(struct client *client,
c9ace8
 	info.mech = mech->name;
c9ace8
 	info.service = service;
c9ace8
 	info.session_id = client_get_session_id(client);
c9ace8
-	info.cert_username = client->ssl_proxy == NULL ? NULL :
c9ace8
-		ssl_proxy_get_peer_name(client->ssl_proxy);
c9ace8
+	if (client->set->auth_ssl_username_from_cert) {
c9ace8
+		const char *error;
c9ace8
+		if (!get_cert_username(client, &info.cert_username, &error)) {
c9ace8
+			client_log_err(client, t_strdup_printf("Cannot get username "
c9ace8
+							       "from certificate: %s", error));
c9ace8
+			sasl_server_auth_failed(client, "Unable to validate certificate");
c9ace8
+			return;
c9ace8
+		}
c9ace8
+	}
c9ace8
 	info.flags = client_get_auth_flags(client);
c9ace8
 	info.local_ip = client->local_ip;
c9ace8
 	info.remote_ip = client->ip;