xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/mail_params.c (revision 63aea4bd5b445e491ff0389fe27ec78b3099dba3)
1 /*	$NetBSD: mail_params.c,v 1.1.1.4 2014/07/06 19:27:51 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	mail_params 3
6 /* SUMMARY
7 /*	global mail configuration parameters
8 /* SYNOPSIS
9 /*	#include <mail_params.h>
10 /*
11 /*	char	*var_myhostname;
12 /*	char	*var_mydomain;
13 /*	char	*var_myorigin;
14 /*	char	*var_mydest;
15 /*	char	*var_relayhost;
16 /*	char	*var_transit_origin;
17 /*	char	*var_transit_dest;
18 /*	char	*var_mail_name;
19 /*	int	var_helpful_warnings;
20 /*	char	*var_syslog_name;
21 /*	char	*var_mail_owner;
22 /*	uid_t	var_owner_uid;
23 /*	gid_t	var_owner_gid;
24 /*	char	*var_sgid_group;
25 /*	gid_t	var_sgid_gid;
26 /*	char	*var_default_privs;
27 /*	uid_t	var_default_uid;
28 /*	gid_t	var_default_gid;
29 /*	char	*var_config_dir;
30 /*	char	*var_daemon_dir;
31 /*	char	*var_data_dir;
32 /*	char	*var_command_dir;
33 /*	char	*var_queue_dir;
34 /*	int	var_use_limit;
35 /*	int	var_idle_limit;
36 /*	int	var_event_drain;
37 /*	int	var_bundle_rcpt;
38 /*	char	*var_procname;
39 /*	int	var_pid;
40 /*	int	var_ipc_timeout;
41 /*	char	*var_pid_dir;
42 /*	int	var_dont_remove;
43 /*	char	*var_inet_interfaces;
44 /*	char	*var_proxy_interfaces;
45 /*	char	*var_inet_protocols;
46 /*	char	*var_mynetworks;
47 /*	char	*var_double_bounce_sender;
48 /*	int	var_line_limit;
49 /*	char	*var_alias_db_map;
50 /*	long	var_message_limit;
51 /*	char	*var_mail_release;
52 /*	char	*var_mail_version;
53 /*	int	var_ipc_idle_limit;
54 /*	int	var_ipc_ttl_limit;
55 /*	char	*var_db_type;
56 /*	char	*var_hash_queue_names;
57 /*	int	var_hash_queue_depth;
58 /*	int	var_trigger_timeout;
59 /*	char	*var_rcpt_delim;
60 /*	int	var_fork_tries;
61 /*	int	var_fork_delay;
62 /*	int	var_flock_tries;
63 /*	int	var_flock_delay;
64 /*	int	var_flock_stale;
65 /*	int	var_disable_dns;
66 /*	int	var_soft_bounce;
67 /*	time_t	var_starttime;
68 /*	int	var_ownreq_special;
69 /*	int	var_daemon_timeout;
70 /*	char	*var_syslog_facility;
71 /*	char	*var_relay_domains;
72 /*	char	*var_fflush_domains;
73 /*	char	*var_mynetworks_style;
74 /*	char	*var_verp_delims;
75 /*	char	*var_verp_filter;
76 /*	char	*var_par_dom_match;
77 /*	char	*var_config_dirs;
78 /*
79 /*	int	var_inet_windowsize;
80 /*	char	*var_import_environ;
81 /*	char	*var_export_environ;
82 /*	char	*var_debug_peer_list;
83 /*	int	var_debug_peer_level;
84 /*	int	var_in_flow_delay;
85 /*	int	var_fault_inj_code;
86 /*	char   *var_bounce_service;
87 /*	char   *var_cleanup_service;
88 /*	char   *var_defer_service;
89 /*	char   *var_pickup_service;
90 /*	char   *var_queue_service;
91 /*	char   *var_rewrite_service;
92 /*	char   *var_showq_service;
93 /*	char   *var_error_service;
94 /*	char   *var_flush_service;
95 /*	char   *var_verify_service;
96 /*	char   *var_trace_service;
97 /*	char   *var_proxymap_service;
98 /*	char   *var_proxywrite_service;
99 /*	int	var_db_create_buf;
100 /*	int	var_db_read_buf;
101 /*	long	var_lmdb_map_size;
102 /*	int	var_proc_limit;
103 /*	int	var_mime_maxdepth;
104 /*	int	var_mime_bound_len;
105 /*	int	var_header_limit;
106 /*	int	var_token_limit;
107 /*	int	var_disable_mime_input;
108 /*	int	var_disable_mime_oconv;
109 /*	int     var_strict_8bitmime;
110 /*	int     var_strict_7bit_hdrs;
111 /*	int     var_strict_8bit_body;
112 /*	int     var_strict_encoding;
113 /*	int     var_verify_neg_cache;
114 /*	int	var_oldlog_compat;
115 /*	int	var_delay_max_res;
116 /*	char	*var_int_filt_classes;
117 /*	int	var_cyrus_sasl_authzid;
118 /*
119 /*	char	*var_multi_conf_dirs;
120 /*	char	*var_multi_wrapper;
121 /*	char	*var_multi_group;
122 /*	char	*var_multi_name;
123 /*	bool	var_multi_enable;
124 /*	bool	var_long_queue_ids;
125 /*	bool	var_daemon_open_fatal;
126 /*
127 /*	void	mail_params_init()
128 /*
129 /*	const	char null_format_string[1];
130 /* DESCRIPTION
131 /*	This module (actually the associated include file) define the names
132 /*	and defaults of all mail configuration parameters.
133 /*
134 /*	mail_params_init() initializes the built-in parameters listed above.
135 /*	These parameters are relied upon by library routines, so they are
136 /*	initialized globally so as to avoid hard-to-find errors due to
137 /*	missing initialization. This routine must be called early, at
138 /*	least before entering a chroot jail.
139 /*
140 /*	null_format_string is a workaround for gcc compilers that complain
141 /*	about empty or null format strings.
142 /* DIAGNOSTICS
143 /*	Fatal errors: out of memory; null system or domain name.
144 /* LICENSE
145 /* .ad
146 /* .fi
147 /*	The Secure Mailer license must be distributed with this software.
148 /* AUTHOR(S)
149 /*	Wietse Venema
150 /*	IBM T.J. Watson Research
151 /*	P.O. Box 704
152 /*	Yorktown Heights, NY 10598, USA
153 /*--*/
154 
155 /* System library. */
156 
157 #include <sys_defs.h>
158 #include <unistd.h>
159 #include <stdlib.h>
160 #include <string.h>
161 #include <pwd.h>
162 #include <grp.h>
163 #include <time.h>
164 #include <ctype.h>
165 
166 #ifdef STRCASECMP_IN_STRINGS_H
167 #include <strings.h>
168 #endif
169 
170 /* Utility library. */
171 
172 #include <msg.h>
173 #include <msg_syslog.h>
174 #include <get_hostname.h>
175 #include <valid_hostname.h>
176 #include <stringops.h>
177 #include <safe.h>
178 #include <safe_open.h>
179 #include <mymalloc.h>
180 #include <dict.h>
181 #ifdef HAS_DB
182 #include <dict_db.h>
183 #endif
184 #ifdef HAS_LMDB
185 #include <dict_lmdb.h>
186 #endif
187 #include <inet_proto.h>
188 #include <vstring_vstream.h>
189 #include <iostuff.h>
190 
191 /* Global library. */
192 
193 #include <mynetworks.h>
194 #include <mail_conf.h>
195 #include <mail_version.h>
196 #include <mail_proto.h>
197 #include <verp_sender.h>
198 #include <own_inet_addr.h>
199 #include <mail_params.h>
200 
201  /*
202   * Special configuration variables.
203   */
204 char   *var_myhostname;
205 char   *var_mydomain;
206 char   *var_myorigin;
207 char   *var_mydest;
208 char   *var_relayhost;
209 char   *var_transit_origin;
210 char   *var_transit_dest;
211 char   *var_mail_name;
212 int     var_helpful_warnings;
213 char   *var_syslog_name;
214 char   *var_mail_owner;
215 uid_t   var_owner_uid;
216 gid_t   var_owner_gid;
217 char   *var_sgid_group;
218 gid_t   var_sgid_gid;
219 char   *var_default_privs;
220 uid_t   var_default_uid;
221 gid_t   var_default_gid;
222 char   *var_config_dir;
223 char   *var_daemon_dir;
224 char   *var_data_dir;
225 char   *var_command_dir;
226 char   *var_queue_dir;
227 int     var_use_limit;
228 int     var_event_drain;
229 int     var_idle_limit;
230 int     var_bundle_rcpt;
231 char   *var_procname;
232 int     var_pid;
233 int     var_ipc_timeout;
234 char   *var_pid_dir;
235 int     var_dont_remove;
236 char   *var_inet_interfaces;
237 char   *var_proxy_interfaces;
238 char   *var_inet_protocols;
239 char   *var_mynetworks;
240 char   *var_double_bounce_sender;
241 int     var_line_limit;
242 char   *var_alias_db_map;
243 long    var_message_limit;
244 char   *var_mail_release;
245 char   *var_mail_version;
246 int     var_ipc_idle_limit;
247 int     var_ipc_ttl_limit;
248 char   *var_db_type;
249 char   *var_hash_queue_names;
250 int     var_hash_queue_depth;
251 int     var_trigger_timeout;
252 char   *var_rcpt_delim;
253 int     var_fork_tries;
254 int     var_fork_delay;
255 int     var_flock_tries;
256 int     var_flock_delay;
257 int     var_flock_stale;
258 int     var_disable_dns;
259 int     var_soft_bounce;
260 time_t  var_starttime;
261 int     var_ownreq_special;
262 int     var_daemon_timeout;
263 char   *var_syslog_facility;
264 char   *var_relay_domains;
265 char   *var_fflush_domains;
266 char   *var_mynetworks_style;
267 char   *var_verp_delims;
268 char   *var_verp_filter;
269 int     var_in_flow_delay;
270 char   *var_par_dom_match;
271 char   *var_config_dirs;
272 
273 int     var_inet_windowsize;
274 char   *var_import_environ;
275 char   *var_export_environ;
276 char   *var_debug_peer_list;
277 int     var_debug_peer_level;
278 int     var_fault_inj_code;
279 char   *var_bounce_service;
280 char   *var_cleanup_service;
281 char   *var_defer_service;
282 char   *var_pickup_service;
283 char   *var_queue_service;
284 char   *var_rewrite_service;
285 char   *var_showq_service;
286 char   *var_error_service;
287 char   *var_flush_service;
288 char   *var_verify_service;
289 char   *var_trace_service;
290 char   *var_proxymap_service;
291 char   *var_proxywrite_service;
292 int     var_db_create_buf;
293 int     var_db_read_buf;
294 long    var_lmdb_map_size;
295 int     var_proc_limit;
296 int     var_mime_maxdepth;
297 int     var_mime_bound_len;
298 int     var_header_limit;
299 int     var_token_limit;
300 int     var_disable_mime_input;
301 int     var_disable_mime_oconv;
302 int     var_strict_8bitmime;
303 int     var_strict_7bit_hdrs;
304 int     var_strict_8bit_body;
305 int     var_strict_encoding;
306 int     var_verify_neg_cache;
307 int     var_oldlog_compat;
308 int     var_delay_max_res;
309 char   *var_int_filt_classes;
310 int     var_cyrus_sasl_authzid;
311 
312 char   *var_multi_conf_dirs;
313 char   *var_multi_wrapper;
314 char   *var_multi_group;
315 char   *var_multi_name;
316 bool    var_multi_enable;
317 bool    var_long_queue_ids;
318 bool    var_daemon_open_fatal;
319 
320 const char null_format_string[1] = "";
321 
322 /* check_myhostname - lookup hostname and validate */
323 
324 static const char *check_myhostname(void)
325 {
326     static const char *name;
327     const char *dot;
328     const char *domain;
329 
330     /*
331      * Use cached result.
332      */
333     if (name)
334 	return (name);
335 
336     /*
337      * If the local machine name is not in FQDN form, try to append the
338      * contents of $mydomain. Use a default domain as a final workaround.
339      */
340     name = get_hostname();
341     if ((dot = strchr(name, '.')) == 0) {
342 	if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
343 	    domain = DEF_MYDOMAIN;
344 	name = concatenate(name, ".", domain, (char *) 0);
345     }
346     return (name);
347 }
348 
349 /* check_mydomainname - lookup domain name and validate */
350 
351 static const char *check_mydomainname(void)
352 {
353     char   *dot;
354 
355     /*
356      * Use a default domain when the hostname is not a FQDN ("foo").
357      */
358     if ((dot = strchr(var_myhostname, '.')) == 0)
359 	return (DEF_MYDOMAIN);
360     return (dot + 1);
361 }
362 
363 /* check_default_privs - lookup default user attributes and validate */
364 
365 static void check_default_privs(void)
366 {
367     struct passwd *pwd;
368 
369     if ((pwd = getpwnam(var_default_privs)) == 0)
370 	msg_fatal("file %s/%s: parameter %s: unknown user name value: %s",
371 		  var_config_dir, MAIN_CONF_FILE,
372 		  VAR_DEFAULT_PRIVS, var_default_privs);
373     if ((var_default_uid = pwd->pw_uid) == 0)
374 	msg_fatal("file %s/%s: parameter %s: user %s has privileged user ID",
375 		  var_config_dir, MAIN_CONF_FILE,
376 		  VAR_DEFAULT_PRIVS, var_default_privs);
377     if ((var_default_gid = pwd->pw_gid) == 0)
378 	msg_fatal("file %s/%s: parameter %s: user %s has privileged group ID",
379 		  var_config_dir, MAIN_CONF_FILE,
380 		  VAR_DEFAULT_PRIVS, var_default_privs);
381 }
382 
383 /* check_mail_owner - lookup owner user attributes and validate */
384 
385 static void check_mail_owner(void)
386 {
387     struct passwd *pwd;
388 
389     if ((pwd = getpwnam(var_mail_owner)) == 0)
390 	msg_fatal("file %s/%s: parameter %s: unknown user name value: %s",
391 		  var_config_dir, MAIN_CONF_FILE,
392 		  VAR_MAIL_OWNER, var_mail_owner);
393     if ((var_owner_uid = pwd->pw_uid) == 0)
394 	msg_fatal("file %s/%s: parameter %s: user %s has privileged user ID",
395 		  var_config_dir, MAIN_CONF_FILE,
396 		  VAR_MAIL_OWNER, var_mail_owner);
397     if ((var_owner_gid = pwd->pw_gid) == 0)
398 	msg_fatal("file %s/%s: parameter %s: user %s has privileged group ID",
399 		  var_config_dir, MAIN_CONF_FILE,
400 		  VAR_MAIL_OWNER, var_mail_owner);
401 
402     /*
403      * This detects only some forms of sharing. Enumerating the entire
404      * password file name space could be expensive. The purpose of this code
405      * is to discourage user ID sharing by developers and package
406      * maintainers.
407      */
408     if ((pwd = getpwuid(var_owner_uid)) != 0
409 	&& strcmp(pwd->pw_name, var_mail_owner) != 0)
410 	msg_fatal("file %s/%s: parameter %s: user %s has same user ID as %s",
411 		  var_config_dir, MAIN_CONF_FILE,
412 		  VAR_MAIL_OWNER, var_mail_owner, pwd->pw_name);
413 }
414 
415 /* check_sgid_group - lookup setgid group attributes and validate */
416 
417 static void check_sgid_group(void)
418 {
419     struct group *grp;
420 
421     if ((grp = getgrnam(var_sgid_group)) == 0)
422 	msg_fatal("file %s/%s: parameter %s: unknown group name: %s",
423 		  var_config_dir, MAIN_CONF_FILE,
424 		  VAR_SGID_GROUP, var_sgid_group);
425     if ((var_sgid_gid = grp->gr_gid) == 0)
426 	msg_fatal("file %s/%s: parameter %s: group %s has privileged group ID",
427 		  var_config_dir, MAIN_CONF_FILE,
428 		  VAR_SGID_GROUP, var_sgid_group);
429 
430     /*
431      * This detects only some forms of sharing. Enumerating the entire group
432      * file name space could be expensive. The purpose of this code is to
433      * discourage group ID sharing by developers and package maintainers.
434      */
435     if ((grp = getgrgid(var_sgid_gid)) != 0
436 	&& strcmp(grp->gr_name, var_sgid_group) != 0)
437 	msg_fatal("file %s/%s: parameter %s: group %s has same group ID as %s",
438 		  var_config_dir, MAIN_CONF_FILE,
439 		  VAR_SGID_GROUP, var_sgid_group, grp->gr_name);
440 }
441 
442 /* check_overlap - disallow UID or GID sharing */
443 
444 static void check_overlap(void)
445 {
446     if (strcmp(var_default_privs, var_mail_owner) == 0)
447 	msg_fatal("file %s/%s: parameters %s and %s specify the same user %s",
448 		  var_config_dir, MAIN_CONF_FILE,
449 		  VAR_DEFAULT_PRIVS, VAR_MAIL_OWNER,
450 		  var_default_privs);
451     if (var_default_uid == var_owner_uid)
452 	msg_fatal("file %s/%s: parameters %s and %s: users %s and %s have the same user ID: %ld",
453 		  var_config_dir, MAIN_CONF_FILE,
454 		  VAR_DEFAULT_PRIVS, VAR_MAIL_OWNER,
455 		  var_default_privs, var_mail_owner,
456 		  (long) var_owner_uid);
457     if (var_default_gid == var_owner_gid)
458 	msg_fatal("file %s/%s: parameters %s and %s: users %s and %s have the same group ID: %ld",
459 		  var_config_dir, MAIN_CONF_FILE,
460 		  VAR_DEFAULT_PRIVS, VAR_MAIL_OWNER,
461 		  var_default_privs, var_mail_owner,
462 		  (long) var_owner_gid);
463     if (var_default_gid == var_sgid_gid)
464 	msg_fatal("file %s/%s: parameters %s and %s: user %s and group %s have the same group ID: %ld",
465 		  var_config_dir, MAIN_CONF_FILE,
466 		  VAR_DEFAULT_PRIVS, VAR_SGID_GROUP,
467 		  var_default_privs, var_sgid_group,
468 		  (long) var_sgid_gid);
469     if (var_owner_gid == var_sgid_gid)
470 	msg_fatal("file %s/%s: parameters %s and %s: user %s and group %s have the same group ID: %ld",
471 		  var_config_dir, MAIN_CONF_FILE,
472 		  VAR_MAIL_OWNER, VAR_SGID_GROUP,
473 		  var_mail_owner, var_sgid_group,
474 		  (long) var_sgid_gid);
475 }
476 
477 #ifdef MYORIGIN_FROM_FILE
478 
479 /* read_param_from_file - read parameter value from file */
480 
481 static char *read_param_from_file(const char *path)
482 {
483     VSTRING *why = vstring_alloc(100);
484     VSTRING *buf = vstring_alloc(100);
485     VSTREAM *fp;
486     char   *bp;
487     char   *result;
488 
489     /*
490      * Ugly macros to make complex expressions less unreadable.
491      */
492 #define SKIP(start, var, cond) do { \
493 	for (var = start; *var && (cond); var++) \
494 	    /* void */; \
495     } while (0)
496 
497 #define TRIM(s) do { \
498 	char *p; \
499 	for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
500 	    /* void */; \
501 	*p = 0; \
502     } while (0)
503 
504     fp = safe_open(path, O_RDONLY, 0, (struct stat *) 0, -1, -1, why);
505     if (fp == 0)
506 	msg_fatal("%s: %s", path, vstring_str(why));
507     vstring_get_nonl(buf, fp);
508     if (vstream_ferror(fp))			/* FIX 20070501 */
509 	msg_fatal("%s: read error: %m", path);
510     vstream_fclose(fp);
511     SKIP(vstring_str(buf), bp, ISSPACE(*bp));
512     TRIM(bp);
513     result = mystrdup(bp);
514 
515     vstring_free(why);
516     vstring_free(buf);
517     return (result);
518 }
519 
520 #endif
521 
522 /* mail_params_init - configure built-in parameters */
523 
524 void    mail_params_init()
525 {
526     static const CONFIG_STR_TABLE first_str_defaults[] = {
527 	VAR_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY, &var_syslog_facility, 1, 0,
528 	VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 0, 0,
529 	VAR_MULTI_CONF_DIRS, DEF_MULTI_CONF_DIRS, &var_multi_conf_dirs, 0, 0,
530 	/* multi_instance_wrapper may have dependencies but not dependents. */
531 	VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0,
532 	VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0,
533 	0,
534     };
535     static const CONFIG_BOOL_TABLE first_bool_defaults[] = {
536 	/* read and process the following before opening tables. */
537 	VAR_DAEMON_OPEN_FATAL, DEF_DAEMON_OPEN_FATAL, &var_daemon_open_fatal,
538 	0,
539     };
540     static const CONFIG_STR_FN_TABLE function_str_defaults[] = {
541 	VAR_MYHOSTNAME, check_myhostname, &var_myhostname, 1, 0,
542 	VAR_MYDOMAIN, check_mydomainname, &var_mydomain, 1, 0,
543 	0,
544     };
545     static const CONFIG_STR_TABLE other_str_defaults[] = {
546 	VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 1, 0,
547 	VAR_SYSLOG_NAME, DEF_SYSLOG_NAME, &var_syslog_name, 1, 0,
548 	VAR_MAIL_OWNER, DEF_MAIL_OWNER, &var_mail_owner, 1, 0,
549 	VAR_SGID_GROUP, DEF_SGID_GROUP, &var_sgid_group, 1, 0,
550 	VAR_MYDEST, DEF_MYDEST, &var_mydest, 0, 0,
551 	VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 1, 0,
552 	VAR_RELAYHOST, DEF_RELAYHOST, &var_relayhost, 0, 0,
553 	VAR_DAEMON_DIR, DEF_DAEMON_DIR, &var_daemon_dir, 1, 0,
554 	VAR_DATA_DIR, DEF_DATA_DIR, &var_data_dir, 1, 0,
555 	VAR_COMMAND_DIR, DEF_COMMAND_DIR, &var_command_dir, 1, 0,
556 	VAR_QUEUE_DIR, DEF_QUEUE_DIR, &var_queue_dir, 1, 0,
557 	VAR_PID_DIR, DEF_PID_DIR, &var_pid_dir, 1, 0,
558 	VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 0, 0,
559 	VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces, 0, 0,
560 	VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender, 1, 0,
561 	VAR_DEFAULT_PRIVS, DEF_DEFAULT_PRIVS, &var_default_privs, 1, 0,
562 	VAR_ALIAS_DB_MAP, DEF_ALIAS_DB_MAP, &var_alias_db_map, 0, 0,
563 	VAR_MAIL_RELEASE, DEF_MAIL_RELEASE, &var_mail_release, 1, 0,
564 	VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0,
565 	VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
566 	VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
567 	VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 0,
568 	VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
569 	VAR_FFLUSH_DOMAINS, DEF_FFLUSH_DOMAINS, &var_fflush_domains, 0, 0,
570 	VAR_EXPORT_ENVIRON, DEF_EXPORT_ENVIRON, &var_export_environ, 0, 0,
571 	VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0,
572 	VAR_MYNETWORKS_STYLE, DEF_MYNETWORKS_STYLE, &var_mynetworks_style, 1, 0,
573 	VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
574 	VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2,
575 	VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0,
576 	VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0,
577 	VAR_CONFIG_DIRS, DEF_CONFIG_DIRS, &var_config_dirs, 0, 0,
578 	VAR_BOUNCE_SERVICE, DEF_BOUNCE_SERVICE, &var_bounce_service, 1, 0,
579 	VAR_CLEANUP_SERVICE, DEF_CLEANUP_SERVICE, &var_cleanup_service, 1, 0,
580 	VAR_DEFER_SERVICE, DEF_DEFER_SERVICE, &var_defer_service, 1, 0,
581 	VAR_PICKUP_SERVICE, DEF_PICKUP_SERVICE, &var_pickup_service, 1, 0,
582 	VAR_QUEUE_SERVICE, DEF_QUEUE_SERVICE, &var_queue_service, 1, 0,
583 	VAR_REWRITE_SERVICE, DEF_REWRITE_SERVICE, &var_rewrite_service, 1, 0,
584 	VAR_SHOWQ_SERVICE, DEF_SHOWQ_SERVICE, &var_showq_service, 1, 0,
585 	VAR_ERROR_SERVICE, DEF_ERROR_SERVICE, &var_error_service, 1, 0,
586 	VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
587 	VAR_VERIFY_SERVICE, DEF_VERIFY_SERVICE, &var_verify_service, 1, 0,
588 	VAR_TRACE_SERVICE, DEF_TRACE_SERVICE, &var_trace_service, 1, 0,
589 	VAR_PROXYMAP_SERVICE, DEF_PROXYMAP_SERVICE, &var_proxymap_service, 1, 0,
590 	VAR_PROXYWRITE_SERVICE, DEF_PROXYWRITE_SERVICE, &var_proxywrite_service, 1, 0,
591 	VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0,
592 	/* multi_instance_wrapper may have dependencies but not dependents. */
593 	VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0,
594 	0,
595     };
596     static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
597 	VAR_MYNETWORKS, mynetworks, &var_mynetworks, 0, 0,
598 	0,
599     };
600     static const CONFIG_INT_TABLE other_int_defaults[] = {
601 	VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
602 	VAR_MAX_USE, DEF_MAX_USE, &var_use_limit, 1, 0,
603 	VAR_DONT_REMOVE, DEF_DONT_REMOVE, &var_dont_remove, 0, 0,
604 	VAR_LINE_LIMIT, DEF_LINE_LIMIT, &var_line_limit, 512, 0,
605 	VAR_HASH_QUEUE_DEPTH, DEF_HASH_QUEUE_DEPTH, &var_hash_queue_depth, 1, 0,
606 	VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
607 	VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
608 	VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
609 	VAR_FAULT_INJ_CODE, DEF_FAULT_INJ_CODE, &var_fault_inj_code, 0, 0,
610 	VAR_DB_CREATE_BUF, DEF_DB_CREATE_BUF, &var_db_create_buf, 1, 0,
611 	VAR_DB_READ_BUF, DEF_DB_READ_BUF, &var_db_read_buf, 1, 0,
612 	VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0,
613 	VAR_TOKEN_LIMIT, DEF_TOKEN_LIMIT, &var_token_limit, 1, 0,
614 	VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0,
615 	VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
616 	VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES,
617 	VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0,
618 	0,
619     };
620     static const CONFIG_LONG_TABLE long_defaults[] = {
621 	VAR_MESSAGE_LIMIT, DEF_MESSAGE_LIMIT, &var_message_limit, 0, 0,
622 	VAR_LMDB_MAP_SIZE, DEF_LMDB_MAP_SIZE, &var_lmdb_map_size, 1, 0,
623 	0,
624     };
625     static const CONFIG_TIME_TABLE time_defaults[] = {
626 	VAR_EVENT_DRAIN, DEF_EVENT_DRAIN, &var_event_drain, 1, 0,
627 	VAR_MAX_IDLE, DEF_MAX_IDLE, &var_idle_limit, 1, 0,
628 	VAR_IPC_TIMEOUT, DEF_IPC_TIMEOUT, &var_ipc_timeout, 1, 0,
629 	VAR_IPC_IDLE, DEF_IPC_IDLE, &var_ipc_idle_limit, 1, 0,
630 	VAR_IPC_TTL, DEF_IPC_TTL, &var_ipc_ttl_limit, 1, 0,
631 	VAR_TRIGGER_TIMEOUT, DEF_TRIGGER_TIMEOUT, &var_trigger_timeout, 1, 0,
632 	VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0,
633 	VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0,
634 	VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0,
635 	VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0,
636 	VAR_IN_FLOW_DELAY, DEF_IN_FLOW_DELAY, &var_in_flow_delay, 0, 10,
637 	0,
638     };
639     static const CONFIG_BOOL_TABLE bool_defaults[] = {
640 	VAR_DISABLE_DNS, DEF_DISABLE_DNS, &var_disable_dns,
641 	VAR_SOFT_BOUNCE, DEF_SOFT_BOUNCE, &var_soft_bounce,
642 	VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special,
643 	VAR_STRICT_8BITMIME, DEF_STRICT_8BITMIME, &var_strict_8bitmime,
644 	VAR_STRICT_7BIT_HDRS, DEF_STRICT_7BIT_HDRS, &var_strict_7bit_hdrs,
645 	VAR_STRICT_8BIT_BODY, DEF_STRICT_8BIT_BODY, &var_strict_8bit_body,
646 	VAR_STRICT_ENCODING, DEF_STRICT_ENCODING, &var_strict_encoding,
647 	VAR_DISABLE_MIME_INPUT, DEF_DISABLE_MIME_INPUT, &var_disable_mime_input,
648 	VAR_DISABLE_MIME_OCONV, DEF_DISABLE_MIME_OCONV, &var_disable_mime_oconv,
649 	VAR_VERIFY_NEG_CACHE, DEF_VERIFY_NEG_CACHE, &var_verify_neg_cache,
650 	VAR_OLDLOG_COMPAT, DEF_OLDLOG_COMPAT, &var_oldlog_compat,
651 	VAR_HELPFUL_WARNINGS, DEF_HELPFUL_WARNINGS, &var_helpful_warnings,
652 	VAR_CYRUS_SASL_AUTHZID, DEF_CYRUS_SASL_AUTHZID, &var_cyrus_sasl_authzid,
653 	VAR_MULTI_ENABLE, DEF_MULTI_ENABLE, &var_multi_enable,
654 	VAR_LONG_QUEUE_IDS, DEF_LONG_QUEUE_IDS, &var_long_queue_ids,
655 	0,
656     };
657     const char *cp;
658     INET_PROTO_INFO *proto_info;
659 
660     /*
661      * Extract syslog_facility early, so that from here on all errors are
662      * logged with the proper facility.
663      */
664     get_mail_conf_str_table(first_str_defaults);
665 
666     if (!msg_syslog_facility(var_syslog_facility))
667 	msg_fatal("file %s/%s: parameter %s: unrecognized value: %s",
668 		  var_config_dir, MAIN_CONF_FILE,
669 		  VAR_SYSLOG_FACILITY, var_syslog_facility);
670 
671     /*
672      * Should daemons terminate after table open error, or should they
673      * continue execution with reduced functionality?
674      */
675     get_mail_conf_bool_table(first_bool_defaults);
676     if (var_daemon_open_fatal)
677 	dict_allow_surrogate = 0;
678 
679     /*
680      * What protocols should we attempt to support? The result is stored in
681      * the global inet_proto_table variable.
682      */
683     proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
684 
685     /*
686      * Variables whose defaults are determined at runtime. Some sites use
687      * short hostnames in the host table; some sites name their system after
688      * the domain.
689      */
690     get_mail_conf_str_fn_table(function_str_defaults);
691     if (!valid_hostname(var_myhostname, DO_GRIPE))
692 	msg_fatal("file %s/%s: parameter %s: bad parameter value: %s",
693 		  var_config_dir, MAIN_CONF_FILE,
694 		  VAR_MYHOSTNAME, var_myhostname);
695     if (!valid_hostname(var_mydomain, DO_GRIPE))
696 	msg_fatal("file %s/%s: parameter %s: bad parameter value: %s",
697 		  var_config_dir, MAIN_CONF_FILE,
698 		  VAR_MYDOMAIN, var_mydomain);
699 
700     /*
701      * Variables that are needed by almost every program.
702      *
703      * XXX Reading the myorigin value from file is originally a Debian Linux
704      * feature. This code is not enabled by default because of problems: 1)
705      * it re-implements its own parameter syntax checks, and 2) it does not
706      * implement $name expansions.
707      */
708     get_mail_conf_str_table(other_str_defaults);
709 #ifdef MYORIGIN_FROM_FILE
710     if (*var_myorigin == '/') {
711 	char   *origin = read_param_from_file(var_myorigin);
712 
713 	if (*origin == 0)
714 	    msg_fatal("%s file %s is empty", VAR_MYORIGIN, var_myorigin);
715 	myfree(var_myorigin);			/* FIX 20070501 */
716 	var_myorigin = origin;
717     }
718 #endif
719     get_mail_conf_int_table(other_int_defaults);
720     get_mail_conf_long_table(long_defaults);
721     get_mail_conf_bool_table(bool_defaults);
722     get_mail_conf_time_table(time_defaults);
723     check_default_privs();
724     check_mail_owner();
725     check_sgid_group();
726     check_overlap();
727 #ifdef HAS_DB
728     dict_db_cache_size = var_db_read_buf;
729 #endif
730 #ifdef HAS_LMDB
731     dict_lmdb_map_size = var_lmdb_map_size;
732 #endif
733     inet_windowsize = var_inet_windowsize;
734 
735     /*
736      * Variables whose defaults are determined at runtime, after other
737      * variables have been set. This dependency is admittedly a bit tricky.
738      * XXX Perhaps we should just register variables, and let the evaluator
739      * figure out in what order to evaluate things.
740      */
741     get_mail_conf_str_fn_table(function_str_defaults_2);
742 
743     /*
744      * FIX 200412 The IPv6 patch did not call own_inet_addr_list() before
745      * entering the chroot jail on Linux IPv6 systems. Linux has the IPv6
746      * interface list in /proc, which is not available after chrooting.
747      */
748     (void) own_inet_addr_list();
749 
750     /*
751      * The PID variable cannot be set from the configuration file!!
752      */
753     set_mail_conf_int(VAR_PID, var_pid = getpid());
754 
755     /*
756      * Neither can the start time variable. It isn't even visible.
757      */
758     time(&var_starttime);
759 
760     /*
761      * Export the syslog name so children can inherit and use it before they
762      * have initialized.
763      */
764     if ((cp = safe_getenv(CONF_ENV_LOGTAG)) == 0
765 	|| strcmp(cp, var_syslog_name) != 0)
766 	if (setenv(CONF_ENV_LOGTAG, var_syslog_name, 1) < 0)
767 	    msg_fatal("setenv %s %s: %m", CONF_ENV_LOGTAG, var_syslog_name);
768 
769     /*
770      * I have seen this happen just too often.
771      */
772     if (strcasecmp(var_myhostname, var_relayhost) == 0)
773 	msg_fatal("%s and %s parameter settings must not be identical: %s",
774 		  VAR_MYHOSTNAME, VAR_RELAYHOST, var_myhostname);
775 
776     /*
777      * XXX These should be caught by a proper parameter parsing algorithm.
778      */
779     if (var_myorigin[strcspn(var_myorigin, ", \t\r\n")])
780 	msg_fatal("%s parameter setting must not contain multiple values: %s",
781 		  VAR_MYORIGIN, var_myorigin);
782 
783     if (var_relayhost[strcspn(var_relayhost, ", \t\r\n")])
784 	msg_fatal("%s parameter setting must not contain multiple values: %s",
785 		  VAR_RELAYHOST, var_relayhost);
786 
787     /*
788      * One more sanity check.
789      */
790     if ((cp = verp_delims_verify(var_verp_delims)) != 0)
791 	msg_fatal("file %s/%s: parameters %s and %s: %s",
792 		  var_config_dir, MAIN_CONF_FILE,
793 		  VAR_VERP_DELIMS, VAR_VERP_FILTER, cp);
794 }
795