From: Timo Sirainen Date: Fri, 20 May 2011 11:08:43 +0000 (+0300) Subject: doveadm: Added support for using local/remote {} settings. X-Git-Tag: 2.0.14~78 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72bc08129fb0aaec8144cc183a998ccc426fef9e;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Added support for using local/remote {} settings. --- diff --git a/src/doveadm/client-connection.c b/src/doveadm/client-connection.c index 0b2f8ea71b..12ed3edd1e 100644 --- a/src/doveadm/client-connection.c +++ b/src/doveadm/client-connection.c @@ -6,7 +6,9 @@ #include "istream.h" #include "ostream.h" #include "strescape.h" +#include "settings-parser.h" #include "master-service.h" +#include "master-service-settings.h" #include "mail-storage-service.h" #include "doveadm-util.h" #include "doveadm-server.h" @@ -20,17 +22,24 @@ #define MAX_INBUF_SIZE 1024 struct client_connection { + pool_t pool; + int fd; struct io *io; struct istream *input; struct ostream *output; + struct ip_addr local_ip, remote_ip; + const struct doveadm_settings *set; unsigned int handshaked:1; unsigned int authenticated:1; }; -static bool doveadm_mail_cmd_server(const char *cmd_name, const char *username, - int argc, char *argv[]) +static bool +doveadm_mail_cmd_server(const char *cmd_name, + const struct doveadm_settings *set, + const struct mail_storage_service_input *input, + int argc, char *argv[]) { enum mail_storage_service_flags service_flags = MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | @@ -50,7 +59,7 @@ static bool doveadm_mail_cmd_server(const char *cmd_name, const char *username, if (doveadm_debug) service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; - ctx = doveadm_mail_cmd_init(cmd); + ctx = doveadm_mail_cmd_init(cmd, set); getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL); while ((c = getopt(argc, argv, getopt_args)) > 0) { switch (c) { @@ -88,10 +97,10 @@ static bool doveadm_mail_cmd_server(const char *cmd_name, const char *username, doveadm_print_header("username", "Username", DOVEADM_PRINT_HEADER_FLAG_STICKY | DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); - doveadm_print_sticky("username", username); + doveadm_print_sticky("username", input->username); } - doveadm_mail_single_user(ctx, argv, username, service_flags); + doveadm_mail_single_user(ctx, argv, input, service_flags); ctx->v.deinit(ctx); doveadm_print_flush(); return !ctx->failed; @@ -99,10 +108,14 @@ static bool doveadm_mail_cmd_server(const char *cmd_name, const char *username, static bool client_handle_command(struct client_connection *conn, char **args) { - const char *flags, *username, *cmd_name; + struct mail_storage_service_input input; + const char *flags, *cmd_name; unsigned int argc; bool ret; + memset(&input, 0, sizeof(input)); + input.service = "doveadm"; + for (argc = 0; args[argc] != NULL; argc++) args[argc] = str_tabunescape(args[argc]); @@ -111,7 +124,7 @@ static bool client_handle_command(struct client_connection *conn, char **args) return FALSE; } flags = args[0]; - username = args[1]; + input.username = args[1]; cmd_name = args[2]; args += 3; argc -= 3; @@ -135,7 +148,7 @@ static bool client_handle_command(struct client_connection *conn, char **args) } o_stream_cork(conn->output); - ret = doveadm_mail_cmd_server(cmd_name, username, argc, args); + ret = doveadm_mail_cmd_server(cmd_name, conn->set, &input, argc, args); if (ret) o_stream_send(conn->output, "\n+\n", 3); else @@ -160,7 +173,7 @@ client_connection_authenticate(struct client_connection *conn) if ((line = i_stream_read_next_line(conn->input)) == NULL) return 0; - if (*doveadm_settings->doveadm_password == '\0') { + if (*conn->set->doveadm_password == '\0') { i_error("doveadm_password not set, " "remote authentication disabled"); return -1; @@ -187,7 +200,7 @@ client_connection_authenticate(struct client_connection *conn) return -1; } pass = t_strndup(data + 9, size - 9); - if (strcmp(pass, doveadm_settings->doveadm_password) != 0) { + if (strcmp(pass, conn->set->doveadm_password) != 0) { i_error("doveadm client authenticated with wrong password"); return -1; } @@ -237,18 +250,52 @@ static void client_connection_input(struct client_connection *conn) client_connection_destroy(&conn); } +static int client_connection_read_settings(struct client_connection *conn) +{ + const struct setting_parser_info *set_roots[] = { + &doveadm_setting_parser_info, + NULL + }; + struct master_service_settings_input input; + struct master_service_settings_output output; + const char *error; + void *set; + + memset(&input, 0, sizeof(input)); + input.roots = set_roots; + input.service = "doveadm"; + input.local_ip = conn->local_ip; + input.remote_ip = conn->remote_ip; + + if (master_service_settings_read(master_service, &input, + &output, &error) < 0) { + i_error("Error reading configuration: %s", error); + return -1; + } + set = master_service_settings_get_others(master_service)[0]; + conn->set = settings_dup(&doveadm_setting_parser_info, set, conn->pool); + return 0; +} + struct client_connection *client_connection_create(int fd, int listen_fd) { struct client_connection *conn; struct stat st; const char *listen_path; + unsigned int port; + pool_t pool; - conn = i_new(struct client_connection, 1); + pool = pool_alloconly_create("doveadm client", 1024*16); + conn = p_new(pool, struct client_connection, 1); + conn->pool = pool; conn->fd = fd; conn->io = io_add(fd, IO_READ, client_connection_input, conn); conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); + (void)net_getsockname(fd, &conn->local_ip, &port); + (void)net_getpeername(fd, &conn->remote_ip, &port); + /* we'll have to do this with stat(), because at least in Linux fstat() always returns mode as 0777 */ if (net_getunixname(listen_fd, &listen_path) == 0 && @@ -260,6 +307,8 @@ struct client_connection *client_connection_create(int fd, int listen_fd) } else { o_stream_send(conn->output, "-\n", 2); } + if (client_connection_read_settings(conn) < 0) + client_connection_destroy(&conn); return conn; } @@ -274,7 +323,7 @@ void client_connection_destroy(struct client_connection **_conn) io_remove(&conn->io); if (close(conn->fd) < 0) i_error("close(client) failed: %m"); - i_free(conn); + pool_unref(&conn->pool); doveadm_client = NULL; master_service_client_connection_destroyed(master_service); diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c index 06a17dfc9d..f79a74a490 100644 --- a/src/doveadm/doveadm-mail-server.c +++ b/src/doveadm/doveadm-mail-server.c @@ -30,7 +30,8 @@ static bool internal_failure = FALSE; static void doveadm_mail_server_handle(struct server_connection *conn, const char *username); -static struct doveadm_server *doveadm_server_get(const char *name) +static struct doveadm_server * +doveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name) { struct doveadm_server *server; char *dup_name; @@ -46,7 +47,7 @@ static struct doveadm_server *doveadm_server_get(const char *name) server = p_new(server_pool, struct doveadm_server, 1); server->name = dup_name = p_strdup(server_pool, name); p_array_init(&server->connections, server_pool, - doveadm_settings->doveadm_worker_count); + ctx->set->doveadm_worker_count); p_array_init(&server->queue, server_pool, DOVEADM_SERVER_QUEUE_MAX); hash_table_insert(servers, dup_name, server); @@ -145,10 +146,9 @@ static void doveadm_server_flush_one(struct doveadm_server *server) static int doveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx, - const char *username, const char **host_r, - const char **error_r) + const struct mail_storage_service_input *input, + const char **host_r, const char **error_r) { - struct mail_storage_service_input input; struct auth_master_connection *auth_conn; struct auth_user_info info; pool_t pool; @@ -157,22 +157,20 @@ doveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx, bool proxying; int ret; - *host_r = doveadm_settings->doveadm_socket_path; + *host_r = ctx->set->doveadm_socket_path; - if (doveadm_settings->doveadm_proxy_port == 0) + if (ctx->set->doveadm_proxy_port == 0) return 0; /* make sure we have an auth connection */ - memset(&input, 0, sizeof(input)); - input.service = "doveadm"; - mail_storage_service_init_settings(ctx->storage_service, &input); + mail_storage_service_init_settings(ctx->storage_service, input); memset(&info, 0, sizeof(info)); info.service = master_service_get_name(master_service); pool = pool_alloconly_create("auth lookup", 1024); auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service); - ret = auth_master_pass_lookup(auth_conn, username, &info, + ret = auth_master_pass_lookup(auth_conn, input->username, &info, pool, &fields); if (ret < 0) { *error_r = fields[0] != NULL ? @@ -196,7 +194,7 @@ doveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx, ret = -1; } else { *host_r = t_strdup_printf("%s:%u", proxy_host, - doveadm_settings->doveadm_proxy_port); + ctx->set->doveadm_proxy_port); } } pool_unref(&pool); @@ -204,7 +202,8 @@ doveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx, } int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, - const char *username, const char **error_r) + const struct mail_storage_service_input *input, + const char **error_r) { struct doveadm_server *server; struct server_connection *conn; @@ -219,28 +218,28 @@ int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, so undo any sticks we might have added already */ doveadm_print_unstick_headers(); - ret = doveadm_mail_server_user_get_host(ctx, username, &host, error_r); + ret = doveadm_mail_server_user_get_host(ctx, input, &host, error_r); if (ret < 0) return -1; if (ret == 0 && - (doveadm_settings->doveadm_worker_count == 0 || doveadm_server)) { + (ctx->set->doveadm_worker_count == 0 || doveadm_server)) { /* run it ourself */ return 0; } - server = doveadm_server_get(host); + server = doveadm_server_get(ctx, host); conn = doveadm_server_find_unused_conn(server); if (conn != NULL) - doveadm_mail_server_handle(conn, username); + doveadm_mail_server_handle(conn, input->username); else if (array_count(&server->connections) < - I_MAX(doveadm_settings->doveadm_worker_count, 1)) { + I_MAX(ctx->set->doveadm_worker_count, 1)) { conn = server_connection_create(server); - doveadm_mail_server_handle(conn, username); + doveadm_mail_server_handle(conn, input->username); } else { if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX) doveadm_server_flush_one(server); - username_dup = i_strdup(username); + username_dup = i_strdup(input->username); array_append(&server->queue, &username_dup, 1); } *error_r = "doveadm server failure"; diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index 8fd5e5d1ef..90bfdb980d 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -195,7 +195,7 @@ doveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx, /* see if we want to execute this command via (another) doveadm server */ - ret = doveadm_mail_server_user(ctx, input->username, error_r); + ret = doveadm_mail_server_user(ctx, input, error_r); if (ret != 0) return ret; @@ -223,20 +223,14 @@ doveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx, return 1; } -void doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx, - char *argv[], const char *username, +void doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx, char *argv[], + const struct mail_storage_service_input *input, enum mail_storage_service_flags service_flags) { - struct mail_storage_service_input input; const char *error; int ret; - if (username == NULL) - i_fatal("USER environment is missing and -u option not used"); - - memset(&input, 0, sizeof(input)); - input.service = "doveadm"; - input.username = username; + i_assert(input->username != NULL); ctx->storage_service = mail_storage_service_init(master_service, NULL, service_flags); @@ -244,7 +238,7 @@ void doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx, if (hook_doveadm_mail_init != NULL) hook_doveadm_mail_init(ctx); - ret = doveadm_mail_next_user(ctx, &input, &error); + ret = doveadm_mail_next_user(ctx, input, &error); if (ret < 0) i_fatal("%s", error); else if (ret == 0) @@ -340,11 +334,13 @@ doveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED) } struct doveadm_mail_cmd_context * -doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd) +doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd, + const struct doveadm_settings *set) { struct doveadm_mail_cmd_context *ctx; ctx = cmd->alloc(); + ctx->set = set; ctx->cmd = cmd; if (ctx->v.init == NULL) ctx->v.init = doveadm_mail_cmd_init_noop; @@ -369,7 +365,7 @@ doveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[]) if (doveadm_debug) service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; - ctx = doveadm_mail_cmd_init(cmd); + ctx = doveadm_mail_cmd_init(cmd, doveadm_settings); getopt_args = t_strconcat("AS:u:", ctx->getopt_args, NULL); username = getenv("USER"); @@ -414,7 +410,15 @@ doveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[]) } if (ctx->iterate_single_user) { - doveadm_mail_single_user(ctx, argv, username, service_flags); + struct mail_storage_service_input input; + + if (username == NULL) + i_fatal("USER environment is missing and -u option not used"); + + memset(&input, 0, sizeof(input)); + input.service = "doveadm"; + input.username = username; + doveadm_mail_single_user(ctx, argv, &input, service_flags); } else { service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP; doveadm_mail_all_users(ctx, argv, wildcard_user, service_flags); diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index a442418e5a..1fbe3fad90 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -39,6 +39,7 @@ struct doveadm_mail_cmd_context { const char *const *args; const char *getopt_args; + const struct doveadm_settings *set; struct mail_storage_service_ctx *storage_service; /* search args aren't set for all mail commands */ struct mail_search_args *search_args; @@ -80,12 +81,14 @@ void doveadm_mail_init(void); void doveadm_mail_deinit(void); struct doveadm_mail_cmd_context * -doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd); -void doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx, - char *argv[], const char *username, +doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd, + const struct doveadm_settings *set); +void doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx, char *argv[], + const struct mail_storage_service_input *input, enum mail_storage_service_flags service_flags); int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, - const char *username, const char **error_r); + const struct mail_storage_service_input *input, + const char **error_r); void doveadm_mail_server_flush(void); int doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,