Beispiel #1
0
int main(int argc, char *argv[])
{
	const enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_UPDATE_PROCTITLE;
	const char *error;

	master_service = master_service_init("ipc", service_flags,
					     &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;
	if (master_service_settings_read_simple(master_service,
						NULL, &error) < 0)
		i_fatal("Error reading configuration: %s", error);
	master_service_init_log(master_service, "ipc: ");

	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);
	ipc_groups_init();
	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);

	clients_destroy_all();
	ipc_groups_deinit();
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #2
0
int main(int argc, char *argv[])
{
	const char *path, *error;

	master_service = master_service_init("config", 0, &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;
	master_service_init_log(master_service, "config: ");

	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);

	config_parse_load_modules();

	path = master_service_get_config_path(master_service);
	if (config_parse_file(path, TRUE, NULL, &error) <= 0)
		i_fatal("%s", error);

	/* notify about our success only after successfully parsing the
	   config file, so if the parsing fails, master won't immediately
	   just recreate this process (and fail again and so on). */
	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);
	config_connections_destroy_all();

	config_filter_deinit(&config_filter);
	module_dir_unload(&modules);
	master_service_deinit(&master_service);
        return 0;
}
static void
mail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
			      struct mail_storage_service_user *user,
			      struct mail_storage_service_privileges *priv)
{
	ctx->log_initialized = TRUE;
	T_BEGIN {
		string_t *str;

		str = t_str_new(256);
		mail_storage_service_var_expand(ctx, str,
			user->user_set->mail_log_prefix,
			user, &user->input, priv);
		user->log_prefix = p_strdup(user->pool, str_c(str));
	} T_END;

	master_service_init_log(ctx->service, user->log_prefix);

	if (master_service_get_client_limit(master_service) == 1)
		i_set_failure_send_prefix(user->log_prefix);
	io_loop_context_add_callbacks(user->ioloop_ctx,
				      mail_storage_service_io_activate_user,
				      mail_storage_service_io_deactivate_user,
				      user);
}
Beispiel #4
0
int main(int argc, char *argv[])
{
	const char *path, *error;

	master_service = master_service_init("config", 0, &argc, &argv, NULL);
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;
	master_service_init_log(master_service, "config: ");

	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);

	master_service_init_finish(master_service);
	config_parse_load_modules();

	path = master_service_get_config_path(master_service);
	if (config_parse_file(path, TRUE, "", &error) <= 0)
		i_fatal("%s", error);

	master_service_run(master_service, client_connected);
	config_connections_destroy_all();

	config_filter_deinit(&config_filter);
	module_dir_unload(&modules);
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #5
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&dict_setting_parser_info,
		NULL
	};
	const char *error;

	master_service = master_service_init("dict", 0, &argc, &argv, NULL);
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;

	if (master_service_settings_read_simple(master_service, set_roots,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);

	master_service_init_log(master_service, "dict: ");
	main_preinit();
	master_service_init_finish(master_service);
	master_service_set_die_callback(master_service, dict_die);

	main_init();
	master_service_run(master_service, client_connected);

	main_deinit();
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #6
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&aggregator_setting_parser_info,
		NULL
	};
	const char *error;

	master_service = master_service_init("aggregator", 0, &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;

	if (master_service_settings_read_simple(master_service, set_roots,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);
	master_service_init_log(master_service, "aggregator: ");

	main_preinit();

	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);
	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);

	notify_connections_destroy_all();
	replicator_connection_destroy(&replicator);
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #7
0
int main(int argc, char *argv[])
{
	const char *error;

	master_service = master_service_init("indexer", 0, &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;

	if (master_service_settings_read_simple(master_service, NULL,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);
	set = master_service_settings_get(master_service);

	master_service_init_log(master_service, "indexer: ");
	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);
	master_service_set_idle_die_callback(master_service, idle_die);

	queue = indexer_queue_init(indexer_client_status_callback);
	indexer_queue_set_listen_callback(queue, queue_listen_callback);
	worker_pool = worker_pool_init("indexer-worker",
				       worker_status_callback);
	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);

	indexer_queue_cancel_all(queue);
	indexer_clients_destroy_all();
	worker_pool_deinit(&worker_pool);
	indexer_queue_deinit(&queue);

	master_service_deinit(&master_service);
        return 0;
}
Beispiel #8
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&doveadm_setting_parser_info,
		NULL
	};
	enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
	const char *error;

	master_service = master_service_init("doveadm", service_flags,
					     &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;

	if (master_service_settings_read_simple(master_service, set_roots,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);

	master_service_init_log(master_service, "doveadm: ");
	main_preinit();
	master_service_set_die_callback(master_service, doveadm_die);

	main_init();
	master_service_init_finish(master_service);
	master_service_run(master_service, client_connected);

	main_deinit();
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #9
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&lda_setting_parser_info,
		&lmtp_setting_parser_info,
		NULL
	};
	enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_USE_SSL_SETTINGS;
	enum mail_storage_service_flags storage_service_flags =
		MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT |
		MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
		MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP |
		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT |
		MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT |
		MAIL_STORAGE_SERVICE_FLAG_AUTOEXPUNGE;
	int c;

	if (IS_STANDALONE()) {
		service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
			MASTER_SERVICE_FLAG_STD_CLIENT;
	} else {
		service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN  ;
	}

	master_service = master_service_init("lmtp", service_flags,
					     &argc, &argv, "D");
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'D':
			storage_service_flags |=
				MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS;
			break;
		default:
			return FATAL_DEFAULT;
		}
	}

	if (t_get_current_dir(&base_dir) < 0)
		i_fatal("getcwd() failed: %m");
	drop_privileges();
	master_service_init_log(master_service,
				t_strdup_printf("lmtp(%s): ", my_pid));

	storage_service = mail_storage_service_init(master_service, set_roots,
						    storage_service_flags);
	restrict_access_allow_coredumps(TRUE);

	main_init();
	master_service_init_finish(master_service);
	master_service_run(master_service, client_connected);

	main_deinit();
	mail_storage_service_deinit(&storage_service);
	master_service_deinit(&master_service);
	return 0;
}
Beispiel #10
0
int main(int argc, char *argv[])
{
	ARRAY_TYPE(const_string) aenvs;
	const char *binary;
	const char *const *envs;
	int c, i;

	master_service = master_service_init("script", 0, &argc, &argv, "+e:");

	t_array_init(&aenvs, 16);
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'e':
			envs = t_strsplit_spaces(optarg,", \t");
			while (*envs != NULL) {
				array_append(&aenvs, envs, 1);
				envs++;
			}
			break;
		default:
			return FATAL_DEFAULT;
		}
	}
	argc -= optind;
	argv += optind;

	array_append_zero(&aenvs);
	accepted_envs = p_strarray_dup(default_pool, array_idx(&aenvs, 0));

	master_service_init_log(master_service, "script: ");
	if (argv[0] == NULL)
		i_fatal("Missing script path");
	restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL);
	restrict_access_allow_coredumps(TRUE);

	master_service_init_finish(master_service);
	master_service_set_service_count(master_service, 1);

	if (argv[0][0] == '/')
		binary = argv[0];
	else
		binary = t_strconcat(PKG_LIBEXECDIR"/", argv[0], NULL);

	i_array_init(&exec_args, argc + 16);
	array_append(&exec_args, &binary, 1);
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];

		array_append(&exec_args, &arg, 1);
	}

	master_service_run(master_service, client_connected);
	array_free(&exec_args);
	i_free(accepted_envs);
	master_service_deinit(&master_service);
	return 0;
}
Beispiel #11
0
int main(int argc, char *argv[])
{
	enum master_service_flags flags = 0;
	int i, c;

	if (getenv(MASTER_IS_PARENT_ENV) == NULL)
		flags |= MASTER_SERVICE_FLAG_STANDALONE;

	master_service = master_service_init("script-login", flags,
					     &argc, &argv, "+d");
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'd':
			drop_to_userdb_privileges = TRUE;
			break;
		default:
			return FATAL_DEFAULT;
		}
	}
	argc -= optind;
	argv += optind;

	master_service_init_log(master_service, "script-login: "******"Missing script path");
		exec_args = i_new(const char *, argc + 2);
		for (i = 0; i < argc; i++)
			exec_args[i] = argv[i];
		exec_args[i] = PKG_LIBEXECDIR"/script-login";
		exec_args[i+1] = NULL;

		if (exec_args[0][0] != '/') {
			exec_args[0] = t_strconcat(PKG_LIBEXECDIR"/",
						   exec_args[0], NULL);
		}

		master_service_run(master_service, client_connected);
	}
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #12
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&stats_setting_parser_info,
		NULL
	};
	const enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_NO_IDLE_DIE |
		MASTER_SERVICE_FLAG_UPDATE_PROCTITLE;
	const char *error;
	void **sets;

	master_service = master_service_init("stats", service_flags,
					     &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;
	if (master_service_settings_read_simple(master_service, set_roots,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);
	master_service_init_log(master_service, "stats: ");

	main_preinit();

	sets = master_service_settings_get_others(master_service);
	stats_settings = sets[0];

	mail_commands_init();
	mail_sessions_init();
	mail_users_init();
	mail_domains_init();
	mail_ips_init();
	mail_global_init();

	master_service_init_finish(master_service);
	master_service_run(master_service, client_connected);

	clients_destroy_all();
	mail_commands_deinit();
	mail_sessions_deinit();
	mail_users_deinit();
	mail_domains_deinit();
	mail_ips_deinit();
	mail_global_deinit();

	if (mail_server_conn != NULL)
		mail_server_connection_destroy(&mail_server_conn);

	module_dir_unload(&modules);
	i_assert(global_used_memory == 0);
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #13
0
int main(int argc, char *argv[])
{
	master_service = master_service_init("dns-client", 0, &argc, &argv, "");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;

	master_service_init_log(master_service, "dns-client: ");
	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);

	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);
	if (dns_client != NULL)
		dns_client_destroy(&dns_client);

	master_service_deinit(&master_service);
        return 0;
}
Beispiel #14
0
int main(int argc, char *argv[])
{
	enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
	enum mail_storage_service_flags storage_service_flags =
		MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT |
		MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
		MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP |
		MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT;
	int c;

	master_service = master_service_init("indexer-worker", service_flags,
					     &argc, &argv, "D");
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'D':
			storage_service_flags |=
				MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS;
			break;
		default:
			return FATAL_DEFAULT;
		}
	}

	drop_privileges();
	master_service_init_log(master_service, "indexer-worker: ");

	storage_service = mail_storage_service_init(master_service, NULL,
						    storage_service_flags);
	restrict_access_allow_coredumps(TRUE);
	master_service_init_finish(master_service);

	master_service_run(master_service, client_connected);

	if (master_conn != NULL)
		master_connection_destroy(&master_conn);
	mail_storage_service_deinit(&storage_service);
	master_service_deinit(&master_service);
        return 0;
}
Beispiel #15
0
int main(int argc, char *argv[])
{
	const char *binary;
	int i;

	master_service = master_service_init("script", 0, &argc, &argv, "+");
	if (master_getopt(master_service) > 0)
		return FATAL_DEFAULT;
	argc -= optind;
	argv += optind;

	master_service_init_log(master_service, "script: ");
	if (argv[0] == NULL)
		i_fatal("Missing script path");
	restrict_access_by_env(NULL, FALSE);
	restrict_access_allow_coredumps(TRUE);

	master_service_init_finish(master_service);
	master_service_set_service_count(master_service, 1);

	if (argv[0][0] == '/')
		binary = argv[0];
	else
		binary = t_strconcat(PKG_LIBEXECDIR"/", argv[0], NULL);

	i_array_init(&exec_args, argc + 16);
	array_append(&exec_args, &binary, 1);
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];

		array_append(&exec_args, &arg, 1);
	}

	master_service_run(master_service, client_connected);
	master_service_deinit(&master_service);
	return 0;
}
static int
mail_storage_service_lookup_real(struct mail_storage_service_ctx *ctx,
				 const struct mail_storage_service_input *input,
				 bool update_log_prefix,
				 struct mail_storage_service_user **user_r,
				 const char **error_r)
{
	enum mail_storage_service_flags flags;
	struct mail_storage_service_user *user;
	const char *username = input->username;
	const struct setting_parser_info *user_info;
	const struct mail_user_settings *user_set;
	const char *const *userdb_fields, *error;
	struct auth_user_reply reply;
	const struct setting_parser_context *set_parser;
	void **sets;
	pool_t user_pool, temp_pool;
	int ret = 1;

	user_pool = pool_alloconly_create(MEMPOOL_GROWING"mail storage service user", 1024*6);
	flags = mail_storage_service_input_get_flags(ctx, input);

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
	    geteuid() != 0) {
		/* we dropped privileges only temporarily. switch back to root
		   before reading settings, so we'll definitely have enough
		   permissions to connect to the config socket. */
		mail_storage_service_seteuid_root();
	}

	if (mail_storage_service_read_settings(ctx, input, user_pool,
					       &user_info, &set_parser,
					       &error) < 0) {
		if (ctx->config_permission_denied) {
			/* just restart and maybe next time we will open the
			   config socket before dropping privileges */
			i_fatal("%s", error);
		}
		i_error("%s", error);
		pool_unref(&user_pool);
		*error_r = MAIL_ERRSTR_CRITICAL_MSG;
		return -1;
	}

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
	    !ctx->log_initialized) {
		/* initialize logging again, in case we only read the
		   settings for the first above */
		ctx->log_initialized = TRUE;
		master_service_init_log(ctx->service,
			t_strconcat(ctx->service->name, ": ", NULL));
		update_log_prefix = TRUE;
	}
	sets = master_service_settings_parser_get_others(master_service,
							 set_parser);
	user_set = sets[0];

	if (update_log_prefix)
		mail_storage_service_set_log_prefix(ctx, user_set, NULL, input, NULL);

	if (ctx->conn == NULL)
		mail_storage_service_first_init(ctx, user_info, user_set);
	/* load global plugins */
	if (mail_storage_service_load_modules(ctx, user_info, user_set, &error) < 0) {
		i_error("%s", error);
		pool_unref(&user_pool);
		*error_r = MAIL_ERRSTR_CRITICAL_MSG;
		return -1;
	}

	if (ctx->userdb_next_pool == NULL)
		temp_pool = pool_alloconly_create("userdb lookup", 2048);
	else {
		temp_pool = ctx->userdb_next_pool;
		ctx->userdb_next_pool = NULL;
		pool_ref(temp_pool);
	}
	if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
		ret = service_auth_userdb_lookup(ctx, input, temp_pool,
						 &username, &userdb_fields,
						 error_r);
		if (ret <= 0) {
			pool_unref(&temp_pool);
			pool_unref(&user_pool);
			return ret;
		}
		if (ctx->userdb_next_fieldsp != NULL)
			*ctx->userdb_next_fieldsp = userdb_fields;
	} else {
		userdb_fields = input->userdb_fields;
	}

	user = p_new(user_pool, struct mail_storage_service_user, 1);
	user->service_ctx = ctx;
	user->pool = user_pool;
	user->input = *input;
	user->input.userdb_fields = userdb_fields == NULL ? NULL :
		p_strarray_dup(user_pool, userdb_fields);
	user->input.username = p_strdup(user_pool, username);
	user->input.session_id = p_strdup(user_pool, input->session_id);
	if (user->input.session_id == NULL) {
		user->input.session_id =
			mail_storage_service_generate_session_id(user_pool,
				input->session_id_prefix);
	}
	user->user_info = user_info;
	user->flags = flags;

	user->set_parser = settings_parser_dup(set_parser, user_pool);

	sets = master_service_settings_parser_get_others(master_service,
							 user->set_parser);
	user->user_set = sets[0];
	user->gid_source = "mail_gid setting";
	user->uid_source = "mail_uid setting";

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
		(void)settings_parse_line(user->set_parser, "mail_debug=yes");

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
		const char *home = getenv("HOME");
		if (home != NULL)
			set_keyval(ctx, user, "mail_home", home);
	}

	if (userdb_fields != NULL) {
		auth_user_fields_parse(userdb_fields, temp_pool, &reply);
		array_sort(&reply.extra_fields, extra_field_key_cmp_p);
		if (user_reply_handle(ctx, user, &reply, &error) < 0) {
			i_error("Invalid settings in userdb: %s", error);
			*error_r = ERRSTR_INVALID_USER_SETTINGS;
			ret = -2;
		}
	}
	if (ret > 0 && !settings_parser_check(user->set_parser, user_pool, &error)) {
		i_error("Invalid settings (probably caused by userdb): %s", error);
		*error_r = ERRSTR_INVALID_USER_SETTINGS;
		ret = -2;
	}
	pool_unref(&temp_pool);

	/* load per-user plugins */
	if (ret > 0) {
		if (mail_storage_service_load_modules(ctx, user_info,
						      user->user_set,
						      &error) < 0) {
			i_error("%s", error);
			*error_r = MAIL_ERRSTR_CRITICAL_MSG;
			ret = -2;
		}
	}

	*user_r = user;
	return ret;
}
struct mail_storage_service_ctx *
mail_storage_service_init(struct master_service *service,
			  const struct setting_parser_info *set_roots[],
			  enum mail_storage_service_flags flags)
{
	struct mail_storage_service_ctx *ctx;
	const char *version;
	pool_t pool;
	unsigned int count;

	version = master_service_get_version_string(service);
	if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
		i_fatal("Version mismatch: libdovecot-storage.so is '%s', "
			"while the running Dovecot binary is '%s'",
			PACKAGE_VERSION, version);
	}

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
	    getuid() != 0) {
		/* service { user } isn't root. the permission drop can't be
		   temporary. */
		flags &= ~MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
	}

	(void)umask(0077);
	io_loop_set_time_moved_callback(current_ioloop,
					mail_storage_service_time_moved);

        mail_storage_init();
	mail_storage_register_all();
	mailbox_list_register_all();

	pool = pool_alloconly_create("mail storage service", 2048);
	ctx = p_new(pool, struct mail_storage_service_ctx, 1);
	ctx->pool = pool;
	ctx->service = service;
	ctx->flags = flags;

	/* @UNSAFE */
	if (set_roots == NULL)
		count = 0;
	else
		for (count = 0; set_roots[count] != NULL; count++) ;
	ctx->set_roots =
		p_new(pool, const struct setting_parser_info *, count + 2);
	ctx->set_roots[0] = &mail_user_setting_parser_info;
	if (set_roots != NULL) {
		memcpy(ctx->set_roots + 1, set_roots,
		       sizeof(*ctx->set_roots) * count);
	}

	/* do all the global initialization. delay initializing plugins until
	   we drop privileges the first time. */
	if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
		/* note: we may not have read any settings yet, so this logging
		   may still be going to wrong location */
		ctx->default_log_prefix =
			p_strconcat(pool, service->name, ": ", NULL);
		master_service_init_log(service, ctx->default_log_prefix);
	}
	dict_drivers_register_builtin();
	return ctx;
}
Beispiel #18
0
int main(int argc, char *argv[])
{
	static const struct setting_parser_info *set_roots[] = {
		&imap_urlauth_worker_setting_parser_info,
		NULL
	};
	enum master_service_flags service_flags = 0;
	enum mail_storage_service_flags storage_service_flags =
		MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
	ARRAY_TYPE (const_string) access_apps;
	const char *access_user = NULL;
	int c;

	if (IS_STANDALONE()) {
		service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
			MASTER_SERVICE_FLAG_STD_CLIENT;
	} else {
		service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
		storage_service_flags |=
			MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
	}

	master_service = master_service_init("imap-urlauth-worker", service_flags,
					     &argc, &argv, "a:");

	t_array_init(&access_apps, 4);
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'a': {
			const char *app = t_strdup(optarg);

			array_append(&access_apps, &app, 1);
			break;
		}
		default:
			return FATAL_DEFAULT;
		}
	}

	if ( optind < argc ) {
		access_user = argv[optind++];
	}

	if (optind != argc) {
		i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
	}

	master_service_init_log(master_service,
				t_strdup_printf("imap-urlauth[%s]: ", my_pid));

	master_service_init_finish(master_service);
	master_service_set_die_callback(master_service, imap_urlauth_worker_die);

	random_init();
	storage_service =
		mail_storage_service_init(master_service,
					  set_roots, storage_service_flags);

	/* fake that we're running, so we know if client was destroyed
	   while handling its initial input */
	io_loop_set_running(current_ioloop);

	if (IS_STANDALONE()) {
		T_BEGIN {
			if (array_count(&access_apps) > 0) {
				(void)array_append_space(&access_apps);
				main_stdio_run(access_user, array_idx(&access_apps,0));
			} else {
				main_stdio_run(access_user, NULL);
			}
		} T_END;
	} else {
Beispiel #19
0
static void client_connected(struct master_service_connection *conn)
{
	enum mail_storage_service_flags flags =
		MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
	string_t *instr, *keys;
	const char **args, *key, *value, *error, *version_line, *data_line;
	struct mail_storage_service_ctx *service_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *user;
	char buf[1024];
	unsigned int i, socket_count;
	int fd = -1;
	ssize_t ret;

	alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS);

	net_set_nonblock(conn->fd, FALSE);
	instr = t_str_new(1024);
	ret = fd_read(conn->fd, buf, sizeof(buf), &fd);
	while (ret > 0) {
		str_append_n(instr, buf, ret);
		if (buf[ret-1] == '\n' &&
		    strchr(str_c(instr), '\n')[1] != '\0') {
			str_truncate(instr, str_len(instr)-1);
			break;
		}

		ret = read(conn->fd, buf, sizeof(buf));
	}

	version_line = str_c(instr);
	data_line = strchr(version_line, '\n');
	if (data_line != NULL)
		version_line = t_strdup_until(version_line, data_line++);
	else
		version_line = NULL;

	if (ret > 0 || version_line != NULL) {
		if (version_line == NULL ||
		    !version_string_verify(version_line, "script-login",
				SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) {
			i_fatal("Client not compatible with this binary "
				"(connecting to wrong socket?)");
		}
	}

	if (ret <= 0) {
		if (ret < 0)
			i_fatal("read() failed: %m");
		else
			i_fatal("read() failed: disconnected");
	}
	if (fd == -1)
		i_fatal("client fd not received");

	alarm(0);

	/* put everything to environment */
	env_clean();
	keys = t_str_new(256);
	args = t_strsplit_tab(data_line);

	if (str_array_length(args) < 3)
		i_fatal("Missing input fields");

	i = 0;
	memset(&input, 0, sizeof(input));
	input.module = "mail"; /* need to get mail_uid, mail_gid */
	input.service = "script-login";
	(void)net_addr2ip(args[i++], &input.local_ip);
	(void)net_addr2ip(args[i++], &input.remote_ip);
	input.username = args[i++];
	input.userdb_fields = args + i;

	env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL));
	env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL));
	env_put(t_strconcat("USER="******"%s ", key);
		}
	}
	env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL));

	master_service_init_log(master_service,
		t_strdup_printf("script-login(%s): ", input.username));

	if (drop_to_userdb_privileges) {
		service_ctx = mail_storage_service_init(master_service, NULL, flags);
		if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0)
			i_fatal("%s", error);
		mail_storage_service_restrict_setenv(service_ctx, user);
		/* we can't exec anything in a chroot */
		env_remove("RESTRICT_CHROOT");
		restrict_access_by_env(getenv("HOME"), TRUE);
	}

	if (dup2(fd, STDIN_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (dup2(fd, STDOUT_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (close(fd) < 0)
		i_fatal("close() failed: %m");
	if (conn->fd != SCRIPT_COMM_FD) {
		if (dup2(conn->fd, SCRIPT_COMM_FD) < 0)
			i_fatal("dup2() failed: %m");
		if (close(conn->fd) < 0)
			i_fatal("close() failed: %m");
	}

	/* close all listener sockets */
	socket_count = master_service_get_socket_count(master_service);
	for (i = 0; i < socket_count; i++) {
		if (close(MASTER_LISTEN_FD_FIRST + i) < 0)
			i_error("close(listener) failed: %m");
	}
	if (close(MASTER_STATUS_FD) < 0)
		i_error("close(status) failed: %m");

	execvp_const(exec_args[0], exec_args);
}