1 /*        $NetBSD: trivial-rewrite.c,v 1.5 2025/02/25 19:15:51 christos Exp $   */
2 
3 /*++
4 /* NAME
5 /*        trivial-rewrite 8
6 /* SUMMARY
7 /*        Postfix address rewriting and resolving daemon
8 /* SYNOPSIS
9 /*        \fBtrivial-rewrite\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /*        The \fBtrivial-rewrite\fR(8) daemon processes three types of client
12 /*        service requests:
13 /* .IP "\fBrewrite \fIcontext address\fR"
14 /*        Rewrite an address to standard form, according to the
15 /*        address rewriting context:
16 /* .RS
17 /* .IP \fBlocal\fR
18 /*        Append the domain names specified with \fB$myorigin\fR or
19 /*        \fB$mydomain\fR to incomplete addresses; do \fBswap_bangpath\fR
20 /*        and \fBallow_percent_hack\fR processing as described below, and
21 /*        strip source routed addresses (\fI@site,@site:user@domain\fR)
22 /*        to \fIuser@domain\fR form.
23 /* .IP \fBremote\fR
24 /*        Append the domain name specified with
25 /*        \fB$remote_header_rewrite_domain\fR to incomplete
26 /*        addresses. Otherwise the result is identical to that of
27 /*        the \fBlocal\fR address rewriting context. This prevents
28 /*        Postfix from appending the local domain to spam from poorly
29 /*        written remote clients.
30 /* .RE
31 /* .IP "\fBresolve \fIsender\fR \fIaddress\fR"
32 /*        Resolve the address to a (\fItransport\fR, \fInexthop\fR,
33 /*        \fIrecipient\fR, \fIflags\fR) quadruple. The meaning of
34 /*        the results is as follows:
35 /* .RS
36 /* .IP \fItransport\fR
37 /*        The delivery agent to use. This is the first field of an entry
38 /*        in the \fBmaster.cf\fR file.
39 /* .IP \fInexthop\fR
40 /*        The host to send to and optional delivery method information.
41 /* .IP \fIrecipient\fR
42 /*        The envelope recipient address that is passed on to \fInexthop\fR.
43 /* .IP \fIflags\fR
44 /*        The address class, whether the address requires relaying,
45 /*        whether the address has problems, and whether the request failed.
46 /* .RE
47 /* .IP "\fBverify \fIsender\fR \fIaddress\fR"
48 /*        Resolve the address for address verification purposes.
49 /* SERVER PROCESS MANAGEMENT
50 /* .ad
51 /* .fi
52 /*        The \fBtrivial-rewrite\fR(8) servers run under control by
53 /*        the Postfix master(8)
54 /*        server.  Each server can handle multiple simultaneous connections.
55 /*        When all servers are busy while a client connects, the master
56 /*        creates a new server process, provided that the trivial-rewrite
57 /*        server process limit is not exceeded.
58 /*        Each trivial-rewrite server terminates after
59 /*        serving at least \fB$max_use\fR clients of after \fB$max_idle\fR
60 /*        seconds of idle time.
61 /* STANDARDS
62 /* .ad
63 /* .fi
64 /*        None. The command does not interact with the outside world.
65 /* SECURITY
66 /* .ad
67 /* .fi
68 /*        The \fBtrivial-rewrite\fR(8) daemon is not security sensitive.
69 /*        By default, this daemon does not talk to remote or local users.
70 /*        It can run at a fixed low privilege in a chrooted environment.
71 /* DIAGNOSTICS
72 /*        Problems and transactions are logged to \fBsyslogd\fR(8)
73 /*        or \fBpostlogd\fR(8).
74 /* CONFIGURATION PARAMETERS
75 /* .ad
76 /* .fi
77 /*        On busy mail systems a long time may pass before a \fBmain.cf\fR
78 /*        change affecting \fBtrivial-rewrite\fR(8) is picked up. Use the command
79 /*        "\fBpostfix reload\fR" to speed up a change.
80 /*
81 /*        The text below provides only a parameter summary. See
82 /*        \fBpostconf\fR(5) for more details including examples.
83 /* COMPATIBILITY CONTROLS
84 /* .ad
85 /* .fi
86 /* .IP "\fBresolve_dequoted_address (yes)\fR"
87 /*        Resolve a recipient address safely instead of correctly, by
88 /*        looking inside quotes.
89 /* .PP
90 /*        Available with Postfix version 2.1 and later:
91 /* .IP "\fBresolve_null_domain (no)\fR"
92 /*        Resolve an address that ends in the "@" null domain as if the
93 /*        local hostname were specified, instead of rejecting the address as
94 /*        invalid.
95 /* .PP
96 /*        Available with Postfix version 2.3 and later:
97 /* .IP "\fBresolve_numeric_domain (no)\fR"
98 /*        Resolve "user@ipaddress" as "user@[ipaddress]", instead of
99 /*        rejecting the address as invalid.
100 /* .PP
101 /*        Available with Postfix version 2.5 and later:
102 /* .IP "\fBallow_min_user (no)\fR"
103 /*        Allow a sender or recipient address to have `-' as the first
104 /*        character.
105 /* ADDRESS REWRITING CONTROLS
106 /* .ad
107 /* .fi
108 /* .IP "\fBmyorigin ($myhostname)\fR"
109 /*        The domain name that locally-posted mail appears to come
110 /*        from, and that locally posted mail is delivered to.
111 /* .IP "\fBallow_percent_hack (yes)\fR"
112 /*        Enable the rewriting of the form "user%domain" to "user@domain".
113 /* .IP "\fBappend_at_myorigin (yes)\fR"
114 /*        With locally submitted mail, append the string "@$myorigin" to mail
115 /*        addresses without domain information.
116 /* .IP "\fBappend_dot_mydomain (Postfix >= 3.0: no, Postfix < 3.0: yes)\fR"
117 /*        With locally submitted mail, append the string ".$mydomain" to
118 /*        addresses that have no ".domain" information.
119 /* .IP "\fBrecipient_delimiter (empty)\fR"
120 /*        The set of characters that can separate an email address
121 /*        localpart, user name, or a .forward file name from its extension.
122 /* .IP "\fBswap_bangpath (yes)\fR"
123 /*        Enable the rewriting of "site!user" into "user@site".
124 /* .PP
125 /*        Available in Postfix 2.2 and later:
126 /* .IP "\fBremote_header_rewrite_domain (empty)\fR"
127 /*        Rewrite or add message headers in mail from remote clients if
128 /*        the remote_header_rewrite_domain parameter value is non-empty,
129 /*        updating incomplete addresses with the domain specified in the
130 /*        remote_header_rewrite_domain parameter, and adding missing headers.
131 /* ROUTING CONTROLS
132 /* .ad
133 /* .fi
134 /*        The following is applicable to Postfix version 2.0 and later.
135 /*        Earlier versions do not have support for: virtual_transport,
136 /*        relay_transport, virtual_alias_domains, virtual_mailbox_domains
137 /*        or proxy_interfaces.
138 /* .IP "\fBlocal_transport (local:$myhostname)\fR"
139 /*        The default mail delivery transport and next-hop destination
140 /*        for final delivery to domains listed with mydestination, and for
141 /*        [ipaddress] destinations that match $inet_interfaces or $proxy_interfaces.
142 /* .IP "\fBvirtual_transport (virtual)\fR"
143 /*        The default mail delivery transport and next-hop destination for
144 /*        final delivery to domains listed with $virtual_mailbox_domains.
145 /* .IP "\fBrelay_transport (relay)\fR"
146 /*        The default mail delivery transport and next-hop destination for
147 /*        the relay domain address class: recipient domains that match
148 /*        $relay_domains.
149 /* .IP "\fBdefault_transport (smtp)\fR"
150 /*        The default mail delivery transport and next-hop destination for
151 /*        the default domain class: recipient domains that do not match
152 /*        $mydestination, $inet_interfaces,
153 /*        $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
154 /*        or $relay_domains.
155 /* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR"
156 /*        A list of Postfix features where the pattern "example.com" also
157 /*        matches subdomains of example.com,
158 /*        instead of requiring an explicit ".example.com" pattern.
159 /* .IP "\fBrelayhost (empty)\fR"
160 /*        The next-hop destination(s) for non-local mail; takes precedence
161 /*        over non-local domains in recipient addresses.
162 /* .IP "\fBtransport_maps (empty)\fR"
163 /*        Optional lookup tables with mappings from recipient address to
164 /*        (message delivery transport, next-hop destination).
165 /* .PP
166 /*        Available in Postfix version 2.3 and later:
167 /* .IP "\fBsender_dependent_relayhost_maps (empty)\fR"
168 /*        A sender-dependent override for the global relayhost parameter
169 /*        setting.
170 /* .PP
171 /*        Available in Postfix version 2.5 and later:
172 /* .IP "\fBempty_address_relayhost_maps_lookup_key (<>)\fR"
173 /*        The sender_dependent_relayhost_maps search string that will be
174 /*        used instead of the null sender address.
175 /* .PP
176 /*        Available in Postfix version 2.7 and later:
177 /* .IP "\fBempty_address_default_transport_maps_lookup_key (<>)\fR"
178 /*        The sender_dependent_default_transport_maps search string that
179 /*        will be used instead of the null sender address.
180 /* .IP "\fBsender_dependent_default_transport_maps (empty)\fR"
181 /*        A sender-dependent override for the global default_transport
182 /*        parameter setting.
183 /* ADDRESS VERIFICATION CONTROLS
184 /* .ad
185 /* .fi
186 /*        Postfix version 2.1 introduces sender and recipient address verification.
187 /*        This feature is implemented by sending probe email messages that
188 /*        are not actually delivered.
189 /*        By default, address verification probes use the same route
190 /*        as regular mail. To override specific aspects of message
191 /*        routing for address verification probes, specify one or more
192 /*        of the following:
193 /* .IP "\fBaddress_verify_local_transport ($local_transport)\fR"
194 /*        Overrides the local_transport parameter setting for address
195 /*        verification probes.
196 /* .IP "\fBaddress_verify_virtual_transport ($virtual_transport)\fR"
197 /*        Overrides the virtual_transport parameter setting for address
198 /*        verification probes.
199 /* .IP "\fBaddress_verify_relay_transport ($relay_transport)\fR"
200 /*        Overrides the relay_transport parameter setting for address
201 /*        verification probes.
202 /* .IP "\fBaddress_verify_default_transport ($default_transport)\fR"
203 /*        Overrides the default_transport parameter setting for address
204 /*        verification probes.
205 /* .IP "\fBaddress_verify_relayhost ($relayhost)\fR"
206 /*        Overrides the relayhost parameter setting for address verification
207 /*        probes.
208 /* .IP "\fBaddress_verify_transport_maps ($transport_maps)\fR"
209 /*        Overrides the transport_maps parameter setting for address verification
210 /*        probes.
211 /* .PP
212 /*        Available in Postfix version 2.3 and later:
213 /* .IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
214 /*        Overrides the sender_dependent_relayhost_maps parameter setting for address
215 /*        verification probes.
216 /* .PP
217 /*        Available in Postfix version 2.7 and later:
218 /* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
219 /*        Overrides the sender_dependent_default_transport_maps parameter
220 /*        setting for address verification probes.
221 /* MISCELLANEOUS CONTROLS
222 /* .ad
223 /* .fi
224 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
225 /*        The default location of the Postfix main.cf and master.cf
226 /*        configuration files.
227 /* .IP "\fBdaemon_timeout (18000s)\fR"
228 /*        How much time a Postfix daemon process may take to handle a
229 /*        request before it is terminated by a built-in watchdog timer.
230 /* .IP "\fBempty_address_recipient (MAILER-DAEMON)\fR"
231 /*        The recipient of mail addressed to the null address.
232 /* .IP "\fBipc_timeout (3600s)\fR"
233 /*        The time limit for sending or receiving information over an internal
234 /*        communication channel.
235 /* .IP "\fBmax_idle (100s)\fR"
236 /*        The maximum amount of time that an idle Postfix daemon process waits
237 /*        for an incoming connection before terminating voluntarily.
238 /* .IP "\fBmax_use (100)\fR"
239 /*        The maximal number of incoming connections that a Postfix daemon
240 /*        process will service before terminating voluntarily.
241 /* .IP "\fBrelocated_maps (empty)\fR"
242 /*        Optional lookup tables with new contact information for users or
243 /*        domains that no longer exist.
244 /* .IP "\fBprocess_id (read-only)\fR"
245 /*        The process ID of a Postfix command or daemon process.
246 /* .IP "\fBprocess_name (read-only)\fR"
247 /*        The process name of a Postfix command or daemon process.
248 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
249 /*        The location of the Postfix top-level queue directory.
250 /* .IP "\fBshow_user_unknown_table_name (yes)\fR"
251 /*        Display the name of the recipient table in the "User unknown"
252 /*        responses.
253 /* .IP "\fBsyslog_facility (mail)\fR"
254 /*        The syslog facility of Postfix logging.
255 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
256 /*        A prefix that is prepended to the process name in syslog
257 /*        records, so that, for example, "smtpd" becomes "prefix/smtpd".
258 /* .PP
259 /*        Available in Postfix version 2.0 and later:
260 /* .IP "\fBhelpful_warnings (yes)\fR"
261 /*        Log warnings about problematic configuration settings, and provide
262 /*        helpful suggestions.
263 /* .PP
264 /*        Available in Postfix 3.3 and later:
265 /* .IP "\fBservice_name (read-only)\fR"
266 /*        The master.cf service name of a Postfix daemon process.
267 /* SEE ALSO
268 /*        postconf(5), configuration parameters
269 /*        transport(5), transport table format
270 /*        relocated(5), format of the "user has moved" table
271 /*        master(8), process manager
272 /*        postlogd(8), Postfix logging
273 /*        syslogd(8), system logging
274 /* README FILES
275 /* .ad
276 /* .fi
277 /*        Use "\fBpostconf readme_directory\fR" or
278 /*        "\fBpostconf html_directory\fR" to locate this information.
279 /* .na
280 /* .nf
281 /*        ADDRESS_CLASS_README, Postfix address classes howto
282 /*        ADDRESS_VERIFICATION_README, Postfix address verification
283 /* LICENSE
284 /* .ad
285 /* .fi
286 /*        The Secure Mailer license must be distributed with this software.
287 /* AUTHOR(S)
288 /*        Wietse Venema
289 /*        IBM T.J. Watson Research
290 /*        P.O. Box 704
291 /*        Yorktown Heights, NY 10598, USA
292 /*
293 /*        Wietse Venema
294 /*        Google, Inc.
295 /*        111 8th Avenue
296 /*        New York, NY 10011, USA
297 /*--*/
298 
299 /* System library. */
300 
301 #include <sys_defs.h>
302 #include <unistd.h>
303 #include <stdlib.h>
304 #include <string.h>
305 
306 /* Utility library. */
307 
308 #include <msg.h>
309 #include <vstring.h>
310 #include <vstream.h>
311 #include <vstring_vstream.h>
312 #include <split_at.h>
313 #include <stringops.h>
314 #include <dict.h>
315 #include <events.h>
316 
317 /* Global library. */
318 
319 #include <mail_params.h>
320 #include <mail_version.h>
321 #include <mail_proto.h>
322 #include <resolve_local.h>
323 #include <mail_conf.h>
324 #include <resolve_clnt.h>
325 #include <rewrite_clnt.h>
326 #include <tok822.h>
327 #include <mail_addr.h>
328 
329 /* Multi server skeleton. */
330 
331 #include <mail_server.h>
332 
333 /* Application-specific. */
334 
335 #include <trivial-rewrite.h>
336 #include <transport.h>
337 
338 static VSTRING *command;
339 
340  /*
341   * Tunable parameters.
342   */
343 char   *var_transport_maps;
344 bool    var_swap_bangpath;
345 bool    var_append_dot_mydomain;
346 bool    var_append_at_myorigin;
347 bool    var_percent_hack;
348 char   *var_local_transport;
349 char   *var_virt_transport;
350 char   *var_relay_transport;
351 int     var_resolve_dequoted;
352 char   *var_virt_alias_maps;            /* XXX virtual_alias_domains */
353 char   *var_virt_mailbox_maps;                    /* XXX virtual_mailbox_domains */
354 char   *var_virt_alias_doms;
355 char   *var_virt_mailbox_doms;
356 char   *var_relocated_maps;
357 char   *var_def_transport;
358 char   *var_snd_def_xport_maps;
359 char   *var_empty_addr;
360 int     var_show_unk_rcpt_table;
361 int     var_resolve_nulldom;
362 char   *var_remote_rwr_domain;
363 char   *var_snd_relay_maps;
364 char   *var_null_relay_maps_key;
365 char   *var_null_def_xport_maps_key;
366 int     var_resolve_num_dom;
367 bool    var_allow_min_user;
368 
369  /*
370   * Shadow personality for address verification.
371   */
372 char   *var_vrfy_xport_maps;
373 char   *var_vrfy_local_xport;
374 char   *var_vrfy_virt_xport;
375 char   *var_vrfy_relay_xport;
376 char   *var_vrfy_def_xport;
377 char   *var_vrfy_snd_def_xport_maps;
378 char   *var_vrfy_relayhost;
379 char   *var_vrfy_relay_maps;
380 
381  /*
382   * Different resolver personalities depending on the kind of request.
383   */
384 RES_CONTEXT resolve_regular = {
385     VAR_LOCAL_TRANSPORT, &var_local_transport,
386     VAR_VIRT_TRANSPORT, &var_virt_transport,
387     VAR_RELAY_TRANSPORT, &var_relay_transport,
388     VAR_DEF_TRANSPORT, &var_def_transport,
389     VAR_SND_DEF_XPORT_MAPS, &var_snd_def_xport_maps, 0,
390     VAR_RELAYHOST, &var_relayhost,
391     VAR_SND_RELAY_MAPS, &var_snd_relay_maps, 0,
392     VAR_TRANSPORT_MAPS, &var_transport_maps, 0
393 };
394 
395 RES_CONTEXT resolve_verify = {
396     VAR_VRFY_LOCAL_XPORT, &var_vrfy_local_xport,
397     VAR_VRFY_VIRT_XPORT, &var_vrfy_virt_xport,
398     VAR_VRFY_RELAY_XPORT, &var_vrfy_relay_xport,
399     VAR_VRFY_DEF_XPORT, &var_vrfy_def_xport,
400     VAR_VRFY_SND_DEF_XPORT_MAPS, &var_vrfy_snd_def_xport_maps, 0,
401     VAR_VRFY_RELAYHOST, &var_vrfy_relayhost,
402     VAR_VRFY_RELAY_MAPS, &var_vrfy_relay_maps, 0,
403     VAR_VRFY_XPORT_MAPS, &var_vrfy_xport_maps, 0
404 };
405 
406  /*
407   * Connection management. When file-based lookup tables change we should
408   * restart at our convenience, but avoid client read errors. We restart
409   * rather than reopen, because the process may be chrooted (and if it isn't
410   * we still need code that handles the chrooted case anyway).
411   *
412   * Three variants are implemented. Only one should be used.
413   *
414   * ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
415   *
416   * This code detaches the trivial-rewrite process from the master, stops
417   * accepting new clients, and handles established clients in the background,
418   * asking them to reconnect the next time they send a request. The master
419   * creates a new process that accepts connections. This is reasonably safe
420   * because the number of trivial-rewrite server processes is small compared
421   * to the number of trivial-rewrite client processes. The few extra
422   * background processes should not make a difference in Postfix's footprint.
423   * However, once a daemon detaches from the master, its exit status will be
424   * lost, and abnormal termination may remain undetected. Timely restart is
425   * achieved by checking the table changed status every 10 seconds or so
426   * before responding to a client request.
427   *
428   * ifdef CHECK_TABLE_STATS_PERIODICALLY
429   *
430   * This code runs every 10 seconds and terminates the process when lookup
431   * tables have changed. This is subject to race conditions when established
432   * clients send a request while the server exits; those clients may read EOF
433   * instead of a server reply. If the experience with the oldest option
434   * (below) is anything to go by, however, then this is unlikely to be a
435   * problem during real deployment.
436   *
437   * ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
438   *
439   * This is the old code. It checks the table changed status when a new client
440   * connects (i.e. before the server calls accept()), and terminates
441   * immediately. This is invisible for the connecting client, but is subject
442   * to race conditions when established clients send a request while the
443   * server exits; those clients may read EOF instead of a server reply. This
444   * has, however, not been a problem in real deployment. With the old code,
445   * timely restart is achieved by setting the ipc_ttl parameter to 60
446   * seconds, so that the table change status is checked several times a
447   * minute.
448   */
449 int     server_flags;
450 
451  /*
452   * Define exactly one of these.
453   */
454 /* #define DETACH_AND_ASK_CLIENTS_TO_RECONNECT    /* correct and complex */
455 #define CHECK_TABLE_STATS_PERIODICALLY  /* quick */
456 /* #define CHECK_TABLE_STATS_BEFORE_ACCEPT        /* slow */
457 
458 /* rewrite_service - read request and send reply */
459 
rewrite_service(VSTREAM * stream,char * unused_service,char ** argv)460 static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
461 {
462     int     status = -1;
463 
464 #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
465     static time_t last;
466     time_t  now;
467     const char *table;
468 
469 #endif
470 
471     /*
472      * Sanity check. This service takes no command-line arguments.
473      */
474     if (argv[0])
475           msg_fatal("unexpected command-line argument: %s", argv[0]);
476 
477     /*
478      * Client connections are long-lived. Be sure to refesh timely.
479      */
480 #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
481     if (server_flags == 0 && (now = event_time()) - last > 10) {
482           if ((table = dict_changed_name()) != 0) {
483               msg_info("table %s has changed -- restarting", table);
484               if (multi_server_drain() == 0)
485                     server_flags = 1;
486           }
487           last = now;
488     }
489 #endif
490 
491     /*
492      * This routine runs whenever a client connects to the UNIX-domain socket
493      * dedicated to address rewriting. All connection-management stuff is
494      * handled by the common code in multi_server.c.
495      */
496     if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
497                       RECV_ATTR_STR(MAIL_ATTR_REQ, command),
498                       ATTR_TYPE_END) == 1) {
499           if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) {
500               status = rewrite_proto(stream);
501           } else if (strcmp(vstring_str(command), RESOLVE_REGULAR) == 0) {
502               status = resolve_proto(&resolve_regular, stream);
503           } else if (strcmp(vstring_str(command), RESOLVE_VERIFY) == 0) {
504               status = resolve_proto(&resolve_verify, stream);
505           } else {
506               msg_warn("bad command %.30s", printable(vstring_str(command), '?'));
507           }
508     }
509     if (status < 0)
510           multi_server_disconnect(stream);
511 }
512 
513 /* pre_accept - see if tables have changed */
514 
515 #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
516 
pre_accept(char * unused_name,char ** unused_argv)517 static void pre_accept(char *unused_name, char **unused_argv)
518 {
519     const char *table;
520 
521     if ((table = dict_changed_name()) != 0) {
522           msg_info("table %s has changed -- restarting", table);
523           exit(0);
524     }
525 }
526 
527 #endif
528 
529 /* post_accept - announce our protocol name */
530 
post_accept(VSTREAM * stream,char * unused_name,char ** unused_argv,HTABLE * unused_attr)531 static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
532                                       HTABLE *unused_attr)
533 {
534 
535     /*
536      * Announce the protocol.
537      */
538     attr_print(stream, ATTR_FLAG_NONE,
539                  SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
540                  ATTR_TYPE_END);
541     (void) vstream_fflush(stream);
542 }
543 
check_table_stats(int unused_event,void * unused_context)544 static void check_table_stats(int unused_event, void *unused_context)
545 {
546     const char *table;
547 
548     if ((table = dict_changed_name()) != 0) {
549           msg_info("table %s has changed -- restarting", table);
550           exit(0);
551     }
552     event_request_timer(check_table_stats, (void *) 0, 10);
553 }
554 
555 /* pre_jail_init - initialize before entering chroot jail */
556 
pre_jail_init(char * unused_name,char ** unused_argv)557 static void pre_jail_init(char *unused_name, char **unused_argv)
558 {
559     command = vstring_alloc(100);
560     rewrite_init();
561     resolve_init();
562     if (*RES_PARAM_VALUE(resolve_regular.transport_maps))
563           resolve_regular.transport_info =
564               transport_pre_init(resolve_regular.transport_maps_name,
565                                  RES_PARAM_VALUE(resolve_regular.transport_maps));
566     if (*RES_PARAM_VALUE(resolve_verify.transport_maps))
567           resolve_verify.transport_info =
568               transport_pre_init(resolve_verify.transport_maps_name,
569                                   RES_PARAM_VALUE(resolve_verify.transport_maps));
570     if (*RES_PARAM_VALUE(resolve_regular.snd_relay_maps))
571           resolve_regular.snd_relay_info =
572               maps_create(resolve_regular.snd_relay_maps_name,
573                               RES_PARAM_VALUE(resolve_regular.snd_relay_maps),
574                               DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
575                               | DICT_FLAG_NO_REGSUB | DICT_FLAG_UTF8_REQUEST);
576     if (*RES_PARAM_VALUE(resolve_verify.snd_relay_maps))
577           resolve_verify.snd_relay_info =
578               maps_create(resolve_verify.snd_relay_maps_name,
579                               RES_PARAM_VALUE(resolve_verify.snd_relay_maps),
580                               DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
581                               | DICT_FLAG_NO_REGSUB | DICT_FLAG_UTF8_REQUEST);
582     if (*RES_PARAM_VALUE(resolve_regular.snd_def_xp_maps))
583           resolve_regular.snd_def_xp_info =
584               maps_create(resolve_regular.snd_def_xp_maps_name,
585                               RES_PARAM_VALUE(resolve_regular.snd_def_xp_maps),
586                               DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
587                               | DICT_FLAG_NO_REGSUB | DICT_FLAG_UTF8_REQUEST);
588     if (*RES_PARAM_VALUE(resolve_verify.snd_def_xp_maps))
589           resolve_verify.snd_def_xp_info =
590               maps_create(resolve_verify.snd_def_xp_maps_name,
591                               RES_PARAM_VALUE(resolve_verify.snd_def_xp_maps),
592                               DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
593                               | DICT_FLAG_NO_REGSUB | DICT_FLAG_UTF8_REQUEST);
594 }
595 
596 /* post_jail_init - initialize after entering chroot jail */
597 
post_jail_init(char * unused_name,char ** unused_argv)598 static void post_jail_init(char *unused_name, char **unused_argv)
599 {
600     if (resolve_regular.transport_info)
601           transport_post_init(resolve_regular.transport_info);
602     if (resolve_verify.transport_info)
603           transport_post_init(resolve_verify.transport_info);
604     check_table_stats(0, (void *) 0);
605 }
606 
607 MAIL_VERSION_STAMP_DECLARE;
608 
609 /* main - pass control to the multi-threaded skeleton code */
610 
main(int argc,char ** argv)611 int     main(int argc, char **argv)
612 {
613     static const CONFIG_STR_TABLE str_table[] = {
614           VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
615           VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 1, 0,
616           VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport, 1, 0,
617           VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport, 1, 0,
618           VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 1, 0,
619           VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0,
620           VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 0, 0,
621           VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
622           VAR_VIRT_MAILBOX_DOMS, DEF_VIRT_MAILBOX_DOMS, &var_virt_mailbox_doms, 0, 0,
623           VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0,
624           VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
625           VAR_VRFY_XPORT_MAPS, DEF_VRFY_XPORT_MAPS, &var_vrfy_xport_maps, 0, 0,
626           VAR_VRFY_LOCAL_XPORT, DEF_VRFY_LOCAL_XPORT, &var_vrfy_local_xport, 1, 0,
627           VAR_VRFY_VIRT_XPORT, DEF_VRFY_VIRT_XPORT, &var_vrfy_virt_xport, 1, 0,
628           VAR_VRFY_RELAY_XPORT, DEF_VRFY_RELAY_XPORT, &var_vrfy_relay_xport, 1, 0,
629           VAR_VRFY_DEF_XPORT, DEF_VRFY_DEF_XPORT, &var_vrfy_def_xport, 1, 0,
630           VAR_VRFY_RELAYHOST, DEF_VRFY_RELAYHOST, &var_vrfy_relayhost, 0, 0,
631           VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain, 0, 0,
632           VAR_SND_RELAY_MAPS, DEF_SND_RELAY_MAPS, &var_snd_relay_maps, 0, 0,
633           VAR_NULL_RELAY_MAPS_KEY, DEF_NULL_RELAY_MAPS_KEY, &var_null_relay_maps_key, 1, 0,
634           VAR_VRFY_RELAY_MAPS, DEF_VRFY_RELAY_MAPS, &var_vrfy_relay_maps, 0, 0,
635           VAR_SND_DEF_XPORT_MAPS, DEF_SND_DEF_XPORT_MAPS, &var_snd_def_xport_maps, 0, 0,
636           VAR_NULL_DEF_XPORT_MAPS_KEY, DEF_NULL_DEF_XPORT_MAPS_KEY, &var_null_def_xport_maps_key, 1, 0,
637           VAR_VRFY_SND_DEF_XPORT_MAPS, DEF_VRFY_SND_DEF_XPORT_MAPS, &var_vrfy_snd_def_xport_maps, 0, 0,
638           0,
639     };
640     static const CONFIG_BOOL_TABLE bool_table[] = {
641           VAR_SWAP_BANGPATH, DEF_SWAP_BANGPATH, &var_swap_bangpath,
642           VAR_APP_AT_MYORIGIN, DEF_APP_AT_MYORIGIN, &var_append_at_myorigin,
643           VAR_PERCENT_HACK, DEF_PERCENT_HACK, &var_percent_hack,
644           VAR_RESOLVE_DEQUOTED, DEF_RESOLVE_DEQUOTED, &var_resolve_dequoted,
645           VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
646           VAR_RESOLVE_NULLDOM, DEF_RESOLVE_NULLDOM, &var_resolve_nulldom,
647           VAR_RESOLVE_NUM_DOM, DEF_RESOLVE_NUM_DOM, &var_resolve_num_dom,
648           VAR_ALLOW_MIN_USER, DEF_ALLOW_MIN_USER, &var_allow_min_user,
649           0,
650     };
651     static const CONFIG_NBOOL_TABLE nbool_table[] = {
652           VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
653           0,
654     };
655 
656     /*
657      * Fingerprint executables and core dumps.
658      */
659     MAIL_VERSION_STAMP_ALLOCATE;
660 
661     multi_server_main(argc, argv, rewrite_service,
662                           CA_MAIL_SERVER_STR_TABLE(str_table),
663                           CA_MAIL_SERVER_BOOL_TABLE(bool_table),
664                           CA_MAIL_SERVER_NBOOL_TABLE(nbool_table),
665                           CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
666                           CA_MAIL_SERVER_POST_INIT(post_jail_init),
667 #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
668                           CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
669 #endif
670                           CA_MAIL_SERVER_POST_ACCEPT(post_accept),
671                           0);
672 }
673