1/*++
2/* NAME
3/*	postconf_builtin 3
4/* SUMMARY
5/*	built-in main.cf parameter support
6/* SYNOPSIS
7/*	#include <postconf.h>
8/*
9/*	void	pcf_register_builtin_parameters(procname, pid)
10/*	const char *procname;
11/*	pid_t	pid;
12/* DESCRIPTION
13/*	pcf_register_builtin_parameters() initializes the global
14/*	main.cf parameter name space and adds all built-in parameter
15/*	information.
16/*
17/*	Arguments:
18/*.IP procname
19/*	Provides the default value for the "process_name" parameter.
20/*.IP pid
21/*	Provides the default value for the "process_id" parameter.
22/* DIAGNOSTICS
23/*	Problems are reported to the standard error stream.
24/* LICENSE
25/* .ad
26/* .fi
27/*	The Secure Mailer license must be distributed with this software.
28/* AUTHOR(S)
29/*	Wietse Venema
30/*	IBM T.J. Watson Research
31/*	P.O. Box 704
32/*	Yorktown Heights, NY 10598, USA
33/*--*/
34
35/* System library. */
36
37#include <sys_defs.h>
38#include <string.h>
39
40#ifdef USE_PATHS_H
41#include <paths.h>
42#endif
43
44/* Utility library. */
45
46#include <msg.h>
47#include <mymalloc.h>
48#include <htable.h>
49#include <vstring.h>
50#include <get_hostname.h>
51#include <stringops.h>
52
53/* Global library. */
54
55#include <mynetworks.h>
56#include <mail_conf.h>
57#include <mail_params.h>
58#include <mail_version.h>
59#include <mail_proto.h>
60#include <mail_addr.h>
61#include <inet_proto.h>
62#include <server_acl.h>
63
64/* Application-specific. */
65
66#include <postconf.h>
67
68 /*
69  * Support for built-in parameters: declarations generated by scanning
70  * actual C source files.
71  */
72#include "time_vars.h"
73#include "bool_vars.h"
74#include "int_vars.h"
75#include "str_vars.h"
76#include "raw_vars.h"
77#include "nint_vars.h"
78#include "nbool_vars.h"
79#include "long_vars.h"
80
81 /*
82  * Support for built-in parameters: manually extracted.
83  */
84#include "install_vars.h"
85
86 /*
87  * Support for built-in parameters: lookup tables generated by scanning
88  * actual C source files.
89  */
90static const CONFIG_TIME_TABLE pcf_time_table[] = {
91#include "time_table.h"
92    0,
93};
94
95static const CONFIG_BOOL_TABLE pcf_bool_table[] = {
96#include "bool_table.h"
97    0,
98};
99
100static const CONFIG_INT_TABLE pcf_int_table[] = {
101#include "int_table.h"
102    0,
103};
104
105static const CONFIG_STR_TABLE pcf_str_table[] = {
106#include "str_table.h"
107#include "install_table.h"
108    0,
109};
110
111static const CONFIG_RAW_TABLE pcf_raw_table[] = {
112#include "raw_table.h"
113    0,
114};
115
116static const CONFIG_NINT_TABLE pcf_nint_table[] = {
117#include "nint_table.h"
118    0,
119};
120
121static const CONFIG_NBOOL_TABLE pcf_nbool_table[] = {
122#include "nbool_table.h"
123    0,
124};
125
126static const CONFIG_LONG_TABLE pcf_long_table[] = {
127#include "long_table.h"
128    0,
129};
130
131 /*
132  * Legacy parameters for backwards compatibility.
133  */
134static const CONFIG_STR_TABLE pcf_legacy_str_table[] = {
135    {"virtual_maps", ""},
136    {"fallback_relay", ""},
137    {"authorized_verp_clients", ""},
138    {"smtpd_client_connection_limit_exceptions", ""},
139    0,
140};
141
142 /*
143  * Parameters whose default values are normally initialized by calling a
144  * function. We direct the calls to our own versions of those functions
145  * because the run-time conditions are slightly different.
146  *
147  * Important: if the evaluation of a parameter default value has any side
148  * effects, then those side effects must happen only once.
149  */
150static const char *pcf_check_myhostname(void);
151static const char *pcf_check_mydomainname(void);
152static const char *pcf_mynetworks(void);
153
154#include "str_fn_vars.h"
155
156static const CONFIG_STR_FN_TABLE pcf_str_fn_table[] = {
157#include "str_fn_table.h"
158    0,
159};
160
161 /*
162  * Parameters whose default values are normally initialized by ad-hoc code.
163  * The AWK script cannot identify these parameters or values, so we provide
164  * our own.
165  *
166  * Important: if the evaluation of a parameter default value has any side
167  * effects, then those side effects must happen only once.
168  */
169static CONFIG_STR_TABLE pcf_adhoc_procname = {VAR_PROCNAME};
170static CONFIG_INT_TABLE pcf_adhoc_pid = {VAR_PID};
171
172#define STR(x) vstring_str(x)
173
174/* pcf_check_myhostname - lookup hostname and validate */
175
176static const char *pcf_check_myhostname(void)
177{
178    static const char *name;
179    const char *dot;
180    const char *domain;
181
182    /*
183     * Use cached result.
184     */
185    if (name)
186	return (name);
187
188    /*
189     * If the local machine name is not in FQDN form, try to append the
190     * contents of $mydomain.
191     */
192    name = get_hostname();
193    if ((dot = strchr(name, '.')) == 0) {
194	if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
195	    domain = DEF_MYDOMAIN;
196	name = concatenate(name, ".", domain, (char *) 0);
197    }
198    return (name);
199}
200
201/* pcf_get_myhostname - look up and store my hostname */
202
203static void pcf_get_myhostname(void)
204{
205    const char *name;
206
207    if ((name = mail_conf_lookup_eval(VAR_MYHOSTNAME)) == 0)
208	name = pcf_check_myhostname();
209    var_myhostname = mystrdup(name);
210}
211
212/* pcf_check_mydomainname - lookup domain name and validate */
213
214static const char *pcf_check_mydomainname(void)
215{
216    static const char *domain;
217    char   *dot;
218
219    /*
220     * Use cached result.
221     */
222    if (domain)
223	return (domain);
224
225    /*
226     * Use the hostname when it is not a FQDN ("foo"), or when the hostname
227     * actually is a domain name ("foo.com").
228     */
229    if (var_myhostname == 0)
230	pcf_get_myhostname();
231    if ((dot = strchr(var_myhostname, '.')) == 0 || strchr(dot + 1, '.') == 0)
232	return (domain = DEF_MYDOMAIN);
233    return (domain = mystrdup(dot + 1));
234}
235
236/* pcf_mynetworks - lookup network address list */
237
238static const char *pcf_mynetworks(void)
239{
240    static const char *networks;
241    INET_PROTO_INFO *proto_info;
242    const char *junk;
243
244    /*
245     * Use cached result.
246     */
247    if (networks)
248	return (networks);
249
250    if (var_inet_interfaces == 0) {
251	if ((pcf_cmd_mode & PCF_SHOW_DEFS)
252	    || (junk = mail_conf_lookup_eval(VAR_INET_INTERFACES)) == 0)
253	    junk = DEF_INET_INTERFACES;
254	var_inet_interfaces = mystrdup(junk);
255    }
256    if (var_mynetworks_style == 0) {
257	if ((pcf_cmd_mode & PCF_SHOW_DEFS)
258	    || (junk = mail_conf_lookup_eval(VAR_MYNETWORKS_STYLE)) == 0)
259	    junk = DEF_MYNETWORKS_STYLE;
260	var_mynetworks_style = mystrdup(junk);
261    }
262    if (var_inet_protocols == 0) {
263	if ((pcf_cmd_mode & PCF_SHOW_DEFS)
264	    || (junk = mail_conf_lookup_eval(VAR_INET_PROTOCOLS)) == 0)
265	    junk = DEF_INET_PROTOCOLS;
266	var_inet_protocols = mystrdup(junk);
267	proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
268    }
269    return (networks = mystrdup(mynetworks()));
270}
271
272/* pcf_conv_bool_parameter - get boolean parameter string value */
273
274static const char *pcf_conv_bool_parameter(char *ptr)
275{
276    CONFIG_BOOL_TABLE *cbt = (CONFIG_BOOL_TABLE *) ptr;
277
278    return (cbt->defval ? "yes" : "no");
279}
280
281/* pcf_conv_time_parameter - get relative time parameter string value */
282
283static const char *pcf_conv_time_parameter(char *ptr)
284{
285    CONFIG_TIME_TABLE *ctt = (CONFIG_TIME_TABLE *) ptr;
286
287    return (ctt->defval);
288}
289
290/* pcf_conv_int_parameter - get integer parameter string value */
291
292static const char *pcf_conv_int_parameter(char *ptr)
293{
294    CONFIG_INT_TABLE *cit = (CONFIG_INT_TABLE *) ptr;
295
296    return (STR(vstring_sprintf(pcf_param_string_buf, "%d", cit->defval)));
297}
298
299/* pcf_conv_str_parameter - get string parameter string value */
300
301static const char *pcf_conv_str_parameter(char *ptr)
302{
303    CONFIG_STR_TABLE *cst = (CONFIG_STR_TABLE *) ptr;
304
305    return (cst->defval);
306}
307
308/* pcf_conv_str_fn_parameter - get string-function parameter string value */
309
310static const char *pcf_conv_str_fn_parameter(char *ptr)
311{
312    CONFIG_STR_FN_TABLE *cft = (CONFIG_STR_FN_TABLE *) ptr;
313
314    return (cft->defval());
315}
316
317/* pcf_conv_raw_parameter - get raw string parameter string value */
318
319static const char *pcf_conv_raw_parameter(char *ptr)
320{
321    CONFIG_RAW_TABLE *rst = (CONFIG_RAW_TABLE *) ptr;
322
323    return (rst->defval);
324}
325
326/* pcf_conv_nint_parameter - get new integer parameter string value */
327
328static const char *pcf_conv_nint_parameter(char *ptr)
329{
330    CONFIG_NINT_TABLE *rst = (CONFIG_NINT_TABLE *) ptr;
331
332    return (rst->defval);
333}
334
335/* pcf_conv_nbool_parameter - get new boolean parameter string value */
336
337static const char *pcf_conv_nbool_parameter(char *ptr)
338{
339    CONFIG_NBOOL_TABLE *bst = (CONFIG_NBOOL_TABLE *) ptr;
340
341    return (bst->defval);
342}
343
344/* pcf_conv_long_parameter - get long parameter string value */
345
346static const char *pcf_conv_long_parameter(char *ptr)
347{
348    CONFIG_LONG_TABLE *clt = (CONFIG_LONG_TABLE *) ptr;
349
350    return (STR(vstring_sprintf(pcf_param_string_buf, "%ld", clt->defval)));
351}
352
353/* pcf_register_builtin_parameters - add built-ins to the global name space */
354
355void    pcf_register_builtin_parameters(const char *procname, pid_t pid)
356{
357    const char *myname = "pcf_register_builtin_parameters";
358    const CONFIG_TIME_TABLE *ctt;
359    const CONFIG_BOOL_TABLE *cbt;
360    const CONFIG_INT_TABLE *cit;
361    const CONFIG_STR_TABLE *cst;
362    const CONFIG_STR_FN_TABLE *cft;
363    const CONFIG_RAW_TABLE *rst;
364    const CONFIG_NINT_TABLE *nst;
365    const CONFIG_NBOOL_TABLE *bst;
366    const CONFIG_LONG_TABLE *lst;
367
368    /*
369     * Sanity checks.
370     */
371    if (pcf_param_table != 0)
372	msg_panic("%s: global parameter table is already initialized", myname);
373
374    /*
375     * Initialize the global parameter table.
376     */
377    pcf_param_table = PCF_PARAM_TABLE_CREATE(1000);
378
379    /*
380     * Add the built-in parameters to the global name space. The class
381     * (built-in) is tentative; some parameters are actually service-defined,
382     * but they have their own default value.
383     */
384    for (ctt = pcf_time_table; ctt->name; ctt++)
385	PCF_PARAM_TABLE_ENTER(pcf_param_table, ctt->name,
386			      PCF_PARAM_FLAG_BUILTIN, (char *) ctt,
387			      pcf_conv_time_parameter);
388    for (cbt = pcf_bool_table; cbt->name; cbt++)
389	PCF_PARAM_TABLE_ENTER(pcf_param_table, cbt->name,
390			      PCF_PARAM_FLAG_BUILTIN, (char *) cbt,
391			      pcf_conv_bool_parameter);
392    for (cit = pcf_int_table; cit->name; cit++)
393	PCF_PARAM_TABLE_ENTER(pcf_param_table, cit->name,
394			      PCF_PARAM_FLAG_BUILTIN, (char *) cit,
395			      pcf_conv_int_parameter);
396    for (cst = pcf_str_table; cst->name; cst++)
397	PCF_PARAM_TABLE_ENTER(pcf_param_table, cst->name,
398			      PCF_PARAM_FLAG_BUILTIN, (char *) cst,
399			      pcf_conv_str_parameter);
400    for (cft = pcf_str_fn_table; cft->name; cft++)
401	PCF_PARAM_TABLE_ENTER(pcf_param_table, cft->name,
402			      PCF_PARAM_FLAG_BUILTIN, (char *) cft,
403			      pcf_conv_str_fn_parameter);
404    for (rst = pcf_raw_table; rst->name; rst++)
405	PCF_PARAM_TABLE_ENTER(pcf_param_table, rst->name,
406			      PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_RAW,
407			      (char *) rst, pcf_conv_raw_parameter);
408    for (nst = pcf_nint_table; nst->name; nst++)
409	PCF_PARAM_TABLE_ENTER(pcf_param_table, nst->name,
410			      PCF_PARAM_FLAG_BUILTIN, (char *) nst,
411			      pcf_conv_nint_parameter);
412    for (bst = pcf_nbool_table; bst->name; bst++)
413	PCF_PARAM_TABLE_ENTER(pcf_param_table, bst->name,
414			      PCF_PARAM_FLAG_BUILTIN, (char *) bst,
415			      pcf_conv_nbool_parameter);
416    for (lst = pcf_long_table; lst->name; lst++)
417	PCF_PARAM_TABLE_ENTER(pcf_param_table, lst->name,
418			      PCF_PARAM_FLAG_BUILTIN, (char *) lst,
419			      pcf_conv_long_parameter);
420
421    /*
422     * Register legacy parameters (used as a backwards-compatible migration
423     * aid).
424     */
425    for (cst = pcf_legacy_str_table; cst->name; cst++)
426	PCF_PARAM_TABLE_ENTER(pcf_param_table, cst->name,
427			      PCF_PARAM_FLAG_LEGACY, (char *) cst,
428			      pcf_conv_str_parameter);
429
430    /*
431     * Register parameters whose default value is normally initialized by
432     * ad-hoc code.
433     */
434    pcf_adhoc_procname.defval = mystrdup(procname);
435    PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_procname.name,
436			  PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY,
437			  (char *) &pcf_adhoc_procname, pcf_conv_str_parameter);
438    pcf_adhoc_pid.defval = pid;
439    PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_pid.name,
440			  PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY,
441			  (char *) &pcf_adhoc_pid, pcf_conv_int_parameter);
442}
443