diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:46:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:46:30 +0000 |
commit | b5896ba9f6047e7031e2bdee0622d543e11a6734 (patch) | |
tree | fd7b460593a2fee1be579bec5697e6d887ea3421 /src/global/mail_conf.c | |
parent | Initial commit. (diff) | |
download | postfix-upstream/3.4.23.tar.xz postfix-upstream/3.4.23.zip |
Adding upstream version 3.4.23.upstream/3.4.23upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/global/mail_conf.c')
-rw-r--r-- | src/global/mail_conf.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/global/mail_conf.c b/src/global/mail_conf.c new file mode 100644 index 0000000..cd79d35 --- /dev/null +++ b/src/global/mail_conf.c @@ -0,0 +1,278 @@ +/*++ +/* NAME +/* mail_conf 3 +/* SUMMARY +/* global configuration parameter management +/* SYNOPSIS +/* #include <mail_conf.h> +/* +/* void mail_conf_read() +/* +/* void mail_conf_suck() +/* +/* void mail_conf_flush() +/* +/* void mail_conf_checkdir(config_dir) +/* const char *config_dir; +/* +/* void mail_conf_update(name, value) +/* const char *name; +/* const char *value; +/* +/* const char *mail_conf_lookup(name) +/* const char *name; +/* +/* const char *mail_conf_eval(string) +/* const char *string; +/* +/* const char *mail_conf_eval_once(string) +/* const char *string; +/* +/* const char *mail_conf_lookup_eval(name) +/* const char *name; +/* DESCRIPTION +/* mail_conf_suck() reads the global Postfix configuration +/* file, and stores its values into a global configuration +/* dictionary. When the configuration directory name is not +/* trusted, this function requires that the directory name is +/* authorized with the alternate_config_directories setting +/* in the default main.cf file. +/* +/* This function requires that all configuration directory +/* override mechanisms set the MAIL_CONFIG environment variable, +/* even if the override was specified via the command line. +/* This reduces the number of pathways that need to be checked +/* for possible security attacks. +/* +/* mail_conf_read() invokes mail_conf_suck() and assigns the values +/* to global variables by calling mail_params_init(). +/* +/* mail_conf_flush() discards the global configuration dictionary. +/* This is needed in programs that read main.cf multiple times, to +/* ensure that deleted parameter settings are handled properly. +/* +/* mail_conf_checkdir() verifies that configuration directory +/* is authorized through settings in the default main.cf file, +/* and terminates the program if it is not. +/* +/* The following routines are wrappers around the generic dictionary +/* access routines. +/* +/* mail_conf_update() updates the named global parameter. This has +/* no effect on parameters whose value has already been looked up. +/* The update succeeds or the program terminates with fatal error. +/* +/* mail_conf_lookup() looks up the value of the named parameter. +/* A null pointer result means the parameter was not found. +/* The result is volatile and should be copied if it is to be +/* used for any appreciable amount of time. +/* +/* mail_conf_eval() recursively expands any $parameters in the +/* string argument. The result is volatile and should be copied +/* if it is to be used for any appreciable amount of time. +/* +/* mail_conf_eval_once() non-recursively expands any $parameters +/* in the string argument. The result is volatile and should +/* be copied if it is to be used for any appreciable amount +/* of time. +/* +/* mail_conf_lookup_eval() looks up the named parameter, and expands any +/* $parameters in the result. The result is volatile and should be +/* copied if it is to be used for any appreciable amount of time. +/* DIAGNOSTICS +/* Fatal errors: malformed numerical value. +/* ENVIRONMENT +/* MAIL_CONFIG, non-default configuration database +/* MAIL_VERBOSE, enable verbose mode +/* FILES +/* /etc/postfix: default Postfix configuration directory. +/* SEE ALSO +/* dict(3) generic dictionary manager +/* mail_conf_int(3) integer-valued parameters +/* mail_conf_str(3) string-valued parameters +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +/* Utility library. */ + +#include <msg.h> +#include <mymalloc.h> +#include <vstream.h> +#include <vstring.h> +#include <dict.h> +#include <safe.h> +#include <stringops.h> +#include <readlline.h> + +/* Global library. */ + +#include "mail_params.h" +#include "mail_conf.h" + +/* mail_conf_checkdir - authorize non-default directory */ + +void mail_conf_checkdir(const char *config_dir) +{ + VSTRING *buf; + VSTREAM *fp; + char *path; + char *name; + char *value; + char *cp; + int found = 0; + + /* + * If running set-[ug]id, require that a non-default configuration + * directory name is blessed as a bona fide configuration directory in + * the default main.cf file. + */ + path = concatenate(DEF_CONFIG_DIR, "/", "main.cf", (char *) 0); + if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) + msg_fatal("open file %s: %m", path); + + buf = vstring_alloc(1); + while (found == 0 && readlline(buf, fp, (int *) 0)) { + if (split_nameval(vstring_str(buf), &name, &value) == 0 + && (strcmp(name, VAR_CONFIG_DIRS) == 0 + || strcmp(name, VAR_MULTI_CONF_DIRS) == 0)) { + while (found == 0 && (cp = mystrtok(&value, CHARS_COMMA_SP)) != 0) + if (strcmp(cp, config_dir) == 0) + found = 1; + } + } + if (vstream_fclose(fp)) + msg_fatal("read file %s: %m", path); + vstring_free(buf); + + if (found == 0) { + msg_error("unauthorized configuration directory name: %s", config_dir); + msg_fatal("specify \"%s = %s\" or \"%s = %s\" in %s", + VAR_CONFIG_DIRS, config_dir, + VAR_MULTI_CONF_DIRS, config_dir, path); + } + myfree(path); +} + +/* mail_conf_read - read global configuration file */ + +void mail_conf_read(void) +{ + mail_conf_suck(); + mail_params_init(); +} + +/* mail_conf_suck - suck in the global configuration file */ + +void mail_conf_suck(void) +{ + char *config_dir; + char *path; + + /* + * The code below requires that all configuration directory override + * mechanisms set the CONF_ENV_PATH environment variable, even if the + * override was specified via the command line. This reduces the number + * of pathways that need to be checked for possible security attacks. + * + * Note: this code necessarily runs before cleanenv() can enforce the + * import_environment scrubbing policy. + */ + + /* + * Permit references to unknown configuration variable names. We rely on + * a separate configuration checking tool to spot misspelled names and + * other kinds of trouble. Enter the configuration directory into the + * default dictionary. + */ + if (var_config_dir) + myfree(var_config_dir); + if ((config_dir = getenv(CONF_ENV_PATH)) == 0) + config_dir = DEF_CONFIG_DIR; + var_config_dir = mystrdup(config_dir); + set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir); + + /* + * If the configuration directory name comes from an untrusted source, + * require that it is listed in the default main.cf file. + */ + if (strcmp(var_config_dir, DEF_CONFIG_DIR) != 0 /* non-default */ + && unsafe()) /* untrusted env and cli */ + mail_conf_checkdir(var_config_dir); + path = concatenate(var_config_dir, "/", "main.cf", (char *) 0); + if (dict_load_file_xt(CONFIG_DICT, path) == 0) + msg_fatal("open %s: %m", path); + myfree(path); +} + +/* mail_conf_flush - discard configuration dictionary */ + +void mail_conf_flush(void) +{ + if (dict_handle(CONFIG_DICT) != 0) + dict_unregister(CONFIG_DICT); +} + +/* mail_conf_eval - expand macros in string */ + +const char *mail_conf_eval(const char *string) +{ +#define RECURSIVE 1 + + return (dict_eval(CONFIG_DICT, string, RECURSIVE)); +} + +/* mail_conf_eval_once - expand one level of macros in string */ + +const char *mail_conf_eval_once(const char *string) +{ +#define NONRECURSIVE 0 + + return (dict_eval(CONFIG_DICT, string, NONRECURSIVE)); +} + +/* mail_conf_lookup - lookup named variable */ + +const char *mail_conf_lookup(const char *name) +{ + return (dict_lookup(CONFIG_DICT, name)); +} + +/* mail_conf_lookup_eval - expand named variable */ + +const char *mail_conf_lookup_eval(const char *name) +{ + const char *value; + +#define RECURSIVE 1 + + if ((value = dict_lookup(CONFIG_DICT, name)) != 0) + value = dict_eval(CONFIG_DICT, value, RECURSIVE); + return (value); +} + +/* mail_conf_update - update parameter */ + +void mail_conf_update(const char *key, const char *value) +{ + dict_update(CONFIG_DICT, key, value); +} |