I don't remember anymore if this is actually a useful patch for someone, or if it's just the beginnings of change to move SSL cert verification into dovecot-auth. As it is, it doesn't look really useful. Index: lib-auth/auth-client.h =================================================================== RCS file: /var/lib/cvs/dovecot/src/lib-auth/auth-client.h,v retrieving revision 1.12 diff -u -r1.12 auth-client.h --- lib-auth/auth-client.h 14 Jan 2006 18:47:23 -0000 1.12 +++ lib-auth/auth-client.h 15 Jan 2006 14:11:17 -0000 @@ -8,8 +8,7 @@ struct auth_request; enum auth_request_flags { - AUTH_REQUEST_FLAG_SECURED = 0x01, - AUTH_REQUEST_FLAG_VALID_CLIENT_CERT = 0x02, + AUTH_REQUEST_FLAG_SECURED = 0x01 }; struct auth_mech_desc { @@ -25,7 +24,7 @@ struct auth_request_info { const char *mech; const char *service; - const char *cert_username; + const char *cert; enum auth_request_flags flags; struct ip_addr local_ip, remote_ip; Index: lib-auth/auth-server-request.c =================================================================== RCS file: /var/lib/cvs/dovecot/src/lib-auth/auth-server-request.c,v retrieving revision 1.25 diff -u -r1.25 auth-server-request.c --- lib-auth/auth-server-request.c 14 Jan 2006 18:47:23 -0000 1.25 +++ lib-auth/auth-server-request.c 15 Jan 2006 14:11:17 -0000 @@ -15,7 +15,7 @@ unsigned int id; - char *mech, *service, *cert_username; + char *mech, *service, *cert; enum auth_request_flags flags; struct ip_addr local_ip, remote_ip; @@ -67,19 +67,6 @@ } } -static bool 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 bool auth_server_send_new_request(struct auth_server_connection *conn, struct auth_request *request) { @@ -93,22 +80,15 @@ request->id, request->mech, request->service); if ((request->flags & AUTH_REQUEST_FLAG_SECURED) != 0) str_append(str, "\tsecured"); - 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) str_printfa(str, "\trip=%s", net_ip2addr(&request->remote_ip)); if (request->initial_resp_base64 != NULL) str_printfa(str, "\tresp=%s", request->initial_resp_base64); + if (request->cert != NULL) + str_printfa(str, "\tcert=%s", request->cert); str_append_c(str, '\n'); ret = o_stream_send(conn->output, str_data(str), str_len(str)); @@ -329,7 +309,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->cert = i_strdup(request_info->cert); request->flags = request_info->flags; request->local_ip = request_info->local_ip; request->remote_ip = request_info->remote_ip; @@ -367,7 +347,7 @@ i_free(request->plaintext_data); i_free(request->mech); i_free(request->service); - i_free(request->cert_username); + i_free(request->cert); i_free(request); } Index: login-common/sasl-server.c =================================================================== RCS file: /var/lib/cvs/dovecot/src/login-common/sasl-server.c,v retrieving revision 1.10 diff -u -r1.10 sasl-server.c --- login-common/sasl-server.c 13 Jan 2006 20:26:39 -0000 1.10 +++ login-common/sasl-server.c 15 Jan 2006 14:11:17 -0000 @@ -3,6 +3,7 @@ #include "common.h" #include "base64.h" #include "buffer.h" +#include "str.h" #include "str-sanitize.h" #include "auth-client.h" #include "ssl-proxy.h" @@ -14,9 +15,6 @@ { enum auth_request_flags auth_flags = 0; - if (client->proxy != NULL && - ssl_proxy_has_valid_client_cert(client->proxy)) - auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT; if (client->secured) auth_flags |= AUTH_REQUEST_FLAG_SECURED; return auth_flags; @@ -103,6 +101,28 @@ } } +static const char *get_client_cert(struct client *client) +{ + buffer_t *buf; + string_t *str; + + if (client->proxy == NULL || + !ssl_proxy_has_valid_client_cert(client->proxy)) + return NULL; + + buf = buffer_create_dynamic(default_pool, 1024); + if (!ssl_proxy_get_client_cert(client->proxy, buf)) { + buffer_free(buf); + return NULL; + } + + /* okay, we have the certificate. now we need it base64 encoded */ + str = t_str_new(MAX_BASE64_ENCODED_SIZE(buf->used)); + base64_encode(buf->data, buf->used, str); + buffer_free(buf); + return str_c(str); +} + void sasl_server_auth_begin(struct client *client, const char *service, const char *mech_name, const char *initial_resp_base64, @@ -134,12 +154,11 @@ 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; info.initial_resp_base64 = initial_resp_base64; + info.cert = get_client_cert(client); client->auth_request = auth_client_request_new(auth_client, NULL, &info, Index: login-common/ssl-proxy-openssl.c =================================================================== RCS file: /var/lib/cvs/dovecot/src/login-common/ssl-proxy-openssl.c,v retrieving revision 1.34 diff -u -r1.34 ssl-proxy-openssl.c --- login-common/ssl-proxy-openssl.c 15 Jan 2006 13:16:53 -0000 1.34 +++ login-common/ssl-proxy-openssl.c 15 Jan 2006 14:11:17 -0000 @@ -495,24 +495,27 @@ return proxy->cert_received && !proxy->cert_broken; } -const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy) +bool ssl_proxy_get_client_cert(struct ssl_proxy *proxy, buffer_t *buffer) { X509 *x509; char buf[1024]; const char *name; + int len, len2; if (!ssl_proxy_has_valid_client_cert(proxy)) - return NULL; + return FALSE; x509 = SSL_get_peer_certificate(proxy->ssl); if (x509 == NULL) - return NULL; /* we should have had it.. */ + return FALSE; /* 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; + len = i2d_X509(x509, NULL); + if (len < 0) + return FALSE; + + len2 = i2d_X509(x509, buffer_append_space_unsafe(buffer, len)); + i_assert(len == len2); + return TRUE; } void ssl_proxy_free(struct ssl_proxy *proxy) Index: login-common/ssl-proxy.h =================================================================== RCS file: /var/lib/cvs/dovecot/src/login-common/ssl-proxy.h,v retrieving revision 1.6 diff -u -r1.6 ssl-proxy.h --- login-common/ssl-proxy.h 13 Jan 2006 20:26:39 -0000 1.6 +++ login-common/ssl-proxy.h 15 Jan 2006 14:11:17 -0000 @@ -11,7 +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(struct ssl_proxy *proxy); -const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy); +bool ssl_proxy_get_client_cert(struct ssl_proxy *proxy, buffer_t *buffer); void ssl_proxy_free(struct ssl_proxy *proxy); void ssl_proxy_init(void);