]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
*-login: Added support for TLS SNI.
authorTimo Sirainen <tss@iki.fi>
Thu, 29 Oct 2009 01:20:46 +0000 (21:20 -0400)
committerTimo Sirainen <tss@iki.fi>
Thu, 29 Oct 2009 01:20:46 +0000 (21:20 -0400)
--HG--
branch : HEAD

src/login-common/login-settings.c
src/login-common/login-settings.h
src/login-common/main.c
src/login-common/ssl-proxy-openssl.c

index e21870bf3ecaba6181a2dadb3f2a6095c8958491..42c38840c782a88dac9334139939b720ed65e288 100644 (file)
@@ -185,6 +185,7 @@ struct login_settings *
 login_settings_read(struct master_service *service, pool_t pool,
                    const struct ip_addr *local_ip,
                    const struct ip_addr *remote_ip,
+                   const char *local_host,
                    void ***other_settings_r)
 {
        struct master_service_settings_input input;
@@ -196,6 +197,7 @@ login_settings_read(struct master_service *service, pool_t pool,
        input.roots = login_set_roots;
        input.module = login_process_name;
        input.service = login_protocol;
+       input.local_host = local_host;
 
        if (local_ip != NULL)
                input.local_ip = *local_ip;
index 8e809877c8e6643584f477cf0a8d1a6051255756..c13ec0163b9bd9f29e9b3b4e5c13c865308f89a3 100644 (file)
@@ -39,6 +39,7 @@ struct login_settings *
 login_settings_read(struct master_service *service, pool_t pool,
                    const struct ip_addr *local_ip,
                    const struct ip_addr *remote_ip,
+                   const char *local_host,
                    void ***other_settings_r);
 
 #endif
index e48abf7143824df7a25294ba4923459fcb50e02d..bba6c7cbd44eb4a4b41e539450e15100b0f9b2d5 100644 (file)
@@ -72,7 +72,7 @@ static void client_connected(const struct master_service_connection *conn)
 
        pool = pool_alloconly_create("login client", 3*1024);
        set = login_settings_read(master_service, pool, &local_ip,
-                                 &conn->remote_ip, &other_sets);
+                                 &conn->remote_ip, NULL, &other_sets);
 
        if (!ssl_connections && !conn->ssl) {
                client = client_create(conn->fd, FALSE, pool, set, other_sets,
@@ -224,7 +224,7 @@ int main(int argc, char *argv[])
 
        set_pool = pool_alloconly_create("global login settings", 4096);
        global_login_settings =
-               login_settings_read(master_service, set_pool, NULL, NULL,
+               login_settings_read(master_service, set_pool, NULL, NULL, NULL,
                                    &global_other_settings);
 
        /* main_preinit() needs to know the client limit, which is set by
index eda9936cf502c2e6bf715bd06f3e0495ee853a25..5268ce66652fca44a5fbe4c93430b3bfbfdd717a 100644 (file)
@@ -590,9 +590,8 @@ ssl_proxy_alloc_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip,
        return sfd[1];
 }
 
-int ssl_proxy_alloc(int fd, const struct ip_addr *ip,
-                   const struct login_settings *set,
-                   struct ssl_proxy **proxy_r)
+static struct ssl_server_context *
+ssl_server_context_get(const struct login_settings *set)
 {
        struct ssl_server_context *ctx, lookup_ctx;
 
@@ -606,7 +605,16 @@ int ssl_proxy_alloc(int fd, const struct ip_addr *ip,
        ctx = hash_table_lookup(ssl_servers, &lookup_ctx);
        if (ctx == NULL)
                ctx = ssl_server_context_init(set);
+       return ctx;
+}
+
+int ssl_proxy_alloc(int fd, const struct ip_addr *ip,
+                   const struct login_settings *set,
+                   struct ssl_proxy **proxy_r)
+{
+       struct ssl_server_context *ctx;
 
+       ctx = ssl_server_context_get(set);
        return ssl_proxy_alloc_common(ctx->ctx, fd, ip, set, proxy_r);
 }
 
@@ -1007,6 +1015,28 @@ end:
        return ret;
 }
 
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+static void ssl_servername_callback(SSL *ssl, int *al ATTR_UNUSED,
+                                   void *context ATTR_UNUSED)
+{
+       struct ssl_server_context *ctx;
+       struct ssl_proxy *proxy;
+       struct client *client;
+       const char *host;
+       void **other_sets;
+
+       proxy = SSL_get_ex_data(ssl, extdata_index);
+       host = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+
+       client = proxy->client;
+       client->set = login_settings_read(master_service, client->pool,
+                                         &client->local_ip, &client->ip, host,
+                                         &other_sets);
+       ctx = ssl_server_context_get(client->set);
+       SSL_set_SSL_CTX(ssl, ctx->ctx);
+}
+#endif
+
 static struct ssl_server_context *
 ssl_server_context_init(const struct login_settings *set)
 {
@@ -1038,6 +1068,14 @@ ssl_server_context_init(const struct login_settings *set)
                        ssl_proxy_get_use_certificate_error(ctx->cert));
        }
 
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+       if (SSL_CTX_set_tlsext_servername_callback(ctx->ctx,
+                                                  ssl_servername_callback) != 1) {
+               if (set->verbose_ssl)
+                       i_debug("OpenSSL library doesn't support SNI");
+       }
+#endif
+
        ssl_proxy_ctx_use_key(ctx->ctx, set);
        SSL_CTX_set_info_callback(ctx->ctx, ssl_info_callback);