struct auth_settings * auth_settings_read(const char *service, pool_t pool, struct master_service_settings_output *output_r) { static const struct setting_parser_info *set_roots[] = { &auth_setting_parser_info, NULL }; struct master_service_settings_input input; struct setting_parser_context *set_parser; const char *error; memset(&input, 0, sizeof(input)); input.roots = set_roots; input.module = "auth"; input.service = service; if (master_service_settings_read(master_service, &input, output_r, &error) < 0) i_fatal("Error reading configuration: %s", error); set_parser = settings_parser_dup(master_service->set_parser, pool); if (!settings_parser_check(set_parser, pool, &error)) i_unreached(); return settings_parser_get_list(set_parser)[1]; }
int config_export_finish(struct config_export_context **_ctx) { struct config_export_context *ctx = *_ctx; const struct config_module_parser *parser; const char *error; unsigned int i; int ret = 0; *_ctx = NULL; if (ctx->failed) { config_export_free(ctx); return -1; } for (i = 0; ctx->parsers[i].root != NULL; i++) { parser = &ctx->parsers[i]; if (!config_module_want_parser(config_module_parsers, ctx->modules, parser->root)) continue; settings_export(ctx, parser->root, FALSE, settings_parser_get(parser->parser), settings_parser_get_changes(parser->parser)); if ((ctx->flags & CONFIG_DUMP_FLAG_CHECK_SETTINGS) != 0) { settings_parse_var_skip(parser->parser); if (!settings_parser_check(parser->parser, ctx->pool, &error)) { if ((ctx->flags & CONFIG_DUMP_FLAG_CALLBACK_ERRORS) != 0) { ctx->callback(NULL, error, CONFIG_KEY_ERROR, ctx->context); } else { i_error("%s", error); ret = -1; break; } } } } config_export_free(ctx); return ret; }
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; }
int master_service_settings_read(struct master_service *service, const struct master_service_settings_input *input, struct master_service_settings_output *output_r, const char **error_r) { ARRAY(const struct setting_parser_info *) all_roots; const struct setting_parser_info *tmp_root; struct setting_parser_context *parser; struct istream *istream; const char *path = NULL, *error; void **sets; unsigned int i; int ret, fd = -1; time_t now, timeout; bool use_environment, retry; memset(output_r, 0, sizeof(*output_r)); if (getenv("DOVECONF_ENV") == NULL && (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) { retry = service->config_fd != -1; for (;;) { fd = master_service_open_config(service, input, &path, error_r); if (fd == -1) { if (errno == EACCES) output_r->permission_denied = TRUE; return -1; } if (config_send_request(service, input, fd, path, error_r) == 0) break; i_close_fd(&fd); if (!retry) { config_exec_fallback(service, input); return -1; } /* config process died, retry connecting */ retry = FALSE; } } if (service->set_pool != NULL) { if (service->set_parser != NULL) settings_parser_deinit(&service->set_parser); p_clear(service->set_pool); } else { service->set_pool = pool_alloconly_create("master service settings", 16384); } p_array_init(&all_roots, service->set_pool, 8); tmp_root = &master_service_setting_parser_info; array_append(&all_roots, &tmp_root, 1); if (service->want_ssl_settings) { tmp_root = &master_service_ssl_setting_parser_info; array_append(&all_roots, &tmp_root, 1); } if (input->roots != NULL) { for (i = 0; input->roots[i] != NULL; i++) array_append(&all_roots, &input->roots[i], 1); } parser = settings_parser_init_list(service->set_pool, array_idx(&all_roots, 0), array_count(&all_roots), SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS); if (fd != -1) { istream = i_stream_create_fd(fd, (size_t)-1); now = time(NULL); timeout = now + CONFIG_READ_TIMEOUT_SECS; do { alarm(timeout - now); ret = config_read_reply_header(istream, path, service->set_pool, input, output_r, error_r); if (ret == 0) { ret = settings_parse_stream_read(parser, istream); if (ret < 0) *error_r = settings_parser_get_error(parser); } alarm(0); if (ret <= 0) break; /* most likely timed out, but just in case some other signal was delivered early check if we need to continue */ now = time(NULL); } while (now < timeout); i_stream_unref(&istream); if (ret != 0) { if (ret > 0) { *error_r = t_strdup_printf( "Timeout reading config from %s", path); } i_close_fd(&fd); config_exec_fallback(service, input); settings_parser_deinit(&parser); return -1; } if ((service->flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0 && service->config_fd == -1 && input->config_path == NULL) service->config_fd = fd; else i_close_fd(&fd); use_environment = FALSE; } else { use_environment = TRUE; } if (use_environment || service->keep_environment) { if (settings_parse_environ(parser) < 0) { *error_r = t_strdup(settings_parser_get_error(parser)); settings_parser_deinit(&parser); return -1; } } if (array_is_created(&service->config_overrides)) { if (master_service_apply_config_overrides(service, parser, error_r) < 0) { settings_parser_deinit(&parser); return -1; } } if (!settings_parser_check(parser, service->set_pool, &error)) { *error_r = t_strdup_printf("Invalid settings: %s", error); settings_parser_deinit(&parser); return -1; } sets = settings_parser_get_list(parser); service->set = sets[0]; service->set_parser = parser; if (service->set->version_ignore && (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) { /* running standalone. we want to ignore plugin versions. */ service->version_string = NULL; } if (service->set->shutdown_clients) master_service_set_die_with_master(master_service, TRUE); /* if we change any settings afterwards, they're in expanded form. especially all settings from userdb are already expanded. */ settings_parse_set_expanded(service->set_parser, TRUE); return 0; }