]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login-common: Split client_create() to client_alloc() and client_init()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 31 Oct 2017 22:49:53 +0000 (00:49 +0200)
committerTimo Sirainen <tss@dovecot.fi>
Mon, 6 Nov 2017 23:09:00 +0000 (01:09 +0200)
client_unref() can be used to free an allocated client that hasn't been
fully created.

src/login-common/client-common.c
src/login-common/client-common.h
src/login-common/main.c

index f46096db1ead45f161ab5508b701afdf562410f0..7dbd24ef80fbe9e84cfb0b058a5bc38fc15db324 100644 (file)
@@ -152,11 +152,10 @@ static bool client_is_trusted(struct client *client)
 }
 
 struct client *
-client_create(int fd, bool ssl, pool_t pool,
-             const struct master_service_connection *conn,
-             const struct login_settings *set,
-             const struct master_service_ssl_settings *ssl_set,
-             void **other_sets)
+client_alloc(int fd, bool ssl, pool_t pool,
+            const struct master_service_connection *conn,
+            const struct login_settings *set,
+            const struct master_service_ssl_settings *ssl_set)
 {
        struct client *client;
 
@@ -201,7 +200,11 @@ client_create(int fd, bool ssl, pool_t pool,
                        net_ip_compare(&conn->real_remote_ip, &conn->real_local_ip);
        }
        client->proxy_ttl = LOGIN_PROXY_TTL;
+       return client;
+}
 
+void client_init(struct client *client, void **other_sets)
+{
        if (last_client == NULL)
                last_client = client;
        DLLIST_PREPEND(&clients, client);
@@ -214,6 +217,7 @@ client_create(int fd, bool ssl, pool_t pool,
 
        hook_login_client_allocated(client);
        client->v.create(client, other_sets);
+       client->create_finished = TRUE;
 
        if (auth_client_is_connected(auth_client))
                client_notify_auth_ready(client);
@@ -221,11 +225,12 @@ client_create(int fd, bool ssl, pool_t pool,
                client_set_auth_waiting(client);
 
        login_refresh_proctitle();
-       return client;
 }
 
 void client_destroy(struct client *client, const char *reason)
 {
+       i_assert(client->create_finished);
+
        if (client->destroyed)
                return;
        client->destroyed = TRUE;
@@ -324,6 +329,12 @@ bool client_unref(struct client **_client)
        if (--client->refcount > 0)
                return TRUE;
 
+       if (!client->create_finished) {
+               pool_unref(&client->preproxy_pool);
+               pool_unref(&client->pool);
+               return FALSE;
+       }
+
        i_assert(client->destroyed);
        i_assert(client->login_proxy == NULL);
 
index 6a84c8f09b7d668b8a0628fe78c1dcdb57be9b1c..1d7de7f0a6133e3e74892648dae78645070d9b8d 100644 (file)
@@ -196,6 +196,7 @@ struct client {
        /* director_username_hash cached, if non-zero */
        unsigned int director_username_hash_cache;
 
+       bool create_finished:1;
        bool destroyed:1;
        bool input_blocked:1;
        bool login_success:1;
@@ -237,11 +238,11 @@ void login_client_hooks_add(struct module *module,
 void login_client_hooks_remove(const struct login_client_hooks *hooks);
 
 struct client *
-client_create(int fd, bool ssl, pool_t pool,
-             const struct master_service_connection *conn,
-             const struct login_settings *set,
-             const struct master_service_ssl_settings *ssl_set,
-             void **other_sets);
+client_alloc(int fd, bool ssl, pool_t pool,
+            const struct master_service_connection *conn,
+            const struct login_settings *set,
+            const struct master_service_ssl_settings *ssl_set);
+void client_init(struct client *client, void **other_sets);
 void client_destroy(struct client *client, const char *reason);
 void client_destroy_success(struct client *client, const char *reason);
 
index 670e0dc85242216b2c8dd235a4d60d3d55a6f51a..e69f2608d275e2536f70e7af121995f1c1810747 100644 (file)
@@ -128,8 +128,9 @@ client_connected_finish(const struct master_service_connection *conn)
                                  &conn->remote_ip, NULL, &ssl_set, &other_sets);
 
        if (!ssl_connections && !conn->ssl) {
-               (void)client_create(conn->fd, FALSE, pool, conn,
-                                   set, ssl_set, other_sets);
+               client = client_alloc(conn->fd, FALSE, pool, conn,
+                                     set, ssl_set);
+               client_init(client, other_sets);
        } else {
                fd_ssl = ssl_proxy_alloc(conn->fd, &conn->remote_ip, pool,
                                         set, ssl_set, &proxy);
@@ -140,8 +141,9 @@ client_connected_finish(const struct master_service_connection *conn)
                        return;
                }
 
-               client = client_create(fd_ssl, TRUE, pool, conn,
-                                      set, ssl_set, other_sets);
+               client = client_alloc(fd_ssl, TRUE, pool, conn,
+                                     set, ssl_set);
+               client_init(client, other_sets);
                client->ssl_proxy = proxy;
                ssl_proxy_set_client(proxy, client);
                ssl_proxy_start(proxy);