master-settings.c revision c3e30ffd8ac58854cc1162c33b4019a6d710b013
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa/* Copyright (C) 2002 Timo Sirainen */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "common.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "array.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "str.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "istream.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "fd-close-on-exec.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "safe-mkdir.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "mkdir-parents.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "unlink-directory.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "syslog-util.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "mail-process.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "master-login-interface.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "settings.h"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <stdio.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <stddef.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <stdlib.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <dirent.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <unistd.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <fcntl.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <sys/stat.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <sys/wait.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <pwd.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include <grp.h>
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksaenum settings_type {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_ROOT,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_SERVER,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_AUTH,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_AUTH_SOCKET,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_AUTH_PASSDB,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_AUTH_USERDB,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_NAMESPACE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_SOCKET,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_DICT,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa SETTINGS_TYPE_PLUGIN
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct settings_parse_ctx {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa enum settings_type type, parent_type;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa enum mail_protocol protocol;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct server_settings *root, *server;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_settings *auth;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct socket_settings *socket;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_socket_settings *auth_socket;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_passdb_settings *auth_passdb;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_userdb_settings *auth_userdb;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct namespace_settings *namespace;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa int level;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#include "master-settings-defs.c"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_STR
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_INT
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_BOOL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_STR(name) DEF_STRUCT_STR(name, auth_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_INT(name) DEF_STRUCT_INT(name, auth_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, auth_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def auth_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(mechanisms),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(realms),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(default_realm),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(cache_size),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(cache_ttl),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(executable),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(user),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(chroot),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(username_chars),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(username_translation),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(username_format),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(master_user_separator),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(anonymous_username),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(krb5_keytab),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(gssapi_hostname),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(verbose),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(debug),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(debug_passwords),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(ssl_require_client_cert),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(ssl_username_from_cert),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(count),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(worker_max_count),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(process_size),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_STR
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_INT
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_BOOL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_STR(name) DEF_STRUCT_STR(name, socket_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_INT(name) DEF_STRUCT_INT(name, socket_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, socket_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def socket_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(path),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_INT(mode),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(user),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(group),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def auth_socket_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STRUCT_STR(type, auth_socket_settings),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_STR
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_INT
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_BOOL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_STR(name) DEF_STRUCT_STR(name, auth_passdb_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_INT(name) DEF_STRUCT_INT(name, auth_passdb_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, auth_passdb_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def auth_passdb_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(driver),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(args),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(deny),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(pass),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(master),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def auth_userdb_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STRUCT_STR(driver, auth_userdb_settings),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STRUCT_STR(args, auth_userdb_settings),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_STR
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_INT
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#undef DEF_BOOL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_STR(name) DEF_STRUCT_STR(name, namespace_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_INT(name) DEF_STRUCT_INT(name, namespace_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, namespace_settings)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic struct setting_def namespace_setting_defs[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(type),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(separator),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(prefix),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_STR(location),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(inbox),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(hidden),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DEF_BOOL(list),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa { 0, NULL, 0 }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct settings default_settings = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(server) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(protocol) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* common */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(base_dir) PKG_RUNDIR,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(log_path) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(info_log_path) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(syslog_facility) "mail",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* general */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(protocols) "imap imaps",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(listen) "*",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_listen) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_disable) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_ca_file) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_key_password) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_parameters_regenerate) 168,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_cipher_list) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_verify_client_cert) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(disable_plaintext_auth) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(verbose_ssl) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(shutdown_clients) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(nfs_check) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(version_ignore) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* login */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_dir) "login",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_executable) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_user) "dovecot",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_greeting) "Dovecot ready.",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_log_format) "%$: %s",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_process_per_connection) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_chroot) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_greeting_capability) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_process_size) 32,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_processes_count) 3,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_max_processes_count) 128,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(login_max_connections) 256,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* mail */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(valid_chroot_dirs) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_chroot) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(max_mail_processes) 1024,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_max_userip_connections) 10,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(verbose_proctitle) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(first_valid_uid) 500,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(last_valid_uid) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(first_valid_gid) 1,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(last_valid_gid) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_extra_groups) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_uid) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_gid) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(default_mail_env) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_location) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_cache_fields) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_never_cache_fields) "imap.envelope",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_cache_min_mail_count) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mailbox_idle_check_interval) 30,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_debug) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_full_filesystem_access) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_max_keyword_length) 50,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_save_crlf) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#ifdef MMAP_CONFLICTS_WRITE
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mmap_disable) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#else
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mmap_disable) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#endif
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(dotlock_use_excl) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(fsync_disable) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_nfs_storage) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_nfs_index) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mailbox_list_index_disable) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(lock_method) "fcntl",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(maildir_stat_dirs) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(maildir_copy_with_hardlinks) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(maildir_copy_preserve_filename) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_read_locks) "fcntl",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_write_locks) "dotlock fcntl",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_lock_timeout) 300,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_dotlock_change_timeout) 120,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_min_index_size) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_dirty_syncs) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_very_dirty_syncs) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mbox_lazy_writes) TRUE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(dbox_rotate_size) 2048,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(dbox_rotate_min_size) 16,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(dbox_rotate_days) 1,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(umask) 0077,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_drop_priv_before_exec) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_executable) PKG_LIBEXECDIR"/imap",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_process_size) 256,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_plugins) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_plugin_dir) MODULEDIR"/imap",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_log_prefix) "%Us(%u): ",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mail_log_max_lines_per_sec) 10,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* imap */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(imap_max_line_length) 65536,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(imap_capability) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(imap_client_workarounds) "outlook-idle",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(imap_logout_format) "bytes=%i/%o",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* pop3 */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_no_flag_updates) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_enable_last) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_reuse_xuidl) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_lock_session) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_uidl_format) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_client_workarounds) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(pop3_logout_format) "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* .. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct auth_settings default_auth_settings = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(parent) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(next) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(name) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mechanisms) "plain",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(realms) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(default_realm) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(cache_size) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(cache_ttl) 3600,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(executable) PKG_LIBEXECDIR"/dovecot-auth",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(user) "root",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(chroot) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(username_chars) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(username_translation) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(username_format) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(master_user_separator) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(anonymous_username) "anonymous",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(krb5_keytab) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(gssapi_hostname) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(verbose) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(debug) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(debug_passwords) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_require_client_cert) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(ssl_username_from_cert) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(count) 1,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(worker_max_count) 30,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(process_size) 256,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* .. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(uid) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(gid) 0,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(passdbs) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(userdbs) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(sockets) NULL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct socket_settings default_socket_settings = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEFAULT_MASTER_SOCKET_PATH "auth-master"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#define DEFAULT_CLIENT_SOCKET_PATH "auth-client"
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(path) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(mode) 0600,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(user) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(group) ""
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct namespace_settings default_namespace_settings = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(parent) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(next) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(type) NULL,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(separator) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(prefix) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(location) "",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(inbox) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(hidden) FALSE,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa MEMBER(list) TRUE
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa};
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic pool_t settings_pool, settings2_pool;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastruct server_settings *settings_root = NULL;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic void fix_base_path(struct settings *set, const char **str)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*str != NULL && **str != '\0' && **str != '/') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *str = p_strconcat(settings_pool,
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->base_dir, "/", *str, NULL);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool parse_uid(const char *str, uid_t *uid_r)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct passwd *pw;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa char *p;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*str >= '0' && *str <= '9') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *uid_r = (uid_t)strtoul(str, &p, 10);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*p == '\0')
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa pw = getpwnam(str);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (pw == NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *uid_r = pw->pw_uid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool parse_gid(const char *str, gid_t *gid_r)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct group *gr;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa char *p;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*str >= '0' && *str <= '9') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *gid_r = (gid_t)strtoul(str, &p, 10);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*p == '\0')
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa gr = getgrnam(str);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (gr == NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *gid_r = gr->gr_gid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool get_login_uid(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct passwd *pw;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if ((pw = getpwnam(set->login_user)) == NULL) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Login user doesn't exist: %s", set->login_user);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->server->login_gid == 0)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->server->login_gid = pw->pw_gid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa else if (set->server->login_gid != pw->pw_gid) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("All login process users must belong to same group "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "(%s vs %s)", dec2str(set->server->login_gid),
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa dec2str(pw->pw_gid));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->login_uid = pw->pw_uid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool auth_settings_verify(struct auth_settings *auth)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct passwd *pw;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_socket_settings *s;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if ((pw = getpwnam(auth->user)) == NULL) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Auth user doesn't exist: %s", auth->user);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (auth->parent->defaults->login_uid == pw->pw_uid &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa master_uid != pw->pw_uid) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("login_user %s (uid %s) must not be same as auth_user",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->user, dec2str(pw->pw_uid));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->uid = pw->pw_uid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->gid = pw->pw_gid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(t_strcut(auth->executable, ' '), X_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't use auth executable %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa t_strcut(auth->executable, ' '));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa fix_base_path(auth->parent->defaults, &auth->chroot);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*auth->chroot != '\0' && access(auth->chroot, X_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't access auth chroot directory %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->chroot);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (auth->ssl_require_client_cert || auth->ssl_username_from_cert) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* if we require valid cert, make sure we also ask for it */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (auth->parent->pop3 != NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->parent->pop3->ssl_verify_client_cert = TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (auth->parent->imap != NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa auth->parent->imap->ssl_verify_client_cert = TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa for (s = auth->sockets; s != NULL; s = s->next) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa fix_base_path(auth->parent->defaults, &s->master.path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa fix_base_path(auth->parent->defaults, &s->client.path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool namespace_settings_verify(struct namespace_settings *ns)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa const char *name;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa name = ns->prefix != NULL ? ns->prefix : "";
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (ns->separator != NULL &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa ns->separator[0] != '\0' && ns->separator[1] != '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Namespace '%s': "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "Hierarchy separator must be only one character long",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa name);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic const char *get_directory(const char *path)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa char *str, *p;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa str = t_strdup_noconst(path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa p = strrchr(str, '/');
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (p == NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return ".";
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa else {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *p = '\0';
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return str;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool settings_is_active(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->protocols == '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* we're probably using this with --exec-mail */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->protocol == MAIL_PROTOCOL_IMAP) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (strstr(set->protocols, "imap") == NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa } else {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (strstr(set->protocols, "pop3") == NULL)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool settings_have_connect_sockets(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct auth_settings *auth;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct server_settings *server;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa for (server = set->server; server != NULL; server = server->next) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa for (auth = server->auths; auth != NULL; auth = auth->next) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (auth->sockets != NULL &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa strcmp(auth->sockets->type, "connect") == 0)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic void unlink_auth_sockets(const char *path, const char *prefix)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa DIR *dirp;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct dirent *dp;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct stat st;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa string_t *str;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa unsigned int prefix_len;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa dirp = opendir(path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (dirp == NULL) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("opendir(%s) failed: %m", path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa prefix_len = strlen(prefix);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa str = t_str_new(256);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa while ((dp = readdir(dirp)) != NULL) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (dp->d_name[0] == '.')
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa continue;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (strncmp(dp->d_name, prefix, prefix_len) != 0)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa continue;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa str_truncate(str, 0);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa str_printfa(str, "%s/%s", path, dp->d_name);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (lstat(str_c(str), &st) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (errno != ENOENT)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("lstat(%s) failed: %m", str_c(str));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa continue;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!S_ISSOCK(st.st_mode))
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa continue;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* try to avoid unlinking sockets if someone's already
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa listening in them. do this only at startup, because
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa when SIGHUPing a child process might catch the new
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa connection before it notices that it's supposed
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa to die. null_fd == -1 check is a bit kludgy, but works.. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (null_fd == -1) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa int fd = net_connect_unix(str_c(str));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (fd != -1 || errno != ECONNREFUSED) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_fatal("Dovecot is already running? "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "Socket already exists: %s",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa str_c(str));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (unlink(str_c(str)) < 0 && errno != ENOENT)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("unlink(%s) failed: %m", str_c(str));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)closedir(dirp);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#ifdef HAVE_MODULES
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool get_imap_capability(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* FIXME: pretty ugly code just for getting the capability
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa automatically */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa static const char *generated_capability = NULL;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa static const char *args[] = {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "uid=65534",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "gid=65534",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa NULL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa };
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa enum master_login_status login_status;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct ip_addr ip;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa char buf[4096];
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa int fd[2], status;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa ssize_t ret;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa unsigned int pos;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa uid_t uid;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (generated_capability != NULL) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* Reloading configuration. Don't try to execute the imap
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa process again. Too risky and the wait() call below will
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa break it anyway. Just use the previous capability list we
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa already had generated. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->imap_generated_capability =
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa p_strdup(settings_pool, generated_capability);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa uid = geteuid();
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (uid != 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* use the current user */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa args[0] = t_strdup_printf("uid=%s", dec2str(uid));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa args[1] = t_strdup_printf("gid=%s", dec2str(getegid()));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa memset(&ip, 0, sizeof(ip));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (pipe(fd) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("pipe() failed: %m");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa fd_close_on_exec(fd[0], TRUE);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa fd_close_on_exec(fd[1], TRUE);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa login_status = create_mail_process(PROCESS_TYPE_IMAP, set, fd[1],
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa &ip, &ip, "dump-capability",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa args, TRUE);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (login_status != MASTER_LOGIN_STATUS_OK) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[0]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[1]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[1]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa alarm(5);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (wait(&status) == -1)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_fatal("imap dump-capability process got stuck");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa alarm(0);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (status != 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[0]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (WIFSIGNALED(status)) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("imap dump-capability process "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "killed with signal %d", WTERMSIG(status));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa } else {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("imap dump-capability process returned %d",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa WIFEXITED(status) ? WEXITSTATUS(status) :
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa status);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa pos = 0;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa while ((ret = read(fd[0], buf + pos, sizeof(buf) - pos)) > 0)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa pos += ret;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (ret < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("read(imap dump-capability process) failed: %m");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[0]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa (void)close(fd[0]);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (pos == 0 || buf[pos-1] != '\n') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("imap dump-capability: Couldn't read capability "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "(got %u bytes)", pos);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa buf[pos-1] = '\0';
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa generated_capability = i_strdup(buf);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->imap_generated_capability =
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa p_strdup(settings_pool, generated_capability);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#endif
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool settings_verify(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa const char *dir;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa int facility;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!get_login_uid(set))
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->mail_uid_t = (uid_t)-1;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->mail_gid_t = (gid_t)-1;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->mail_uid != '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!parse_uid(set->mail_uid, &set->mail_uid_t))
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->mail_gid != '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!parse_gid(set->mail_gid, &set->mail_gid_t))
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->protocol == MAIL_PROTOCOL_POP3 &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa *set->pop3_uidl_format == '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("POP3 enabled but pop3_uidl_format not set");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(t_strcut(set->mail_executable, ' '), X_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't use mail executable %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa t_strcut(set->mail_executable, ' '));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->log_path != '\0' && access(set->log_path, W_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa dir = get_directory(set->log_path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(dir, W_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't write to log directory %s: %m", dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->info_log_path != '\0' &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa access(set->info_log_path, W_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa dir = get_directory(set->info_log_path);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(dir, W_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't write to info log directory %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!syslog_facility_find(set->syslog_facility, &facility)) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Unknown syslog_facility '%s'", set->syslog_facility);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#ifdef HAVE_SSL
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!set->ssl_disable) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->ssl_ca_file != '\0' &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa access(set->ssl_ca_file, R_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_fatal("Can't use SSL CA file %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->ssl_ca_file);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(set->ssl_cert_file, R_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't use SSL certificate %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->ssl_cert_file);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(set->ssl_key_file, R_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't use SSL key file %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->ssl_key_file);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#else
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (!set->ssl_disable) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("SSL support not compiled in but ssl_disable=no");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#endif
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->max_mail_processes < 1) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("max_mail_processes must be at least 1");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->last_valid_uid != 0 &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->first_valid_uid > set->last_valid_uid) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("first_valid_uid can't be larger than last_valid_uid");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->last_valid_gid != 0 &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->first_valid_gid > set->last_valid_gid) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("first_valid_gid can't be larger than last_valid_gid");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->mail_drop_priv_before_exec && *set->mail_chroot != '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("mail_drop_priv_before_exec=yes and mail_chroot "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "don't work together");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (access(t_strcut(set->login_executable, ' '), X_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't use login executable %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa t_strcut(set->login_executable, ' '));
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->login_processes_count < 1) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("login_processes_count must be at least 1");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (set->login_max_connections < 1) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("login_max_connections must be at least 1");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#ifdef HAVE_MODULES
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->mail_plugins != '\0' &&
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Can't access mail module directory: %s: %m",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->mail_plugin_dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#else
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (*set->mail_plugins != '\0') {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("Module support wasn't built into Dovecot, "
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa "can't load modules: %s", set->mail_plugins);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa#endif
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return TRUE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa}
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksastatic bool settings_do_fixes(struct settings *set)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa{
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa struct stat st;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* since base dir is under /var/run by default, it may have been
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa deleted. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (mkdir_parents(set->base_dir, 0777) < 0 && errno != EEXIST) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("mkdir(%s) failed: %m", set->base_dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* allow base_dir to be a symlink, so don't use lstat() */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (stat(set->base_dir, &st) < 0) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("stat(%s) failed: %m", set->base_dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa return FALSE;
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if ((st.st_mode & 0310) != 0310 || (st.st_mode & 0777) == 0777) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* FIXME: backwards compatibility: fix permissions so that
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa login processes can find ssl-parameters file. Group rx is
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa enough, but change it to world-rx so that we don't have to
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa start changing groups and causing possibly other problems.
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa The second check is to fix 1.0beta1's accidental 0777
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa mode change.. */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_warning("Fixing permissions of %s to be world-readable",
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa set->base_dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (chmod(set->base_dir, 0755) < 0)
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("chmod(%s) failed: %m", set->base_dir);
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa }
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* remove auth worker sockets left by unclean exits */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa unlink_auth_sockets(set->base_dir, "auth-worker.");
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa /* Make sure our permanent state directory exists */
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa if (mkdir_parents(PKG_STATEDIR, 0750) < 0 && errno != EEXIST) {
2a18c4c4599ac56a28a7e38bb286b5db8b05b68cEugen Kuksa i_error("mkdir(%s) failed: %m", PKG_STATEDIR);
return FALSE;
}
if (!settings_have_connect_sockets(set)) {
/* we are not using external authentication, so make sure the
login directory exists with correct permissions and it's
empty. with external auth we wouldn't want to delete
existing sockets or break the permissions required by the
auth server. */
if (safe_mkdir(set->login_dir, 0750,
master_uid, set->server->login_gid) == 0) {
i_warning("Corrected permissions for login directory "
"%s", set->login_dir);
}
unlink_auth_sockets(set->login_dir, "");
}
#ifdef HAVE_MODULES
if (*set->mail_plugins != '\0' && set->protocol == MAIL_PROTOCOL_IMAP &&
*set->imap_capability == '\0') {
if (!get_imap_capability(set))
return FALSE;
}
#endif
return TRUE;
}
static bool settings_fix(struct settings *set, bool nochecks, bool nofixes)
{
/* fix relative paths */
fix_base_path(set, &set->login_dir);
if (*set->mail_location == '\0') {
/* keep this for backwards compatibility */
set->mail_location = set->default_mail_env;
} else if (*set->default_mail_env != '\0') {
i_error("Both mail_location and default_mail_env set. "
"Use only one of them.");
return FALSE;
}
if (nochecks)
return TRUE;
if (!settings_verify(set))
return FALSE;
return nofixes ? TRUE : settings_do_fixes(set);
}
static int pid_file_is_running(const char *path)
{
char buf[32];
int fd;
ssize_t ret;
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT)
return 0;
i_error("open(%s) failed: %m", path);
return -1;
}
ret = read(fd, buf, sizeof(buf));
if (ret <= 0) {
if (ret == 0)
i_error("Empty PID file in %s, overriding", path);
else
i_error("read(%s) failed: %m", path);
} else {
pid_t pid;
if (buf[ret-1] == '\n')
ret--;
buf[ret] = '\0';
pid = atoi(buf);
if (pid == getpid() || (kill(pid, 0) < 0 && errno == ESRCH)) {
/* doesn't exist */
ret = 0;
} else {
i_error("Dovecot is already running with PID %s "
"(read from %s)", buf, path);
ret = 1;
}
}
(void)close(fd);
return ret;
}
static struct auth_settings *
auth_settings_new(struct server_settings *server, const char *name)
{
struct auth_settings *auth;
auth = p_new(settings_pool, struct auth_settings, 1);
/* copy defaults */
*auth = server->auth_defaults;
auth->parent = server;
auth->name = p_strdup(settings_pool, name);
auth->next = server->auths;
server->auths = auth;
return auth;
}
static struct auth_settings *
parse_new_auth(struct server_settings *server, const char *name,
const char **errormsg)
{
struct auth_settings *auth;
if (strchr(name, '/') != NULL) {
*errormsg = "Authentication process name must not contain '/'";
return NULL;
}
for (auth = server->auths; auth != NULL; auth = auth->next) {
if (strcmp(auth->name, name) == 0) {
*errormsg = "Authentication process already exists "
"with the same name";
return NULL;
}
}
return auth_settings_new(server, name);
}
static struct auth_passdb_settings *
auth_passdb_settings_new(struct auth_settings *auth, const char *type)
{
struct auth_passdb_settings *as, **as_p;
as = p_new(settings_pool, struct auth_passdb_settings, 1);
as->parent = auth;
as->driver = str_lcase(p_strdup(settings_pool, type));
as_p = &auth->passdbs;
while (*as_p != NULL)
as_p = &(*as_p)->next;
*as_p = as;
return as;
}
static struct auth_userdb_settings *
auth_userdb_settings_new(struct auth_settings *auth, const char *type)
{
struct auth_userdb_settings *as, **as_p;
as = p_new(settings_pool, struct auth_userdb_settings, 1);
as->parent = auth;
as->driver = str_lcase(p_strdup(settings_pool, type));
as_p = &auth->userdbs;
while (*as_p != NULL)
as_p = &(*as_p)->next;
*as_p = as;
return as;
}
static struct auth_socket_settings *
auth_socket_settings_new(struct auth_settings *auth, const char *type)
{
struct auth_socket_settings *as, **as_p;
as = p_new(settings_pool, struct auth_socket_settings, 1);
as->parent = auth;
as->type = str_lcase(p_strdup(settings_pool, type));
as->master = default_socket_settings;
as->client = default_socket_settings;
as->master.path = DEFAULT_MASTER_SOCKET_PATH;
as->client.path = DEFAULT_CLIENT_SOCKET_PATH;
as_p = &auth->sockets;
while (*as_p != NULL)
as_p = &(*as_p)->next;
*as_p = as;
return as;
}
static struct auth_socket_settings *
parse_new_auth_socket(struct auth_settings *auth, const char *name,
const char **errormsg)
{
if (strcmp(name, "connect") != 0 && strcmp(name, "listen") != 0) {
*errormsg = "Unknown auth socket type";
return NULL;
}
if ((auth->sockets != NULL && strcmp(name, "connect") == 0) ||
(auth->sockets != NULL &&
strcmp(auth->sockets->type, "listen") == 0)) {
*errormsg = "With connect auth socket no other sockets "
"can be used in same auth section";
return NULL;
}
return auth_socket_settings_new(auth, name);
}
static struct namespace_settings *
namespace_settings_new(struct server_settings *server, const char *type)
{
struct namespace_settings *ns, **ns_p;
ns = p_new(settings_pool, struct namespace_settings, 1);
*ns = default_namespace_settings;
ns->parent = server;
ns->type = str_lcase(p_strdup(settings_pool, type));
ns_p = &server->namespaces;
while (*ns_p != NULL)
ns_p = &(*ns_p)->next;
*ns_p = ns;
return ns;
}
static struct namespace_settings *
parse_new_namespace(struct server_settings *server, const char *name,
const char **errormsg)
{
if (strcasecmp(name, "private") != 0 &&
strcasecmp(name, "shared") != 0 &&
strcasecmp(name, "public") != 0) {
*errormsg = "Unknown namespace type";
return NULL;
}
return namespace_settings_new(server, name);
}
static const char *parse_setting(const char *key, const char *value,
struct settings_parse_ctx *ctx)
{
const char *error;
/* backwards compatibility */
if (strcmp(key, "auth") == 0) {
ctx->auth = parse_new_auth(ctx->server, value, &error);
return ctx->auth == NULL ? error : NULL;
}
if (strcmp(key, "login") == 0) {
i_warning("Ignoring deprecated 'login' section handling. "
"Use protocol imap/pop3 { .. } instead. "
"Some settings may have been read incorrectly.");
return NULL;
}
switch (ctx->type) {
case SETTINGS_TYPE_ROOT:
case SETTINGS_TYPE_SERVER:
error = NULL;
if (ctx->protocol == MAIL_PROTOCOL_ANY ||
ctx->protocol == MAIL_PROTOCOL_IMAP) {
error = parse_setting_from_defs(settings_pool,
setting_defs,
ctx->server->imap,
key, value);
}
if (error == NULL &&
(ctx->protocol == MAIL_PROTOCOL_ANY ||
ctx->protocol == MAIL_PROTOCOL_POP3)) {
error = parse_setting_from_defs(settings_pool,
setting_defs,
ctx->server->pop3,
key, value);
}
if (error == NULL)
return NULL;
if (strncmp(key, "auth_", 5) == 0) {
return parse_setting_from_defs(settings_pool,
auth_setting_defs,
ctx->auth,
key + 5, value);
}
return error;
case SETTINGS_TYPE_AUTH:
if (strncmp(key, "auth_", 5) == 0)
key += 5;
return parse_setting_from_defs(settings_pool, auth_setting_defs,
ctx->auth, key, value);
case SETTINGS_TYPE_AUTH_SOCKET:
return parse_setting_from_defs(settings_pool,
auth_socket_setting_defs,
ctx->auth_socket, key, value);
case SETTINGS_TYPE_AUTH_PASSDB:
return parse_setting_from_defs(settings_pool,
auth_passdb_setting_defs,
ctx->auth_passdb, key, value);
case SETTINGS_TYPE_AUTH_USERDB:
return parse_setting_from_defs(settings_pool,
auth_userdb_setting_defs,
ctx->auth_userdb, key, value);
case SETTINGS_TYPE_NAMESPACE:
return parse_setting_from_defs(settings_pool,
namespace_setting_defs,
ctx->namespace, key, value);
case SETTINGS_TYPE_SOCKET:
return parse_setting_from_defs(settings_pool,
socket_setting_defs,
ctx->socket, key, value);
case SETTINGS_TYPE_DICT:
key = p_strdup(settings_pool, key);
value = p_strdup(settings_pool, value);
array_append(&ctx->server->dicts, &key, 1);
array_append(&ctx->server->dicts, &value, 1);
return NULL;
case SETTINGS_TYPE_PLUGIN:
key = p_strdup(settings_pool, key);
value = p_strdup(settings_pool, value);
if (ctx->protocol == MAIL_PROTOCOL_ANY ||
ctx->protocol == MAIL_PROTOCOL_IMAP) {
array_append(&ctx->server->imap->plugin_envs, &key, 1);
array_append(&ctx->server->imap->plugin_envs,
&value, 1);
}
if (ctx->protocol == MAIL_PROTOCOL_ANY ||
ctx->protocol == MAIL_PROTOCOL_POP3) {
array_append(&ctx->server->pop3->plugin_envs, &key, 1);
array_append(&ctx->server->pop3->plugin_envs,
&value, 1);
}
return NULL;
}
i_unreached();
}
static struct server_settings *
create_new_server(const char *name,
struct settings *imap_defaults,
struct settings *pop3_defaults)
{
struct server_settings *server;
server = p_new(settings_pool, struct server_settings, 1);
server->name = p_strdup(settings_pool, name);
server->imap = p_new(settings_pool, struct settings, 1);
server->pop3 = p_new(settings_pool, struct settings, 1);
server->auth_defaults = default_auth_settings;
*server->imap = *imap_defaults;
*server->pop3 = *pop3_defaults;
p_array_init(&server->dicts, settings_pool, 4);
p_array_init(&server->imap->plugin_envs, settings_pool, 8);
p_array_init(&server->pop3->plugin_envs, settings_pool, 8);
server->imap->server = server;
server->imap->protocol = MAIL_PROTOCOL_IMAP;
server->imap->login_executable = PKG_LIBEXECDIR"/imap-login";
server->imap->mail_executable = PKG_LIBEXECDIR"/imap";
server->imap->mail_plugin_dir = MODULEDIR"/imap";
server->pop3->server = server;
server->pop3->protocol = MAIL_PROTOCOL_POP3;
server->pop3->login_executable = PKG_LIBEXECDIR"/pop3-login";
server->pop3->mail_executable = PKG_LIBEXECDIR"/pop3";
server->pop3->mail_plugin_dir = MODULEDIR"/pop3";
return server;
}
static bool parse_section(const char *type, const char *name,
struct settings_parse_ctx *ctx, const char **errormsg)
{
struct server_settings *server;
if (type == NULL) {
/* section closing */
if (ctx->level-- > 0) {
ctx->type = ctx->parent_type;
ctx->protocol = MAIL_PROTOCOL_ANY;
switch (ctx->type) {
case SETTINGS_TYPE_AUTH_SOCKET:
ctx->parent_type = SETTINGS_TYPE_AUTH;
break;
default:
ctx->parent_type = SETTINGS_TYPE_ROOT;
break;
}
} else {
ctx->type = SETTINGS_TYPE_ROOT;
ctx->server = ctx->root;
ctx->auth = &ctx->root->auth_defaults;
ctx->namespace = NULL;
}
return TRUE;
}
ctx->level++;
ctx->parent_type = ctx->type;
if (strcmp(type, "server") == 0) {
if (ctx->type != SETTINGS_TYPE_ROOT) {
*errormsg = "Server section not allowed here";
return FALSE;
}
ctx->type = SETTINGS_TYPE_SERVER;
ctx->server = create_new_server(name, ctx->server->imap,
ctx->server->pop3);
server = ctx->root;
while (server->next != NULL)
server = server->next;
server->next = ctx->server;
return TRUE;
}
if (strcmp(type, "protocol") == 0) {
if ((ctx->type != SETTINGS_TYPE_ROOT &&
ctx->type != SETTINGS_TYPE_SERVER) ||
ctx->level != 1) {
*errormsg = "Protocol section not allowed here";
return FALSE;
}
if (strcmp(name, "imap") == 0)
ctx->protocol = MAIL_PROTOCOL_IMAP;
else if (strcmp(name, "pop3") == 0)
ctx->protocol = MAIL_PROTOCOL_POP3;
else if (strcmp(name, "lda") == 0)
ctx->protocol = MAIL_PROTOCOL_LDA;
else {
*errormsg = "Unknown protocol name";
return FALSE;
}
return TRUE;
}
if (strcmp(type, "auth") == 0) {
if (ctx->type != SETTINGS_TYPE_ROOT &&
ctx->type != SETTINGS_TYPE_SERVER) {
*errormsg = "Auth section not allowed here";
return FALSE;
}
ctx->type = SETTINGS_TYPE_AUTH;
ctx->auth = parse_new_auth(ctx->server, name, errormsg);
return ctx->auth != NULL;
}
if (ctx->type == SETTINGS_TYPE_AUTH &&
strcmp(type, "socket") == 0) {
ctx->type = SETTINGS_TYPE_AUTH_SOCKET;
ctx->auth_socket = parse_new_auth_socket(ctx->auth,
name, errormsg);
return ctx->auth_socket != NULL;
}
if (ctx->type == SETTINGS_TYPE_AUTH && strcmp(type, "passdb") == 0) {
ctx->type = SETTINGS_TYPE_AUTH_PASSDB;
ctx->auth_passdb = auth_passdb_settings_new(ctx->auth, name);
return TRUE;
}
if (ctx->type == SETTINGS_TYPE_AUTH && strcmp(type, "userdb") == 0) {
ctx->type = SETTINGS_TYPE_AUTH_USERDB;
ctx->auth_userdb = auth_userdb_settings_new(ctx->auth, name);
return TRUE;
}
if (ctx->type == SETTINGS_TYPE_AUTH_SOCKET) {
ctx->type = SETTINGS_TYPE_SOCKET;
if (strcmp(type, "master") == 0) {
ctx->socket = &ctx->auth_socket->master;
ctx->socket->used = TRUE;
return TRUE;
}
if (strcmp(type, "client") == 0) {
ctx->socket = &ctx->auth_socket->client;
ctx->socket->used = TRUE;
return TRUE;
}
}
if (strcmp(type, "namespace") == 0) {
if (ctx->type != SETTINGS_TYPE_ROOT &&
ctx->type != SETTINGS_TYPE_SERVER) {
*errormsg = "Namespace section not allowed here";
return FALSE;
}
ctx->type = SETTINGS_TYPE_NAMESPACE;
ctx->namespace = parse_new_namespace(ctx->server, name,
errormsg);
return ctx->namespace != NULL;
}
if (strcmp(type, "dict") == 0) {
if (ctx->type != SETTINGS_TYPE_ROOT &&
ctx->type != SETTINGS_TYPE_SERVER) {
*errormsg = "Plugin section not allowed here";
return FALSE;
}
ctx->type = SETTINGS_TYPE_DICT;
return TRUE;
}
if (strcmp(type, "plugin") == 0) {
if (ctx->type != SETTINGS_TYPE_ROOT &&
ctx->type != SETTINGS_TYPE_SERVER) {
*errormsg = "Plugin section not allowed here";
return FALSE;
}
ctx->type = SETTINGS_TYPE_PLUGIN;
return TRUE;
}
*errormsg = "Unknown section type";
return FALSE;
}
bool master_settings_read(const char *path, bool nochecks, bool nofixes)
{
struct settings_parse_ctx ctx;
struct server_settings *server, *prev;
struct auth_settings *auth;
struct namespace_settings *ns;
pool_t temp;
memset(&ctx, 0, sizeof(ctx));
p_clear(settings_pool);
ctx.type = SETTINGS_TYPE_ROOT;
ctx.protocol = MAIL_PROTOCOL_ANY;
ctx.server = ctx.root =
create_new_server("default",
&default_settings, &default_settings);
ctx.auth = &ctx.server->auth_defaults;
if (!settings_read(path, NULL, parse_setting, parse_section, &ctx))
return FALSE;
if (ctx.level != 0) {
i_error("Missing '}'");
return FALSE;
}
/* If server sections were defined, skip the root */
if (ctx.root->next != NULL)
ctx.root = ctx.root->next;
if (!nochecks && !nofixes) {
ctx.root->defaults = settings_is_active(ctx.root->imap) ?
ctx.root->imap : ctx.root->pop3;
path = t_strconcat(ctx.root->defaults->base_dir,
"/master.pid", NULL);
if (pid_file_is_running(path) != 0)
return FALSE;
}
prev = NULL;
for (server = ctx.root; server != NULL; server = server->next) {
if ((*server->imap->protocols == '\0' ||
*server->pop3->protocols == '\0') && !nochecks) {
i_error("No protocols given in configuration file");
return FALSE;
}
/* --exec-mail is used if nochecks=TRUE. Allow it regardless
of what's in protocols setting. */
if (!settings_is_active(server->imap) && !nochecks) {
if (strcmp(server->imap->protocols, "none") == 0) {
if (!settings_fix(server->imap, nochecks,
nofixes))
return FALSE;
server->defaults = server->imap;
}
server->imap = NULL;
} else {
if (!settings_fix(server->imap, nochecks, nofixes))
return FALSE;
server->defaults = server->imap;
}
if (!settings_is_active(server->pop3) && !nochecks)
server->pop3 = NULL;
else {
if (!settings_fix(server->pop3, nochecks, nofixes))
return FALSE;
if (server->defaults == NULL)
server->defaults = server->pop3;
}
if (server->defaults == NULL) {
if (prev == NULL)
ctx.root = server->next;
else
prev->next = server->next;
} else {
auth = server->auths;
if (auth == NULL) {
i_error("Missing auth section for server %s",
server->name);
return FALSE;
}
if (!nochecks) {
for (; auth != NULL; auth = auth->next) {
if (!auth_settings_verify(auth))
return FALSE;
}
ns = server->namespaces;
for (; ns != NULL; ns = ns->next) {
if (!namespace_settings_verify(ns))
return FALSE;
}
}
prev = server;
}
}
if (ctx.root == NULL) {
/* We aren't actually checking them separately, but if it
contains only invalid protocols we'll get here.. */
i_error("Invalid protocols given in configuration file");
return FALSE;
}
/* settings ok, swap them */
temp = settings_pool;
settings_pool = settings2_pool;
settings2_pool = temp;
settings_root = ctx.root;
return TRUE;
}
static void settings_dump(const struct setting_def *def, const void **sets,
const char **set_names, unsigned int count,
bool nondefaults, unsigned int indent)
{
const char **str;
unsigned int i;
str = t_new(const char *, count);
for (; def->name != NULL; def++) {
bool same = TRUE;
t_push();
switch (def->type) {
case SET_STR: {
const char *const *strp;
for (i = 0; i < count; i++) {
strp = CONST_PTR_OFFSET(sets[i], def->offset);
str[i] = *strp != NULL ? *strp : "";
}
break;
}
case SET_INT: {
const unsigned int *n;
for (i = 0; i < count; i++) {
n = CONST_PTR_OFFSET(sets[i], def->offset);
str[i] = dec2str(*n);
}
break;
}
case SET_BOOL: {
const bool *b;
for (i = 0; i < count; i++) {
b = CONST_PTR_OFFSET(sets[i], def->offset);
str[i] = *b ? "yes" : "no";
}
break;
}
}
for (i = 2; i < count; i++) {
if (strcmp(str[i], str[i-1]) != 0)
same = FALSE;
}
if (same) {
if (!nondefaults || strcmp(str[0], str[1]) != 0) {
for (i = 0; i < indent; i++)
putc(' ', stdout);
printf("%s: %s\n", def->name, str[1]);
}
} else {
for (i = 0; i < indent; i++)
putc(' ', stdout);
for (i = 1; i < count; i++) {
printf("%s(%s): %s\n", def->name,
set_names[i], str[i]);
}
}
t_pop();
}
}
static void
namespace_settings_dump(struct namespace_settings *ns, bool nondefaults)
{
const void *sets[2];
sets[0] = t_malloc0(sizeof(struct namespace_settings));
for (; ns != NULL; ns = ns->next) {
printf("namespace:\n");
sets[1] = ns;
settings_dump(namespace_setting_defs, sets, NULL, 2,
nondefaults, 2);
}
}
static void auth_settings_dump(struct auth_settings *auth, bool nondefaults)
{
const struct auth_passdb_settings *passdb;
const struct auth_userdb_settings *userdb;
const struct auth_socket_settings *socket;
const void *sets[2], *sets2[2];
const void *empty_defaults;
empty_defaults = t_malloc0(sizeof(struct auth_passdb_settings) +
sizeof(struct auth_userdb_settings) +
sizeof(struct auth_socket_settings));
sets[0] = &default_auth_settings;
sets2[0] = empty_defaults;
for (; auth != NULL; auth = auth->next) {
printf("auth %s:\n", auth->name);
sets[1] = auth;
settings_dump(auth_setting_defs, sets, NULL, 2, nondefaults, 2);
passdb = auth->passdbs;
for (; passdb != NULL; passdb = passdb->next) {
printf(" passdb:\n");
sets2[1] = passdb;
settings_dump(auth_passdb_setting_defs, sets2, NULL, 2,
nondefaults, 4);
}
userdb = auth->userdbs;
for (; userdb != NULL; userdb = userdb->next) {
printf(" userdb:\n");
sets2[1] = userdb;
settings_dump(auth_userdb_setting_defs, sets2, NULL, 2,
nondefaults, 4);
}
socket = auth->sockets;
for (; socket != NULL; socket = socket->next) {
printf(" socket:\n");
sets2[1] = socket;
settings_dump(auth_socket_setting_defs, sets2, NULL, 2,
nondefaults, 4);
if (socket->client.used) {
printf(" client:\n");
sets2[1] = &socket->client;
settings_dump(socket_setting_defs, sets2, NULL,
2, nondefaults, 6);
}
if (socket->master.used) {
printf(" master:\n");
sets2[1] = &socket->master;
settings_dump(socket_setting_defs, sets2, NULL,
2, nondefaults, 6);
}
}
}
}
static void plugin_settings_dump(const struct settings *set)
{
const char *const *envs;
unsigned int i, count;
envs = array_get(&set->plugin_envs, &count);
i_assert((count % 2) == 0);
if (count == 0)
return;
printf("plugin:\n");
for (i = 0; i < count; i += 2)
printf(" %s: %s\n", envs[i], envs[i+1]);
}
static void dict_settings_dump(const struct server_settings *set)
{
const char *const *dicts;
unsigned int i, count;
dicts = array_get(&set->dicts, &count);
i_assert((count % 2) == 0);
if (count == 0)
return;
printf("dict:\n");
for (i = 0; i < count; i += 2)
printf(" %s: %s\n", dicts[i], dicts[i+1]);
}
void master_settings_dump(struct server_settings *set, bool nondefaults)
{
const void *sets[4];
const char *set_names[4];
unsigned int count;
sets[0] = &default_settings;
sets[1] = set->defaults;
set_names[0] = NULL;
set_names[1] = "default";
count = 2;
if (set->imap != NULL) {
sets[count] = set->imap;
set_names[count] = "imap";
count++;
}
if (set->pop3 != NULL) {
sets[count] = set->pop3;
set_names[count] = "pop3";
count++;
}
settings_dump(setting_defs, sets, set_names, count, nondefaults, 0);
namespace_settings_dump(set->namespaces, nondefaults);
auth_settings_dump(set->auths, nondefaults);
plugin_settings_dump(set->defaults);
dict_settings_dump(set);
}
void master_settings_init(void)
{
settings_pool = pool_alloconly_create("settings", 4096);
settings2_pool = pool_alloconly_create("settings2", 4096);
}
void master_settings_deinit(void)
{
pool_unref(settings_pool);
pool_unref(settings2_pool);
}