xref: /netbsd-src/external/ibm-public/postfix/dist/src/postscreen/postscreen.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: postscreen.c,v 1.1.1.2 2011/05/11 09:11:07 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	postscreen 8
6 /* SUMMARY
7 /*	Postfix zombie blocker
8 /* SYNOPSIS
9 /*	\fBpostscreen\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /*	The Postfix \fBpostscreen\fR(8) server performs triage on
12 /*	multiple inbound SMTP connections at the same time. While
13 /*	a single \fBpostscreen\fR(8) process keeps spambots away
14 /*	from Postfix SMTP server processes, more Postfix SMTP server
15 /*	processes remain available for legitimate clients.
16 /*
17 /*	This program should not be used on SMTP ports that receive
18 /*	mail from end-user clients (MUAs). In a typical deployment,
19 /*	\fBpostscreen\fR(8) is used on the "port 25" service, while
20 /*	MUA clients submit mail via the \fBsubmission\fR service.
21 /*
22 /*	\fBpostscreen\fR(8) maintains a temporary whitelist for
23 /*	clients that have passed a number of tests.  When an SMTP
24 /*	client IP address is whitelisted, \fBpostscreen\fR(8) hands
25 /*	off the connection immediately to a Postfix SMTP server
26 /*	process. This minimizes the overhead for legitimate mail.
27 /*
28 /*	By default, \fBpostscreen\fR(8) logs statistics and hands
29 /*	off every connection to a Postfix SMTP server process, while
30 /*	excluding clients in mynetworks from all tests (primarily,
31 /*	to avoid problems with non-standard SMTP implementations
32 /*	in network appliances).  This mode is useful for non-destructive
33 /*	testing.
34 /*
35 /*	In a typical production setting, \fBpostscreen\fR(8) is
36 /*	configured to reject mail from clients that fail one or
37 /*	more tests. \fBpostscreen\fR(8) logs rejected mail with the
38 /*	client address, helo, sender and recipient information.
39 /*
40 /*	\fBpostscreen\fR(8) is not an SMTP proxy; this is intentional.
41 /*	The purpose is to keep spambots away from Postfix SMTP
42 /*	server processes, while minimizing overhead for legitimate
43 /*	traffic.
44 /* SECURITY
45 /* .ad
46 /* .fi
47 /*	The \fBpostscreen\fR(8) server is moderately security-sensitive.
48 /*	It talks to untrusted clients on the network. The process
49 /*	can be run chrooted at fixed low privilege.
50 /* STANDARDS
51 /*	RFC 821 (SMTP protocol)
52 /*	RFC 1123 (Host requirements)
53 /*	RFC 1652 (8bit-MIME transport)
54 /*	RFC 1869 (SMTP service extensions)
55 /*	RFC 1870 (Message Size Declaration)
56 /*	RFC 1985 (ETRN command)
57 /*	RFC 2034 (SMTP Enhanced Status Codes)
58 /*	RFC 2821 (SMTP protocol)
59 /*	Not: RFC 2920 (SMTP Pipelining)
60 /*	RFC 3207 (STARTTLS command)
61 /*	RFC 3461 (SMTP DSN Extension)
62 /*	RFC 3463 (Enhanced Status Codes)
63 /*	RFC 5321 (SMTP protocol, including multi-line 220 banners)
64 /* DIAGNOSTICS
65 /*	Problems and transactions are logged to \fBsyslogd\fR(8).
66 /* BUGS
67 /*	The \fBpostscreen\fR(8) built-in SMTP protocol engine
68 /*	currently does not announce support for AUTH, XCLIENT or
69 /*	XFORWARD.
70 /*	Support for AUTH may be added in the future.
71 /*	In the mean time, if you need to make these services available
72 /*	on port 25, then do not enable the optional "after 220
73 /*	server greeting" tests, and do not use DNSBLs that reject
74 /*	traffic from dial-up and residential networks.
75 /*
76 /*	The optional "after 220 server greeting" tests involve
77 /*	\fBpostscreen\fR(8)'s built-in SMTP protocol engine. When
78 /*	these tests succeed, \fBpostscreen\fR(8) adds the client
79 /*	to the temporary whitelist but it cannot not hand off the
80 /*	"live" connection to a Postfix SMTP server process in the
81 /*	middle of a session.  Instead, \fBpostscreen\fR(8) defers
82 /*	attempts to deliver mail with a 4XX status, and waits for
83 /*	the client to disconnect.  The next time a good client
84 /*	connects, it will be allowed to talk to a Postfix SMTP
85 /*	server process to deliver mail. \fBpostscreen\fR(8) mitigates
86 /*	the impact of this limitation by giving such tests a long
87 /*	expiration time.
88 /* CONFIGURATION PARAMETERS
89 /* .ad
90 /* .fi
91 /*	Changes to main.cf are not picked up automatically, as
92 /*	\fBpostscreen\fR(8) processes may run for several hours.
93 /*	Use the command "postfix reload" after a configuration
94 /*	change.
95 /*
96 /*	The text below provides only a parameter summary. See
97 /*	\fBpostconf\fR(5) for more details including examples.
98 /*
99 /*	NOTE: Some \fBpostscreen\fR(8) parameters implement
100 /*	stress-dependent behavior.  This is supported only when the
101 /*	default parameter value is stress-dependent (that is, it
102 /*	looks like ${stress?X}${stress:Y}, or it is the $\fIname\fR
103 /*	of an smtpd parameter with a stress-dependent default).
104 /*	Other parameters always evaluate as if the \fBstress\fR
105 /*	parameter value is the empty string.
106 /* COMPATIBILITY CONTROLS
107 /* .ad
108 /* .fi
109 /* .IP "\fBpostscreen_command_filter ($smtpd_command_filter)\fR"
110 /*	A mechanism to transform commands from remote SMTP clients.
111 /* .IP "\fBpostscreen_discard_ehlo_keyword_address_maps ($smtpd_discard_ehlo_keyword_address_maps)\fR"
112 /*	Lookup tables, indexed by the remote SMTP client address, with
113 /*	case insensitive lists of EHLO keywords (pipelining, starttls, auth,
114 /*	etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO response
115 /*	to a remote SMTP client.
116 /* .IP "\fBpostscreen_discard_ehlo_keywords ($smtpd_discard_ehlo_keywords)\fR"
117 /*	A case insensitive list of EHLO keywords (pipelining, starttls,
118 /*	auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
119 /*	response to a remote SMTP client.
120 /* TROUBLE SHOOTING CONTROLS
121 /* .ad
122 /* .fi
123 /* .IP "\fBpostscreen_expansion_filter (see 'postconf -d' output)\fR"
124 /*	List of characters that are permitted in postscreen_reject_footer
125 /*	attribute expansions.
126 /* .IP "\fBpostscreen_reject_footer ($smtpd_reject_footer)\fR"
127 /*	Optional information that is appended after a 4XX or 5XX server
128 /*	response.
129 /* .IP "\fBsoft_bounce (no)\fR"
130 /*	Safety net to keep mail queued that would otherwise be returned to
131 /*	the sender.
132 /* PERMANENT WHITE/BLACKLIST TEST
133 /* .ad
134 /* .fi
135 /*	This test is executed immediately after a remote SMTP client
136 /*	connects. If a client is permanently whitelisted, the client
137 /*	will be handed off immediately to a Postfix SMTP server
138 /*	process.
139 /* .IP "\fBpostscreen_access_list (permit_mynetworks)\fR"
140 /*	Permanent white/blacklist for remote SMTP client IP addresses.
141 /* .IP "\fBpostscreen_blacklist_action (ignore)\fR"
142 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client is
143 /*	permanently blacklisted with the postscreen_access_list parameter.
144 /* BEFORE-GREETING TESTS
145 /* .ad
146 /* .fi
147 /*	These tests are executed before the remote SMTP client
148 /*	receives the "220 servername" greeting. If no tests remain
149 /*	after the successful completion of this phase, the client
150 /*	will be handed off immediately to a Postfix SMTP server
151 /*	process.
152 /* .IP "\fBdnsblog_service_name (dnsblog)\fR"
153 /*	The name of the \fBdnsblog\fR(8) service entry in master.cf.
154 /* .IP "\fBpostscreen_dnsbl_action (ignore)\fR"
155 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
156 /*	DNSBL score is equal to or greater than a threshold (as defined
157 /*	with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
158 /*	parameters).
159 /* .IP "\fBpostscreen_dnsbl_reply_map (empty)\fR"
160 /*	A mapping from actual DNSBL domain name which includes a secret
161 /*	password, to the DNSBL domain name that postscreen will reply with
162 /*	when it rejects mail.
163 /* .IP "\fBpostscreen_dnsbl_sites (empty)\fR"
164 /*	Optional list of DNS white/blacklist domains, filters and weight
165 /*	factors.
166 /* .IP "\fBpostscreen_dnsbl_threshold (1)\fR"
167 /*	The inclusive lower bound for blocking an SMTP client, based on
168 /*	its combined DNSBL score as defined with the postscreen_dnsbl_sites
169 /*	parameter.
170 /* .IP "\fBpostscreen_greet_action (ignore)\fR"
171 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
172 /*	before its turn within the time specified with the postscreen_greet_wait
173 /*	parameter.
174 /* .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
175 /*	The \fItext\fR in the optional "220-\fItext\fR..." server
176 /*	response that
177 /*	\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
178 /*	text..." response, in an attempt to confuse bad SMTP clients so
179 /*	that they speak before their turn (pre-greet).
180 /* .IP "\fBpostscreen_greet_wait (${stress?2}${stress:6}s)\fR"
181 /*	The amount of time that \fBpostscreen\fR(8) will wait for an SMTP
182 /*	client to send a command before its turn, and for DNS blocklist
183 /*	lookup results to arrive (default: up to 2 seconds under stress,
184 /*	up to 6 seconds otherwise).
185 /* .IP "\fBsmtpd_service_name (smtpd)\fR"
186 /*	The internal service that \fBpostscreen\fR(8) forwards allowed
187 /*	connections to.
188 /* AFTER-GREETING TESTS
189 /* .ad
190 /* .fi
191 /*	These tests are executed after the remote SMTP client
192 /*	receives the "220 servername" greeting. If a client passes
193 /*	all tests during this phase, it will receive a 4XX response
194 /*	to RCPT TO commands until the client hangs up. After this,
195 /*	the client will be allowed to talk directly to a Postfix
196 /*	SMTP server process.
197 /* .IP "\fBpostscreen_bare_newline_action (ignore)\fR"
198 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client sends
199 /*	a bare newline character, that is, a newline not preceded by carriage
200 /*	return.
201 /* .IP "\fBpostscreen_bare_newline_enable (no)\fR"
202 /*	Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
203 /*	server.
204 /* .IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
205 /*	Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
206 /* .IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
207 /*	List of commands that the \fBpostscreen\fR(8) server considers in
208 /*	violation of the SMTP protocol.
209 /* .IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
210 /*	Require that a remote SMTP client sends HELO or EHLO before
211 /*	commencing a MAIL transaction.
212 /* .IP "\fBpostscreen_non_smtp_command_action (drop)\fR"
213 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client sends
214 /*	non-SMTP commands as specified with the postscreen_forbidden_commands
215 /*	parameter.
216 /* .IP "\fBpostscreen_non_smtp_command_enable (no)\fR"
217 /*	Enable "non-SMTP command" tests in the \fBpostscreen\fR(8) server.
218 /* .IP "\fBpostscreen_pipelining_action (enforce)\fR"
219 /*	The action that \fBpostscreen\fR(8) takes when an SMTP client sends
220 /*	multiple commands instead of sending one command and waiting for
221 /*	the server to respond.
222 /* .IP "\fBpostscreen_pipelining_enable (no)\fR"
223 /*	Enable "pipelining" SMTP protocol tests in the \fBpostscreen\fR(8)
224 /*	server.
225 /* CACHE CONTROLS
226 /* .ad
227 /* .fi
228 /* .IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
229 /*	The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
230 /* .IP "\fBpostscreen_cache_map (btree:$data_directory/postscreen_cache)\fR"
231 /*	Persistent storage for the \fBpostscreen\fR(8) server decisions.
232 /* .IP "\fBpostscreen_cache_retention_time (7d)\fR"
233 /*	The amount of time that \fBpostscreen\fR(8) will cache an expired
234 /*	temporary whitelist entry before it is removed.
235 /* .IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
236 /*	The amount of time that \fBpostscreen\fR(8) will use the result from
237 /*	a successful "bare newline" SMTP protocol test.
238 /* .IP "\fBpostscreen_dnsbl_ttl (1h)\fR"
239 /*	The amount of time that \fBpostscreen\fR(8) will use the result from
240 /*	a successful DNS blocklist test.
241 /* .IP "\fBpostscreen_greet_ttl (1d)\fR"
242 /*	The amount of time that \fBpostscreen\fR(8) will use the result from
243 /*	a successful PREGREET test.
244 /* .IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR"
245 /*	The amount of time that \fBpostscreen\fR(8) will use the result from
246 /*	a successful "non_smtp_command" SMTP protocol test.
247 /* .IP "\fBpostscreen_pipelining_ttl (30d)\fR"
248 /*	The amount of time that \fBpostscreen\fR(8) will use the result from
249 /*	a successful "pipelining" SMTP protocol test.
250 /* RESOURCE CONTROLS
251 /* .ad
252 /* .fi
253 /* .IP "\fBline_length_limit (2048)\fR"
254 /*	Upon input, long lines are chopped up into pieces of at most
255 /*	this length; upon delivery, long lines are reconstructed.
256 /* .IP "\fBpostscreen_client_connection_count_limit ($smtpd_client_connection_count_limit)\fR"
257 /*	How many simultaneous connections any client is allowed to have
258 /*	with the \fBpostscreen\fR(8) daemon.
259 /* .IP "\fBpostscreen_command_count_limit (20)\fR"
260 /*	The limit on the total number of commands per SMTP session for
261 /*	\fBpostscreen\fR(8)'s built-in SMTP protocol engine.
262 /* .IP "\fBpostscreen_command_time_limit (${stress?10}${stress:300}s)\fR"
263 /*	The time limit to read an entire command line with \fBpostscreen\fR(8)'s
264 /*	built-in SMTP protocol engine.
265 /* .IP "\fBpostscreen_post_queue_limit ($default_process_limit)\fR"
266 /*	The number of clients that can be waiting for service from a
267 /*	real SMTP server process.
268 /* .IP "\fBpostscreen_pre_queue_limit ($default_process_limit)\fR"
269 /*	The number of non-whitelisted clients that can be waiting for
270 /*	a decision whether they will receive service from a real SMTP server
271 /*	process.
272 /* .IP "\fBpostscreen_watchdog_timeout (10s)\fR"
273 /*	How much time a \fBpostscreen\fR(8) process may take to respond to
274 /*	an SMTP client command or to perform a cache operation before it
275 /*	is terminated by a built-in watchdog timer.
276 /* STARTTLS CONTROLS
277 /* .ad
278 /* .fi
279 /* .IP "\fBpostscreen_tls_security_level ($smtpd_tls_security_level)\fR"
280 /*	The SMTP TLS security level for the \fBpostscreen\fR(8) server; when
281 /*	a non-empty value is specified, this overrides the obsolete parameters
282 /*	postscreen_use_tls and postscreen_enforce_tls.
283 /* .IP "\fBtlsproxy_service_name (tlsproxy)\fR"
284 /*	The name of the \fBtlsproxy\fR(8) service entry in master.cf.
285 /* OBSOLETE STARTTLS SUPPORT CONTROLS
286 /* .ad
287 /* .fi
288 /*	These parameters are supported for compatibility with
289 /*	\fBsmtpd\fR(8) legacy parameters.
290 /* .IP "\fBpostscreen_use_tls ($smtpd_use_tls)\fR"
291 /*	Opportunistic TLS: announce STARTTLS support to SMTP clients,
292 /*	but do not require that clients use TLS encryption.
293 /* .IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
294 /*	Mandatory TLS: announce STARTTLS support to SMTP clients, and
295 /*	require that clients use TLS encryption.
296 /* MISCELLANEOUS CONTROLS
297 /* .ad
298 /* .fi
299 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
300 /*	The default location of the Postfix main.cf and master.cf
301 /*	configuration files.
302 /* .IP "\fBdelay_logging_resolution_limit (2)\fR"
303 /*	The maximal number of digits after the decimal point when logging
304 /*	sub-second delay values.
305 /* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
306 /*	The location of all postfix administrative commands.
307 /* .IP "\fBmax_idle (100s)\fR"
308 /*	The maximum amount of time that an idle Postfix daemon process waits
309 /*	for an incoming connection before terminating voluntarily.
310 /* .IP "\fBprocess_id (read-only)\fR"
311 /*	The process ID of a Postfix command or daemon process.
312 /* .IP "\fBprocess_name (read-only)\fR"
313 /*	The process name of a Postfix command or daemon process.
314 /* .IP "\fBsyslog_facility (mail)\fR"
315 /*	The syslog facility of Postfix logging.
316 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
317 /*	The mail system name that is prepended to the process name in syslog
318 /*	records, so that "smtpd" becomes, for example, "postfix/smtpd".
319 /* SEE ALSO
320 /*	smtpd(8), Postfix SMTP server
321 /*	tlsproxy(8), Postfix TLS proxy server
322 /*	dnsblog(8), DNS black/whitelist logger
323 /*	syslogd(8), system logging
324 /* README FILES
325 /* .ad
326 /* .fi
327 /*	Use "\fBpostconf readme_directory\fR" or "\fBpostconf
328 /*	html_directory\fR" to locate this information.
329 /* .nf
330 /* .na
331 /*	POSTSCREEN_README, Postfix Postscreen Howto
332 /* LICENSE
333 /* .ad
334 /* .fi
335 /*	The Secure Mailer license must be distributed with this software.
336 /* HISTORY
337 /* .ad
338 /* .fi
339 /*	This service was introduced with Postfix version 2.8.
340 /*
341 /*	Many ideas in \fBpostscreen\fR(8) were explored in earlier
342 /*	work by Michael Tokarev, in OpenBSD spamd, and in MailChannels
343 /*	Traffic Control.
344 /* AUTHOR(S)
345 /*	Wietse Venema
346 /*	IBM T.J. Watson Research
347 /*	P.O. Box 704
348 /*	Yorktown Heights, NY 10598, USA
349 /*--*/
350 
351 /* System library. */
352 
353 #include <sys_defs.h>
354 #include <sys/stat.h>
355 #include <stdlib.h>
356 
357 /* Utility library. */
358 
359 #include <msg.h>
360 #include <mymalloc.h>
361 #include <events.h>
362 #include <myaddrinfo.h>
363 #include <dict_cache.h>
364 #include <set_eugid.h>
365 #include <vstream.h>
366 #include <name_code.h>
367 
368 /* Global library. */
369 
370 #include <mail_conf.h>
371 #include <mail_params.h>
372 #include <mail_version.h>
373 #include <mail_proto.h>
374 #include <data_redirect.h>
375 #include <string_list.h>
376 
377 /* Master server protocols. */
378 
379 #include <mail_server.h>
380 
381 /* Application-specific. */
382 
383 #include <postscreen.h>
384 
385  /*
386   * Configuration parameters.
387   */
388 int     var_proc_limit;
389 char   *var_smtpd_service;
390 char   *var_smtpd_banner;
391 bool    var_disable_vrfy_cmd;
392 bool    var_helo_required;
393 
394 char   *var_smtpd_cmd_filter;
395 char   *var_psc_cmd_filter;
396 
397 char   *var_smtpd_forbid_cmds;
398 char   *var_psc_forbid_cmds;
399 
400 char   *var_smtpd_ehlo_dis_words;
401 char   *var_smtpd_ehlo_dis_maps;
402 char   *var_psc_ehlo_dis_words;
403 char   *var_psc_ehlo_dis_maps;
404 
405 char   *var_smtpd_tls_level;
406 bool    var_smtpd_use_tls;
407 bool    var_smtpd_enforce_tls;
408 char   *var_psc_tls_level;
409 bool    var_psc_use_tls;
410 bool    var_psc_enforce_tls;
411 
412 bool    var_psc_disable_vrfy;
413 bool    var_psc_helo_required;
414 
415 char   *var_psc_cache_map;
416 int     var_psc_cache_scan;
417 int     var_psc_cache_ret;
418 int     var_psc_post_queue_limit;
419 int     var_psc_pre_queue_limit;
420 int     var_psc_watchdog;
421 
422 char   *var_psc_acl;
423 char   *var_psc_blist_action;
424 
425 char   *var_psc_greet_ttl;
426 int     var_psc_greet_wait;
427 
428 char   *var_psc_pregr_banner;
429 char   *var_psc_pregr_action;
430 int     var_psc_pregr_ttl;
431 
432 char   *var_psc_dnsbl_sites;
433 char   *var_psc_dnsbl_reply;
434 int     var_psc_dnsbl_thresh;
435 char   *var_psc_dnsbl_action;
436 int     var_psc_dnsbl_ttl;
437 
438 bool    var_psc_pipel_enable;
439 char   *var_psc_pipel_action;
440 int     var_psc_pipel_ttl;
441 
442 bool    var_psc_nsmtp_enable;
443 char   *var_psc_nsmtp_action;
444 int     var_psc_nsmtp_ttl;
445 
446 bool    var_psc_barlf_enable;
447 char   *var_psc_barlf_action;
448 int     var_psc_barlf_ttl;
449 
450 int     var_psc_cmd_count;
451 char   *var_psc_cmd_time;
452 
453 char   *var_dnsblog_service;
454 char   *var_tlsproxy_service;
455 
456 char   *var_smtpd_rej_footer;
457 char   *var_psc_rej_footer;
458 
459 int     var_smtpd_cconn_limit;
460 int     var_psc_cconn_limit;
461 
462 char   *var_smtpd_exp_filter;
463 char   *var_psc_exp_filter;
464 
465  /*
466   * Global variables.
467   */
468 int     psc_check_queue_length;		/* connections being checked */
469 int     psc_post_queue_length;		/* being sent to real SMTPD */
470 DICT_CACHE *psc_cache_map;		/* cache table handle */
471 VSTRING *psc_temp;			/* scratchpad */
472 char   *psc_smtpd_service_name;		/* path to real SMTPD */
473 int     psc_pregr_action;		/* PSC_ACT_DROP/ENFORCE/etc */
474 int     psc_dnsbl_action;		/* PSC_ACT_DROP/ENFORCE/etc */
475 int     psc_pipel_action;		/* PSC_ACT_DROP/ENFORCE/etc */
476 int     psc_nsmtp_action;		/* PSC_ACT_DROP/ENFORCE/etc */
477 int     psc_barlf_action;		/* PSC_ACT_DROP/ENFORCE/etc */
478 int     psc_min_ttl;			/* Update with new tests! */
479 int     psc_max_ttl;			/* Update with new tests! */
480 STRING_LIST *psc_forbid_cmds;		/* CONNECT GET POST */
481 int     psc_stress_greet_wait;		/* stressed greet wait */
482 int     psc_normal_greet_wait;		/* stressed greet wait */
483 int     psc_stress_cmd_time_limit;	/* stressed command limit */
484 int     psc_normal_cmd_time_limit;	/* normal command time limit */
485 int     psc_stress;			/* stress level */
486 int     psc_lowat_check_queue_length;	/* stress low-water mark */
487 int     psc_hiwat_check_queue_length;	/* stress high-water mark */
488 DICT   *psc_dnsbl_reply;		/* DNSBL name mapper */
489 HTABLE *psc_client_concurrency;		/* per-client concurrency */
490 
491  /*
492   * Local variables.
493   */
494 static ARGV *psc_acl;			/* permanent white/backlist */
495 static int psc_blist_action;		/* PSC_ACT_DROP/ENFORCE/etc */
496 
497 /* psc_dump - dump some statistics before exit */
498 
499 static void psc_dump(void)
500 {
501 
502     /*
503      * Dump preliminary cache cleanup statistics when the process commits
504      * suicide while a cache cleanup run is in progress. We can't currently
505      * distinguish between "postfix reload" (we should restart) or "maximal
506      * idle time reached" (we could finish the cache cleanup first).
507      */
508     if (psc_cache_map) {
509 	dict_cache_close(psc_cache_map);
510 	psc_cache_map = 0;
511     }
512 }
513 
514 /* psc_drain - delayed exit after "postfix reload" */
515 
516 static void psc_drain(char *unused_service, char **unused_argv)
517 {
518     int     count;
519 
520     /*
521      * After "postfix reload", complete work-in-progress in the background,
522      * instead of dropping already-accepted connections on the floor.
523      *
524      * Unfortunately we must close all writable tables, so we can't store or
525      * look up reputation information. The reason is that we don't have any
526      * multi-writer safety guarantees. We also can't use the single-writer
527      * proxywrite service, because its latency guarantees are too weak.
528      *
529      * All error retry counts shall be limited. Instead of blocking here, we
530      * could retry failed fork() operations in the event call-back routines,
531      * but we don't need perfection. The host system is severely overloaded
532      * and service levels are already way down.
533      *
534      * XXX Some Berkeley DB versions break with close-after-fork. Every new
535      * version is an improvement over its predecessor.
536      */
537     if (psc_cache_map != 0) {
538 	dict_cache_close(psc_cache_map);
539 	psc_cache_map = 0;
540     }
541     for (count = 0; /* see below */ ; count++) {
542 	if (count >= 5) {
543 	    msg_fatal("fork: %m");
544 	} else if (event_server_drain() != 0) {
545 	    msg_warn("fork: %m");
546 	    sleep(1);
547 	    continue;
548 	} else {
549 	    return;
550 	}
551     }
552 }
553 
554 /* psc_service - handle new client connection */
555 
556 static void psc_service(VSTREAM *smtp_client_stream,
557 			        char *unused_service,
558 			        char **unused_argv)
559 {
560     const char *myname = "psc_service";
561     PSC_STATE *state;
562     struct sockaddr_storage addr_storage;
563     SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
564     MAI_HOSTADDR_STR smtp_client_addr;
565     MAI_SERVPORT_STR smtp_client_port;
566     int     aierr;
567     const char *stamp_str;
568     int     saved_flags;
569 
570     /*
571      * This program handles all incoming connections, so it must not block.
572      * We use event-driven code for all operations that introduce latency.
573      *
574      * Note: instead of using VSTREAM-level timeouts, we enforce limits on the
575      * total amount of time to receive a complete SMTP command line.
576      */
577     non_blocking(vstream_fileno(smtp_client_stream), NON_BLOCKING);
578 
579     /*
580      * We use the event_server framework. This means we get already-accepted
581      * connections so we have to invoke getpeername() to find out the remote
582      * address and port.
583      */
584 #define PSC_SERVICE_DISCONNECT_AND_RETURN(stream) do { \
585 	event_server_disconnect(stream); \
586 	return; \
587     } while (0);
588 
589     /*
590      * Look up the remote SMTP client address and port.
591      */
592     if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
593 		    & addr_storage, &addr_storage_len) < 0) {
594 	msg_warn("getpeername: %m -- dropping this connection");
595 	/* Best effort - if this non-blocking write(2) fails, so be it. */
596 	(void) write(vstream_fileno(smtp_client_stream),
597 		     "421 4.3.2 No system resources\r\n",
598 		     sizeof("421 4.3.2 No system resources\r\n") - 1);
599 	PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
600     }
601 
602     /*
603      * Convert the remote SMTP client address and port to printable form for
604      * logging and access control.
605      */
606     if ((aierr = sockaddr_to_hostaddr((struct sockaddr *) & addr_storage,
607 				      addr_storage_len, &smtp_client_addr,
608 				      &smtp_client_port, 0)) != 0) {
609 	msg_warn("cannot convert client address/port to string: %s"
610 		 " -- dropping this connection",
611 		 MAI_STRERROR(aierr));
612 	/* Best effort - if this non-blocking write(2) fails, so be it. */
613 	(void) write(vstream_fileno(smtp_client_stream),
614 		     "421 4.3.2 No system resources\r\n",
615 		     sizeof("421 4.3.2 No system resources\r\n") - 1);
616 	PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
617     }
618     if (strncasecmp("::ffff:", smtp_client_addr.buf, 7) == 0)
619 	memmove(smtp_client_addr.buf, smtp_client_addr.buf + 7,
620 		sizeof(smtp_client_addr.buf) - 7);
621     if (msg_verbose > 1)
622 	msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
623 		 myname, psc_post_queue_length, psc_check_queue_length,
624 		 smtp_client_addr.buf, smtp_client_port.buf);
625 
626     msg_info("CONNECT from [%s]:%s", smtp_client_addr.buf, smtp_client_port.buf);
627 
628     /*
629      * Bundle up all the loose session pieces. This zeroes all flags and time
630      * stamps.
631      */
632     state = psc_new_session_state(smtp_client_stream, smtp_client_addr.buf,
633 				  smtp_client_port.buf);
634 
635     /*
636      * Reply with 421 when the client has too many open connections.
637      */
638     if (var_psc_cconn_limit > 0
639 	&& state->client_concurrency > var_psc_cconn_limit) {
640 	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
641 		 state->smtp_client_addr, state->smtp_client_port);
642 	PSC_DROP_SESSION_STATE(state,
643 			       "421 4.7.0 Error: too many connections\r\n");
644 	return;
645     }
646 
647     /*
648      * Reply with 421 when we can't forward more connections.
649      */
650     if (var_psc_post_queue_limit > 0
651 	&& psc_post_queue_length >= var_psc_post_queue_limit) {
652 	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: all server ports busy",
653 		 state->smtp_client_addr, state->smtp_client_port);
654 	PSC_DROP_SESSION_STATE(state,
655 			       "421 4.3.2 All server ports are busy\r\n");
656 	return;
657     }
658 
659     /*
660      * The permanent white/blacklist has highest precedence.
661      */
662     if (psc_acl != 0) {
663 	switch (psc_acl_eval(state, psc_acl, VAR_PSC_ACL)) {
664 
665 	    /*
666 	     * Permanently blacklisted.
667 	     */
668 	case PSC_ACL_ACT_BLACKLIST:
669 	    msg_info("BLACKLISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
670 	    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
671 	    switch (psc_blist_action) {
672 	    case PSC_ACT_DROP:
673 		PSC_DROP_SESSION_STATE(state,
674 			     "521 5.3.2 Service currently unavailable\r\n");
675 		return;
676 	    case PSC_ACT_ENFORCE:
677 		PSC_ENFORCE_SESSION_STATE(state,
678 			     "550 5.3.2 Service currently unavailable\r\n");
679 		break;
680 	    case PSC_ACT_IGNORE:
681 		PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
682 
683 		/*
684 		 * Not: PSC_PASS_SESSION_STATE. Repeat this test the next
685 		 * time.
686 		 */
687 		break;
688 	    default:
689 		msg_panic("%s: unknown blacklist action value %d",
690 			  myname, psc_blist_action);
691 	    }
692 	    break;
693 
694 	    /*
695 	     * Permanently whitelisted.
696 	     */
697 	case PSC_ACL_ACT_WHITELIST:
698 	    msg_info("WHITELISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
699 	    psc_conclude(state);
700 	    return;
701 
702 	    /*
703 	     * Other: dunno (don't know) or error.
704 	     */
705 	default:
706 	    break;
707 	}
708     }
709 
710     /*
711      * The temporary whitelist (i.e. the postscreen cache) has the lowest
712      * precedence. This cache contains information about the results of prior
713      * tests. Whitelist the client when all enabled test results are still
714      * valid.
715      */
716     if ((state->flags & PSC_STATE_MASK_ANY_FAIL) == 0
717 	&& psc_cache_map != 0
718 	&& (stamp_str = psc_cache_lookup(psc_cache_map, state->smtp_client_addr)) != 0) {
719 	saved_flags = state->flags;
720 	psc_parse_tests(state, stamp_str, event_time());
721 	state->flags |= saved_flags;
722 	if (msg_verbose)
723 	    msg_info("%s: cached + recent flags: %s",
724 		     myname, psc_print_state_flags(state->flags, myname));
725 	if ((state->flags & PSC_STATE_MASK_ANY_TODO_FAIL) == 0) {
726 	    msg_info("PASS OLD [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
727 	    psc_conclude(state);
728 	    return;
729 	}
730     } else {
731 	saved_flags = state->flags;
732 	psc_new_tests(state);
733 	state->flags |= saved_flags;
734 	if (msg_verbose)
735 	    msg_info("%s: new + recent flags: %s",
736 		     myname, psc_print_state_flags(state->flags, myname));
737     }
738 
739     /*
740      * Reply with 421 when we can't analyze more connections.
741      */
742     if (var_psc_pre_queue_limit > 0
743 	&& psc_check_queue_length - psc_post_queue_length
744 	>= var_psc_pre_queue_limit) {
745 	msg_info("reject: connect from [%s]:%s: all screening ports busy",
746 		 state->smtp_client_addr, state->smtp_client_port);
747 	PSC_DROP_SESSION_STATE(state,
748 			       "421 4.3.2 All screening ports are busy\r\n");
749 	return;
750     }
751 
752     /*
753      * If the client has no up-to-date results for some tests, do those tests
754      * first. Otherwise, skip the tests and hand off the connection.
755      */
756     if (state->flags & PSC_STATE_MASK_EARLY_TODO)
757 	psc_early_tests(state);
758     else if (state->flags & (PSC_STATE_MASK_SMTPD_TODO | PSC_STATE_FLAG_NOFORWARD))
759 	psc_smtpd_tests(state);
760     else
761 	psc_conclude(state);
762 }
763 
764 /* psc_cache_validator - validate one cache entry */
765 
766 static int psc_cache_validator(const char *client_addr,
767 			               const char *stamp_str,
768 			               char *unused_context)
769 {
770     PSC_STATE dummy;
771 
772     /*
773      * This function is called by the cache cleanup pseudo thread.
774      *
775      * When an entry is removed from the cache, the client will be reported as
776      * "NEW" in the next session where it passes all tests again. To avoid
777      * silly logging we remove the cache entry only after all tests have
778      * expired longer ago than the cache retention time.
779      */
780     psc_parse_tests(&dummy, stamp_str, event_time() - var_psc_cache_ret);
781     return ((dummy.flags & PSC_STATE_MASK_ANY_TODO) == 0);
782 }
783 
784 /* pre_jail_init - pre-jail initialization */
785 
786 static void pre_jail_init(char *unused_name, char **unused_argv)
787 {
788     VSTRING *redirect;
789 
790     /*
791      * Open read-only maps before dropping privilege, for consistency with
792      * other Postfix daemons.
793      */
794     psc_acl_pre_jail_init();
795     if (*var_psc_acl)
796 	psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
797     if (*var_psc_forbid_cmds)
798 	psc_forbid_cmds = string_list_init(MATCH_FLAG_NONE,
799 					   var_psc_forbid_cmds);
800     if (*var_psc_dnsbl_reply)
801 	psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
802 				    DICT_FLAG_DUP_WARN);
803 
804     /*
805      * Never, ever, get killed by a master signal, as that would corrupt the
806      * database when we're in the middle of an update.
807      */
808     if (setsid() < 0)
809 	msg_warn("setsid: %m");
810 
811     /*
812      * Security: don't create root-owned files that contain untrusted data.
813      * And don't create Postfix-owned files in root-owned directories,
814      * either. We want a correct relationship between (file or directory)
815      * ownership and (file or directory) content. To open files before going
816      * to jail, temporarily drop root privileges.
817      */
818     SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
819     redirect = vstring_alloc(100);
820 
821     /*
822      * Keep state in persistent external map. As a safety measure we sync the
823      * database on each update. This hurts on LINUX file systems that sync
824      * all dirty disk blocks whenever any application invokes fsync().
825      *
826      * Start the cache maintenance pseudo thread after dropping privileges.
827      */
828 #define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
829 	    DICT_FLAG_OPEN_LOCK)
830 
831     if (*var_psc_cache_map)
832 	psc_cache_map =
833 	    dict_cache_open(data_redirect_map(redirect, var_psc_cache_map),
834 			    O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS);
835 
836     /*
837      * Clean up and restore privilege.
838      */
839     vstring_free(redirect);
840     RESTORE_SAVED_EUGID();
841 
842     /*
843      * Initialize the dummy SMTP engine.
844      */
845     psc_smtpd_pre_jail_init();
846 }
847 
848 /* pre_accept - see if tables have changed */
849 
850 static void pre_accept(char *unused_name, char **unused_argv)
851 {
852     static time_t last_event_time;
853     time_t  new_event_time;
854     const char *name;
855 
856     /*
857      * If some table has changed then stop accepting new connections. Don't
858      * check the tables more than once a second.
859      */
860     new_event_time = event_time();
861     if (new_event_time >= last_event_time + 1
862 	&& (name = dict_changed_name()) != 0) {
863 	msg_info("table %s has changed - finishing in the background", name);
864 	event_server_drain();
865     } else {
866 	last_event_time = new_event_time;
867     }
868 }
869 
870 /* post_jail_init - post-jail initialization */
871 
872 static void post_jail_init(char *unused_name, char **unused_argv)
873 {
874     const NAME_CODE actions[] = {
875 	PSC_NAME_ACT_DROP, PSC_ACT_DROP,
876 	PSC_NAME_ACT_ENFORCE, PSC_ACT_ENFORCE,
877 	PSC_NAME_ACT_IGNORE, PSC_ACT_IGNORE,
878 	PSC_NAME_ACT_CONT, PSC_ACT_IGNORE,	/* compatibility */
879 	0, -1,
880     };
881     int     cache_flags;
882     const char *tmp;
883 
884     /*
885      * This routine runs after the skeleton code has entered the chroot jail.
886      * Prevent automatic process suicide after a limited number of client
887      * requests. It is OK to terminate after a limited amount of idle time.
888      */
889     var_use_limit = 0;
890 
891     /*
892      * Workaround for parameters whose values may contain "$", and that have
893      * a default of "$parametername". Not sure if it would be a good idea to
894      * always to this in the mail_conf_raw(3) module.
895      */
896     if (*var_psc_rej_footer == '$'
897 	&& mail_conf_lookup(var_psc_rej_footer + 1)) {
898 	tmp = mail_conf_eval_once(var_psc_rej_footer);
899 	myfree(var_psc_rej_footer);
900 	var_psc_rej_footer = mystrdup(tmp);
901     }
902     if (*var_psc_exp_filter == '$'
903 	&& mail_conf_lookup(var_psc_exp_filter + 1)) {
904 	tmp = mail_conf_eval_once(var_psc_exp_filter);
905 	myfree(var_psc_exp_filter);
906 	var_psc_exp_filter = mystrdup(tmp);
907     }
908 
909     /*
910      * Other one-time initialization.
911      */
912     psc_temp = vstring_alloc(10);
913     vstring_sprintf(psc_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service);
914     psc_smtpd_service_name = mystrdup(STR(psc_temp));
915     psc_dnsbl_init();
916     psc_early_init();
917     psc_smtpd_init();
918 
919     if ((psc_blist_action = name_code(actions, NAME_CODE_FLAG_NONE,
920 				      var_psc_blist_action)) < 0)
921 	msg_fatal("bad %s value: %s", VAR_PSC_BLIST_ACTION,
922 		  var_psc_blist_action);
923     if ((psc_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE,
924 				      var_psc_dnsbl_action)) < 0)
925 	msg_fatal("bad %s value: %s", VAR_PSC_DNSBL_ACTION,
926 		  var_psc_dnsbl_action);
927     if ((psc_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE,
928 				      var_psc_pregr_action)) < 0)
929 	msg_fatal("bad %s value: %s", VAR_PSC_PREGR_ACTION,
930 		  var_psc_pregr_action);
931     if ((psc_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE,
932 				      var_psc_pipel_action)) < 0)
933 	msg_fatal("bad %s value: %s", VAR_PSC_PIPEL_ACTION,
934 		  var_psc_pipel_action);
935     if ((psc_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE,
936 				      var_psc_nsmtp_action)) < 0)
937 	msg_fatal("bad %s value: %s", VAR_PSC_NSMTP_ACTION,
938 		  var_psc_nsmtp_action);
939     if ((psc_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE,
940 				      var_psc_barlf_action)) < 0)
941 	msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION,
942 		  var_psc_barlf_action);
943 
944     /*
945      * Start the cache maintenance pseudo thread last. Early cleanup makes
946      * verbose logging more informative (we get positive confirmation that
947      * the cleanup thread runs).
948      */
949     cache_flags = DICT_CACHE_FLAG_STATISTICS;
950     if (msg_verbose > 1)
951 	cache_flags |= DICT_CACHE_FLAG_VERBOSE;
952     if (psc_cache_map != 0 && var_psc_cache_scan > 0)
953 	dict_cache_control(psc_cache_map,
954 			   DICT_CACHE_CTL_FLAGS, cache_flags,
955 			   DICT_CACHE_CTL_INTERVAL, var_psc_cache_scan,
956 			   DICT_CACHE_CTL_VALIDATOR, psc_cache_validator,
957 			   DICT_CACHE_CTL_CONTEXT, (char *) 0,
958 			   DICT_CACHE_CTL_END);
959 
960     /*
961      * Pre-compute the minimal and maximal TTL.
962      */
963     psc_min_ttl =
964 	PSC_MIN(PSC_MIN(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
965 		PSC_MIN(PSC_MIN(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
966 			var_psc_barlf_ttl));
967     psc_max_ttl =
968 	PSC_MAX(PSC_MAX(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
969 		PSC_MAX(PSC_MAX(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
970 			var_psc_barlf_ttl));
971 
972     /*
973      * Pre-compute the stress and normal command time limits.
974      */
975     mail_conf_update(VAR_STRESS, "yes");
976     psc_stress_cmd_time_limit =
977 	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
978     psc_stress_greet_wait =
979 	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
980 
981     mail_conf_update(VAR_STRESS, "");
982     psc_normal_cmd_time_limit =
983 	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
984     psc_normal_greet_wait =
985 	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
986 
987     psc_lowat_check_queue_length = .7 * var_psc_pre_queue_limit;
988     psc_hiwat_check_queue_length = .9 * var_psc_pre_queue_limit;
989     if (msg_verbose)
990 	msg_info(VAR_PSC_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
991 		 psc_stress_cmd_time_limit, psc_normal_cmd_time_limit,
992 		 psc_lowat_check_queue_length, psc_hiwat_check_queue_length);
993 
994     if (psc_lowat_check_queue_length == 0)
995 	msg_panic("compiler error: 0.7 * %d = %d", var_psc_pre_queue_limit,
996 		  psc_lowat_check_queue_length);
997     if (psc_hiwat_check_queue_length == 0)
998 	msg_panic("compiler error: 0.9 * %d = %d", var_psc_pre_queue_limit,
999 		  psc_hiwat_check_queue_length);
1000 
1001     /*
1002      * Per-client concurrency.
1003      */
1004     psc_client_concurrency = htable_create(var_psc_pre_queue_limit);
1005 }
1006 
1007 MAIL_VERSION_STAMP_DECLARE;
1008 
1009 /* main - pass control to the multi-threaded skeleton */
1010 
1011 int     main(int argc, char **argv)
1012 {
1013 
1014     /*
1015      * List smtpd(8) parameters before any postscreen(8) parameters that have
1016      * defaults dependencies on them.
1017      */
1018     static const CONFIG_STR_TABLE str_table[] = {
1019 	VAR_SMTPD_SERVICE, DEF_SMTPD_SERVICE, &var_smtpd_service, 1, 0,
1020 	VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
1021 	VAR_SMTPD_FORBID_CMDS, DEF_SMTPD_FORBID_CMDS, &var_smtpd_forbid_cmds, 0, 0,
1022 	VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
1023 	VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
1024 	VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0,
1025 	VAR_SMTPD_CMD_FILTER, DEF_SMTPD_CMD_FILTER, &var_smtpd_cmd_filter, 0, 0,
1026 	VAR_PSC_CACHE_MAP, DEF_PSC_CACHE_MAP, &var_psc_cache_map, 0, 0,
1027 	VAR_PSC_PREGR_BANNER, DEF_PSC_PREGR_BANNER, &var_psc_pregr_banner, 0, 0,
1028 	VAR_PSC_PREGR_ACTION, DEF_PSC_PREGR_ACTION, &var_psc_pregr_action, 1, 0,
1029 	VAR_PSC_DNSBL_SITES, DEF_PSC_DNSBL_SITES, &var_psc_dnsbl_sites, 0, 0,
1030 	VAR_PSC_DNSBL_ACTION, DEF_PSC_DNSBL_ACTION, &var_psc_dnsbl_action, 1, 0,
1031 	VAR_PSC_PIPEL_ACTION, DEF_PSC_PIPEL_ACTION, &var_psc_pipel_action, 1, 0,
1032 	VAR_PSC_NSMTP_ACTION, DEF_PSC_NSMTP_ACTION, &var_psc_nsmtp_action, 1, 0,
1033 	VAR_PSC_BARLF_ACTION, DEF_PSC_BARLF_ACTION, &var_psc_barlf_action, 1, 0,
1034 	VAR_PSC_ACL, DEF_PSC_ACL, &var_psc_acl, 0, 0,
1035 	VAR_PSC_BLIST_ACTION, DEF_PSC_BLIST_ACTION, &var_psc_blist_action, 1, 0,
1036 	VAR_PSC_FORBID_CMDS, DEF_PSC_FORBID_CMDS, &var_psc_forbid_cmds, 0, 0,
1037 	VAR_PSC_EHLO_DIS_WORDS, DEF_PSC_EHLO_DIS_WORDS, &var_psc_ehlo_dis_words, 0, 0,
1038 	VAR_PSC_EHLO_DIS_MAPS, DEF_PSC_EHLO_DIS_MAPS, &var_psc_ehlo_dis_maps, 0, 0,
1039 	VAR_PSC_DNSBL_REPLY, DEF_PSC_DNSBL_REPLY, &var_psc_dnsbl_reply, 0, 0,
1040 	VAR_PSC_TLS_LEVEL, DEF_PSC_TLS_LEVEL, &var_psc_tls_level, 0, 0,
1041 	VAR_PSC_CMD_FILTER, DEF_PSC_CMD_FILTER, &var_psc_cmd_filter, 0, 0,
1042 	VAR_DNSBLOG_SERVICE, DEF_DNSBLOG_SERVICE, &var_dnsblog_service, 1, 0,
1043 	VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
1044 	0,
1045     };
1046     static const CONFIG_INT_TABLE int_table[] = {
1047 	VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
1048 	VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 0, 0,
1049 	VAR_PSC_CMD_COUNT, DEF_PSC_CMD_COUNT, &var_psc_cmd_count, 1, 0,
1050 	VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
1051 	0,
1052     };
1053     static const CONFIG_NINT_TABLE nint_table[] = {
1054 	VAR_PSC_POST_QLIMIT, DEF_PSC_POST_QLIMIT, &var_psc_post_queue_limit, 5, 0,
1055 	VAR_PSC_PRE_QLIMIT, DEF_PSC_PRE_QLIMIT, &var_psc_pre_queue_limit, 10, 0,
1056 	VAR_PSC_CCONN_LIMIT, DEF_PSC_CCONN_LIMIT, &var_psc_cconn_limit, 0, 0,
1057 	0,
1058     };
1059     static const CONFIG_TIME_TABLE time_table[] = {
1060 	VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, &var_psc_greet_wait, 1, 0,
1061 	VAR_PSC_PREGR_TTL, DEF_PSC_PREGR_TTL, &var_psc_pregr_ttl, 1, 0,
1062 	VAR_PSC_DNSBL_TTL, DEF_PSC_DNSBL_TTL, &var_psc_dnsbl_ttl, 1, 0,
1063 	VAR_PSC_PIPEL_TTL, DEF_PSC_PIPEL_TTL, &var_psc_pipel_ttl, 1, 0,
1064 	VAR_PSC_NSMTP_TTL, DEF_PSC_NSMTP_TTL, &var_psc_nsmtp_ttl, 1, 0,
1065 	VAR_PSC_BARLF_TTL, DEF_PSC_BARLF_TTL, &var_psc_barlf_ttl, 1, 0,
1066 	VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0,
1067 	VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 1, 0,
1068 	VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0,
1069 	0,
1070     };
1071     static const CONFIG_BOOL_TABLE bool_table[] = {
1072 	VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required,
1073 	VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
1074 	VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
1075 	VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
1076 	VAR_PSC_PIPEL_ENABLE, DEF_PSC_PIPEL_ENABLE, &var_psc_pipel_enable,
1077 	VAR_PSC_NSMTP_ENABLE, DEF_PSC_NSMTP_ENABLE, &var_psc_nsmtp_enable,
1078 	VAR_PSC_BARLF_ENABLE, DEF_PSC_BARLF_ENABLE, &var_psc_barlf_enable,
1079 	0,
1080     };
1081     static const CONFIG_RAW_TABLE raw_table[] = {
1082 	VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0,
1083 	VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
1084 	VAR_PSC_REJ_FOOTER, DEF_PSC_REJ_FOOTER, &var_psc_rej_footer, 0, 0,
1085 	VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
1086 	VAR_PSC_EXP_FILTER, DEF_PSC_EXP_FILTER, &var_psc_exp_filter, 1, 0,
1087 	0,
1088     };
1089     static const CONFIG_NBOOL_TABLE nbool_table[] = {
1090 	VAR_PSC_HELO_REQUIRED, DEF_PSC_HELO_REQUIRED, &var_psc_helo_required,
1091 	VAR_PSC_DISABLE_VRFY, DEF_PSC_DISABLE_VRFY, &var_psc_disable_vrfy,
1092 	VAR_PSC_USE_TLS, DEF_PSC_USE_TLS, &var_psc_use_tls,
1093 	VAR_PSC_ENFORCE_TLS, DEF_PSC_ENFORCE_TLS, &var_psc_enforce_tls,
1094 	0,
1095     };
1096 
1097     /*
1098      * Fingerprint executables and core dumps.
1099      */
1100     MAIL_VERSION_STAMP_ALLOCATE;
1101 
1102     event_server_main(argc, argv, psc_service,
1103 		      MAIL_SERVER_STR_TABLE, str_table,
1104 		      MAIL_SERVER_INT_TABLE, int_table,
1105 		      MAIL_SERVER_NINT_TABLE, nint_table,
1106 		      MAIL_SERVER_TIME_TABLE, time_table,
1107 		      MAIL_SERVER_BOOL_TABLE, bool_table,
1108 		      MAIL_SERVER_RAW_TABLE, raw_table,
1109 		      MAIL_SERVER_NBOOL_TABLE, nbool_table,
1110 		      MAIL_SERVER_PRE_INIT, pre_jail_init,
1111 		      MAIL_SERVER_POST_INIT, post_jail_init,
1112 		      MAIL_SERVER_PRE_ACCEPT, pre_accept,
1113 		      MAIL_SERVER_SOLITARY,
1114 		      MAIL_SERVER_SLOW_EXIT, psc_drain,
1115 		      MAIL_SERVER_EXIT, psc_dump,
1116 		      MAIL_SERVER_WATCHDOG, &var_psc_watchdog,
1117 		      0);
1118 }
1119