]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: server: Allow creating server with custom SSL settings.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 9 Feb 2018 21:06:49 +0000 (22:06 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 25 May 2018 20:54:12 +0000 (22:54 +0200)
Normally, the settings are obtained through lib-master, but that is not
really suitable for the test suite.

src/lib-smtp/smtp-server-connection.c
src/lib-smtp/smtp-server-private.h
src/lib-smtp/smtp-server.c
src/lib-smtp/smtp-server.h

index f75221b0fda70820795d81a7360ef79410faf72a..f767d2a8e81230e228faf52a84d6da776bdd215a 100644 (file)
@@ -339,9 +339,42 @@ smtp_server_connection_handle_command(struct smtp_server_connection *conn,
        return (cmd == NULL || !cmd->input_locked);
 }
 
+static int
+smtp_server_connection_init_ssl_ctx(struct smtp_server_connection *conn,
+                                   const char **error_r)
+{
+       struct smtp_server *server = conn->server;
+       const char *error;
+
+       if (conn->ssl_ctx != NULL || conn->set.ssl == NULL)
+               return 0;
+       if (conn->set.ssl == server->set.ssl) {
+               if (smtp_server_init_ssl_ctx(server, error_r) < 0)
+                       return -1;
+               conn->ssl_ctx = server->ssl_ctx;
+               ssl_iostream_context_ref(conn->ssl_ctx);
+               return 0;
+       }
+
+       if (ssl_iostream_server_context_cache_get(conn->set.ssl,
+               &conn->ssl_ctx, &error) < 0) {
+               *error_r = t_strdup_printf("Couldn't initialize SSL context: %s",
+                                          error);
+               return -1;
+       }
+       return 0;
+}
+
 int smtp_server_connection_ssl_init(struct smtp_server_connection *conn)
 {
        const char *error;
+       int ret;
+
+       if (smtp_server_connection_init_ssl_ctx(conn, &error) < 0) {
+               smtp_server_connection_error(conn,
+                       "Couldn't initialize SSL: %s", error);
+               return -1;
+       }
 
        smtp_server_connection_debug(conn, "Starting SSL handshake");
 
@@ -356,9 +389,16 @@ int smtp_server_connection_ssl_init(struct smtp_server_connection *conn)
        }
 
        smtp_server_connection_input_halt(conn);
-       if (master_service_ssl_init(master_service,
-                               &conn->conn.input, &conn->conn.output,
-                               &conn->ssl_iostream, &error) < 0) {
+       if (conn->ssl_ctx == NULL) {
+               ret = master_service_ssl_init(master_service,
+                       &conn->conn.input, &conn->conn.output,
+                       &conn->ssl_iostream, &error);
+       } else {
+               ret = io_stream_create_ssl_server(conn->ssl_ctx,
+                       conn->set.ssl, &conn->conn.input, &conn->conn.output,
+                       &conn->ssl_iostream, &error);
+       }
+       if (ret < 0) {
                smtp_server_connection_error(conn,
                        "Couldn't initialize SSL server for %s: %s",
                        conn->conn.name, error);
@@ -785,6 +825,10 @@ smtp_server_connection_alloc(struct smtp_server *server,
                conn->set.protocol = server->set.protocol;
                if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
                        conn->set.rawlog_dir = p_strdup(pool, set->rawlog_dir);
+
+               if (set->ssl != NULL)
+                       conn->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
+
                if (set->hostname != NULL && *set->hostname != '\0')
                        conn->set.hostname = p_strdup(pool, set->hostname);
                if (set->login_greeting != NULL &&
@@ -1046,6 +1090,8 @@ smtp_server_connection_disconnect(struct smtp_server_connection *conn,
        if (conn->smtp_parser != NULL)
                smtp_command_parser_deinit(&conn->smtp_parser);
        ssl_iostream_destroy(&conn->ssl_iostream);
+       if (conn->ssl_ctx != NULL)
+               ssl_iostream_context_unref(&conn->ssl_ctx);
 
        if (conn->callbacks != NULL &&
                conn->callbacks->conn_disconnect != NULL) {
index 58972646ca57b257d7a3f80d6357a3428d30ddab..876c84d20598ec94f6ddb5079839fb24cb8ebb5c 100644 (file)
@@ -143,6 +143,7 @@ struct smtp_server_connection {
        struct timeout *to_idle;
        struct istream *raw_input;
        struct ostream *raw_output;
+       struct ssl_iostream_context *ssl_ctx;
        struct ssl_iostream *ssl_iostream;
        struct smtp_command_parser *smtp_parser;
 
@@ -179,6 +180,7 @@ struct smtp_server {
        struct smtp_server_settings set;
 
        struct ioloop *ioloop;
+       struct ssl_iostream_context *ssl_ctx;
 
        ARRAY(struct smtp_server_command_reg) commands_reg;
 
@@ -357,4 +359,10 @@ bool smtp_server_transaction_has_rcpt(struct smtp_server_transaction *trans);
 unsigned int
 smtp_server_transaction_rcpt_count(struct smtp_server_transaction *trans);
 
+/*
+ * Server
+ */
+
+int smtp_server_init_ssl_ctx(struct smtp_server *server, const char **error_r);
+
 #endif
index 4cc0fabef83b2656fdaba22f156acc13101af787..d83652046e8aaa44c119350ed20ea646791a9c19 100644 (file)
@@ -30,6 +30,12 @@ struct smtp_server *smtp_server_init(const struct smtp_server_settings *set)
        server->pool = pool;
        server->set.protocol = set->protocol;
        server->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
+
+       if (set->ssl != NULL) {
+               server->set.ssl =
+                       ssl_iostream_settings_dup(server->pool, set->ssl);
+       }
+
        if (set->hostname != NULL && *set->hostname != '\0')
                server->set.hostname = p_strdup(pool, set->hostname);
        else
@@ -78,6 +84,8 @@ void smtp_server_deinit(struct smtp_server **_server)
 
        connection_list_deinit(&server->conn_list);
 
+       if (server->ssl_ctx != NULL)
+               ssl_iostream_context_unref(&server->ssl_ctx);
        pool_unref(&server->pool);
        *_server = NULL;
 }
@@ -97,3 +105,19 @@ void smtp_server_switch_ioloop(struct smtp_server *server)
                smtp_server_connection_switch_ioloop(conn);
        }
 }
+
+int smtp_server_init_ssl_ctx(struct smtp_server *server, const char **error_r)
+{
+       const char *error;
+
+       if (server->ssl_ctx != NULL || server->set.ssl == NULL)
+               return 0;
+
+       if (ssl_iostream_server_context_cache_get(server->set.ssl,
+               &server->ssl_ctx, &error) < 0) {
+               *error_r = t_strdup_printf("Couldn't initialize SSL context: %s",
+                                          error);
+               return -1;
+       }
+       return 0;
+}
index 972d5219c59955b01bd953991fbd0d59e08da9ff..fe33c8fedf37633359b2c05860260a688fee9d68 100644 (file)
@@ -240,6 +240,9 @@ struct smtp_server_settings {
        const char *login_greeting;
        const char *rawlog_dir;
 
+       /* SSL settings; if NULL, master_service_ssl_init() is used instead */
+       const struct ssl_iostream_settings *ssl;
+
        /* The maximum time in milliseconds a client is allowed to be idle
           before it is disconnected. */
        unsigned int max_client_idle_time_msecs;