changeset 3635:c12df370e1b2 HEAD

Added ssl_username_from_cert setting. Not actually tested yet..
author Timo Sirainen <tss@iki.fi>
date Sat, 01 Oct 2005 13:52:14 +0300
parents 377f69be914f
children 08b768956051
files dovecot-example.conf src/auth/auth-request.c src/auth/auth-request.h src/auth/auth.c src/auth/auth.h src/auth/passdb-blocking.c src/auth/passdb-bsdauth.c src/auth/passdb-passwd.c src/auth/passdb-shadow.c src/lib-auth/auth-client.h src/lib-auth/auth-server-request.c src/login-common/sasl-server.c src/login-common/ssl-proxy-openssl.c src/login-common/ssl-proxy.c src/login-common/ssl-proxy.h src/master/auth-process.c src/master/master-settings.c src/master/master-settings.h
diffstat 18 files changed, 85 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Sat Oct 01 13:46:57 2005 +0300
+++ b/dovecot-example.conf	Sat Oct 01 13:52:14 2005 +0300
@@ -707,6 +707,10 @@
 
   # Require a valid SSL client certificate or the authentication fails.
   #ssl_require_client_cert = no
+
+  # Take the username from client's SSL certificate, using X509_NAME_oneline()
+  # which typically uses subject's Distinguished Name.
+  #ssl_username_from_cert = no
 }
 
 # It's possible to export the authentication interface to other programs,
--- a/src/auth/auth-request.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/auth-request.c	Sat Oct 01 13:52:14 2005 +0300
@@ -120,7 +120,14 @@
 {
 	if (strcmp(key, "user") == 0)
 		request->user = p_strdup(request->pool, value);
-	if (strcmp(key, "service") == 0)
+	else if (strcmp(key, "cert_username") == 0) {
+		if (request->auth->ssl_username_from_cert) {
+			/* get username from SSL certificate. it overrides
+			   the username given by the auth mechanism. */
+			request->user = p_strdup(request->pool, value);
+			request->cert_username = TRUE;
+		}
+	} else if (strcmp(key, "service") == 0)
 		request->service = p_strdup(request->pool, value);
 	else if (strcmp(key, "lip") == 0)
 		net_addr2ip(value, &request->local_ip);
@@ -415,6 +422,12 @@
 {
 	unsigned char *p;
 
+	if (request->cert_username) {
+		/* cert_username overrides the username given by
+		   authentication mechanism. */
+		return TRUE;
+	}
+
 	if (*username == '\0') {
 		/* Some PAM plugins go nuts with empty usernames */
 		*error_r = "Empty username";
--- a/src/auth/auth-request.h	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/auth-request.h	Sat Oct 01 13:52:14 2005 +0300
@@ -58,6 +58,8 @@
 	unsigned int no_failure_delay:1;
 	unsigned int no_login:1;
 	unsigned int proxy:1;
+	unsigned int cert_username:1;
+
 	/* ... mechanism specific data ... */
 };
 
--- a/src/auth/auth.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/auth.c	Sat Oct 01 13:52:14 2005 +0300
@@ -221,6 +221,8 @@
 
 	auth->ssl_require_client_cert =
 		getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
+	auth->ssl_username_from_cert =
+		getenv("SSL_USERNAME_FROM_CERT") != NULL;
 }
 
 void auth_deinit(struct auth *auth)
--- a/src/auth/auth.h	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/auth.h	Sat Oct 01 13:52:14 2005 +0300
@@ -42,6 +42,7 @@
 	char username_chars[256];
         char username_translation[256];
 	int ssl_require_client_cert;
+        int ssl_username_from_cert;
 
 	int verbose, verbose_debug;
 };
--- a/src/auth/passdb-blocking.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/passdb-blocking.c	Sat Oct 01 13:52:14 2005 +0300
@@ -59,7 +59,7 @@
 	}
 
 	/* username may have changed, update it */
-	request->user = p_strdup_until(request->pool, reply, p);
+        auth_request_set_field(request, "user", t_strdup_until(reply, p), NULL);
 
 	*password_r = t_strdup_until(p + 1, p2);
 	reply = p2 + 1;
--- a/src/auth/passdb-bsdauth.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/passdb-bsdauth.c	Sat Oct 01 13:52:14 2005 +0300
@@ -47,7 +47,7 @@
 	}
 
 	/* make sure we're using the username exactly as it's in the database */
-	request->user = p_strdup(request->pool, pw->pw_name);
+        auth_request_set_field(request, "user", pw->pw_name, NULL);
 
 	callback(PASSDB_RESULT_OK, request);
 }
--- a/src/auth/passdb-passwd.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/passdb-passwd.c	Sat Oct 01 13:52:14 2005 +0300
@@ -44,7 +44,7 @@
 	}
 
 	/* make sure we're using the username exactly as it's in the database */
-	request->user = p_strdup(request->pool, pw->pw_name);
+        auth_request_set_field(request, "user", pw->pw_name, NULL);
 
 	callback(PASSDB_RESULT_OK, request);
 }
--- a/src/auth/passdb-shadow.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/auth/passdb-shadow.c	Sat Oct 01 13:52:14 2005 +0300
@@ -44,7 +44,7 @@
 	}
 
 	/* make sure we're using the username exactly as it's in the database */
-	request->user = p_strdup(request->pool, spw->sp_namp);
+        auth_request_set_field(request, "user", spw->sp_namp, NULL);
 
 	callback(PASSDB_RESULT_OK, request);
 }
--- a/src/lib-auth/auth-client.h	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/lib-auth/auth-client.h	Sat Oct 01 13:52:14 2005 +0300
@@ -25,6 +25,7 @@
 struct auth_request_info {
 	const char *mech;
 	const char *service;
+	const char *cert_username;
 	enum auth_request_flags flags;
 
 	struct ip_addr local_ip, remote_ip;
--- a/src/lib-auth/auth-server-request.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/lib-auth/auth-server-request.c	Sat Oct 01 13:52:14 2005 +0300
@@ -15,7 +15,7 @@
 
 	unsigned int id;
 
-	char *mech, *service;
+	char *mech, *service, *cert_username;
         enum auth_request_flags flags;
 	struct ip_addr local_ip, remote_ip;
 
@@ -67,6 +67,19 @@
 	}
 }
 
+static int is_valid_string(const char *str)
+{
+	const char *p;
+
+	/* make sure we're not sending any characters that have a special
+	   meaning. */
+	for (p = str; *p != '\0'; p++) {
+		if (*p == '\t' || *p == '\n' || *p == '\r')
+			return FALSE;
+	}
+	return TRUE;
+}
+
 static int auth_server_send_new_request(struct auth_server_connection *conn,
 					struct auth_request *request)
 {
@@ -83,6 +96,13 @@
 	if ((request->flags & AUTH_REQUEST_FLAG_VALID_CLIENT_CERT) != 0)
 		str_append(str, "\tvalid-client-cert");
 
+	if (request->cert_username != NULL) {
+		if (!is_valid_string(request->cert_username)) {
+			t_pop();
+			return FALSE;
+		}
+		str_printfa(str, "\tcert_username=%s", request->cert_username);
+	}
 	if (request->local_ip.family != 0)
 		str_printfa(str, "\tlip=%s", net_ip2addr(&request->local_ip));
 	if (request->remote_ip.family != 0)
@@ -309,6 +329,7 @@
 	request->conn = conn;
 	request->mech = i_strdup(request_info->mech);
 	request->service = i_strdup(request_info->service);
+	request->cert_username = i_strdup(request_info->cert_username);
 	request->flags = request_info->flags;
 	request->local_ip = request_info->local_ip;
 	request->remote_ip = request_info->remote_ip;
@@ -346,6 +367,7 @@
 	i_free(request->plaintext_data);
 	i_free(request->mech);
 	i_free(request->service);
+	i_free(request->cert_username);
 	i_free(request);
 }
 
--- a/src/login-common/sasl-server.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/login-common/sasl-server.c	Sat Oct 01 13:52:14 2005 +0300
@@ -134,6 +134,8 @@
 	memset(&info, 0, sizeof(info));
 	info.mech = mech->name;
 	info.service = service;
+	info.cert_username = client->proxy == NULL ? NULL :
+		ssl_proxy_get_peer_name(client->proxy);
 	info.flags = client_get_auth_flags(client);
 	info.local_ip = client->local_ip;
 	info.remote_ip = client->ip;
--- a/src/login-common/ssl-proxy-openssl.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/login-common/ssl-proxy-openssl.c	Sat Oct 01 13:52:14 2005 +0300
@@ -379,6 +379,26 @@
 	return proxy->cert_received && !proxy->cert_broken;
 }
 
+const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy)
+{
+	X509 *x509;
+	char buf[1024];
+	const char *name;
+
+	if (!ssl_proxy_has_valid_client_cert(proxy))
+		return NULL;
+
+	x509 = SSL_get_peer_certificate(proxy->ssl);
+	if (x509 == NULL)
+		return NULL; /* we should have had it.. */
+
+	X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf));
+	name = t_strndup(buf, sizeof(buf));
+	X509_free(x509);
+
+	return *name == '\0' ? NULL : name;
+}
+
 void ssl_proxy_free(struct ssl_proxy *proxy)
 {
 	ssl_proxy_unref(proxy);
--- a/src/login-common/ssl-proxy.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/login-common/ssl-proxy.c	Sat Oct 01 13:52:14 2005 +0300
@@ -21,6 +21,11 @@
 	return FALSE;
 }
 
+const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy __attr_unused__)
+{
+	return NULL;
+}
+
 void ssl_proxy_free(struct ssl_proxy *proxy __attr_unused__) {}
 
 void ssl_proxy_init(void) {}
--- a/src/login-common/ssl-proxy.h	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/login-common/ssl-proxy.h	Sat Oct 01 13:52:14 2005 +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);
 int ssl_proxy_has_valid_client_cert(struct ssl_proxy *proxy);
+const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy);
 void ssl_proxy_free(struct ssl_proxy *proxy);
 
 void ssl_proxy_init(void);
--- a/src/master/auth-process.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/master/auth-process.c	Sat Oct 01 13:52:14 2005 +0300
@@ -456,6 +456,8 @@
 		env_put("VERBOSE_DEBUG=1");
 	if (set->ssl_require_client_cert)
 		env_put("SSL_REQUIRE_CLIENT_CERT=1");
+	if (set->ssl_username_from_cert)
+		env_put("SSL_USERNAME_FROM_CERT=1");
 
 	restrict_process_size(set->process_size, (unsigned int)-1);
 }
--- a/src/master/master-settings.c	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/master/master-settings.c	Sat Oct 01 13:52:14 2005 +0300
@@ -159,6 +159,7 @@
 	DEF(SET_BOOL, verbose),
 	DEF(SET_BOOL, debug),
 	DEF(SET_BOOL, ssl_require_client_cert),
+	DEF(SET_BOOL, ssl_username_from_cert),
 
 	DEF(SET_INT, count),
 	DEF(SET_INT, worker_max_count),
@@ -356,6 +357,7 @@
 	MEMBER(verbose) FALSE,
 	MEMBER(debug) FALSE,
 	MEMBER(ssl_require_client_cert) FALSE,
+	MEMBER(ssl_username_from_cert) FALSE,
 
 	MEMBER(count) 1,
 	MEMBER(worker_max_count) 30,
@@ -433,7 +435,7 @@
 		return FALSE;
 	}
 
-	if (auth->ssl_require_client_cert) {
+	if (auth->ssl_require_client_cert || auth->ssl_username_from_cert) {
 		/* if we require valid cert, make sure we also ask for it */
 		if (auth->parent->pop3 != NULL)
 			auth->parent->pop3->ssl_verify_client_cert = TRUE;
--- a/src/master/master-settings.h	Sat Oct 01 13:46:57 2005 +0300
+++ b/src/master/master-settings.h	Sat Oct 01 13:52:14 2005 +0300
@@ -165,6 +165,7 @@
 
 	int verbose, debug;
 	int ssl_require_client_cert;
+	int ssl_username_from_cert;
 
 	unsigned int count;
 	unsigned int worker_max_count;