master-settings.c revision 770d5738e9e3e7e65af6246272f1094f7a94fe35
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "common.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "array.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "str.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "istream.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "fd-close-on-exec.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "safe-mkdir.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "mkdir-parents.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "unlink-directory.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "syslog-util.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "mail-process.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "master-login-interface.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "settings.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <stdio.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <stddef.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <stdlib.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <dirent.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <unistd.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <fcntl.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <signal.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <sys/stat.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <sys/wait.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <pwd.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <grp.h>
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina#ifdef HAVE_SYS_RESOURCE_H
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher# include <sys/resource.h>
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#endif
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Boseenum settings_type {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_ROOT,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_SERVER,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_AUTH,
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose SETTINGS_TYPE_AUTH_SOCKET,
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose SETTINGS_TYPE_AUTH_PASSDB,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_AUTH_USERDB,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_NAMESPACE,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_SOCKET,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_DICT,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose SETTINGS_TYPE_PLUGIN
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose};
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bosestruct settings_parse_ctx {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose enum settings_type type, parent_type;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov enum mail_protocol protocol;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose struct server_settings *root, *server;
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose struct auth_settings *auth;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose struct socket_settings *socket;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose struct auth_socket_settings *auth_socket;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose struct auth_passdb_settings *auth_passdb;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct auth_userdb_settings *auth_userdb;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose struct namespace_settings *namespace;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose int level;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose};
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov#include "master-settings-defs.c"
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov#undef DEF_STR
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#undef DEF_INT
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#undef DEF_BOOL
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#define DEF_STR(name) DEF_STRUCT_STR(name, auth_settings)
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose#define DEF_INT(name) DEF_STRUCT_INT(name, auth_settings)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, auth_settings)
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bosestatic struct setting_def auth_setting_defs[] = {
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(mechanisms),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(realms),
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose DEF_STR(default_realm),
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose DEF_INT(cache_size),
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose DEF_INT(cache_ttl),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_INT(cache_negative_ttl),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(executable),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(user),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(chroot),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(username_chars),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(username_translation),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(username_format),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(master_user_separator),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(anonymous_username),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(krb5_keytab),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(gssapi_hostname),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_STR(winbind_helper_path),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_INT(failure_delay),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_BOOL(verbose),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_BOOL(debug),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_BOOL(debug_passwords),
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEF_BOOL(ssl_require_client_cert),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_BOOL(ssl_username_from_cert),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_BOOL(use_winbind),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_INT(count),
3d9bafcbb5c0fbf23351004ded4dea6aa13127fcSumit Bose DEF_INT(worker_max_count),
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose DEF_INT(process_size),
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose { 0, NULL, 0 }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose};
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov#undef DEF_STR
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov#undef DEF_INT
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#undef DEF_BOOL
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#define DEF_STR(name) DEF_STRUCT_STR(name, socket_settings)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#define DEF_INT(name) DEF_STRUCT_INT(name, socket_settings)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, socket_settings)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bosestatic struct setting_def socket_setting_defs[] = {
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_STR(path),
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_INT(mode),
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_STR(user),
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_STR(group),
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose { 0, NULL, 0 }
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose};
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bosestatic struct setting_def auth_socket_setting_defs[] = {
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_STRUCT_STR(type, auth_socket_settings),
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov { 0, NULL, 0 }
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose};
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose#undef DEF_STR
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose#undef DEF_INT
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose#undef DEF_BOOL
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose#define DEF_STR(name) DEF_STRUCT_STR(name, auth_passdb_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define DEF_INT(name) DEF_STRUCT_INT(name, auth_passdb_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, auth_passdb_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic struct setting_def auth_passdb_setting_defs[] = {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_STR(driver),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_STR(args),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_BOOL(deny),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_BOOL(pass),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_BOOL(master),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher { 0, NULL, 0 }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher};
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidekstatic struct setting_def auth_userdb_setting_defs[] = {
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STRUCT_STR(driver, auth_userdb_settings),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STRUCT_STR(args, auth_userdb_settings),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher { 0, NULL, 0 }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher};
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#undef DEF_STR
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#undef DEF_INT
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#undef DEF_BOOL
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define DEF_STR(name) DEF_STRUCT_STR(name, namespace_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define DEF_INT(name) DEF_STRUCT_INT(name, namespace_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, namespace_settings)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic struct setting_def namespace_setting_defs[] = {
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose DEF_STR(type),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher DEF_STR(separator),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STR(prefix),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STR(location),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STR(alias_for),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_BOOL(inbox),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_BOOL(hidden),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_STR(list),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek DEF_BOOL(subscriptions),
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek { 0, NULL, 0 }
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek};
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidekstruct settings default_settings = {
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(server) NULL,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(protocol) 0,
bfdb2eeed95bde6cd065a9a47a7cb1773990ccfbOndrej Kos
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* common */
af58b15fa7f20e33736d79c6a4b3becb568517caLukas Slebodnik MEMBER(base_dir) PKG_RUNDIR,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(log_path) "",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(info_log_path) "",
bfdb2eeed95bde6cd065a9a47a7cb1773990ccfbOndrej Kos MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(syslog_facility) "mail",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek /* general */
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(protocols) "imap imaps",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(listen) "*",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(ssl_listen) "",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(ssl) "yes",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_ca_file) "",
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_key_password) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_parameters_regenerate) 168,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_cipher_list) "",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(ssl_cert_username_field) "commonName",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(ssl_verify_client_cert) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(disable_plaintext_auth) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(verbose_ssl) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(shutdown_clients) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(nfs_check) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(version_ignore) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher /* login */
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(login_dir) "login",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_executable) NULL,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_user) "dovecot",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_greeting) PACKAGE_NAME" ready.",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_log_format) "%$: %s",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(login_process_per_connection) TRUE,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_chroot) TRUE,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(login_trusted_networks) "",
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(login_process_size) 64,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(login_processes_count) 3,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(login_max_processes_count) 128,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(login_max_connections) 256,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose /* mail */
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(valid_chroot_dirs) "",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(mail_chroot) "",
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(max_mail_processes) 512,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(mail_max_userip_connections) 10,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose MEMBER(verbose_proctitle) FALSE,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(first_valid_uid) 500,
7d056853e4a5fe6daa5743e38d21b4493f4fca27Jakub Hrozek MEMBER(last_valid_uid) 0,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(first_valid_gid) 1,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(last_valid_gid) 0,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(mail_access_groups) "",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(mail_privileged_group) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_uid) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_gid) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
a5b55bdfcda8bfce8cb2ced981773998093d7857Pavel Reichl MEMBER(mail_location) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_cache_fields) "",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(mail_never_cache_fields) "imap.envelope",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_cache_min_mail_count) 0,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mailbox_idle_check_interval) 30,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_debug) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_full_filesystem_access) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_max_keyword_length) 50,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_save_crlf) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#ifdef MMAP_CONFLICTS_WRITE
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mmap_disable) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#else
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mmap_disable) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#endif
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(dotlock_use_excl) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(fsync_disable) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_nfs_storage) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_nfs_index) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mailbox_list_index_disable) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(lock_method) "fcntl",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(maildir_stat_dirs) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(maildir_copy_with_hardlinks) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(maildir_copy_preserve_filename) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_read_locks) "fcntl",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_write_locks) "dotlock fcntl",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_lock_timeout) 300,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_dotlock_change_timeout) 120,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_min_index_size) 0,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_dirty_syncs) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_very_dirty_syncs) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mbox_lazy_writes) TRUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(dbox_rotate_size) 2048,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(dbox_rotate_min_size) 16,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(dbox_rotate_days) 1,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(umask) 0077,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_drop_priv_before_exec) FALSE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
af58b15fa7f20e33736d79c6a4b3becb568517caLukas Slebodnik MEMBER(mail_executable) PKG_LIBEXECDIR"/imap",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(mail_process_size) 256,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_plugins) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_plugin_dir) MODULEDIR"/imap",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(mail_log_prefix) "%Us(%u): ",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(mail_log_max_lines_per_sec) 10,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher /* imap */
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_max_line_length) 65536,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_capability) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_client_workarounds) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_logout_format) "bytes=%i/%o",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_id_send) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(imap_id_log) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher /* pop3 */
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_no_flag_updates) FALSE,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_enable_last) FALSE,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_reuse_xuidl) FALSE,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_lock_session) FALSE,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_uidl_format) "%08Xu%08Xv",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_client_workarounds) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(pop3_logout_format) "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher /* dict */
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(dict_db_config) NULL,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(dict_process_count) 1,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher /* .. */
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher};
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagherstruct auth_settings default_auth_settings = {
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(parent) NULL,
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher MEMBER(next) NULL,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher MEMBER(name) NULL,
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher MEMBER(mechanisms) "plain",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(realms) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(default_realm) "",
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(cache_size) 0,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher MEMBER(cache_ttl) 3600,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(cache_negative_ttl) 3600,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(executable) PKG_LIBEXECDIR"/dovecot-auth",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(user) "root",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(chroot) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(username_chars) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(username_translation) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(username_format) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(master_user_separator) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(anonymous_username) "anonymous",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(krb5_keytab) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(gssapi_hostname) "",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(winbind_helper_path) "/usr/bin/ntlm_auth",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(failure_delay) 2,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(verbose) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(debug) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(debug_passwords) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_require_client_cert) FALSE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(ssl_username_from_cert) FALSE,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(use_winbind) FALSE,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(count) 1,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(worker_max_count) 30,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(process_size) 256,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* .. */
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(uid) 0,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek MEMBER(gid) 0,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(passdbs) NULL,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher MEMBER(userdbs) NULL,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(sockets) NULL
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose};
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
cb446b6149d28c204954ae75143b89aef14115dcSumit Bosestruct socket_settings default_socket_settings = {
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose#define DEFAULT_MASTER_SOCKET_PATH "auth-master"
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov#define DEFAULT_CLIENT_SOCKET_PATH "auth-client"
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(path) "",
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(mode) 0600,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(user) "",
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(group) ""
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose};
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
cb446b6149d28c204954ae75143b89aef14115dcSumit Bosestruct namespace_settings default_namespace_settings = {
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(parent) NULL,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(next) NULL,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(type) NULL,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(separator) "",
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(prefix) "",
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(location) "",
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(alias_for) NULL,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(inbox) FALSE,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(hidden) FALSE,
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose MEMBER(list) "yes",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov MEMBER(subscriptions) TRUE
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose};
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic pool_t settings_pool, settings2_pool;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstruct server_settings *settings_root = NULL;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
cb446b6149d28c204954ae75143b89aef14115dcSumit Bosestatic void fix_base_path(struct settings *set, const char **str)
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (*str != NULL && **str != '\0' && **str != '/') {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher *str = p_strconcat(settings_pool,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov set->base_dir, "/", *str, NULL);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic bool parse_uid(const char *str, uid_t *uid_r)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose struct passwd *pw;
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose char *p;
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
7d056853e4a5fe6daa5743e38d21b4493f4fca27Jakub Hrozek if (*str >= '0' && *str <= '9') {
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose *uid_r = (uid_t)strtoul(str, &p, 10);
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose if (*p == '\0')
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose return TRUE;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose pw = getpwnam(str);
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose if (pw == NULL)
cb446b6149d28c204954ae75143b89aef14115dcSumit Bose return FALSE;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher *uid_r = pw->pw_uid;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return TRUE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherstatic bool parse_gid(const char *str, gid_t *gid_r)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher{
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher struct group *gr;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher char *p;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (*str >= '0' && *str <= '9') {
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher *gid_r = (gid_t)strtoul(str, &p, 10);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (*p == '\0')
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return TRUE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher }
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher gr = getgrnam(str);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (gr == NULL)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return FALSE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher *gid_r = gr->gr_gid;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return TRUE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherstatic bool get_login_uid(struct settings *set)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher{
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher struct passwd *pw;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if ((pw = getpwnam(set->login_user)) == NULL) {
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher i_error("Login user doesn't exist: %s", set->login_user);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return FALSE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher }
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (set->server->login_gid == 0)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher set->server->login_gid = pw->pw_gid;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher else if (set->server->login_gid != pw->pw_gid) {
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher i_error("All login process users must belong to same group "
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher "(%s vs %s)", dec2str(set->server->login_gid),
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher dec2str(pw->pw_gid));
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return FALSE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher }
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher set->login_uid = pw->pw_uid;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher return TRUE;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherstatic bool auth_settings_verify(struct auth_settings *auth)
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher{
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher struct passwd *pw;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher struct auth_socket_settings *s;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if ((pw = getpwnam(auth->user)) == NULL) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Auth user doesn't exist: %s", auth->user);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (auth->parent->defaults->login_uid == pw->pw_uid &&
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher master_uid != pw->pw_uid) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("login_user %s (uid %s) must not be same as auth_user",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher auth->user, dec2str(pw->pw_uid));
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek }
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek auth->uid = pw->pw_uid;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek auth->gid = pw->pw_gid;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (access(t_strcut(auth->executable, ' '), X_OK) < 0) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Can't use auth executable %s: %m",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher t_strcut(auth->executable, ' '));
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher fix_base_path(auth->parent->defaults, &auth->chroot);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (*auth->chroot != '\0' && access(auth->chroot, X_OK) < 0) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Can't access auth chroot directory %s: %m",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov auth->chroot);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose if (auth->ssl_require_client_cert || auth->ssl_username_from_cert) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher /* if we require valid cert, make sure we also ask for it */
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (auth->parent->pop3 != NULL)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov auth->parent->pop3->ssl_verify_client_cert = TRUE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (auth->parent->imap != NULL)
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher auth->parent->imap->ssl_verify_client_cert = TRUE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher for (s = auth->sockets; s != NULL; s = s->next) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (auth->count > 1 && strcmp(s->type, "listen") == 0) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Currently auth process count must be 1 if "
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher "you're using auth socket listeners.");
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov fix_base_path(auth->parent->defaults, &s->master.path);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher fix_base_path(auth->parent->defaults, &s->client.path);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return TRUE;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek}
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidekstatic bool namespace_settings_verify(struct server_settings *server,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct namespace_settings *ns)
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek{
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek struct namespace_settings *n;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek const char *name;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek name = ns->prefix != NULL ? ns->prefix : "";
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (ns->separator != NULL &&
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ns->separator[0] != '\0' && ns->separator[1] != '\0') {
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek i_error("Namespace '%s': "
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek "Hierarchy separator must be only one character long",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher name);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return FALSE;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (strcmp(ns->list, "yes") != 0 &&
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher strcmp(ns->list, "no") != 0 &&
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher strcmp(ns->list, "children") != 0) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Namespace '%s': Invalid list value: %s",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher name, ns->list);
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return FALSE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (ns->alias_for != NULL) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose for (n = server->namespaces; n != ns; n = n->next) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (strcmp(n->prefix, ns->alias_for) == 0)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose break;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (n == ns) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose i_error("Namespace '%s': alias_for points to "
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose "unknown namespace: %s", name, ns->alias_for);
1e4a582e29c119e2c0e58a02dcb41b829e6b5e39Lukas Slebodnik return FALSE;
1e4a582e29c119e2c0e58a02dcb41b829e6b5e39Lukas Slebodnik }
1e4a582e29c119e2c0e58a02dcb41b829e6b5e39Lukas Slebodnik if (n->alias_for != NULL) {
1e4a582e29c119e2c0e58a02dcb41b829e6b5e39Lukas Slebodnik i_error("Namespace '%s': alias_for chaining isn't "
1e4a582e29c119e2c0e58a02dcb41b829e6b5e39Lukas Slebodnik "allowed: %s -> %s", name, ns->alias_for,
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose n->alias_for);
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return FALSE;
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik }
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik return TRUE;
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik}
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnikstatic const char *get_directory(const char *path)
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik{
cdcca90249aadb72bf2978a63c202c5b68642224Lukas Slebodnik char *str, *p;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose str = t_strdup_noconst(path);
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose p = strrchr(str, '/');
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose if (p == NULL)
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose return ".";
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose else {
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose *p = '\0';
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose return str;
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose }
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose}
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bosestatic bool settings_is_active(struct settings *set)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose{
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (*set->protocols == '\0') {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose /* we're probably using this with --exec-mail */
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return TRUE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (set->protocol == MAIL_PROTOCOL_IMAP) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (strstr(set->protocols, "imap") == NULL)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return FALSE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose } else {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (strstr(set->protocols, "pop3") == NULL)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return FALSE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return TRUE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose}
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bosestatic bool settings_have_connect_sockets(struct settings *set)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose{
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct auth_settings *auth;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose struct server_settings *server;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose for (server = set->server; server != NULL; server = server->next) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose for (auth = server->auths; auth != NULL; auth = auth->next) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose if (auth->sockets != NULL &&
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose strcmp(auth->sockets->type, "connect") == 0)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return TRUE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return FALSE;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose}
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bosestatic bool settings_have_nonplaintext_auths(struct settings *set)
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose{
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose struct auth_settings *auth;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose struct server_settings *server;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose const char *const *tmp;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose for (server = set->server; server != NULL; server = server->next) {
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose for (auth = server->auths; auth != NULL; auth = auth->next) {
tmp = t_strsplit_spaces(auth->mechanisms, " ");
for (; *tmp != NULL; tmp++) {
if (strcasecmp(*tmp, "PLAIN") != 0 &&
strcasecmp(*tmp, "LOGIN") != 0)
return TRUE;
}
}
}
return FALSE;
}
static void unlink_auth_sockets(const char *path, const char *prefix)
{
DIR *dirp;
struct dirent *dp;
struct stat st;
string_t *str;
unsigned int prefix_len;
dirp = opendir(path);
if (dirp == NULL) {
i_error("opendir(%s) failed: %m", path);
return;
}
prefix_len = strlen(prefix);
str = t_str_new(256);
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_name[0] == '.')
continue;
if (strncmp(dp->d_name, prefix, prefix_len) != 0)
continue;
str_truncate(str, 0);
str_printfa(str, "%s/%s", path, dp->d_name);
if (lstat(str_c(str), &st) < 0) {
if (errno != ENOENT)
i_error("lstat(%s) failed: %m", str_c(str));
continue;
}
if (!S_ISSOCK(st.st_mode))
continue;
/* try to avoid unlinking sockets if someone's already
listening in them. do this only at startup, because
when SIGHUPing a child process might catch the new
connection before it notices that it's supposed
to die. null_fd == -1 check is a bit kludgy, but works.. */
if (null_fd == -1) {
int fd = net_connect_unix(str_c(str));
if (fd != -1 || errno != ECONNREFUSED) {
i_fatal("Dovecot is already running? "
"Socket already exists: %s",
str_c(str));
}
}
if (unlink(str_c(str)) < 0 && errno != ENOENT)
i_error("unlink(%s) failed: %m", str_c(str));
}
(void)closedir(dirp);
}
#ifdef HAVE_MODULES
static const char *
get_process_capability(enum process_type ptype, struct settings *set)
{
/* FIXME: pretty ugly code just for getting the capability
automatically */
static const char *args[] = {
"uid=65534",
"gid=65534",
"home=/tmp",
NULL
};
const char *pname = process_names[ptype];
enum master_login_status login_status;
struct mail_login_request request;
char buf[4096];
int fd[2], status;
ssize_t ret;
unsigned int pos;
uid_t uid;
pid_t pid;
uid = geteuid();
if (uid != 0) {
/* use the current user */
args[0] = t_strdup_printf("uid=%s", dec2str(uid));
args[1] = t_strdup_printf("gid=%s", dec2str(getegid()));
}
if (pipe(fd) < 0) {
i_error("pipe() failed: %m");
return NULL;
}
fd_close_on_exec(fd[0], TRUE);
fd_close_on_exec(fd[1], TRUE);
memset(&request, 0, sizeof(request));
request.fd = fd[1];
login_status = create_mail_process(ptype, set, &request,
"dump-capability", args, NULL, TRUE,
&pid);
if (login_status != MASTER_LOGIN_STATUS_OK) {
(void)close(fd[0]);
(void)close(fd[1]);
return NULL;
}
(void)close(fd[1]);
alarm(5);
if (wait(&status) == -1) {
i_fatal("%s dump-capability process %d got stuck",
pname, (int)pid);
}
alarm(0);
if (status != 0) {
(void)close(fd[0]);
if (WIFSIGNALED(status)) {
i_error("%s dump-capability process "
"killed with signal %d",
pname, WTERMSIG(status));
} else {
i_error("%s dump-capability process returned %d",
pname, WIFEXITED(status) ? WEXITSTATUS(status) :
status);
}
return NULL;
}
pos = 0;
while ((ret = read(fd[0], buf + pos, sizeof(buf) - pos)) > 0)
pos += ret;
if (ret < 0) {
i_error("read(%s dump-capability process) failed: %m", pname);
(void)close(fd[0]);
return NULL;
}
(void)close(fd[0]);
if (pos == 0 || buf[pos-1] != '\n') {
i_error("%s dump-capability: Couldn't read capability "
"(got %u bytes)", pname, pos);
return NULL;
}
buf[pos-1] = '\0';
return i_strdup(buf);
}
static bool get_imap_capability(struct settings *set)
{
static const char *generated_capability = NULL;
if (generated_capability != NULL) {
/* Reloading configuration. Don't try to execute the imap
process again. Too risky and the wait() call below will
break it anyway. Just use the previous capability list we
already had generated. */
set->imap_generated_capability =
p_strdup(settings_pool, generated_capability);
return TRUE;
}
generated_capability = get_process_capability(PROCESS_TYPE_IMAP, set);
if (generated_capability == NULL)
return FALSE;
set->imap_generated_capability =
p_strdup(settings_pool, generated_capability);
return TRUE;
}
#endif
static bool settings_verify(struct settings *set)
{
const char *dir;
int facility;
if (!get_login_uid(set))
return FALSE;
set->mail_uid_t = (uid_t)-1;
set->mail_gid_t = (gid_t)-1;
set->mail_priv_gid_t = (gid_t)-1;
if (*set->mail_uid != '\0') {
if (!parse_uid(set->mail_uid, &set->mail_uid_t)) {
i_error("Non-existing mail_uid: %s", set->mail_uid);
return FALSE;
}
}
if (*set->mail_gid != '\0') {
if (!parse_gid(set->mail_gid, &set->mail_gid_t)) {
i_error("Non-existing mail_gid: %s", set->mail_uid);
return FALSE;
}
}
if (*set->mail_privileged_group != '\0') {
if (!parse_gid(set->mail_privileged_group,
&set->mail_priv_gid_t)) {
i_error("Non-existing mail_privileged_group: %s",
set->mail_privileged_group);
return FALSE;
}
}
if (set->protocol != MAIL_PROTOCOL_ANY &&
access(t_strcut(set->mail_executable, ' '), X_OK) < 0) {
i_error("Can't use mail executable %s: %m",
t_strcut(set->mail_executable, ' '));
return FALSE;
}
if (*set->log_path != '\0' && access(set->log_path, W_OK) < 0) {
dir = get_directory(set->log_path);
if (access(dir, W_OK) < 0) {
i_error("Can't write to log directory %s: %m", dir);
return FALSE;
}
}
if (*set->info_log_path != '\0' &&
access(set->info_log_path, W_OK) < 0) {
dir = get_directory(set->info_log_path);
if (access(dir, W_OK) < 0) {
i_error("Can't write to info log directory %s: %m",
dir);
return FALSE;
}
}
if (!syslog_facility_find(set->syslog_facility, &facility)) {
i_error("Unknown syslog_facility '%s'", set->syslog_facility);
return FALSE;
}
if (strcmp(set->ssl, "no") != 0 &&
strcmp(set->ssl, "yes") != 0 &&
strcmp(set->ssl, "required") != 0) {
i_error("ssl setting: Invalid value: %s", set->ssl);
return FALSE;
}
#ifdef HAVE_SSL
if (strcmp(set->ssl, "no") != 0) {
if (*set->ssl_ca_file != '\0' &&
access(set->ssl_ca_file, R_OK) < 0) {
i_fatal("Can't use SSL CA file %s: %m",
set->ssl_ca_file);
}
if (access(set->ssl_cert_file, R_OK) < 0) {
i_error("Can't use SSL certificate %s: %m",
set->ssl_cert_file);
return FALSE;
}
if (access(set->ssl_key_file, R_OK) < 0) {
i_error("Can't use SSL key file %s: %m",
set->ssl_key_file);
return FALSE;
}
}
#else
if (strcmp(set->ssl, "no") != 0) {
i_error("SSL support not compiled in but ssl=%s", set->ssl);
return FALSE;
}
#endif
if (strcmp(set->ssl, "no") == 0 && set->disable_plaintext_auth &&
strncmp(set->listen, "127.", 4) != 0 &&
!settings_have_nonplaintext_auths(set)) {
i_warning("There is no way to login to this server: "
"disable_plaintext_auth=yes, ssl=no, "
"no non-plaintext auth mechanisms.");
}
if (set->max_mail_processes < 1) {
i_error("max_mail_processes must be at least 1");
return FALSE;
}
if (set->last_valid_uid != 0 &&
set->first_valid_uid > set->last_valid_uid) {
i_error("first_valid_uid can't be larger than last_valid_uid");
return FALSE;
}
if (set->last_valid_gid != 0 &&
set->first_valid_gid > set->last_valid_gid) {
i_error("first_valid_gid can't be larger than last_valid_gid");
return FALSE;
}
if (set->mail_drop_priv_before_exec && *set->mail_chroot != '\0') {
i_error("mail_drop_priv_before_exec=yes and mail_chroot "
"don't work together");
return FALSE;
}
if (set->protocol != MAIL_PROTOCOL_ANY &&
access(t_strcut(set->login_executable, ' '), X_OK) < 0) {
i_error("Can't use login executable %s: %m",
t_strcut(set->login_executable, ' '));
return FALSE;
}
if (set->login_processes_count < 1) {
i_error("login_processes_count must be at least 1");
return FALSE;
}
if (set->login_max_connections < 1) {
i_error("login_max_connections must be at least 1");
return FALSE;
}
if (set->mail_nfs_index && !set->mmap_disable) {
i_error("mail_nfs_index=yes requires mmap_disable=yes");
return FALSE;
}
if (set->mail_nfs_index && set->fsync_disable) {
i_error("mail_nfs_index=yes requires fsync_disable=no");
return FALSE;
}
#ifdef HAVE_MODULES
if (*set->mail_plugins != '\0' &&
access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
i_error("Can't access mail module directory: %s: %m",
set->mail_plugin_dir);
return FALSE;
}
#else
if (*set->mail_plugins != '\0') {
i_error("Module support wasn't built into Dovecot, "
"can't load modules: %s", set->mail_plugins);
return FALSE;
}
#endif
return TRUE;
}
static bool settings_do_fixes(struct settings *set)
{
struct stat st;
/* since base dir is under /var/run by default, it may have been
deleted. */
if (mkdir_parents(set->base_dir, 0777) < 0 && errno != EEXIST) {
i_error("mkdir(%s) failed: %m", set->base_dir);
return FALSE;
}
/* allow base_dir to be a symlink, so don't use lstat() */
if (stat(set->base_dir, &st) < 0) {
i_error("stat(%s) failed: %m", set->base_dir);
return FALSE;
}
/* remove auth worker sockets left by unclean exits */
unlink_auth_sockets(set->base_dir, "auth-worker.");
/* Make sure our permanent state directory exists */
if (mkdir_parents(PKG_STATEDIR, 0750) < 0 && errno != EEXIST) {
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 (nochecks)
return TRUE;
if (!settings_verify(set))
return FALSE;
return nofixes ? TRUE : settings_do_fixes(set);
}
static void pid_file_check_running(const char *path)
{
char buf[32];
int fd;
ssize_t ret;
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT)
return;
i_fatal("open(%s) failed: %m", path);
}
ret = read(fd, buf, sizeof(buf));
if (ret <= 0) {
if (ret == 0)
i_error("Empty PID file in %s, overriding", path);
else
i_fatal("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 */
} else {
i_fatal("Dovecot is already running with PID %s "
"(read from %s)", buf, path);
}
}
(void)close(fd);
}
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) {
*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;
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;
}
static void
settings_warn_needed_fds(struct server_settings *server ATTR_UNUSED)
{
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
unsigned int fd_count = 0;
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
return;
/* count only log pipes needed for login and mail processes. we need
more, but they're the ones that can use up most of the fds */
for (; server != NULL; server = server->next) {
if (server->imap != NULL)
fd_count += server->imap->login_max_processes_count;
if (server->pop3 != NULL)
fd_count += server->pop3->login_max_processes_count;
fd_count += server->defaults->max_mail_processes;
}
if (rlim.rlim_cur < fd_count) {
i_warning("fd limit %d is lower than what Dovecot can use under "
"full load (more than %u). Either grow the limit or "
"change login_max_processes_count and "
"max_mail_processes settings",
(int)rlim.rlim_cur, fd_count);
}
#endif
}
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);
pid_file_check_running(path);
}
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) {
server->imap->protocol = MAIL_PROTOCOL_ANY;
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(server, 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;
}
if (!nochecks)
settings_warn_needed_fds(ctx.root);
/* 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;
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]);
}
}
}
}
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_set;
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_set = auth->sockets;
for (; socket_set != NULL; socket_set = socket_set->next) {
printf(" socket:\n");
sets2[1] = socket_set;
settings_dump(auth_socket_setting_defs, sets2, NULL, 2,
nondefaults, 4);
if (socket_set->client.used) {
printf(" client:\n");
sets2[1] = &socket_set->client;
settings_dump(socket_setting_defs, sets2, NULL,
2, nondefaults, 6);
}
if (socket_set->master.used) {
printf(" master:\n");
sets2[1] = &socket_set->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);
}