doveadm-mail-server.c revision a07e0d83e1fd465d7ee13771ded72a8d152b5bbb
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hash.h"
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "strescape.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "auth-master.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "mail-storage.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "mail-storage-service.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "server-connection.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "doveadm-settings.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "doveadm-print.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "doveadm-server.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#include "doveadm-mail.h"
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#define DOVEADM_SERVER_CONNECTIONS_MAX 4
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#define DOVEADM_SERVER_QUEUE_MAX 16
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen#define DOVEADM_MAIL_SERVER_FAILED() \
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen (internal_failure || master_service_is_killed(master_service))
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenstruct doveadm_mail_server_cmd {
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen struct server_connection *conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *username;
75e8db37023fde9ac15550bf426be8719d94a821Timo Sirainen};
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic HASH_TABLE(char *, struct doveadm_server *) servers;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenstatic pool_t server_pool;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstatic bool internal_failure = FALSE;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen const char *username);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
e627cdc5ef30d87959f9510832427e33a2f1d84aTimo Sirainenstatic struct doveadm_server *
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct doveadm_server *server;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen char *dup_name;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (!hash_table_is_created(servers)) {
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen hash_table_create(&servers, server_pool, 0, str_hash, strcmp);
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen }
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen server = hash_table_lookup(servers, name);
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen if (server == NULL) {
1727610dbc69920b7f0d0622b4e5d7127c59093dTimo Sirainen server = p_new(server_pool, struct doveadm_server, 1);
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen server->name = dup_name = p_strdup(server_pool, name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_array_init(&server->connections, server_pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->set->doveadm_worker_count);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen p_array_init(&server->queue, server_pool,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen DOVEADM_SERVER_QUEUE_MAX);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen hash_table_insert(servers, dup_name, server);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return server;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenstatic struct server_connection *
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
1727610dbc69920b7f0d0622b4e5d7127c59093dTimo Sirainen{
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainen struct server_connection *const *connp;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen array_foreach(&server->connections, connp) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (server_connection_is_idle(*connp))
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen return *connp;
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen }
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen return NULL;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen}
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen{
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen struct server_connection *const *connp;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach(&server->connections, connp) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!server_connection_is_idle(*connp))
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen return FALSE;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen}
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void doveadm_cmd_callback(int exit_code, const char *error,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct doveadm_mail_server_cmd *servercmd = context;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct doveadm_server *server =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server_connection_get_server(servercmd->conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *username = t_strdup(servercmd->username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen i_free(servercmd->username);
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen i_free(servercmd);
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen switch (exit_code) {
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen case 0:
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen break;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen case SERVER_EXIT_CODE_DISCONNECTED:
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen i_error("%s: Command %s failed for %s: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server->name, cmd_ctx->cmd->name, username, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen internal_failure = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_loop_stop(current_ioloop);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case EX_NOUSER:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s: No such user: %s", server->name, username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cmd_ctx->exit_code == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_ctx->exit_code = EX_NOUSER;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cmd_ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_ctx->exit_code = exit_code;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen break;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (array_count(&server->queue) > 0) {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen struct server_connection *conn;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen char *username = *usernamep;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen conn = doveadm_server_find_unused_conn(server);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (conn != NULL) {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen array_delete(&server->queue, 0, 1);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen doveadm_mail_server_handle(conn, username);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen i_free(username);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen io_loop_stop(current_ioloop);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen const char *username)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen{
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen struct doveadm_mail_server_cmd *servercmd;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen string_t *cmd;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen unsigned int i;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* <flags> <username> <command> [<args>] */
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen cmd = t_str_new(256);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (doveadm_debug)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen str_append_c(cmd, 'D');
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen else if (doveadm_verbose)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen str_append_c(cmd, 'v');
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen str_append_c(cmd, '\t');
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen str_append_tabescaped(cmd, username);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen str_append_c(cmd, '\t');
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->cmd->name);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen for (i = 0; cmd_ctx->full_args[i] != NULL; i++) {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen str_append_c(cmd, '\t');
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->full_args[i]);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen }
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen str_append_c(cmd, '\n');
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen servercmd = i_new(struct doveadm_mail_server_cmd, 1);
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen servercmd->conn = conn;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen servercmd->username = i_strdup(username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server_connection_cmd(conn, str_c(cmd), cmd_ctx->cmd_input,
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen doveadm_cmd_callback, servercmd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen{
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int count = array_count(&server->queue);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen do {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_loop_run(current_ioloop);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen } while (array_count(&server->queue) == count &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_server_have_used_connections(server) &&
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen !DOVEADM_MAIL_SERVER_FAILED());
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstatic int
24ec3e51a1bd7aaf09c92a7ff7498e225796d7e0Timo Sirainendoveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx,
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen const struct mail_storage_service_input *input,
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen const char **user_r, const char **host_r,
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen const char **error_r)
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen{
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen struct auth_master_connection *auth_conn;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen struct auth_user_info info;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen pool_t pool;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen const char *auth_socket_path, *proxy_host, *proxy_hostip, *const *fields;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen unsigned int i;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen in_port_t proxy_port;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen bool proxying;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen int ret;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen *user_r = input->username;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *host_r = ctx->set->doveadm_socket_path;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (ctx->set->doveadm_port == 0)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen return 0;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* make sure we have an auth connection */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen i_zero(&info);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.service = master_service_get_name(master_service);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen info.local_ip = input->local_ip;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen info.remote_ip = input->remote_ip;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen info.local_port = input->local_port;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen info.remote_port = input->remote_port;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen pool = pool_alloconly_create("auth lookup", 1024);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen auth_socket_path = auth_master_get_socket_path(auth_conn);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen ret = auth_master_pass_lookup(auth_conn, input->username, &info,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen pool, &fields);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret < 0) {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen *error_r = fields[0] != NULL ?
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen t_strdup(fields[0]) : "passdb lookup failed";
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *error_r = t_strdup_printf("%s: %s (to see if user is proxied, "
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen "because doveadm_port is set)",
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen auth_socket_path, *error_r);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen } else if (ret == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* user not found from passdb. it could be in userdb though,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen so just continue with the default host */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen } else {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen proxy_host = NULL; proxy_hostip = NULL; proxying = FALSE;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen proxy_port = ctx->set->doveadm_port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; fields[i] != NULL; i++) {
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (strncmp(fields[i], "proxy", 5) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (fields[i][5] == '\0' || fields[i][5] == '='))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen proxying = TRUE;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen else if (strncmp(fields[i], "host=", 5) == 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen proxy_host = fields[i]+5;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen else if (strncmp(fields[i], "hostip=", 7) == 0)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen proxy_hostip = fields[i]+7;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen else if (strncmp(fields[i], "user=", 5) == 0)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *user_r = t_strdup(fields[i]+5);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen else if (strncmp(fields[i], "destuser=", 9) == 0)
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen *user_r = t_strdup(fields[i]+9);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen else if (strncmp(fields[i], "port=", 5) == 0) {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (net_str2port(fields[i]+5, &proxy_port) < 0)
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen proxy_port = 0;
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen if (proxy_hostip != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen proxy_host = proxy_hostip;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!proxying)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen ret = 0;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen else if (proxy_host == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup_printf("%s: Proxy is missing destination host",
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen auth_socket_path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strstr(auth_socket_path, "/auth-userdb") != NULL) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen *error_r = t_strdup_printf(
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s (maybe set auth_socket_path=director-userdb)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen }
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen ret = -1;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *host_r = t_strdup_printf("%s:%u", proxy_host, proxy_port);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenint doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_storage_service_input *input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen struct doveadm_server *server;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct server_connection *conn;
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen const char *user, *host;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *username_dup;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(cmd_ctx == ctx || cmd_ctx == NULL);
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen cmd_ctx = ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen ret = doveadm_mail_server_user_get_host(ctx, input, &user, &host, error_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen /* run it ourself */
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen return 0;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* server sends the sticky headers for each row as well,
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen so undo any sticks we might have added already */
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen doveadm_print_unstick_headers();
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server = doveadm_server_get(ctx, host);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn = doveadm_server_find_unused_conn(server);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (conn != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_mail_server_handle(conn, user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (array_count(&server->connections) <
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen I_MAX(ctx->set->doveadm_worker_count, 1)) {
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if (server_connection_create(server, &conn) < 0)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen internal_failure = TRUE;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen else
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen doveadm_mail_server_handle(conn, user);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen } else {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen doveadm_server_flush_one(server);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen username_dup = i_strdup(user);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen array_append(&server->queue, &username_dup, 1);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen *error_r = "doveadm server failure";
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen}
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic struct doveadm_server *doveadm_server_find_used(void)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct hash_iterate_context *iter;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct doveadm_server *ret = NULL;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen char *key;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen struct doveadm_server *server;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen iter = hash_table_iterate_init(servers);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen while (hash_table_iterate(iter, servers, &key, &server)) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (doveadm_server_have_used_connections(server)) {
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen ret = server;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen break;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen hash_table_iterate_deinit(&iter);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen return ret;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen}
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic void doveadm_servers_destroy_all_connections(void)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen{
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen struct hash_iterate_context *iter;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen char *key;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen struct doveadm_server *server;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen iter = hash_table_iterate_init(servers);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen while (hash_table_iterate(iter, servers, &key, &server)) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen while (array_count(&server->connections) > 0) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen struct server_connection *const *connp, *conn;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen connp = array_idx(&server->connections, 0);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen conn = *connp;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen server_connection_destroy(&conn);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen }
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen hash_table_iterate_deinit(&iter);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen}
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenvoid doveadm_mail_server_flush(void)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen{
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen struct doveadm_server *server;
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (!hash_table_is_created(servers)) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen cmd_ctx = NULL;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen return;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen }
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen while ((server = doveadm_server_find_used()) != NULL &&
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen !DOVEADM_MAIL_SERVER_FAILED())
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen doveadm_server_flush_one(server);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen doveadm_servers_destroy_all_connections();
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen if (master_service_is_killed(master_service))
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen i_error("Aborted");
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen if (DOVEADM_MAIL_SERVER_FAILED())
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen doveadm_mail_failed_error(cmd_ctx, MAIL_ERROR_TEMP);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen hash_table_destroy(&servers);
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen pool_unref(&server_pool);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen cmd_ctx = NULL;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen