<commit_before>/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */

#include "auth-common.h"
#include "array.h"
#include "ioloop.h"
#include "network.h"
#include "lib-signals.h"
#include "restrict-access.h"
#include "child-wait.h"
#include "sql-api.h"
#include "module-dir.h"
#include "randgen.h"
#include "process-title.h"
#include "settings-parser.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "master-interface.h"
#include "password-scheme.h"
#include "passdb-cache.h"
#include "mech.h"
#include "auth.h"
#include "auth-penalty.h"
#include "auth-request-handler.h"
#include "auth-worker-server.h"
#include "auth-worker-client.h"
#include "auth-master-connection.h"
#include "auth-client-connection.h"

#include <unistd.h>

#define AUTH_PENALTY_ANVIL_PATH "anvil-auth-penalty"

enum auth_socket_type {
	AUTH_SOCKET_UNKNOWN = 0,
	AUTH_SOCKET_CLIENT,
	AUTH_SOCKET_LOGIN_CLIENT,
	AUTH_SOCKET_MASTER,
	AUTH_SOCKET_USERDB
};

bool worker = FALSE, shutdown_request = FALSE;
time_t process_start_time;
struct auth_penalty *auth_penalty;

static pool_t auth_set_pool;
static struct module *modules = NULL;
static struct mechanisms_register *mech_reg;
static ARRAY_DEFINE(listen_fd_types, enum auth_socket_type);

void auth_refresh_proctitle(void)
{
	if (!global_auth_settings->verbose_proctitle)
		return;

	process_title_set(t_strdup_printf(
		"[%u wait, %u passdb, %u userdb]",
		auth_request_state_count[AUTH_REQUEST_STATE_NEW] +
		auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] +
		auth_request_state_count[AUTH_REQUEST_STATE_FINISHED],
		auth_request_state_count[AUTH_REQUEST_STATE_PASSDB],
		auth_request_state_count[AUTH_REQUEST_STATE_USERDB]));
}

static const char *const *read_global_settings(void)
{
	struct master_service_settings_output set_output;
	const char **services;
	unsigned int i, count;

	auth_set_pool = pool_alloconly_create("auth settings", 8192);
	global_auth_settings =
		auth_settings_read(NULL, auth_set_pool, &set_output);

	/* strdup() the service names, because they're allocated from
	   set parser pool, and we'll later clear it. */
	count = str_array_length(set_output.specific_services);
	services = p_new(auth_set_pool, const char *, count + 1);
	for (i = 0; i < count; i++) {
		services[i] = p_strdup(auth_set_pool,
				       set_output.specific_services[i]);
	}
	return services;
}

static void main_preinit(void)
{
	struct module_dir_load_settings mod_set;
	const char *const *services;

	/* Open /dev/urandom before chrooting */
	random_init();

	/* Load built-in SQL drivers (if any) */
	sql_drivers_init();
	sql_drivers_register_all();

	/* Initialize databases so their configuration files can be readable
	   only by root. Also load all modules here. */
	passdbs_init();
	userdbs_init();

	services = read_global_settings();

	memset(&mod_set, 0, sizeof(mod_set));
	mod_set.version = master_service_get_version_string(master_service);
	mod_set.require_init_funcs = TRUE;
	mod_set.debug = global_auth_settings->debug;

	modules = module_dir_load(AUTH_MODULE_DIR, NULL, &mod_set);
	module_dir_init(modules);

	auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
	mech_init(global_auth_settings);
	mech_reg = mech_register_init(global_auth_settings);
	auths_preinit(global_auth_settings, auth_set_pool,
		      mech_reg, services);

	/* Password lookups etc. may require roots, allow it. */
	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);
}

static void main_init(void)
{
	i_array_init(&listen_fd_types, 8);

        process_start_time = ioloop_time;

	/* If auth caches aren't used, just ignore these signals */
	lib_signals_ignore(SIGHUP, TRUE);
	lib_signals_ignore(SIGUSR2, TRUE);

	child_wait_init();
	password_schemes_init();
	auth_worker_server_init();
	auths_init();
	auth_request_handler_init();
	auth_master_connections_init();
	auth_client_connections_init();

	if (worker) {
		/* workers have only a single connection from the master
		   auth process */
		master_service_set_client_limit(master_service, 1);
	} else {
		/* caching is handled only by the main auth process */
		passdb_cache_init(global_auth_settings);
	}
	auth_refresh_proctitle();
}

static void main_deinit(void)
{
	if (auth_worker_client != NULL)
		auth_worker_client_destroy(&auth_worker_client);
	else
		auth_request_handler_flush_failures(TRUE);

	auth_client_connections_deinit();
	auth_master_connections_deinit();
        auth_worker_server_deinit();

	auths_deinit();
	auth_request_handler_deinit();
	passdb_cache_deinit();

	mech_register_deinit(&mech_reg);
	mech_deinit(global_auth_settings);
	auth_penalty_deinit(&auth_penalty);

	/* allow modules to unregister their dbs/drivers/etc. before freeing
	   the whole data structures containing them. */
	module_dir_unload(&modules);
<commit_msg>auth: Deinit auth request handler before pass/userdbs<commit_after>/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */

#include "auth-common.h"
#include "array.h"
#include "ioloop.h"
#include "network.h"
#include "lib-signals.h"
#include "restrict-access.h"
#include "child-wait.h"
#include "sql-api.h"
#include "module-dir.h"
#include "randgen.h"
#include "process-title.h"
#include "settings-parser.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "master-interface.h"
#include "password-scheme.h"
#include "passdb-cache.h"
#include "mech.h"
#include "auth.h"
#include "auth-penalty.h"
#include "auth-request-handler.h"
#include "auth-worker-server.h"
#include "auth-worker-client.h"
#include "auth-master-connection.h"
#include "auth-client-connection.h"

#include <unistd.h>

#define AUTH_PENALTY_ANVIL_PATH "anvil-auth-penalty"

enum auth_socket_type {
	AUTH_SOCKET_UNKNOWN = 0,
	AUTH_SOCKET_CLIENT,
	AUTH_SOCKET_LOGIN_CLIENT,
	AUTH_SOCKET_MASTER,
	AUTH_SOCKET_USERDB
};

bool worker = FALSE, shutdown_request = FALSE;
time_t process_start_time;
struct auth_penalty *auth_penalty;

static pool_t auth_set_pool;
static struct module *modules = NULL;
static struct mechanisms_register *mech_reg;
static ARRAY_DEFINE(listen_fd_types, enum auth_socket_type);

void auth_refresh_proctitle(void)
{
	if (!global_auth_settings->verbose_proctitle)
		return;

	process_title_set(t_strdup_printf(
		"[%u wait, %u passdb, %u userdb]",
		auth_request_state_count[AUTH_REQUEST_STATE_NEW] +
		auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] +
		auth_request_state_count[AUTH_REQUEST_STATE_FINISHED],
		auth_request_state_count[AUTH_REQUEST_STATE_PASSDB],
		auth_request_state_count[AUTH_REQUEST_STATE_USERDB]));
}

static const char *const *read_global_settings(void)
{
	struct master_service_settings_output set_output;
	const char **services;
	unsigned int i, count;

	auth_set_pool = pool_alloconly_create("auth settings", 8192);
	global_auth_settings =
		auth_settings_read(NULL, auth_set_pool, &set_output);

	/* strdup() the service names, because they're allocated from
	   set parser pool, and we'll later clear it. */
	count = str_array_length(set_output.specific_services);
	services = p_new(auth_set_pool, const char *, count + 1);
	for (i = 0; i < count; i++) {
		services[i] = p_strdup(auth_set_pool,
				       set_output.specific_services[i]);
	}
	return services;
}

static void main_preinit(void)
{
	struct module_dir_load_settings mod_set;
	const char *const *services;

	/* Open /dev/urandom before chrooting */
	random_init();

	/* Load built-in SQL drivers (if any) */
	sql_drivers_init();
	sql_drivers_register_all();

	/* Initialize databases so their configuration files can be readable
	   only by root. Also load all modules here. */
	passdbs_init();
	userdbs_init();

	services = read_global_settings();

	memset(&mod_set, 0, sizeof(mod_set));
	mod_set.version = master_service_get_version_string(master_service);
	mod_set.require_init_funcs = TRUE;
	mod_set.debug = global_auth_settings->debug;

	modules = module_dir_load(AUTH_MODULE_DIR, NULL, &mod_set);
	module_dir_init(modules);

	auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
	mech_init(global_auth_settings);
	mech_reg = mech_register_init(global_auth_settings);
	auths_preinit(global_auth_settings, auth_set_pool,
		      mech_reg, services);

	/* Password lookups etc. may require roots, allow it. */
	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);
}

static void main_init(void)
{
	i_array_init(&listen_fd_types, 8);

        process_start_time = ioloop_time;

	/* If auth caches aren't used, just ignore these signals */
	lib_signals_ignore(SIGHUP, TRUE);
	lib_signals_ignore(SIGUSR2, TRUE);

	child_wait_init();
	password_schemes_init();
	auth_worker_server_init();
	auths_init();
	auth_request_handler_init();
	auth_master_connections_init();
	auth_client_connections_init();

	if (worker) {
		/* workers have only a single connection from the master
		   auth process */
		master_service_set_client_limit(master_service, 1);
	} else {
		/* caching is handled only by the main auth process */
		passdb_cache_init(global_auth_settings);
	}
	auth_refresh_proctitle();
}

static void main_deinit(void)
{
	if (auth_worker_client != NULL)
		auth_worker_client_destroy(&auth_worker_client);
	else
		auth_request_handler_flush_failures(TRUE);

	auth_client_connections_deinit();
	auth_master_connections_deinit();
        auth_worker_server_deinit();

	auth_request_handler_deinit();
	/* there may still be some async auth requests left, but above
	   functions should have marked all of them as destroyed. pass/userdb
	   deinits should abort the pending requests, which still triggers
	   callbacks, which should avoid crashes by checking the destroyed
	   state. */
	auths_deinit();
	passdb_cache_deinit();

	mech_register_deinit(&mech_reg);
	mech_deinit(global_auth_settings);
	auth_penalty_deinit(&auth_penalty);

	/* allow modules to unregister their dbs/drivers/etc. before freeing
	   the whole data structures containing them. */
	module_dir_unload(&modules);

{'fraction_non_alphanumeric': 0.10403929036784605, 'fraction_numerical': 0.003808760148341185, 'mean_word_length': 6.026760563380281, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1017190', 'n_tokens_mistral': 3642, 'n_tokens_neox': 3469, 'n_words': 726}