xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/mail_conf.c (revision ca453df649ce9db45b64d73678ba06cbccf9aa11)
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