#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 |
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) {
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;
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]);
return FALSE;
}
flags = args[0];
- username = args[1];
+ input.username = args[1];
cmd_name = args[2];
args += 3;
argc -= 3;
}
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
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;
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;
}
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 &&
} else {
o_stream_send(conn->output, "-\n", 2);
}
+ if (client_connection_read_settings(conn) < 0)
+ client_connection_destroy(&conn);
return 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);
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;
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);
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;
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 ?
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);
}
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;
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";
/* 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;
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);
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)
}
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;
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");
}
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);
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;
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,