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 user_reply_handle(struct mail_storage_service_ctx *ctx, struct mail_storage_service_user *user, const struct auth_user_reply *reply, const char **error_r) { const char *home = reply->home; const char *chroot = reply->chroot; const char *const *str, *line, *p; unsigned int i, count; int ret = 0; if (reply->uid != (uid_t)-1) { if (reply->uid == 0) { *error_r = "userdb returned 0 as uid"; return -1; } user->uid_source = "userdb lookup"; set_keyval(ctx, user, "mail_uid", dec2str(reply->uid)); } if (reply->gid != (uid_t)-1) { user->gid_source = "userdb lookup"; set_keyval(ctx, user, "mail_gid", dec2str(reply->gid)); } if (home != NULL && chroot == NULL && *user->user_set->valid_chroot_dirs != '\0' && (p = strstr(home, "/./")) != NULL) { /* wu-ftpd like <chroot>/./<home> - check only if there's even a possibility of using them (non-empty valid_chroot_dirs) */ chroot = t_strdup_until(home, p); home = p + 2; } if (home != NULL) set_keyval(ctx, user, "mail_home", home); if (chroot != NULL) { if (!validate_chroot(user->user_set, chroot)) { *error_r = t_strdup_printf( "userdb returned invalid chroot directory: %s " "(see valid_chroot_dirs setting)", chroot); return -1; } set_keyval(ctx, user, "mail_chroot", chroot); } user->anonymous = reply->anonymous; str = array_get(&reply->extra_fields, &count); for (i = 0; i < count; i++) { line = str[i]; if (strncmp(line, "system_groups_user="******"nice=", 5) == 0) { #ifdef HAVE_SETPRIORITY int n; if (str_to_int(line + 5, &n) < 0) { i_error("userdb returned invalid nice value %s", line + 5); } else if (n != 0) { if (setpriority(PRIO_PROCESS, 0, n) < 0) i_error("setpriority(%d) failed: %m", n); } #endif } else if (strncmp(line, "auth_token=", 11) == 0) { user->auth_token = p_strdup(user->pool, line+11); } else if (strncmp(line, "auth_user="******"admin=", 6) == 0) { user->admin = line[6] == 'y' || line[6] == 'Y' || line[6] == '1'; } else T_BEGIN { ret = set_line(ctx, user, line); } T_END; if (ret < 0) break; } if (ret < 0) { *error_r = t_strdup_printf("Invalid userdb input '%s': %s", str[i], settings_parser_get_error(user->set_parser)); } 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; }