doveadm-mail-server.c revision 1e09e09669964343557a0027188f486e9d4ccba8
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen#include "lib.h"
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen#include "array.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "hash.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "str.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "strescape.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "ioloop.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "master-service.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "auth-master.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-storage.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-storage-service.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "server-connection.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "doveadm-settings.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "doveadm-print.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "doveadm-server.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "doveadm-mail.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#define DOVEADM_SERVER_CONNECTIONS_MAX 4
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#define DOVEADM_SERVER_QUEUE_MAX 16
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define DOVEADM_MAIL_SERVER_FAILED() \
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (internal_failure || master_service_is_killed(master_service))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct doveadm_mail_server_cmd {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct server_connection *conn;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *username;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic HASH_TABLE(char *, struct doveadm_server *) servers;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic pool_t server_pool;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool internal_failure = FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *username);
2c25e1360d4b5cc55eda969a3a7204d950de5a8fTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct doveadm_server *
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct doveadm_server *server;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen char *dup_name;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!hash_table_is_created(servers)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hash_table_create(&servers, server_pool, 0, str_hash, strcmp);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen server = hash_table_lookup(servers, name);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (server == NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen server = p_new(server_pool, struct doveadm_server, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen server->name = dup_name = p_strdup(server_pool, name);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen p_array_init(&server->connections, server_pool,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->set->doveadm_worker_count);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen p_array_init(&server->queue, server_pool,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen DOVEADM_SERVER_QUEUE_MAX);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen hash_table_insert(servers, dup_name, server);
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen }
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen return server;
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct server_connection *
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen{
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen struct server_connection *const *connp;
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen array_foreach(&server->connections, connp) {
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen if (server_connection_is_idle(*connp))
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen return *connp;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct server_connection *const *connp;
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_foreach(&server->connections, connp) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!server_connection_is_idle(*connp))
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void doveadm_cmd_callback(enum server_cmd_reply reply, void *context)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct doveadm_mail_server_cmd *servercmd = context;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct doveadm_server *server =
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen server_connection_get_server(servercmd->conn);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *username = t_strdup(servercmd->username);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_free(servercmd->username);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_free(servercmd);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen switch (reply) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case SERVER_CMD_REPLY_INTERNAL_FAILURE:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("%s: Internal failure for %s", server->name, username);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen internal_failure = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen master_service_stop(master_service);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case SERVER_CMD_REPLY_UNKNOWN_USER:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("%s: No such user: %s", server->name, username);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (cmd_ctx->exit_code == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen cmd_ctx->exit_code = EX_NOUSER;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case SERVER_CMD_REPLY_FAIL:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen doveadm_mail_failed_error(cmd_ctx, MAIL_ERROR_TEMP);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case SERVER_CMD_REPLY_OK:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (array_count(&server->queue) > 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct server_connection *conn;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *username = *usernamep;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen conn = doveadm_server_find_unused_conn(server);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (conn != NULL) {
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen array_delete(&server->queue, 0, 1);
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen doveadm_mail_server_handle(conn, username);
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen i_free(username);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen master_service_stop(master_service);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen}
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const char *username)
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct doveadm_mail_server_cmd *servercmd;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen string_t *cmd;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen unsigned int i;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen /* <flags> <username> <command> [<args>] */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen cmd = t_str_new(256);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (doveadm_debug)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen str_append_c(cmd, 'D');
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen else if (doveadm_verbose)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_c(cmd, 'v');
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen str_append_c(cmd, '\t');
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_tabescaped(cmd, username);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen str_append_c(cmd, '\t');
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->cmd->name);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for (i = 0; cmd_ctx->full_args[i] != NULL; i++) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_c(cmd, '\t');
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->full_args[i]);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_c(cmd, '\n');
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen servercmd = i_new(struct doveadm_mail_server_cmd, 1);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen servercmd->conn = conn;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen servercmd->username = i_strdup(username);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen server_connection_cmd(conn, str_c(cmd),
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen doveadm_cmd_callback, servercmd);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen unsigned int count = array_count(&server->queue);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen do {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen master_service_run(master_service, NULL);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen } while (array_count(&server->queue) == count &&
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen doveadm_server_have_used_connections(server) &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen !DOVEADM_MAIL_SERVER_FAILED());
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainenstatic int
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainendoveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct mail_storage_service_input *input,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char **host_r, const char **error_r)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct auth_master_connection *auth_conn;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct auth_user_info info;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen pool_t pool;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen const char *auth_socket_path, *proxy_host, *const *fields;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen unsigned int i;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen bool proxying;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen *host_r = ctx->set->doveadm_socket_path;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (ctx->set->doveadm_port == 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* make sure we have an auth connection */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen memset(&info, 0, sizeof(info));
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen info.service = master_service_get_name(master_service);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen pool = pool_alloconly_create("auth lookup", 1024);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen auth_socket_path = auth_master_get_socket_path(auth_conn);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen ret = auth_master_pass_lookup(auth_conn, input->username, &info,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen pool, &fields);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (ret < 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen *error_r = fields[0] != NULL ?
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen t_strdup(fields[0]) : "passdb lookup failed";
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen *error_r = t_strdup_printf("%s: %s (to see if user is proxied, "
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen "because doveadm_proxy_port is set)",
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen auth_socket_path, *error_r);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen } else if (ret == 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* user not found from passdb. it could be in userdb though,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen so just continue with the default host */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen } else {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen proxy_host = NULL; proxying = FALSE;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen for (i = 0; fields[i] != NULL; i++) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (strncmp(fields[i], "proxy", 5) == 0 &&
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen (fields[i][5] == '\0' || fields[i][5] == '='))
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen proxying = TRUE;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen else if (strncmp(fields[i], "host=", 5) == 0)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen proxy_host = fields[i]+5;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (!proxying)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen ret = 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen else if (proxy_host == NULL) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen *error_r = t_strdup_printf("%s: Proxy is missing destination host",
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen auth_socket_path);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (strstr(auth_socket_path, "/auth-userdb") != NULL) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen *error_r = t_strdup_printf(
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "%s (maybe set auth_socket_path=director-userdb)",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen *error_r);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = -1;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen } else {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *host_r = t_strdup_printf("%s:%u", proxy_host,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->set->doveadm_port);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool_unref(&pool);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct mail_storage_service_input *input,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char **error_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct doveadm_server *server;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct server_connection *conn;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *host;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen char *username_dup;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen int ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_assert(cmd_ctx == ctx || cmd_ctx == NULL);
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen cmd_ctx = ctx;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = doveadm_mail_server_user_get_host(ctx, input, &host, error_r);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (ret < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
if (ret == 0 &&
(ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
/* run it ourself */
return 0;
}
/* server sends the sticky headers for each row as well,
so undo any sticks we might have added already */
doveadm_print_unstick_headers();
server = doveadm_server_get(ctx, host);
conn = doveadm_server_find_unused_conn(server);
if (conn != NULL)
doveadm_mail_server_handle(conn, input->username);
else if (array_count(&server->connections) <
I_MAX(ctx->set->doveadm_worker_count, 1)) {
if (server_connection_create(server, &conn) < 0)
internal_failure = TRUE;
else
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(input->username);
array_append(&server->queue, &username_dup, 1);
}
*error_r = "doveadm server failure";
return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1;
}
static struct doveadm_server *doveadm_server_find_used(void)
{
struct hash_iterate_context *iter;
struct doveadm_server *ret = NULL;
char *key;
struct doveadm_server *server;
iter = hash_table_iterate_init(servers);
while (hash_table_iterate(iter, servers, &key, &server)) {
if (doveadm_server_have_used_connections(server)) {
ret = server;
break;
}
}
hash_table_iterate_deinit(&iter);
return ret;
}
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)) {
while (array_count(&server->connections) > 0) {
struct server_connection *const *connp, *conn;
connp = array_idx(&server->connections, 0);
conn = *connp;
server_connection_destroy(&conn);
}
}
hash_table_iterate_deinit(&iter);
}
void doveadm_mail_server_flush(void)
{
struct doveadm_server *server;
if (!hash_table_is_created(servers)) {
cmd_ctx = NULL;
return;
}
while ((server = doveadm_server_find_used()) != NULL &&
!DOVEADM_MAIL_SERVER_FAILED())
doveadm_server_flush_one(server);
doveadm_servers_destroy_all_connections();
if (master_service_is_killed(master_service))
i_error("Aborted");
if (DOVEADM_MAIL_SERVER_FAILED())
doveadm_mail_failed_error(cmd_ctx, MAIL_ERROR_TEMP);
hash_table_destroy(&servers);
pool_unref(&server_pool);
cmd_ctx = NULL;
}