doveadm-mail-server.c revision a07e0d83e1fd465d7ee13771ded72a8d152b5bbb
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
afd0d073a0afd1c8cf6473b4ae76919586eaa1faTimo Sirainen (internal_failure || master_service_is_killed(master_service))
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic HASH_TABLE(char *, struct doveadm_server *) servers;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen hash_table_create(&servers, server_pool, 0, str_hash, strcmp);
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,
ef4d0eafab4d26bba047551db1e23ceff8aa9404Timo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void doveadm_cmd_callback(int exit_code, const char *error,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct doveadm_mail_server_cmd *servercmd = context;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server_connection_get_server(servercmd->conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *username = t_strdup(servercmd->username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server->name, cmd_ctx->cmd->name, username, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s: No such user: %s", server->name, username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cmd_ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen conn = doveadm_server_find_unused_conn(server);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen unsigned int i;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* <flags> <username> <command> [<args>] */
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->cmd->name);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen for (i = 0; cmd_ctx->full_args[i] != NULL; i++) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->full_args[i]);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen servercmd = i_new(struct doveadm_mail_server_cmd, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen server_connection_cmd(conn, str_c(cmd), cmd_ctx->cmd_input,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int count = array_count(&server->queue);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen } while (array_count(&server->queue) == count &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_server_have_used_connections(server) &&
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 **error_r)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen const char *auth_socket_path, *proxy_host, *proxy_hostip, *const *fields;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen unsigned int i;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* make sure we have an auth connection */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.service = master_service_get_name(master_service);
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,
e49e973f363a56ad186fce372310d5ec6d83d8faTimo Sirainen *error_r = t_strdup_printf("%s: %s (to see if user is proxied, "
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen "because doveadm_port is set)",
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 */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen proxy_host = NULL; proxy_hostip = NULL; proxying = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (fields[i][5] == '\0' || fields[i][5] == '='))
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen else if (strncmp(fields[i], "hostip=", 7) == 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen else if (strncmp(fields[i], "destuser=", 9) == 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen else if (strncmp(fields[i], "port=", 5) == 0) {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (net_str2port(fields[i]+5, &proxy_port) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup_printf("%s: Proxy is missing destination host",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strstr(auth_socket_path, "/auth-userdb") != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s (maybe set auth_socket_path=director-userdb)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *host_r = t_strdup_printf("%s:%u", proxy_host, proxy_port);
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)
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen ret = doveadm_mail_server_user_get_host(ctx, input, &user, &host, error_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen /* run it ourself */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* server sends the sticky headers for each row as well,
f7992ce3ff735b8eb2f59b07f1d565dafcc0452eTimo Sirainen so undo any sticks we might have added already */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn = doveadm_server_find_unused_conn(server);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if (server_connection_create(server, &conn) < 0)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen array_append(&server->queue, &username_dup, 1);
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic struct doveadm_server *doveadm_server_find_used(void)
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen while (hash_table_iterate(iter, servers, &key, &server)) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainen if (doveadm_server_have_used_connections(server)) {
3fe9483b2b412a14493e3120751b0e99ecfe9388Timo Sirainenstatic void doveadm_servers_destroy_all_connections(void)
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;
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen while ((server = doveadm_server_find_used()) != NULL &&