From: Timo Sirainen Date: Thu, 29 Jul 2021 17:12:53 +0000 (+0300) Subject: doveadm: server-connection - Replace doveadm_server with doveadm_client_settings X-Git-Tag: 2.4.0~4763 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a13d89376b2fe59ec93ffe3909ef3f84847f814a;p=thirdparty%2Fdovecot%2Fcore.git doveadm: server-connection - Replace doveadm_server with doveadm_client_settings --- diff --git a/src/doveadm/doveadm-dsync.c b/src/doveadm/doveadm-dsync.c index 4d390d7229..455655d976 100644 --- a/src/doveadm/doveadm-dsync.c +++ b/src/doveadm/doveadm-dsync.c @@ -28,7 +28,6 @@ #include "doveadm-settings.h" #include "doveadm-mail.h" #include "doveadm-print.h" -#include "doveadm-server.h" #include "client-connection.h" #include "server-connection.h" #include "dsync/dsync-brain.h" @@ -896,21 +895,24 @@ dsync_connect_tcp(struct dsync_cmd_context *ctx, const struct master_service_ssl_settings *ssl_set, const char *target, bool ssl, const char **error_r) { - struct doveadm_server *server; + struct doveadm_client_settings conn_set; struct server_connection *conn; struct ioloop *prev_ioloop, *ioloop; const char *p, *error; - server = p_new(ctx->ctx.pool, struct doveadm_server, 1); - server->name = p_strdup(ctx->ctx.pool, target); - p = strrchr(server->name, ':'); - server->hostname = p == NULL ? server->name : - p_strdup_until(ctx->ctx.pool, server->name, p); - if (p == NULL) - server->port = doveadm_settings->doveadm_port; - else if (net_str2port(p+1, &server->port) < 0) { - *error_r = t_strdup_printf("Invalid port number: %s", p+1); - return -1; + i_zero(&conn_set); + if (strchr(target, '/') != NULL) + conn_set.socket_path = target; + else { + p = strrchr(target, ':'); + conn_set.hostname = p == NULL ? target : + p_strdup_until(ctx->ctx.pool, target, p); + if (p == NULL) + conn_set.port = doveadm_settings->doveadm_port; + else if (net_str2port(p+1, &conn_set.port) < 0) { + *error_r = t_strdup_printf("Invalid port number: %s", p+1); + return -1; + } } if (ssl) { @@ -919,13 +921,11 @@ dsync_connect_tcp(struct dsync_cmd_context *ctx, "Couldn't initialize SSL context: %s", error); return -1; } - server->ssl_flags = AUTH_PROXY_SSL_FLAG_YES; - server->ssl_ctx = ctx->ssl_ctx; + conn_set.ssl_flags = AUTH_PROXY_SSL_FLAG_YES; + conn_set.ssl_ctx = ctx->ssl_ctx; } - server->username = p_strdup(ctx->ctx.pool, - ctx->ctx.set->doveadm_username); - server->password = p_strdup(ctx->ctx.pool, - ctx->ctx.set->doveadm_password); + conn_set.username = ctx->ctx.set->doveadm_username; + conn_set.password = ctx->ctx.set->doveadm_password; prev_ioloop = current_ioloop; ioloop = io_loop_create(); @@ -933,15 +933,15 @@ dsync_connect_tcp(struct dsync_cmd_context *ctx, if (doveadm_verbose_proctitle) { process_title_set(t_strdup_printf( - "[dsync - connecting to %s]", server->name)); + "[dsync - connecting to %s]", target)); } - if (server_connection_create(server, &conn, &error) < 0) { + if (server_connection_create(&conn_set, &conn, &error) < 0) { ctx->error = p_strdup_printf(ctx->ctx.pool, "Couldn't create server connection: %s", error); } else { if (doveadm_verbose_proctitle) { process_title_set(t_strdup_printf( - "[dsync - running dsync-server on %s]", server->name)); + "[dsync - running dsync-server on %s]", target)); } dsync_server_run_command(ctx, conn); diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c index 686da77d47..863ca36817 100644 --- a/src/doveadm/doveadm-mail-server.c +++ b/src/doveadm/doveadm-mail-server.c @@ -45,8 +45,10 @@ struct doveadm_mail_server_cmd { }; struct doveadm_server_request { + pool_t pool; struct doveadm_server *server; - char *username; + struct doveadm_client_settings set; + const char *username; }; static HASH_TABLE(char *, struct doveadm_server *) servers; @@ -63,13 +65,13 @@ static void doveadm_mail_server_handle(struct doveadm_server *server, static void doveadm_server_request_free(struct doveadm_server_request *request) { - i_free(request->username); + ssl_iostream_context_unref(&request->set.ssl_ctx); + pool_unref(&request->pool); } static struct doveadm_server *doveadm_server_get(const char *name) { struct doveadm_server *server; - const char *p; char *dup_name; if (!hash_table_is_created(servers)) { @@ -84,13 +86,6 @@ static struct doveadm_server *doveadm_server_get(const char *name) if (server == NULL) { server = p_new(server_pool, struct doveadm_server, 1); server->name = dup_name = p_strdup(server_pool, name); - server->username = p_strdup(server_pool, - doveadm_settings->doveadm_username); - server->password = p_strdup(server_pool, - doveadm_settings->doveadm_password); - p = strrchr(server->name, ':'); - server->hostname = p == NULL ? server->name : - p_strdup_until(server_pool, server->name, p); hash_table_insert(servers, dup_name, server); } @@ -301,11 +296,18 @@ doveadm_cmd_redirect_finish(struct doveadm_mail_server_cmd *servercmd, server_name = t_strdup_printf("%s:%u", net_ip2addr(ip), port); new_server = doveadm_server_get(server_name); - new_server->ip = *ip; - new_server->ssl_flags = ssl_flags; - new_server->port = port; - if (server_connection_create(new_server, &conn, &error) < 0) { + struct doveadm_client_settings conn_set = { + .hostname = net_ip2addr(ip), + .ip = *ip, + .port = port, + .username = doveadm_settings->doveadm_username, + .password = doveadm_settings->doveadm_password, + .ssl_flags = ssl_flags, + .log_passthrough = TRUE, + }; + + if (server_connection_create(&conn_set, &conn, &error) < 0) { *error_r = t_strdup_printf( "Failed to create redirect connection to %s: %s", new_server->name, error); @@ -313,6 +315,7 @@ doveadm_cmd_redirect_finish(struct doveadm_mail_server_cmd *servercmd, } servercmd->conn = conn; + servercmd->server = new_server; if (servercmd->input != NULL) i_stream_seek(servercmd->input, 0); server_connection_cmd(conn, servercmd->proxy_ttl, @@ -374,6 +377,8 @@ static int doveadm_cmd_redirect(struct doveadm_mail_server_cmd *servercmd, const char *destination) { struct doveadm_server *orig_server = servercmd->server; + const struct doveadm_client_settings *client_set = + server_connection_get_settings(servercmd->conn); struct ip_addr ip; in_port_t port; const char *destuser, *host, *error; @@ -386,14 +391,14 @@ static int doveadm_cmd_redirect(struct doveadm_mail_server_cmd *servercmd, return -1; } if (port == 0) - port = orig_server->port; + port = client_set->port; if (cmd_ctx->cctx->proxy_redirect_reauth) { ret = doveadm_cmd_redirect_relookup(servercmd, &ip, port, destuser, &error); } else { ret = doveadm_cmd_redirect_finish(servercmd, &ip, port, - orig_server->ssl_flags, + client_set->ssl_flags, &error); } if (ret < 0) { @@ -535,7 +540,7 @@ static int doveadm_mail_server_request_queue_handle_next(const char **error_r) request_copy = *request; array_pop_front(&doveadm_server_request_queue); - if (server_connection_create(request_copy.server, &conn, error_r) < 0) { + if (server_connection_create(&request_copy.set, &conn, error_r) < 0) { internal_failure = TRUE; return -1; } @@ -664,12 +669,19 @@ int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, so undo any sticks we might have added already */ doveadm_print_unstick_headers(); + struct doveadm_client_settings conn_set = { + .socket_path = socket_path, + .hostname = proxy_set.host, + .ip = proxy_set.host_ip, + .port = proxy_set.port, + .username = ctx->set->doveadm_username, + .password = ctx->set->doveadm_password, + .ssl_flags = proxy_set.ssl_flags, + }; + server_name = socket_path != NULL ? socket_path : t_strdup_printf("%s:%u", proxy_set.host, proxy_set.port); server = doveadm_server_get(server_name); - server->ip = proxy_set.host_ip; - server->ssl_flags = proxy_set.ssl_flags; - server->port = proxy_set.port; unsigned int limit = I_MAX(ctx->set->doveadm_worker_count, 1); /* Make sure there's space for the new request. Either by creating a @@ -693,7 +705,7 @@ int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, } if (server_connections_count() <= limit) { - if (server_connection_create(server, &conn, error_r) < 0) { + if (server_connection_create(&conn_set, &conn, error_r) < 0) { internal_failure = TRUE; return -1; } else { @@ -702,27 +714,15 @@ int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, } } else { request = array_append_space(&doveadm_server_request_queue); - request->username = i_strdup(proxy_set.username); + request->pool = pool_alloconly_create("doveadm server request", 256); request->server = server; + request->username = p_strdup(request->pool, proxy_set.username); + doveadm_client_settings_dup(&conn_set, &request->set, request->pool); } *error_r = "doveadm server failure"; return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1; } -static void doveadm_servers_destroy_all_connections(void) -{ - struct hash_iterate_context *iter; - char *key; - struct doveadm_server *server; - - iter = hash_table_iterate_init(servers); - while (hash_table_iterate(iter, servers, &key, &server)) - ssl_iostream_context_unref(&server->ssl_ctx); - hash_table_iterate_deinit(&iter); - - server_connections_destroy_all(); -} - void doveadm_mail_server_flush(void) { struct doveadm_server_request *request; @@ -755,7 +755,7 @@ void doveadm_mail_server_flush(void) server_connections_count() > 0) io_loop_run(current_ioloop); - doveadm_servers_destroy_all_connections(); + server_connections_destroy_all(); if (master_service_is_killed(master_service)) i_error("Aborted"); if (DOVEADM_MAIL_SERVER_FAILED()) diff --git a/src/doveadm/doveadm-server.h b/src/doveadm/doveadm-server.h index 0bc6d161a9..46fdaa86f0 100644 --- a/src/doveadm/doveadm-server.h +++ b/src/doveadm/doveadm-server.h @@ -9,19 +9,6 @@ extern struct doveadm_print_vfuncs doveadm_print_server_vfuncs; struct doveadm_server { /* hostname:port or UNIX socket path. Used mainly for logging. */ const char *name; - /* If this contains '/', it's a UNIX socket path. Otherwise it's - the hostname without port. */ - const char *hostname; - /* Host's IP to use, if known. Otherwise DNS lookup is done. */ - struct ip_addr ip; - /* Port to use for TCP connections. */ - in_port_t port; - - const char *username, *password; - - /* ssl related settings */ - enum auth_proxy_ssl_flags ssl_flags; - struct ssl_iostream_context *ssl_ctx; }; #endif diff --git a/src/doveadm/server-connection.c b/src/doveadm/server-connection.c index 78151a4a37..428f06e709 100644 --- a/src/doveadm/server-connection.c +++ b/src/doveadm/server-connection.c @@ -32,7 +32,8 @@ enum server_reply_state { struct server_connection { struct connection conn; - struct doveadm_server *server; + + struct doveadm_client_settings set; pool_t pool; struct timeout *to_destroy; @@ -66,6 +67,27 @@ static int server_connection_init_ssl(struct server_connection *conn, const char **error_r); static void server_connection_destroy(struct server_connection **_conn); +void doveadm_client_settings_dup(const struct doveadm_client_settings *src, + struct doveadm_client_settings *dest_r, + pool_t pool) +{ + i_zero(dest_r); + + dest_r->socket_path = p_strdup(pool, src->socket_path); + dest_r->hostname = p_strdup(pool, src->hostname); + dest_r->ip = src->ip; + dest_r->port = src->port; + + dest_r->username = p_strdup(pool, src->username); + dest_r->password = p_strdup(pool, src->password); + + dest_r->ssl_flags = src->ssl_flags; + if (src->ssl_ctx != NULL) { + dest_r->ssl_ctx = src->ssl_ctx; + ssl_iostream_context_ref(dest_r->ssl_ctx); + } +} + static void server_set_print_pending(struct server_connection *conn) { if (!array_is_created(&print_pending_connections)) @@ -260,16 +282,16 @@ server_connection_authenticate(struct server_connection *conn) string_t *plain = t_str_new(128); string_t *cmd = t_str_new(128); - if (*conn->server->password == '\0') { + if (*conn->set.password == '\0') { e_error(conn->conn.event, "doveadm_password not set, " "can't authenticate to remote server"); return -1; } str_append_c(plain, '\0'); - str_append(plain, conn->server->username); + str_append(plain, conn->set.username); str_append_c(plain, '\0'); - str_append(plain, conn->server->password); + str_append(plain, conn->set.password); str_append(cmd, "PLAIN\t"); base64_encode(plain->data, plain->used, cmd); @@ -307,7 +329,7 @@ static void server_connection_print_log(struct server_connection *conn) "Doveadm server sent invalid log type 0x%02x", line[0]); line++; - i_log_type(&ctx, "remote(%s): %s", conn->server->name, line); + i_log_type(&ctx, "remote(%s): %s", conn->conn.name, line); } } @@ -377,7 +399,7 @@ static void server_connection_input(struct connection *_conn) return; } if (!conn->ssl_done && - (conn->server->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) != 0) { + (conn->set.ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) != 0) { connection_input_halt(&conn->conn); if (conn->conn.minor_version < DOVEADM_PROTO_MINOR_MIN_STARTTLS) { e_error(conn->conn.event, @@ -496,28 +518,28 @@ static int server_connection_init_ssl(struct server_connection *conn, struct ssl_iostream_settings ssl_set; const char *error; - if (conn->server->ssl_flags == 0) + if (conn->set.ssl_flags == 0) return 0; doveadm_get_ssl_settings(&ssl_set, pool_datastack_create()); - if ((conn->server->ssl_flags & AUTH_PROXY_SSL_FLAG_ANY_CERT) != 0) + if ((conn->set.ssl_flags & AUTH_PROXY_SSL_FLAG_ANY_CERT) != 0) ssl_set.allow_invalid_cert = TRUE; if (ssl_set.allow_invalid_cert) ssl_set.verbose_invalid_cert = TRUE; - if (conn->server->ssl_ctx == NULL && - ssl_iostream_client_context_cache_get(&ssl_set, - &conn->server->ssl_ctx, + if (conn->set.ssl_ctx == NULL && + ssl_iostream_client_context_cache_get(&ssl_set, &conn->set.ssl_ctx, &error) < 0) { *error_r = t_strdup_printf( "Couldn't initialize SSL client: %s", error); return -1; } + const char *hostname = + conn->set.hostname != NULL ? conn->set.hostname : ""; connection_input_halt(&conn->conn); - if (io_stream_create_ssl_client(conn->server->ssl_ctx, - conn->server->hostname, &ssl_set, + if (io_stream_create_ssl_client(conn->set.ssl_ctx, hostname, &ssl_set, &conn->conn.input, &conn->conn.output, &conn->ssl_iostream, &error) < 0) { *error_r = t_strdup_printf( @@ -554,7 +576,7 @@ static void server_connection_connected(struct connection *_conn, bool success) server_connection_output, conn); connection_input_halt(&conn->conn); - if (((conn->server->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0 && + if (((conn->set.ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0 && server_connection_init_ssl(conn, &error) < 0)) { e_error(conn->conn.event, "%s", error); /* Can't safely destroy the connection here, so delay it */ @@ -588,7 +610,7 @@ static struct connection_settings doveadm_client_set = { .client_connect_timeout_msecs = DOVEADM_TCP_CONNECT_TIMEOUT_SECS, }; -int server_connection_create(struct doveadm_server *server, +int server_connection_create(const struct doveadm_client_settings *set, struct server_connection **conn_r, const char **error_r) { @@ -596,8 +618,8 @@ int server_connection_create(struct doveadm_server *server, pool_t pool; int ret; - i_assert(server->username != NULL); - i_assert(server->password != NULL); + i_assert(set->username != NULL); + i_assert(set->password != NULL); if (doveadm_clients == NULL) { doveadm_clients = @@ -608,33 +630,32 @@ int server_connection_create(struct doveadm_server *server, pool = pool_alloconly_create("doveadm server connection", 1024*16); conn = p_new(pool, struct server_connection, 1); conn->pool = pool; - conn->server = server; - if (strchr(server->hostname, '/') != NULL) { + doveadm_client_settings_dup(set, &conn->set, pool); + + if (set->socket_path != NULL) { connection_init_client_unix(doveadm_clients, &conn->conn, - server->hostname); - } else if (server->ip.family != 0) { + set->socket_path); + } else if (set->ip.family != 0) { connection_init_client_ip(doveadm_clients, &conn->conn, - server->hostname, &server->ip, - server->port); + set->hostname, &set->ip, set->port); } else { struct ip_addr *ips; unsigned int ips_count; - ret = net_gethostbyname(server->hostname, &ips, &ips_count); + ret = net_gethostbyname(set->hostname, &ips, &ips_count); if (ret != 0) { *error_r = t_strdup_printf( "Lookup of host %s failed: %s", - server->hostname, net_gethosterror(ret)); + set->hostname, net_gethosterror(ret)); pool_unref(&pool); return -1; } connection_init_client_ip(doveadm_clients, &conn->conn, - server->hostname, &ips[0], - server->port); + set->hostname, &ips[0], set->port); } if (connection_client_connect(&conn->conn) < 0) { *error_r = t_strdup_printf( - "net_connect(%s) failed: %m", server->name); + "net_connect(%s) failed: %m", conn->conn.name); connection_deinit(&conn->conn); pool_unref(&pool); return -1; @@ -689,6 +710,7 @@ static void server_connection_destroy(struct server_connection **_conn) timeout_remove(&conn->to_destroy); connection_deinit(&conn->conn); + ssl_iostream_context_unref(&conn->set.ssl_ctx); pool_unref(&conn->pool); } @@ -701,6 +723,12 @@ void server_connection_get_dest(struct server_connection *conn, } } +const struct doveadm_client_settings * +server_connection_get_settings(struct server_connection *conn) +{ + return &conn->set; +} + void server_connection_cmd(struct server_connection *conn, int proxy_ttl, const char *line, struct istream *cmd_input, server_cmd_callback_t *callback, void *context) diff --git a/src/doveadm/server-connection.h b/src/doveadm/server-connection.h index c5b37b9cd8..ccf7fd12fc 100644 --- a/src/doveadm/server-connection.h +++ b/src/doveadm/server-connection.h @@ -1,9 +1,10 @@ #ifndef SERVER_CONNECTION_H #define SERVER_CONNECTION_H +#include "doveadm-server.h" + #define SERVER_EXIT_CODE_DISCONNECTED 1000 -struct doveadm_server; struct server_connection; struct ssl_iostream; @@ -21,12 +22,40 @@ typedef void server_connection_print_t(const unsigned char *data, size_t size, bool finished, void *context); -int server_connection_create(struct doveadm_server *server, +struct doveadm_client_settings { + /* UNIX socket path to connect to, if non-NULL. */ + const char *socket_path; + + /* Hostname to connect to, if UNIX socket path wasn't specified. */ + const char *hostname; + /* Host's IP to use, if known. Otherwise DNS lookup is done. */ + struct ip_addr ip; + /* Port to use for TCP connections. */ + in_port_t port; + + /* Username and password for authentication */ + const char *username, *password; + + /* SSL flags. */ + enum auth_proxy_ssl_flags ssl_flags; + /* SSL context, or NULL to create a new one. */ + struct ssl_iostream_context *ssl_ctx; +}; + +/* Duplicate doveadm client settings. Note that the ssl_ctx is referenced by + this call, so it must be unreferenced later. */ +void doveadm_client_settings_dup(const struct doveadm_client_settings *src, + struct doveadm_client_settings *dest_r, + pool_t pool); + +int server_connection_create(const struct doveadm_client_settings *set, struct server_connection **conn_r, const char **error_r); void server_connection_get_dest(struct server_connection *conn, struct ip_addr *ip_r, in_port_t *port_r); +const struct doveadm_client_settings * +server_connection_get_settings(struct server_connection *conn); void server_connection_set_print(struct server_connection *conn, server_connection_print_t *callback,