]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Added support for using local/remote {} settings.
authorTimo Sirainen <tss@iki.fi>
Fri, 20 May 2011 11:08:43 +0000 (14:08 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 20 May 2011 11:08:43 +0000 (14:08 +0300)
src/doveadm/client-connection.c
src/doveadm/doveadm-mail-server.c
src/doveadm/doveadm-mail.c
src/doveadm/doveadm-mail.h

index 0b2f8ea71ba03f3f566c2598e85d0c539a12d048..12ed3edd1e861431591ea32b81c0c1aec7e9c8b1 100644 (file)
@@ -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"
 #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);
index 06a17dfc9df5e47b2308982267d73e06eb294d24..f79a74a490a2bd59ae1deb848c74d499a82ff08d 100644 (file)
@@ -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";
index 8fd5e5d1efd3a30ee82afab291b6715cb354e11a..90bfdb980d557c7ebdf10dbd3e2ab6a34be5472c 100644 (file)
@@ -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);
index a442418e5a8ad67fac9d055caaf395dc282c9ac7..1fbe3fad900ceaf0ed5b2ded73e9d0bf5a656f11 100644 (file)
@@ -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,