master-service-settings.c revision 4307c886579381dbb1897ea1388ae6978c96f560
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen#define DOVECOT_CONFIG_SOCKET_PATH PKG_RUNDIR"/config"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#define CONFIG_HANDSHAKE "VERSION\tconfig\t2\t0\n"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen { type, #name, offsetof(struct master_service_settings, name), NULL }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenmaster_service_settings_check(void *_set, pool_t pool, const char **error_r);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenstatic const struct setting_define master_service_setting_defines[] = {
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenstatic const struct master_service_settings master_service_default_settings = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .log_timestamp = DEFAULT_FAILURE_STAMP_FORMAT,
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenconst struct setting_parser_info master_service_setting_parser_info = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .struct_size = sizeof(struct master_service_settings),
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen/* <settings checks> */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenmaster_service_settings_check(void *_set, pool_t pool ATTR_UNUSED,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* default to syslog logging */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen/* </settings checks> */
e75ff6a1854ee9befb751d14023bd5fa756fbf3bTimo Sirainenmaster_service_exec_config(struct master_service *service,
e75ff6a1854ee9befb751d14023bd5fa756fbf3bTimo Sirainen const struct master_service_settings_input *input)
e1237f7e7f978e23c86cf51b69742291c316f75cTimo Sirainen const char **conf_argv, *binary_path = service->argv[0];
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen unsigned int i, argv_max_count;
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if (!service->keep_environment && !input->preserve_environment) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* @UNSAFE */
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv = t_new(const char *, argv_max_count);
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = t_strconcat("service=", service->name, NULL);
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainenconfig_exec_fallback(struct master_service *service,
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen const struct master_service_settings_input *input)
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen path = input->config_path != NULL ? input->config_path :
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode)) {
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen /* it's a file, not a socket/pipe */
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainenmaster_service_open_config(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen *path_r = path = input->config_path != NULL ? input->config_path :
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (service->config_fd != -1 && input->config_path == NULL) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* use the already opened config socket */
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (service->config_path_is_default && input->config_path == NULL) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* first try to connect to the default config socket.
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen configuration may contain secrets, so in default config
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen this fails because the socket is 0600. it's useful for
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen developers though. :) */
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen fd = net_connect_unix(DOVECOT_CONFIG_SOCKET_PATH);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* fallback to executing doveconf */
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen *error_r = errno == EACCES ? eacces_error_get("stat", path) :
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen if (!S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode)) {
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen /* it's not an UNIX socket, don't even try to connect */
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen fd = net_connect_unix_with_retries(path, 1000);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen *error_r = t_strdup_printf("net_connect_unix(%s) failed: %m",
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen const struct master_service_settings_input *input)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tmodule=%s", input->module);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tservice=%s", input->service);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tuser=%s", input->username);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tlip=%s", net_ip2addr(&input->local_ip));
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\trip=%s", net_ip2addr(&input->remote_ip));
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen str_printfa(str, "\tlname=%s", input->local_name);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainenconfig_send_request(const struct master_service_settings_input *input,
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen int fd, const char *path, const char **error_r)
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen ret = write_full(fd, str_data(str), str_len(str));
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen *error_r = t_strdup_printf("write_full(%s) failed: %m", path);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenmaster_service_apply_config_overrides(struct master_service *service,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const char **error_r)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const char *const *overrides;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen unsigned int i, count;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen overrides = array_get(&service->config_overrides, &count);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen for (i = 0; i < count; i++) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (settings_parse_line(parser, overrides[i]) < 0) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen settings_parse_set_key_expandeded(parser, service->set_pool,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainenconfig_read_reply_header(struct istream *istream, const char *path, pool_t pool,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct master_service_settings_input *input,
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen struct master_service_settings_output *output_r,
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen const char **error_r)
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen t_strdup_printf("read(%s) failed: %m", path) :
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen t_strdup_printf("read(%s) failed: EOF", path);
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen const char *const *arg = t_strsplit_tab(line);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen else if (strcmp(*arg, "service-uses-remote") == 0)
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen output_r->specific_services = array_idx(&services, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint master_service_settings_read(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output *output_r,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ARRAY_DEFINE(all_roots, const struct setting_parser_info *);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i;
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) {
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen fd = master_service_open_config(service, input, &path, error_r);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen if (config_send_request(input, fd, path, error_r) < 0) {
e774b2f08b0909382ddc3d2869ae7e3b97205184Timo Sirainen pool_alloconly_create("master service settings", 8192);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p_array_init(&all_roots, service->set_pool, 8);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tmp_root = &master_service_setting_parser_info;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen array_append(&all_roots, &input->roots[i], 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser = settings_parser_init_list(service->set_pool,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_idx(&all_roots, 0), array_count(&all_roots),
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen istream = i_stream_create_fd(fd, (size_t)-1, FALSE);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen /* most likely timed out, but just in case some other
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen signal was delivered early check if we need to
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0 &&
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen service->config_fd == -1 && input->config_path == NULL)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (array_is_created(&service->config_overrides)) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (master_service_apply_config_overrides(service, parser,
8c4b2e0734326ef8e534f25e8ee78ace1fc22d15Timo Sirainen if (!settings_parser_check(parser, service->set_pool, &error)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *error_r = t_strdup_printf("Invalid settings: %s", error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* running standalone. we want to ignore plugin versions. */
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen master_service_set_die_with_master(master_service, TRUE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* if we change any settings afterwards, they're in expanded form.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen especially all settings from userdb are already expanded. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen settings_parse_set_expanded(service->set_parser, TRUE);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainenint master_service_settings_read_simple(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const char **error_r)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return master_service_settings_read(service, &input, &output, error_r);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainenpool_t master_service_settings_detach(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmaster_service_settings_get(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen sets = settings_parser_get_list(service->set_parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid **master_service_settings_get_others(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return settings_parser_get_list(service->set_parser) + 1;
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainenmaster_service_get_settings_parser(struct master_service *service)
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainenint master_service_set(struct master_service *service, const char *line)
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen return settings_parse_line(service->set_parser, line);
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainenbool master_service_set_has_config_override(struct master_service *service,
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen const char *key)
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen if (!array_is_created(&service->config_overrides))
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen key_root = settings_parse_unalias(service->set_parser, key);
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen array_foreach(&service->config_overrides, override) {