1 /* $NetBSD: mail_conf.c,v 1.1.1.2 2011/03/02 19:32:15 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* mail_conf 3 6 /* SUMMARY 7 /* global configuration parameter management 8 /* SYNOPSIS 9 /* #include <mail_conf.h> 10 /* 11 /* void mail_conf_read() 12 /* 13 /* void mail_conf_suck() 14 /* 15 /* void mail_conf_flush() 16 /* 17 /* void mail_conf_update(name, value) 18 /* const char *name; 19 /* const char *value; 20 /* 21 /* const char *mail_conf_lookup(name) 22 /* const char *name; 23 /* 24 /* const char *mail_conf_eval(string) 25 /* const char *string; 26 /* 27 /* const char *mail_conf_eval_once(string) 28 /* const char *string; 29 /* 30 /* const char *mail_conf_lookup_eval(name) 31 /* const char *name; 32 /* DESCRIPTION 33 /* mail_conf_suck() reads the global Postfix configuration file, and 34 /* stores its values into a global configuration dictionary. 35 /* 36 /* mail_conf_read() invokes mail_conf_suck() and assigns the values 37 /* to global variables by calling mail_params_init(). 38 /* 39 /* mail_conf_flush() discards the global configuration dictionary. 40 /* This is needed in programs that read main.cf multiple times, to 41 /* ensure that deleted parameter settings are handled properly. 42 /* 43 /* The following routines are wrappers around the generic dictionary 44 /* access routines. 45 /* 46 /* mail_conf_update() updates the named global parameter. This has 47 /* no effect on parameters whose value has already been looked up. 48 /* The update succeeds or the program terminates with fatal error. 49 /* 50 /* mail_conf_lookup() looks up the value of the named parameter. 51 /* A null pointer result means the parameter was not found. 52 /* The result is volatile and should be copied if it is to be 53 /* used for any appreciable amount of time. 54 /* 55 /* mail_conf_eval() recursively expands any $parameters in the 56 /* string argument. The result is volatile and should be copied 57 /* if it is to be used for any appreciable amount of time. 58 /* 59 /* mail_conf_eval_once() non-recursively expands any $parameters 60 /* in the string argument. The result is volatile and should 61 /* be copied if it is to be used for any appreciable amount 62 /* of time. 63 /* 64 /* mail_conf_lookup_eval() looks up the named parameter, and expands any 65 /* $parameters in the result. The result is volatile and should be 66 /* copied if it is to be used for any appreciable amount of time. 67 /* DIAGNOSTICS 68 /* Fatal errors: malformed numerical value. 69 /* ENVIRONMENT 70 /* MAIL_CONFIG, non-default configuration database 71 /* MAIL_VERBOSE, enable verbose mode 72 /* FILES 73 /* /etc/postfix: default Postfix configuration directory. 74 /* SEE ALSO 75 /* dict(3) generic dictionary manager 76 /* mail_conf_int(3) integer-valued parameters 77 /* mail_conf_str(3) string-valued parameters 78 /* LICENSE 79 /* .ad 80 /* .fi 81 /* The Secure Mailer license must be distributed with this software. 82 /* AUTHOR(S) 83 /* Wietse Venema 84 /* IBM T.J. Watson Research 85 /* P.O. Box 704 86 /* Yorktown Heights, NY 10598, USA 87 /*--*/ 88 89 /* System library. */ 90 91 #include <sys_defs.h> 92 #include <unistd.h> 93 #include <stdlib.h> 94 #include <string.h> 95 96 /* Utility library. */ 97 98 #include <msg.h> 99 #include <mymalloc.h> 100 #include <vstream.h> 101 #include <vstring.h> 102 #include <dict.h> 103 #include <safe.h> 104 #include <stringops.h> 105 #include <readlline.h> 106 107 /* Global library. */ 108 109 #include "mail_params.h" 110 #include "mail_conf.h" 111 112 /* mail_conf_checkdir - authorize non-default directory */ 113 114 static void mail_conf_checkdir(const char *config_dir) 115 { 116 VSTRING *buf; 117 VSTREAM *fp; 118 char *path; 119 char *name; 120 char *value; 121 char *cp; 122 int found = 0; 123 124 /* 125 * If running set-[ug]id, require that a non-default configuration 126 * directory name is blessed as a bona fide configuration directory in 127 * the default main.cf file. 128 */ 129 path = concatenate(DEF_CONFIG_DIR, "/", "main.cf", (char *) 0); 130 if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) 131 msg_fatal("open file %s: %m", path); 132 133 buf = vstring_alloc(1); 134 while (found == 0 && readlline(buf, fp, (int *) 0)) { 135 if (split_nameval(vstring_str(buf), &name, &value) == 0 136 && (strcmp(name, VAR_CONFIG_DIRS) == 0 137 || strcmp(name, VAR_MULTI_CONF_DIRS) == 0)) { 138 while (found == 0 && (cp = mystrtok(&value, ", \t\r\n")) != 0) 139 if (strcmp(cp, config_dir) == 0) 140 found = 1; 141 } 142 } 143 if (vstream_fclose(fp)) 144 msg_fatal("read file %s: %m", path); 145 vstring_free(buf); 146 147 if (found == 0) { 148 msg_error("untrusted configuration directory name: %s", config_dir); 149 msg_fatal("specify \"%s = %s\" in %s", 150 VAR_CONFIG_DIRS, config_dir, path); 151 } 152 myfree(path); 153 } 154 155 /* mail_conf_read - read global configuration file */ 156 157 void mail_conf_read(void) 158 { 159 mail_conf_suck(); 160 mail_params_init(); 161 } 162 163 /* mail_conf_suck - suck in the global configuration file */ 164 165 void mail_conf_suck(void) 166 { 167 char *config_dir; 168 char *path; 169 170 /* 171 * Permit references to unknown configuration variable names. We rely on 172 * a separate configuration checking tool to spot misspelled names and 173 * other kinds of trouble. Enter the configuration directory into the 174 * default dictionary. 175 */ 176 dict_unknown_allowed = 1; 177 if (var_config_dir) 178 myfree(var_config_dir); 179 if ((config_dir = getenv(CONF_ENV_PATH)) == 0) 180 config_dir = DEF_CONFIG_DIR; 181 var_config_dir = mystrdup(config_dir); 182 set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir); 183 184 /* 185 * If the configuration directory name comes from a different trust 186 * domain, require that it is listed in the default main.cf file. 187 */ 188 if (strcmp(var_config_dir, DEF_CONFIG_DIR) != 0 /* non-default */ 189 && safe_getenv(CONF_ENV_PATH) == 0 /* non-default */ 190 && geteuid() != 0) /* untrusted */ 191 mail_conf_checkdir(var_config_dir); 192 path = concatenate(var_config_dir, "/", "main.cf", (char *) 0); 193 dict_load_file(CONFIG_DICT, path); 194 myfree(path); 195 } 196 197 /* mail_conf_flush - discard configuration dictionary */ 198 199 void mail_conf_flush(void) 200 { 201 if (dict_handle(CONFIG_DICT) != 0) 202 dict_unregister(CONFIG_DICT); 203 } 204 205 /* mail_conf_eval - expand macros in string */ 206 207 const char *mail_conf_eval(const char *string) 208 { 209 #define RECURSIVE 1 210 211 return (dict_eval(CONFIG_DICT, string, RECURSIVE)); 212 } 213 214 /* mail_conf_eval_once - expand one level of macros in string */ 215 216 const char *mail_conf_eval_once(const char *string) 217 { 218 #define NONRECURSIVE 0 219 220 return (dict_eval(CONFIG_DICT, string, NONRECURSIVE)); 221 } 222 223 /* mail_conf_lookup - lookup named variable */ 224 225 const char *mail_conf_lookup(const char *name) 226 { 227 return (dict_lookup(CONFIG_DICT, name)); 228 } 229 230 /* mail_conf_lookup_eval - expand named variable */ 231 232 const char *mail_conf_lookup_eval(const char *name) 233 { 234 const char *value; 235 236 #define RECURSIVE 1 237 238 if ((value = dict_lookup(CONFIG_DICT, name)) != 0) 239 value = dict_eval(CONFIG_DICT, value, RECURSIVE); 240 return (value); 241 } 242 243 /* mail_conf_update - update parameter */ 244 245 void mail_conf_update(const char *key, const char *value) 246 { 247 dict_update(CONFIG_DICT, key, value); 248 } 249