static int master_service_apply_config_overrides(struct master_service *service, struct setting_parser_context *parser, const char **error_r) { const char *const *overrides; unsigned int i, count; overrides = array_get(&service->config_overrides, &count); for (i = 0; i < count; i++) { if (settings_parse_line(parser, overrides[i]) < 0) { *error_r = t_strdup_printf( "Invalid -o parameter %s: %s", overrides[i], settings_parser_get_error(parser)); return -1; } settings_parse_set_key_expandeded(parser, service->set_pool, t_strcut(overrides[i], '=')); } return 0; }
static void set_keyval(struct mail_storage_service_ctx *ctx, struct mail_storage_service_user *user, const char *key, const char *value) { struct setting_parser_context *set_parser = user->set_parser; const char *str; if (master_service_set_has_config_override(ctx->service, key)) { /* this setting was already overridden with -o parameter */ if (mail_user_set_get_mail_debug(user->user_info, user->user_set)) { i_debug("Ignoring overridden (-o) userdb setting: %s", key); } return; } str = t_strconcat(key, "=", value, NULL); if (settings_parse_line(set_parser, str) < 0) { i_fatal("Invalid userdb input '%s': %s", str, settings_parser_get_error(set_parser)); } }
static int set_line(struct mail_storage_service_ctx *ctx, struct mail_storage_service_user *user, const char *line) { struct setting_parser_context *set_parser = user->set_parser; bool mail_debug; const char *key, *orig_key, *append_value = NULL; unsigned int len; int ret; mail_debug = mail_user_set_get_mail_debug(user->user_info, user->user_set); if (strchr(line, '=') == NULL) line = t_strconcat(line, "=yes", NULL); orig_key = key = t_strcut(line, '='); len = strlen(key); if (len > 0 && key[len-1] == '+') { /* key+=value */ append_value = line + len + 1; key = t_strndup(key, len-1); } if (!settings_parse_is_valid_key(set_parser, key)) { /* assume it's a plugin setting */ key = t_strconcat("plugin/", key, NULL); line = t_strconcat("plugin/", line, NULL); } if (master_service_set_has_config_override(ctx->service, key)) { /* this setting was already overridden with -o parameter */ if (mail_debug) { i_debug("Ignoring overridden (-o) userdb setting: %s", key); } return 1; } if (append_value != NULL) { const void *value; enum setting_type type; value = settings_parse_get_value(set_parser, key, &type); if (type == SET_STR) { const char *const *strp = value; line = t_strdup_printf("%s=%s%s", key, *strp, append_value); } else { i_error("Ignoring %s userdb setting. " "'+' can only be used for strings.", orig_key); } } ret = settings_parse_line(set_parser, line); if (mail_debug && ret >= 0) { if (strstr(key, "pass") != NULL) { /* possibly a password field (e.g. imapc_password). hide the value. */ line = t_strconcat(key, "=<hidden>", NULL); } i_debug(ret == 0 ? "Unknown userdb setting: %s" : "Added userdb setting: %s", line); } 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; }
static int cmd_dsync_run_local(struct dsync_cmd_context *ctx, struct mail_user *user, struct dsync_brain *brain, struct dsync_ibc *ibc2, bool *changes_during_sync_r) { struct dsync_brain *brain2; struct mail_user *user2; struct setting_parser_context *set_parser; const char *set_line, *location; bool brain1_running, brain2_running, changed1, changed2; int ret; if (ctx->local_location_from_arg) location = ctx->ctx.args[0]; else { i_assert(ctx->local_location != NULL); location = ctx->local_location; } i_set_failure_prefix("dsync(%s): ", user->username); /* update mail_location and create another user for the second location. */ set_parser = mail_storage_service_user_get_settings_parser(ctx->ctx.cur_service_user); set_line = t_strconcat("mail_location=", location, NULL); if (settings_parse_line(set_parser, set_line) < 0) i_unreached(); ret = mail_storage_service_next(ctx->ctx.storage_service, ctx->ctx.cur_service_user, &user2); if (ret < 0) { ctx->ctx.exit_code = ret == -1 ? EX_TEMPFAIL : EX_CONFIG; return -1; } doveadm_user_init_dsync(user2); if (mail_namespaces_get_root_sep(user->namespaces) != mail_namespaces_get_root_sep(user2->namespaces)) { i_error("Mail locations must use the same " "virtual mailbox hierarchy separator " "(specify separator for the default namespace)"); ctx->ctx.exit_code = EX_CONFIG; mail_user_unref(&user2); return -1; } if (paths_are_equal(user, user2, MAILBOX_LIST_PATH_TYPE_MAILBOX) && paths_are_equal(user, user2, MAILBOX_LIST_PATH_TYPE_INDEX)) { i_error("Both source and destination mail_location " "points to same directory: %s", mailbox_list_get_root_forced(user->namespaces->list, MAILBOX_LIST_PATH_TYPE_MAILBOX)); ctx->ctx.exit_code = EX_CONFIG; mail_user_unref(&user2); return -1; } brain2 = dsync_brain_slave_init(user2, ibc2, TRUE); mail_user_unref(&user2); brain1_running = brain2_running = TRUE; changed1 = changed2 = TRUE; while (brain1_running || brain2_running) { if (dsync_brain_has_failed(brain) || dsync_brain_has_failed(brain2)) break; i_assert(changed1 || changed2); brain1_running = dsync_brain_run(brain, &changed1); brain2_running = dsync_brain_run(brain2, &changed2); } *changes_during_sync_r = dsync_brain_has_unexpected_changes(brain2); if (dsync_brain_deinit(&brain2) < 0) { ctx->ctx.exit_code = EX_TEMPFAIL; return -1; } return 0; }
int master_service_set(struct master_service *service, const char *line) { return settings_parse_line(service->set_parser, line); }