Mercurial > dovecot > core-2.2
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;