bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "lib.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "array.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "hash.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "str.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "strescape.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "ioloop.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "master-service.h"
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen#include "auth-master.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "mail-storage.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "mail-storage-service.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "server-connection.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "doveadm-settings.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "doveadm-print.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "doveadm-server.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "doveadm-mail.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#define DOVEADM_SERVER_CONNECTIONS_MAX 4
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#define DOVEADM_SERVER_QUEUE_MAX 16
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#define DOVEADM_MAIL_SERVER_FAILED() \
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen (internal_failure || master_service_is_killed(master_service))
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainenstruct doveadm_mail_server_cmd {
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen struct server_connection *conn;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen char *username;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen};
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenstatic HASH_TABLE(char *, struct doveadm_server *) servers;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic pool_t server_pool;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic bool internal_failure = FALSE;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen const char *username);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainenstatic struct doveadm_server *
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct doveadm_server *server;
1b7459fda7de40f963e64da1886af68ad05fd10dTimo Sirainen const char *p;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen char *dup_name;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (!hash_table_is_created(servers)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create(&servers, server_pool, 0, str_hash, strcmp);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen server = hash_table_lookup(servers, name);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (server == NULL) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen server = p_new(server_pool, struct doveadm_server, 1);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen server->name = dup_name = p_strdup(server_pool, name);
1b7459fda7de40f963e64da1886af68ad05fd10dTimo Sirainen p = strrchr(server->name, ':');
1b7459fda7de40f963e64da1886af68ad05fd10dTimo Sirainen server->hostname = p == NULL ? server->name :
1b7459fda7de40f963e64da1886af68ad05fd10dTimo Sirainen p_strdup_until(server_pool, server->name, p);
1b7459fda7de40f963e64da1886af68ad05fd10dTimo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen p_array_init(&server->connections, server_pool,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen ctx->set->doveadm_worker_count);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen p_array_init(&server->queue, server_pool,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen DOVEADM_SERVER_QUEUE_MAX);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen hash_table_insert(servers, dup_name, server);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic struct server_connection *
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct server_connection *const *connp;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen array_foreach(&server->connections, connp) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (server_connection_is_idle(*connp))
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return *connp;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return NULL;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct server_connection *const *connp;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen array_foreach(&server->connections, connp) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (!server_connection_is_idle(*connp))
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return TRUE;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return FALSE;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
956b8eea7ae479a38b25175447fc8eac2df30480Timo Sirainenstatic void doveadm_cmd_callback(int exit_code, const char *error,
956b8eea7ae479a38b25175447fc8eac2df30480Timo Sirainen void *context)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen struct doveadm_mail_server_cmd *servercmd = context;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen struct doveadm_server *server =
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen server_connection_get_server(servercmd->conn);
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen const char *username = t_strdup(servercmd->username);
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen i_free(servercmd->username);
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen i_free(servercmd);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen switch (exit_code) {
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen case 0:
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen break;
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen case SERVER_EXIT_CODE_DISCONNECTED:
ecd14e4323bfe9953db9be89dc75858592018a75Timo Sirainen i_error("%s: Command %s failed for %s: %s",
ecd14e4323bfe9953db9be89dc75858592018a75Timo Sirainen server->name, cmd_ctx->cmd->name, username, error);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen internal_failure = TRUE;
b91b14dfb49823ffa445aa50c56d23c67b888cd4Timo Sirainen io_loop_stop(current_ioloop);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return;
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen case EX_NOUSER:
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen i_error("%s: No such user: %s", server->name, username);
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen if (cmd_ctx->exit_code == 0)
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen cmd_ctx->exit_code = EX_NOUSER;
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen break;
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen default:
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen if (cmd_ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
8ad7aa4ddf9e37fc1aefdf84f90071f49fc2619cTimo Sirainen cmd_ctx->exit_code = exit_code;
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen break;
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (array_count(&server->queue) > 0) {
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen struct server_connection *conn;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen char *username = *usernamep;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen conn = doveadm_server_find_unused_conn(server);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (conn != NULL) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen array_delete(&server->queue, 0, 1);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen doveadm_mail_server_handle(conn, username);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_free(username);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
b91b14dfb49823ffa445aa50c56d23c67b888cd4Timo Sirainen io_loop_stop(current_ioloop);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen const char *username)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen struct doveadm_mail_server_cmd *servercmd;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen string_t *cmd;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen unsigned int i;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* <flags> <username> <command> [<args>] */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen cmd = t_str_new(256);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (doveadm_debug)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen str_append_c(cmd, 'D');
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen else if (doveadm_verbose)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen str_append_c(cmd, 'v');
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen str_append_c(cmd, '\t');
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(cmd, username);
2cc88ff507e244faa63683f804833b321a62c665Timo Sirainen str_append_c(cmd, '\t');
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(cmd, cmd_ctx->cmd->name);
10b8040903b1d1591f1d44552ff466c8789b8814Timo Sirainen for (i = 0; cmd_ctx->full_args[i] != NULL; i++) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen str_append_c(cmd, '\t');
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(cmd, cmd_ctx->full_args[i]);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen str_append_c(cmd, '\n');
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen servercmd = i_new(struct doveadm_mail_server_cmd, 1);
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen servercmd->conn = conn;
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen servercmd->username = i_strdup(username);
32c779d5d0b3dabc697408e6b5d9d2e652180b33Timo Sirainen server_connection_cmd(conn, str_c(cmd), cmd_ctx->cmd_input,
ab530005cbeae9ea2301ef884c913e51870ea912Timo Sirainen doveadm_cmd_callback, servercmd);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen unsigned int count = array_count(&server->queue);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen do {
06c303e21a11e11209f40a2658f2864819d59f70Timo Sirainen io_loop_run(current_ioloop);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen } while (array_count(&server->queue) == count &&
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen doveadm_server_have_used_connections(server) &&
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen !DOVEADM_MAIL_SERVER_FAILED());
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainenstatic int
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainendoveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen const struct mail_storage_service_input *input,
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen const char **user_r, const char **host_r,
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen const char **error_r)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen struct auth_master_connection *auth_conn;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen struct auth_user_info info;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen pool_t pool;
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen const char *auth_socket_path, *proxy_host, *proxy_hostip, *const *fields;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch unsigned int i;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t proxy_port;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen bool proxying;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen int ret;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen *user_r = input->username;
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen *host_r = ctx->set->doveadm_socket_path;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
1e09e09669964343557a0027188f486e9d4ccba8Timo Sirainen if (ctx->set->doveadm_port == 0)
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen return 0;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* make sure we have an auth connection */
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&info);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen info.service = master_service_get_name(master_service);
b372fc2d5331a7669e91b05a09404f3303895ce2Timo Sirainen info.local_ip = input->local_ip;
b372fc2d5331a7669e91b05a09404f3303895ce2Timo Sirainen info.remote_ip = input->remote_ip;
b372fc2d5331a7669e91b05a09404f3303895ce2Timo Sirainen info.local_port = input->local_port;
b372fc2d5331a7669e91b05a09404f3303895ce2Timo Sirainen info.remote_port = input->remote_port;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen pool = pool_alloconly_create("auth lookup", 1024);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service);
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen auth_socket_path = auth_master_get_socket_path(auth_conn);
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen ret = auth_master_pass_lookup(auth_conn, input->username, &info,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen pool, &fields);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (ret < 0) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen *error_r = fields[0] != NULL ?
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen t_strdup(fields[0]) : "passdb lookup failed";
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen *error_r = t_strdup_printf("%s: %s (to see if user is proxied, "
7bf0bc502847098575465a650c5967d17bc0e6ceTimo Sirainen "because doveadm_port is set)",
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen auth_socket_path, *error_r);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen } else if (ret == 0) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* user not found from passdb. it could be in userdb though,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen so just continue with the default host */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen } else {
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen proxy_host = NULL; proxy_hostip = NULL; proxying = FALSE;
22d87bd260a4476da878df48206eba0b37322a6cTimo Sirainen proxy_port = ctx->set->doveadm_port;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen for (i = 0; fields[i] != NULL; i++) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (strncmp(fields[i], "proxy", 5) == 0 &&
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen (fields[i][5] == '\0' || fields[i][5] == '='))
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen proxying = TRUE;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen else if (strncmp(fields[i], "host=", 5) == 0)
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen proxy_host = fields[i]+5;
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen else if (strncmp(fields[i], "hostip=", 7) == 0)
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen proxy_hostip = fields[i]+7;
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen else if (strncmp(fields[i], "user=", 5) == 0)
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen *user_r = t_strdup(fields[i]+5);
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen else if (strncmp(fields[i], "destuser=", 9) == 0)
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen *user_r = t_strdup(fields[i]+9);
22d87bd260a4476da878df48206eba0b37322a6cTimo Sirainen else if (strncmp(fields[i], "port=", 5) == 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (net_str2port(fields[i]+5, &proxy_port) < 0)
22d87bd260a4476da878df48206eba0b37322a6cTimo Sirainen proxy_port = 0;
22d87bd260a4476da878df48206eba0b37322a6cTimo Sirainen }
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen }
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen if (proxy_hostip != NULL)
a07e0d83e1fd465d7ee13771ded72a8d152b5bbbTimo Sirainen proxy_host = proxy_hostip;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (!proxying)
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen ret = 0;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen else if (proxy_host == NULL) {
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen *error_r = t_strdup_printf("%s: Proxy is missing destination host",
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen auth_socket_path);
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen if (strstr(auth_socket_path, "/auth-userdb") != NULL) {
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen *error_r = t_strdup_printf(
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen "%s (maybe set auth_socket_path=director-userdb)",
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen *error_r);
cd8bd47fd52b3835253b0f341c8cab3d40a50cecTimo Sirainen }
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen ret = -1;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen } else {
22d87bd260a4476da878df48206eba0b37322a6cTimo Sirainen *host_r = t_strdup_printf("%s:%u", proxy_host, proxy_port);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen pool_unref(&pool);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen return ret;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenint doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen const struct mail_storage_service_input *input,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen const char **error_r)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct doveadm_server *server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct server_connection *conn;
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen const char *user, *host;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen char *username_dup;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen int ret;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_assert(cmd_ctx == ctx || cmd_ctx == NULL);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen cmd_ctx = ctx;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen ret = doveadm_mail_server_user_get_host(ctx, input, &user, &host, error_r);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (ret < 0)
68801dacbac0279d81364d1ea9473d49bd8207e3Timo Sirainen return ret;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (ret == 0 &&
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen (ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* run it ourself */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen return 0;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
db4cad7df8f3a1a584b1f72a06995b188871dc5aTimo Sirainen /* server sends the sticky headers for each row as well,
db4cad7df8f3a1a584b1f72a06995b188871dc5aTimo Sirainen so undo any sticks we might have added already */
db4cad7df8f3a1a584b1f72a06995b188871dc5aTimo Sirainen doveadm_print_unstick_headers();
db4cad7df8f3a1a584b1f72a06995b188871dc5aTimo Sirainen
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen server = doveadm_server_get(ctx, host);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen conn = doveadm_server_find_unused_conn(server);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (conn != NULL)
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen doveadm_mail_server_handle(conn, user);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen else if (array_count(&server->connections) <
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen I_MAX(ctx->set->doveadm_worker_count, 1)) {
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (server_connection_create(server, &conn) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen internal_failure = TRUE;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen else
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen doveadm_mail_server_handle(conn, user);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen } else {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen doveadm_server_flush_one(server);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
ae369149607cd8b9e3f6afdcf7c16cff1abdda54Timo Sirainen username_dup = i_strdup(user);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen array_append(&server->queue, &username_dup, 1);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
2cc88ff507e244faa63683f804833b321a62c665Timo Sirainen *error_r = "doveadm server failure";
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic struct doveadm_server *doveadm_server_find_used(void)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct hash_iterate_context *iter;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct doveadm_server *ret = NULL;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen char *key;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen struct doveadm_server *server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen iter = hash_table_iterate_init(servers);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, servers, &key, &server)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (doveadm_server_have_used_connections(server)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen ret = server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen break;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen hash_table_iterate_deinit(&iter);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return ret;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic void doveadm_servers_destroy_all_connections(void)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct hash_iterate_context *iter;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen char *key;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen struct doveadm_server *server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen iter = hash_table_iterate_init(servers);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, servers, &key, &server)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen while (array_count(&server->connections) > 0) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct server_connection *const *connp, *conn;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen connp = array_idx(&server->connections, 0);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen conn = *connp;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen server_connection_destroy(&conn);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen hash_table_iterate_deinit(&iter);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenvoid doveadm_mail_server_flush(void)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct doveadm_server *server;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (!hash_table_is_created(servers)) {
584c79069470319ce9e0d4ed34d9604726cfefb1Timo Sirainen cmd_ctx = NULL;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return;
584c79069470319ce9e0d4ed34d9604726cfefb1Timo Sirainen }
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen while ((server = doveadm_server_find_used()) != NULL &&
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen !DOVEADM_MAIL_SERVER_FAILED())
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen doveadm_server_flush_one(server);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen doveadm_servers_destroy_all_connections();
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (master_service_is_killed(master_service))
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_error("Aborted");
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (DOVEADM_MAIL_SERVER_FAILED())
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(cmd_ctx, MAIL_ERROR_TEMP);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen hash_table_destroy(&servers);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen pool_unref(&server_pool);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen cmd_ctx = NULL;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}