main.c revision f859b51cf6aedc3c5b0d2307122100fa9959867f
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen#include "auth-common.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "array.h"
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen#include "ioloop.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "network.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "lib-signals.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "restrict-access.h"
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen#include "child-wait.h"
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen#include "sql-api.h"
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen#include "module-dir.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "randgen.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "process-title.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "settings-parser.h"
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainen#include "master-service.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "master-service-settings.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "master-interface.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "password-scheme.h"
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen#include "passdb-cache.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "mech.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-penalty.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-request-handler.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-worker-server.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-worker-client.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-master-connection.h"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include "auth-client-connection.h"
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#include <unistd.h>
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen#define AUTH_PENALTY_ANVIL_PATH "anvil-auth-penalty"
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainenenum auth_socket_type {
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen AUTH_SOCKET_UNKNOWN = 0,
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen AUTH_SOCKET_CLIENT,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen AUTH_SOCKET_LOGIN_CLIENT,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen AUTH_SOCKET_MASTER,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen AUTH_SOCKET_USERDB
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen};
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenbool worker = FALSE, shutdown_request = FALSE;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainentime_t process_start_time;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstruct auth_penalty *auth_penalty;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic pool_t auth_set_pool;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic struct module *modules = NULL;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic struct mechanisms_register *mech_reg;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic ARRAY_DEFINE(listen_fd_types, enum auth_socket_type);
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainenvoid auth_refresh_proctitle(void)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen if (!global_auth_settings->verbose_proctitle)
087939d3fa9c4056419386c9d6c81f147de534cdTimo Sirainen return;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen process_title_set(t_strdup_printf(
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen "[%u wait, %u passdb, %u userdb]",
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen auth_request_state_count[AUTH_REQUEST_STATE_NEW] +
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] +
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_state_count[AUTH_REQUEST_STATE_FINISHED],
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_state_count[AUTH_REQUEST_STATE_PASSDB],
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_state_count[AUTH_REQUEST_STATE_USERDB]));
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen}
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic const char *const *read_global_settings(void)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen struct master_service_settings_output set_output;
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen const char **services;
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen unsigned int i, count;
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_set_pool = pool_alloconly_create("auth settings", 8192);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen global_auth_settings =
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_settings_read(NULL, auth_set_pool, &set_output);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* strdup() the service names, because they're allocated from
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen set parser pool, and we'll later clear it. */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen count = str_array_length(set_output.specific_services);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen services = p_new(auth_set_pool, const char *, count + 1);
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen for (i = 0; i < count; i++) {
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen services[i] = p_strdup(auth_set_pool,
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen set_output.specific_services[i]);
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen }
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen return services;
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen}
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainenstatic void main_preinit(void)
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen{
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen struct module_dir_load_settings mod_set;
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen const char *const *services;
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen /* Open /dev/urandom before chrooting */
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen random_init();
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* Load built-in SQL drivers (if any) */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen sql_drivers_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen sql_drivers_register_all();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* Initialize databases so their configuration files can be readable
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen only by root. Also load all modules here. */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen passdbs_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen userdbs_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen services = read_global_settings();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen memset(&mod_set, 0, sizeof(mod_set));
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mod_set.version = master_service_get_version_string(master_service);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mod_set.require_init_funcs = TRUE;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mod_set.debug = global_auth_settings->debug;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen modules = module_dir_load(AUTH_MODULE_DIR, NULL, &mod_set);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen module_dir_init(modules);
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mech_init(global_auth_settings);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mech_reg = mech_register_init(global_auth_settings);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auths_preinit(global_auth_settings, auth_set_pool,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen mech_reg, services);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* Password lookups etc. may require roots, allow it. */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen restrict_access_by_env(NULL, FALSE);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen restrict_access_allow_coredumps(TRUE);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen}
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
1d4f710106fb498750456724628da6063e012e6dTimo Sirainenstatic void main_init(void)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen i_array_init(&listen_fd_types, 8);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen process_start_time = ioloop_time;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* If auth caches aren't used, just ignore these signals */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen lib_signals_ignore(SIGHUP, TRUE);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen lib_signals_ignore(SIGUSR2, TRUE);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen child_wait_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen password_schemes_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_worker_server_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auths_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_handler_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_master_connections_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_client_connections_init();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (worker) {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* workers have only a single connection from the master
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth process */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen master_service_set_client_limit(master_service, 1);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen } else {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* caching is handled only by the main auth process */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen passdb_cache_init(global_auth_settings);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen }
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_refresh_proctitle();
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic void main_deinit(void)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (auth_worker_client != NULL)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen auth_worker_client_destroy(&auth_worker_client);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen else
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen auth_request_handler_flush_failures(TRUE);
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auth_client_connections_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auth_master_connections_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auth_worker_server_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auths_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auth_request_handler_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen passdb_cache_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen mech_register_deinit(&mech_reg);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen mech_deinit(global_auth_settings);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen auth_penalty_deinit(&auth_penalty);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen /* allow modules to unregister their dbs/drivers/etc. before freeing
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen the whole data structures containing them. */
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen module_dir_unload(&modules);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen userdbs_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen passdbs_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen password_schemes_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen sql_drivers_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen random_deinit();
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen array_free(&listen_fd_types);
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen pool_unref(&auth_set_pool);
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen}
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainenstatic void worker_connected(struct master_service_connection *conn)
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen{
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen if (auth_worker_client != NULL) {
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen i_error("Auth workers can handle only a single client");
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen return;
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen }
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen master_service_client_connection_accept(conn);
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen (void)auth_worker_client_create(auth_find_service(NULL), conn->fd);
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen}
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainenstatic void client_connected(struct master_service_connection *conn)
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen{
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen enum auth_socket_type *type;
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen const char *path, *name, *suffix;
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen struct auth *auth;
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen type = array_idx_modifiable(&listen_fd_types, conn->listen_fd);
38318f5e82662615cd88e99e398efe4a630ce020Timo Sirainen if (*type == AUTH_SOCKET_UNKNOWN) {
/* figure out if this is a server or network socket by
checking the socket path name. */
if (net_getunixname(conn->listen_fd, &path) < 0)
i_fatal("getsockname(%d) failed: %m", conn->listen_fd);
name = strrchr(path, '/');
if (name == NULL)
name = path;
else
name++;
suffix = strrchr(name, '-');
if (suffix == NULL)
suffix = name;
else
suffix++;
if (strcmp(suffix, "login") == 0)
*type = AUTH_SOCKET_LOGIN_CLIENT;
else if (strcmp(suffix, "master") == 0)
*type = AUTH_SOCKET_MASTER;
else if (strcmp(suffix, "userdb") == 0)
*type = AUTH_SOCKET_USERDB;
else
*type = AUTH_SOCKET_CLIENT;
}
auth = auth_find_service(NULL);
switch (*type) {
case AUTH_SOCKET_MASTER:
(void)auth_master_connection_create(auth, conn->fd, FALSE);
break;
case AUTH_SOCKET_USERDB:
(void)auth_master_connection_create(auth, conn->fd, TRUE);
break;
case AUTH_SOCKET_LOGIN_CLIENT:
(void)auth_client_connection_create(auth, conn->fd, TRUE);
break;
case AUTH_SOCKET_CLIENT:
(void)auth_client_connection_create(auth, conn->fd, FALSE);
break;
default:
i_unreached();
}
master_service_client_connection_accept(conn);
}
static void auth_die(void)
{
/* do nothing. auth clients should disconnect soon. */
}
int main(int argc, char *argv[])
{
int c;
master_service = master_service_init("auth", 0, &argc, &argv, "w");
master_service_init_log(master_service, "auth: ");
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'w':
worker = TRUE;
break;
default:
return FATAL_DEFAULT;
}
}
main_preinit();
master_service_init_finish(master_service);
master_service_set_die_callback(master_service, auth_die);
main_init();
master_service_run(master_service, worker ? worker_connected :
client_connected);
main_deinit();
master_service_deinit(&master_service);
return 0;
}