Home | History | Annotate | Line # | Download | only in postscreen
      1 /*	$NetBSD: postscreen.c,v 1.7 2026/05/09 18:49:19 christos 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 provides additional
     12 /*	protection against mail server overload. One \fBpostscreen\fR(8)
     13 /*	process handles multiple inbound SMTP connections, and decides
     14 /*	which clients may talk to a Postfix SMTP server process.
     15 /*	By keeping spambots away, \fBpostscreen\fR(8) leaves more
     16 /*	SMTP server processes available for legitimate clients, and
     17 /*	delays the onset of server overload conditions.
     18 /*
     19 /*	This program should not be used on SMTP ports that receive
     20 /*	mail from end-user clients (MUAs). In a typical deployment,
     21 /*	\fBpostscreen\fR(8) handles the MX service on TCP port 25, and
     22 /*	\fBsmtpd\fR(8) receives mail from MUAs on the \fBsubmission\fR
     23 /*	service (TCP port 587) which requires client authentication.
     24 /*	Alternatively, a site could set up a dedicated, non-postscreen,
     25 /*	"port 25" server that provides \fBsubmission\fR service and
     26 /*	client authentication, but no MX service.
     27 /*
     28 /*	\fBpostscreen\fR(8) maintains a temporary allowlist for
     29 /*	clients that have passed a number of tests.  When an SMTP
     30 /*	client IP address is allowlisted, \fBpostscreen\fR(8) hands
     31 /*	off the connection immediately to a Postfix SMTP server
     32 /*	process. This minimizes the overhead for legitimate mail.
     33 /*
     34 /*	By default, \fBpostscreen\fR(8) logs statistics and hands
     35 /*	off each connection to a Postfix SMTP server process, while
     36 /*	excluding clients in mynetworks from all tests (primarily,
     37 /*	to avoid problems with non-standard SMTP implementations
     38 /*	in network appliances).  This default mode blocks no clients,
     39 /*	and is useful for non-destructive testing.
     40 /*
     41 /*	In a typical production setting, \fBpostscreen\fR(8) is
     42 /*	configured to reject mail from clients that fail one or
     43 /*	more tests. \fBpostscreen\fR(8) logs rejected mail with the
     44 /*	client address, helo, sender and recipient information.
     45 /*
     46 /*	\fBpostscreen\fR(8) is not an SMTP proxy; this is intentional.
     47 /*	The purpose is to keep spambots away from Postfix SMTP
     48 /*	server processes, while minimizing overhead for legitimate
     49 /*	traffic.
     50 /* SECURITY
     51 /* .ad
     52 /* .fi
     53 /*	The \fBpostscreen\fR(8) server is moderately security-sensitive.
     54 /*	It talks to untrusted clients on the network. The process
     55 /*	can be run chrooted at fixed low privilege.
     56 /* STANDARDS
     57 /*	RFC 821 (SMTP protocol)
     58 /*	RFC 1123 (Host requirements)
     59 /*	RFC 1652 (8bit-MIME transport)
     60 /*	RFC 1869 (SMTP service extensions)
     61 /*	RFC 1870 (Message Size Declaration)
     62 /*	RFC 1985 (ETRN command)
     63 /*	RFC 2034 (SMTP Enhanced Status Codes)
     64 /*	RFC 2821 (SMTP protocol)
     65 /*	Not: RFC 2920 (SMTP Pipelining)
     66 /*	RFC 3030 (CHUNKING without BINARYMIME)
     67 /*	RFC 3207 (STARTTLS command)
     68 /*	RFC 3461 (SMTP DSN Extension)
     69 /*	RFC 3463 (Enhanced Status Codes)
     70 /*	RFC 5321 (SMTP protocol, including multi-line 220 banners)
     71 /* DIAGNOSTICS
     72 /*	Problems and transactions are logged to \fBsyslogd\fR(8)
     73 /*	or \fBpostlogd\fR(8).
     74 /* BUGS
     75 /*	The \fBpostscreen\fR(8) built-in SMTP protocol engine
     76 /*	currently does not announce support for AUTH, XCLIENT or
     77 /*	XFORWARD.
     78 /*	If you need to make these services available
     79 /*	on port 25, then do not enable the optional "after 220
     80 /*	server greeting" tests.
     81 /*
     82 /*	The optional "after 220 server greeting" tests may result in
     83 /*	unexpected delivery delays from senders that retry email delivery
     84 /*	from a different IP address.  Reason: after passing these tests a
     85 /*	new client must disconnect, and reconnect from the same IP
     86 /*	address before it can deliver mail. See POSTSCREEN_README, section
     87 /*	"Tests after the 220 SMTP server greeting", for a discussion.
     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}:{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 /* .PP
    121 /*	Available in Postfix version 3.1 and later:
    122 /* .IP "\fBdns_ncache_ttl_fix_enable (no)\fR"
    123 /*	Enable a workaround for future libc incompatibility.
    124 /* .PP
    125 /*	Available in Postfix version 3.4 and later:
    126 /* .IP "\fBpostscreen_reject_footer_maps ($smtpd_reject_footer_maps)\fR"
    127 /*	Optional lookup table for information that is appended after a 4XX
    128 /*	or 5XX \fBpostscreen\fR(8) server response.
    129 /* .PP
    130 /*	Available in Postfix 3.6 and later:
    131 /* .IP "\fBrespectful_logging (see 'postconf -d' output)\fR"
    132 /*	Avoid logging that implies white is better than black.
    133 /* TROUBLE SHOOTING CONTROLS
    134 /* .ad
    135 /* .fi
    136 /* .IP "\fBpostscreen_expansion_filter (see 'postconf -d' output)\fR"
    137 /*	List of characters that are permitted in postscreen_reject_footer
    138 /*	attribute expansions.
    139 /* .IP "\fBpostscreen_reject_footer ($smtpd_reject_footer)\fR"
    140 /*	Optional information that is appended after a 4XX or 5XX
    141 /*	\fBpostscreen\fR(8) server
    142 /*	response.
    143 /* .IP "\fBsoft_bounce (no)\fR"
    144 /*	Safety net to keep mail queued that would otherwise be returned to
    145 /*	the sender.
    146 /* BEFORE-POSTSCREEN PROXY AGENT
    147 /* .ad
    148 /* .fi
    149 /*	Available in Postfix version 2.10 and later:
    150 /* .IP "\fBpostscreen_upstream_proxy_protocol (empty)\fR"
    151 /*	The name of the proxy protocol used by an optional before-postscreen
    152 /*	proxy agent.
    153 /* .IP "\fBpostscreen_upstream_proxy_timeout (5s)\fR"
    154 /*	The time limit for the proxy protocol specified with the
    155 /*	postscreen_upstream_proxy_protocol parameter.
    156 /* PERMANENT ALLOW/DENYLIST TEST
    157 /* .ad
    158 /* .fi
    159 /*	This test is executed immediately after a remote SMTP client
    160 /*	connects. If a client is permanently allowlisted, the client
    161 /*	will be handed off immediately to a Postfix SMTP server
    162 /*	process.
    163 /* .IP "\fBpostscreen_access_list (permit_mynetworks)\fR"
    164 /*	Permanent allow/denylist for remote SMTP client IP addresses.
    165 /* .IP "\fBpostscreen_blacklist_action (ignore)\fR"
    166 /*	Renamed to postscreen_denylist_action in Postfix 3.6.
    167 /* MAIL EXCHANGER POLICY TESTS
    168 /* .ad
    169 /* .fi
    170 /*	When \fBpostscreen\fR(8) is configured to monitor all primary
    171 /*	and backup MX addresses, it can refuse to allowlist clients
    172 /*	that connect to a backup MX address only. For small sites,
    173 /*	this requires configuring primary and backup MX addresses
    174 /*	on the same MTA. Larger sites would have to share the
    175 /*	\fBpostscreen\fR(8) cache between primary and backup MTAs,
    176 /*	which would introduce a common point of failure.
    177 /* .IP "\fBpostscreen_allowlist_interfaces (static:all)\fR"
    178 /*	A list of local \fBpostscreen\fR(8) server IP addresses where a
    179 /*	non-allowlisted remote SMTP client can obtain \fBpostscreen\fR(8)'s temporary
    180 /*	allowlist status.
    181 /* BEFORE 220 GREETING TESTS
    182 /* .ad
    183 /* .fi
    184 /*	These tests are executed before the remote SMTP client
    185 /*	receives the "220 servername" greeting. If no tests remain
    186 /*	after the successful completion of this phase, the client
    187 /*	will be handed off immediately to a Postfix SMTP server
    188 /*	process.
    189 /* .IP "\fBdnsblog_service_name (dnsblog)\fR"
    190 /*	The name of the \fBdnsblog\fR(8) service entry in master.cf.
    191 /* .IP "\fBpostscreen_dnsbl_action (ignore)\fR"
    192 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client's combined
    193 /*	DNSBL score is equal to or greater than a threshold (as defined
    194 /*	with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
    195 /*	parameters).
    196 /* .IP "\fBpostscreen_dnsbl_reply_map (empty)\fR"
    197 /*	A mapping from an actual DNSBL domain name which includes a secret
    198 /*	password, to the DNSBL domain name that postscreen will reply with
    199 /*	when it rejects mail.
    200 /* .IP "\fBpostscreen_dnsbl_sites (empty)\fR"
    201 /*	Optional list of patterns with DNS allow/denylist domains, filters
    202 /*	and weight
    203 /*	factors.
    204 /* .IP "\fBpostscreen_dnsbl_threshold (1)\fR"
    205 /*	The inclusive lower bound for blocking a remote SMTP client, based on
    206 /*	its combined DNSBL score as defined with the postscreen_dnsbl_sites
    207 /*	parameter.
    208 /* .IP "\fBpostscreen_greet_action (ignore)\fR"
    209 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client speaks
    210 /*	before its turn within the time specified with the postscreen_greet_wait
    211 /*	parameter.
    212 /* .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
    213 /*	The \fItext\fR in the optional "220-\fItext\fR..." server
    214 /*	response that
    215 /*	\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
    216 /*	text..." response, in an attempt to confuse bad SMTP clients so
    217 /*	that they speak before their turn (pre-greet).
    218 /* .IP "\fBpostscreen_greet_wait (normal: 6s, overload: 2s)\fR"
    219 /*	The amount of time that \fBpostscreen\fR(8) will wait for an SMTP
    220 /*	client to send a command before its turn, and for DNS blocklist
    221 /*	lookup results to arrive (default: up to 2 seconds under stress,
    222 /*	up to 6 seconds otherwise).
    223 /* .IP "\fBsmtpd_service_name (smtpd)\fR"
    224 /*	The internal service that \fBpostscreen\fR(8) hands off allowed
    225 /*	connections to.
    226 /* .PP
    227 /*	Available in Postfix version 2.11 and later:
    228 /* .IP "\fBpostscreen_dnsbl_whitelist_threshold (0)\fR"
    229 /*	Renamed to postscreen_dnsbl_allowlist_threshold in Postfix 3.6.
    230 /* .PP
    231 /*	Available in Postfix version 3.0 and later:
    232 /* .IP "\fBpostscreen_dnsbl_timeout (10s)\fR"
    233 /*	The time limit for DNSBL or DNSWL lookups.
    234 /* .PP
    235 /*	Available in Postfix version 3.6 and later:
    236 /* .IP "\fBpostscreen_denylist_action (ignore)\fR"
    237 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client is
    238 /*	permanently denylisted with the postscreen_access_list parameter.
    239 /* .IP "\fBpostscreen_allowlist_interfaces (static:all)\fR"
    240 /*	A list of local \fBpostscreen\fR(8) server IP addresses where a
    241 /*	non-allowlisted remote SMTP client can obtain \fBpostscreen\fR(8)'s temporary
    242 /*	allowlist status.
    243 /* .IP "\fBpostscreen_dnsbl_allowlist_threshold (0)\fR"
    244 /*	Allow a remote SMTP client to skip "before" and "after 220
    245 /*	greeting" protocol tests, based on its combined DNSBL score as
    246 /*	defined with the postscreen_dnsbl_sites parameter.
    247 /* AFTER 220 GREETING TESTS
    248 /* .ad
    249 /* .fi
    250 /*	These tests are executed after the remote SMTP client
    251 /*	receives the "220 servername" greeting. If a client passes
    252 /*	all tests during this phase, it will receive a 4XX response
    253 /*	to all RCPT TO commands. After the client reconnects, it
    254 /*	will be allowed to talk directly to a Postfix SMTP server
    255 /*	process.
    256 /* .IP "\fBpostscreen_bare_newline_action (ignore)\fR"
    257 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client sends
    258 /*	a bare newline character, that is, a newline not preceded by carriage
    259 /*	return.
    260 /* .IP "\fBpostscreen_bare_newline_enable (no)\fR"
    261 /*	Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
    262 /*	server.
    263 /* .IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
    264 /*	Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
    265 /* .IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
    266 /*	List of commands that the \fBpostscreen\fR(8) server considers in
    267 /*	violation of the SMTP protocol.
    268 /* .IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
    269 /*	Require that a remote SMTP client sends HELO or EHLO before
    270 /*	commencing a MAIL transaction.
    271 /* .IP "\fBpostscreen_non_smtp_command_action (drop)\fR"
    272 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client sends
    273 /*	non-SMTP commands as specified with the postscreen_forbidden_commands
    274 /*	parameter.
    275 /* .IP "\fBpostscreen_non_smtp_command_enable (no)\fR"
    276 /*	Enable "non-SMTP command" tests in the \fBpostscreen\fR(8) server.
    277 /* .IP "\fBpostscreen_pipelining_action (enforce)\fR"
    278 /*	The action that \fBpostscreen\fR(8) takes when a remote SMTP client
    279 /*	sends
    280 /*	multiple commands instead of sending one command and waiting for
    281 /*	the server to respond.
    282 /* .IP "\fBpostscreen_pipelining_enable (no)\fR"
    283 /*	Enable "pipelining" SMTP protocol tests in the \fBpostscreen\fR(8)
    284 /*	server.
    285 /* CACHE CONTROLS
    286 /* .ad
    287 /* .fi
    288 /* .IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
    289 /*	The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
    290 /* .IP "\fBpostscreen_cache_map (btree:$data_directory/postscreen_cache)\fR"
    291 /*	Persistent storage for the \fBpostscreen\fR(8) server decisions.
    292 /* .IP "\fBpostscreen_cache_retention_time (7d)\fR"
    293 /*	The amount of time that \fBpostscreen\fR(8) will cache an expired
    294 /*	temporary allowlist entry before it is removed.
    295 /* .IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
    296 /*	The amount of time that \fBpostscreen\fR(8) remembers that a client
    297 /*	IP address passed a "bare newline" SMTP protocol test, before it
    298 /*	address is required to pass that test again.
    299 /* .IP "\fBpostscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)\fR"
    300 /*	The maximum amount of time that \fBpostscreen\fR(8) remembers that a
    301 /*	client IP address passed a DNS-based reputation test, before it is
    302 /*	required to pass that test again.
    303 /* .IP "\fBpostscreen_dnsbl_min_ttl (60s)\fR"
    304 /*	The minimum amount of time that \fBpostscreen\fR(8) remembers that a
    305 /*	client IP address passed a DNS-based reputation test, before it
    306 /*	is required to pass that test again.
    307 /* .IP "\fBpostscreen_greet_ttl (1d)\fR"
    308 /*	The amount of time that \fBpostscreen\fR(8) remembers that a client
    309 /*	IP address passed a PREGREET test, before it is required to pass
    310 /*	that test again.
    311 /* .IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR"
    312 /*	The amount of time that \fBpostscreen\fR(8) remembers that a client
    313 /*	IP address passed a "non_smtp_command" SMTP protocol test, before
    314 /*	it is required to pass that test again.
    315 /* .IP "\fBpostscreen_pipelining_ttl (30d)\fR"
    316 /*	The amount of time that \fBpostscreen\fR(8) remembers that a client
    317 /*	IP address passed a "pipelining" SMTP protocol test, before it is
    318 /*	required to pass that test again.
    319 /* RESOURCE CONTROLS
    320 /* .ad
    321 /* .fi
    322 /* .IP "\fBline_length_limit (2048)\fR"
    323 /*	Upon input, long lines are chopped up into pieces of at most
    324 /*	this length; upon delivery, long lines are reconstructed.
    325 /* .IP "\fBpostscreen_client_connection_count_limit ($smtpd_client_connection_count_limit)\fR"
    326 /*	How many simultaneous connections any remote SMTP client is
    327 /*	allowed to have
    328 /*	with the \fBpostscreen\fR(8) daemon.
    329 /* .IP "\fBpostscreen_command_count_limit (20)\fR"
    330 /*	The limit on the total number of commands per SMTP session for
    331 /*	\fBpostscreen\fR(8)'s built-in SMTP protocol engine.
    332 /* .IP "\fBpostscreen_command_time_limit (normal: 300s, overload: 10s)\fR"
    333 /*	The time limit to read an entire command line with \fBpostscreen\fR(8)'s
    334 /*	built-in SMTP protocol engine.
    335 /* .IP "\fBpostscreen_post_queue_limit ($default_process_limit)\fR"
    336 /*	The number of clients that can be waiting for service from a
    337 /*	real Postfix SMTP server process.
    338 /* .IP "\fBpostscreen_pre_queue_limit ($default_process_limit)\fR"
    339 /*	The number of non-allowlisted clients that can be waiting for
    340 /*	a decision whether they will receive service from a real Postfix
    341 /*	SMTP server
    342 /*	process.
    343 /* .IP "\fBpostscreen_watchdog_timeout (10s)\fR"
    344 /*	How much time a \fBpostscreen\fR(8) process may take to respond to
    345 /*	a remote SMTP client command or to perform a cache operation before it
    346 /*	is terminated by a built-in watchdog timer.
    347 /* STARTTLS CONTROLS
    348 /* .ad
    349 /* .fi
    350 /* .IP "\fBpostscreen_tls_security_level ($smtpd_tls_security_level)\fR"
    351 /*	The SMTP TLS security level for the \fBpostscreen\fR(8) server; when
    352 /*	a non-empty value is specified, this overrides the obsolete parameters
    353 /*	postscreen_use_tls and postscreen_enforce_tls.
    354 /* .IP "\fBtlsproxy_service_name (tlsproxy)\fR"
    355 /*	The name of the \fBtlsproxy\fR(8) service entry in master.cf.
    356 /* OBSOLETE STARTTLS SUPPORT CONTROLS
    357 /* .ad
    358 /* .fi
    359 /*	These parameters are supported for compatibility with
    360 /*	\fBsmtpd\fR(8) legacy parameters.
    361 /* .IP "\fBpostscreen_use_tls ($smtpd_use_tls)\fR"
    362 /*	Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
    363 /*	but do not require that clients use TLS encryption.
    364 /* .IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
    365 /*	Mandatory TLS: announce STARTTLS support to remote SMTP clients, and
    366 /*	require that clients use TLS encryption.
    367 /* MISCELLANEOUS CONTROLS
    368 /* .ad
    369 /* .fi
    370 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
    371 /*	The default location of the Postfix main.cf and master.cf
    372 /*	configuration files.
    373 /* .IP "\fBdelay_logging_resolution_limit (2)\fR"
    374 /*	The maximal number of digits after the decimal point when logging
    375 /*	delay values.
    376 /* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
    377 /*	The location of all postfix administrative commands.
    378 /* .IP "\fBmax_idle (100s)\fR"
    379 /*	The maximum amount of time that an idle Postfix daemon process waits
    380 /*	for an incoming connection before terminating voluntarily.
    381 /* .IP "\fBprocess_id (read-only)\fR"
    382 /*	The process ID of a Postfix command or daemon process.
    383 /* .IP "\fBprocess_name (read-only)\fR"
    384 /*	The process name of a Postfix command or daemon process.
    385 /* .IP "\fBsyslog_facility (mail)\fR"
    386 /*	The syslog facility of Postfix logging.
    387 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
    388 /*	A prefix that is prepended to the process name in syslog
    389 /*	records, so that, for example, "smtpd" becomes "prefix/smtpd".
    390 /* .PP
    391 /*	Available in Postfix 3.3 and later:
    392 /* .IP "\fBservice_name (read-only)\fR"
    393 /*	The master.cf service name of a Postfix daemon process.
    394 /* .PP
    395 /*	Available in Postfix 3.5 and later:
    396 /* .IP "\fBinfo_log_address_format (external)\fR"
    397 /*	The email address form that will be used in non-debug logging
    398 /*	(info, warning, etc.).
    399 /* SEE ALSO
    400 /*	smtpd(8), Postfix SMTP server
    401 /*	tlsproxy(8), Postfix TLS proxy server
    402 /*	dnsblog(8), DNS allow/denylist logger
    403 /*	postlogd(8), Postfix logging
    404 /*	syslogd(8), system logging
    405 /* README FILES
    406 /* .ad
    407 /* .fi
    408 /*	Use "\fBpostconf readme_directory\fR" or "\fBpostconf
    409 /*	html_directory\fR" to locate this information.
    410 /* .nf
    411 /* .na
    412 /*	POSTSCREEN_README, Postfix Postscreen Howto
    413 /* LICENSE
    414 /* .ad
    415 /* .fi
    416 /*	The Secure Mailer license must be distributed with this software.
    417 /* HISTORY
    418 /* .ad
    419 /* .fi
    420 /*	This service was introduced with Postfix version 2.8.
    421 /*
    422 /*	Many ideas in \fBpostscreen\fR(8) were explored in earlier
    423 /*	work by Michael Tokarev, in OpenBSD spamd, and in MailChannels
    424 /*	Traffic Control.
    425 /* AUTHOR(S)
    426 /*	Wietse Venema
    427 /*	IBM T.J. Watson Research
    428 /*	P.O. Box 704
    429 /*	Yorktown Heights, NY 10598, USA
    430 /*
    431 /*	Wietse Venema
    432 /*	Google, Inc.
    433 /*	111 8th Avenue
    434 /*	New York, NY 10011, USA
    435 /*
    436 /*	Wietse Venema
    437 /*	porcupine.org
    438 /*--*/
    439 
    440 /* System library. */
    441 
    442 #include <sys_defs.h>
    443 #include <sys/stat.h>
    444 #include <stdlib.h>
    445 
    446 /* Utility library. */
    447 
    448 #include <msg.h>
    449 #include <mymalloc.h>
    450 #include <events.h>
    451 #include <myaddrinfo.h>
    452 #include <dict_cache.h>
    453 #include <set_eugid.h>
    454 #include <vstream.h>
    455 #include <name_code.h>
    456 #include <inet_proto.h>
    457 
    458 /* Global library. */
    459 
    460 #include <mail_conf.h>
    461 #include <mail_params.h>
    462 #include <mail_version.h>
    463 #include <mail_proto.h>
    464 #include <data_redirect.h>
    465 #include <string_list.h>
    466 
    467 /* Master server protocols. */
    468 
    469 #include <mail_server.h>
    470 
    471 /* Application-specific. */
    472 
    473 #include <postscreen.h>
    474 
    475  /*
    476   * Configuration parameters.
    477   */
    478 char   *var_smtpd_service;
    479 char   *var_smtpd_banner;
    480 bool    var_disable_vrfy_cmd;
    481 bool    var_helo_required;
    482 
    483 char   *var_smtpd_cmd_filter;
    484 char   *var_psc_cmd_filter;
    485 
    486 char   *var_smtpd_forbid_cmds;
    487 char   *var_psc_forbid_cmds;
    488 
    489 char   *var_smtpd_ehlo_dis_words;
    490 char   *var_smtpd_ehlo_dis_maps;
    491 char   *var_psc_ehlo_dis_words;
    492 char   *var_psc_ehlo_dis_maps;
    493 
    494 char   *var_smtpd_tls_level;
    495 bool    var_smtpd_use_tls;
    496 bool    var_smtpd_enforce_tls;
    497 char   *var_psc_tls_level;
    498 bool    var_psc_use_tls;
    499 bool    var_psc_enforce_tls;
    500 
    501 bool    var_psc_disable_vrfy;
    502 bool    var_psc_helo_required;
    503 
    504 char   *var_psc_cache_map;
    505 int     var_psc_cache_scan;
    506 int     var_psc_cache_ret;
    507 int     var_psc_post_queue_limit;
    508 int     var_psc_pre_queue_limit;
    509 int     var_psc_watchdog;
    510 
    511 char   *var_psc_acl;
    512 char   *var_psc_dnlist_action;
    513 
    514 char   *var_psc_greet_ttl;
    515 int     var_psc_greet_wait;
    516 
    517 char   *var_psc_pregr_banner;
    518 char   *var_psc_pregr_action;
    519 int     var_psc_pregr_ttl;
    520 
    521 char   *var_psc_dnsbl_sites;
    522 char   *var_psc_dnsbl_reply;
    523 int     var_psc_dnsbl_thresh;
    524 int     var_psc_dnsbl_althresh;
    525 char   *var_psc_dnsbl_action;
    526 int     var_psc_dnsbl_min_ttl;
    527 int     var_psc_dnsbl_max_ttl;
    528 int     var_psc_dnsbl_tmout;
    529 
    530 bool    var_psc_pipel_enable;
    531 char   *var_psc_pipel_action;
    532 int     var_psc_pipel_ttl;
    533 
    534 bool    var_psc_nsmtp_enable;
    535 char   *var_psc_nsmtp_action;
    536 int     var_psc_nsmtp_ttl;
    537 
    538 bool    var_psc_barlf_enable;
    539 char   *var_psc_barlf_action;
    540 int     var_psc_barlf_ttl;
    541 
    542 int     var_psc_cmd_count;
    543 int     var_psc_cmd_time;
    544 
    545 char   *var_dnsblog_service;
    546 char   *var_tlsproxy_service;
    547 
    548 char   *var_smtpd_rej_footer;
    549 char   *var_psc_rej_footer;
    550 char   *var_psc_rej_ftr_maps;
    551 
    552 int     var_smtpd_cconn_limit;
    553 int     var_psc_cconn_limit;
    554 
    555 char   *var_smtpd_exp_filter;
    556 char   *var_psc_exp_filter;
    557 
    558 char   *var_psc_allist_if;
    559 char   *var_psc_uproxy_proto;
    560 int     var_psc_uproxy_tmout;
    561 
    562  /*
    563   * Global variables.
    564   */
    565 int     psc_check_queue_length;		/* connections being checked */
    566 int     psc_post_queue_length;		/* being sent to real SMTPD */
    567 DICT_CACHE *psc_cache_map;		/* cache table handle */
    568 VSTRING *psc_temp;			/* scratchpad */
    569 char   *psc_smtpd_service_name;		/* path to real SMTPD */
    570 int     psc_pregr_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    571 int     psc_dnsbl_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    572 int     psc_pipel_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    573 int     psc_nsmtp_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    574 int     psc_barlf_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    575 int     psc_min_ttl;			/* Update with new tests! */
    576 STRING_LIST *psc_forbid_cmds;		/* CONNECT GET POST */
    577 int     psc_stress_greet_wait;		/* stressed greet wait */
    578 int     psc_normal_greet_wait;		/* stressed greet wait */
    579 int     psc_stress_cmd_time_limit;	/* stressed command limit */
    580 int     psc_normal_cmd_time_limit;	/* normal command time limit */
    581 int     psc_stress;			/* stress level */
    582 int     psc_lowat_check_queue_length;	/* stress low-water mark */
    583 int     psc_hiwat_check_queue_length;	/* stress high-water mark */
    584 DICT   *psc_dnsbl_reply;		/* DNSBL name mapper */
    585 HTABLE *psc_client_concurrency;		/* per-client concurrency */
    586 
    587  /*
    588   * Local variables and functions.
    589   */
    590 static ARGV *psc_acl;			/* permanent allow/denylist */
    591 static int psc_dnlist_action;		/* PSC_ACT_DROP/ENFORCE/etc */
    592 static ADDR_MATCH_LIST *psc_allist_if;	/* allowlist interfaces */
    593 
    594 static void psc_endpt_lookup_done(int, VSTREAM *,
    595 			             MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *,
    596 			            MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *);
    597 
    598 /* psc_dump - dump some statistics before exit */
    599 
    600 static void psc_dump(char *unused_service, char **unused_argv)
    601 {
    602 
    603     /*
    604      * Dump preliminary cache cleanup statistics when the process commits
    605      * suicide while a cache cleanup run is in progress. We can't currently
    606      * distinguish between "postfix reload" (we should restart) or "maximal
    607      * idle time reached" (we could finish the cache cleanup first).
    608      */
    609     if (psc_cache_map) {
    610 	dict_cache_close(psc_cache_map);
    611 	psc_cache_map = 0;
    612     }
    613 }
    614 
    615 /* psc_drain - delayed exit after "postfix reload" */
    616 
    617 static void psc_drain(char *unused_service, char **unused_argv)
    618 {
    619     int     count;
    620 
    621     /*
    622      * After "postfix reload", complete work-in-progress in the background,
    623      * instead of dropping already-accepted connections on the floor.
    624      *
    625      * Unfortunately we must close all writable tables, so we can't store or
    626      * look up reputation information. The reason is that we don't have any
    627      * multi-writer safety guarantees. We also can't use the single-writer
    628      * proxywrite service, because its latency guarantees are too weak.
    629      *
    630      * All error retry counts shall be limited. Instead of blocking here, we
    631      * could retry failed fork() operations in the event call-back routines,
    632      * but we don't need perfection. The host system is severely overloaded
    633      * and service levels are already way down.
    634      *
    635      * XXX Some Berkeley DB versions break with close-after-fork. Every new
    636      * version is an improvement over its predecessor.
    637      *
    638      * XXX Don't assume that it is OK to share the same LMDB lockfile descriptor
    639      * between different processes.
    640      */
    641     if (psc_cache_map != 0			/* XXX && psc_cache_map
    642 	    requires locking */ ) {
    643 	dict_cache_close(psc_cache_map);
    644 	psc_cache_map = 0;
    645     }
    646     for (count = 0; /* see below */ ; count++) {
    647 	if (count >= 5) {
    648 	    msg_fatal("fork: %m");
    649 	} else if (event_server_drain() != 0) {
    650 	    msg_warn("fork: %m");
    651 	    sleep(1);
    652 	    continue;
    653 	} else {
    654 	    return;
    655 	}
    656     }
    657 }
    658 
    659 /* psc_service - handle new client connection */
    660 
    661 static void psc_service(VSTREAM *smtp_client_stream,
    662 			        char *unused_service,
    663 			        char **unused_argv)
    664 {
    665 
    666     /*
    667      * For sanity, require that at least one of INET or INET6 is enabled.
    668      * Otherwise, we can't look up interface information, and we can't
    669      * convert names or addresses.
    670      */
    671     if (inet_proto_info()->ai_family_list[0] == 0)
    672 	msg_fatal("all network protocols are disabled (%s = %s)",
    673 		  VAR_INET_PROTOCOLS, var_inet_protocols);
    674 
    675     /*
    676      * This program handles all incoming connections, so it must not block.
    677      * We use event-driven code for all operations that introduce latency.
    678      *
    679      * Note: instead of using VSTREAM-level timeouts, we enforce limits on the
    680      * total amount of time to receive a complete SMTP command line.
    681      */
    682     non_blocking(vstream_fileno(smtp_client_stream), NON_BLOCKING);
    683 
    684     /*
    685      * Look up the remote SMTP client address and port.
    686      */
    687     psc_endpt_lookup(smtp_client_stream, psc_endpt_lookup_done);
    688 }
    689 
    690 /* psc_warn_compat_respectful_logging - compatibility warning */
    691 
    692 static void psc_warn_compat_respectful_logging(PSC_STATE *state)
    693 {
    694     msg_info("using backwards-compatible default setting "
    695 	     VAR_RESPECTFUL_LOGGING "=no for client [%s]:%s",
    696 	     PSC_CLIENT_ADDR_PORT(state));
    697     warn_compat_respectful_logging = 0;
    698 }
    699 
    700 /* psc_endpt_lookup_done - endpoint lookup completed */
    701 
    702 static void psc_endpt_lookup_done(int endpt_status,
    703 				          VSTREAM *smtp_client_stream,
    704 				          MAI_HOSTADDR_STR *smtp_client_addr,
    705 				          MAI_SERVPORT_STR *smtp_client_port,
    706 				          MAI_HOSTADDR_STR *smtp_server_addr,
    707 				          MAI_SERVPORT_STR *smtp_server_port)
    708 {
    709     const char *myname = "psc_endpt_lookup_done";
    710     PSC_STATE *state;
    711     const char *stamp_str;
    712     int     saved_flags;
    713 
    714     /*
    715      * Best effort - if this non-blocking write(2) fails, so be it.
    716      */
    717     if (endpt_status < 0) {
    718 	(void) write(vstream_fileno(smtp_client_stream),
    719 		     "421 4.3.2 No system resources\r\n",
    720 		     sizeof("421 4.3.2 No system resources\r\n") - 1);
    721 	event_server_disconnect(smtp_client_stream);
    722 	return;
    723     }
    724     if (msg_verbose > 1)
    725 	msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
    726 		 myname, psc_post_queue_length, psc_check_queue_length,
    727 		 smtp_client_addr->buf, smtp_client_port->buf);
    728 
    729     msg_info("CONNECT from [%s]:%s to [%s]:%s",
    730 	     smtp_client_addr->buf, smtp_client_port->buf,
    731 	     smtp_server_addr->buf, smtp_server_port->buf);
    732 
    733     /*
    734      * Bundle up all the loose session pieces. This zeroes all flags and time
    735      * stamps.
    736      */
    737     state = psc_new_session_state(smtp_client_stream, smtp_client_addr->buf,
    738 				  smtp_client_port->buf,
    739 				  smtp_server_addr->buf,
    740 				  smtp_server_port->buf);
    741 
    742     /*
    743      * Reply with 421 when the client has too many open connections.
    744      */
    745     if (var_psc_cconn_limit > 0
    746 	&& state->client_info->concurrency > var_psc_cconn_limit) {
    747 	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
    748 		 state->smtp_client_addr, state->smtp_client_port);
    749 	PSC_DROP_SESSION_STATE(state,
    750 			       "421 4.7.0 Error: too many connections\r\n");
    751 	return;
    752     }
    753 
    754     /*
    755      * Reply with 421 when we can't forward more connections.
    756      */
    757     if (var_psc_post_queue_limit > 0
    758 	&& psc_post_queue_length >= var_psc_post_queue_limit) {
    759 	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: all server ports busy",
    760 		 state->smtp_client_addr, state->smtp_client_port);
    761 	PSC_DROP_SESSION_STATE(state,
    762 			       "421 4.3.2 All server ports are busy\r\n");
    763 	return;
    764     }
    765 
    766     /*
    767      * The permanent allow/denylist has highest precedence.
    768      */
    769     if (psc_acl != 0) {
    770 	switch (psc_acl_eval(state, psc_acl, VAR_PSC_ACL)) {
    771 
    772 	    /*
    773 	     * Permanently denylisted.
    774 	     */
    775 	case PSC_ACL_ACT_DENYLIST:
    776 	    msg_info("%sLISTED [%s]:%s",
    777 		     var_respectful_logging ? "DENY" : "BLACK",
    778 		     PSC_CLIENT_ADDR_PORT(state));
    779 	    if (warn_compat_respectful_logging)
    780 		psc_warn_compat_respectful_logging(state);
    781 	    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_DNLIST_FAIL);
    782 	    switch (psc_dnlist_action) {
    783 	    case PSC_ACT_DROP:
    784 		PSC_DROP_SESSION_STATE(state,
    785 			     "521 5.3.2 Service currently unavailable\r\n");
    786 		return;
    787 	    case PSC_ACT_ENFORCE:
    788 		PSC_ENFORCE_SESSION_STATE(state,
    789 			     "550 5.3.2 Service currently unavailable\r\n");
    790 		break;
    791 	    case PSC_ACT_IGNORE:
    792 		PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_DNLIST_FAIL);
    793 
    794 		/*
    795 		 * Not: PSC_PASS_SESSION_STATE. Repeat this test the next
    796 		 * time.
    797 		 */
    798 		break;
    799 	    default:
    800 		msg_panic("%s: unknown denylist action value %d",
    801 			  myname, psc_dnlist_action);
    802 	    }
    803 	    break;
    804 
    805 	    /*
    806 	     * Permanently allowlisted.
    807 	     */
    808 	case PSC_ACL_ACT_ALLOWLIST:
    809 	    msg_info("%sLISTED [%s]:%s",
    810 		     var_respectful_logging ? "ALLOW" : "WHITE",
    811 		     PSC_CLIENT_ADDR_PORT(state));
    812 	    if (warn_compat_respectful_logging)
    813 		psc_warn_compat_respectful_logging(state);
    814 	    psc_conclude(state);
    815 	    return;
    816 
    817 	    /*
    818 	     * Other: dunno (don't know) or error.
    819 	     */
    820 	default:
    821 	    break;
    822 	}
    823     }
    824 
    825     /*
    826      * The temporary allowlist (i.e. the postscreen cache) has the lowest
    827      * precedence. This cache contains information about the results of prior
    828      * tests. Allowlist the client when all enabled test results are still
    829      * valid.
    830      */
    831     if ((state->flags & PSC_STATE_MASK_ANY_FAIL) == 0
    832 	&& state->client_info->concurrency == 1
    833 	&& psc_cache_map != 0
    834 	&& (stamp_str = psc_cache_lookup(psc_cache_map, state->smtp_client_addr)) != 0) {
    835 	saved_flags = state->flags;
    836 	psc_parse_tests(state, stamp_str, event_time());
    837 	state->flags |= saved_flags;
    838 	if (msg_verbose)
    839 	    msg_info("%s: cached + recent flags: %s",
    840 		     myname, psc_print_state_flags(state->flags, myname));
    841 	if ((state->flags & PSC_STATE_MASK_ANY_TODO_FAIL) == 0) {
    842 	    msg_info("PASS OLD [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
    843 	    psc_conclude(state);
    844 	    return;
    845 	}
    846     } else if (state->client_info->concurrency > 1) {
    847 	saved_flags = state->flags;
    848 	psc_todo_tests(state, event_time());
    849 	state->flags |= saved_flags;
    850 	if (msg_verbose)
    851 	    msg_info("%s: new + recent flags: %s",
    852 		     myname, psc_print_state_flags(state->flags, myname));
    853     } else {
    854 	saved_flags = state->flags;
    855 	psc_new_tests(state);
    856 	state->flags |= saved_flags;
    857 	if (msg_verbose)
    858 	    msg_info("%s: new + recent flags: %s",
    859 		     myname, psc_print_state_flags(state->flags, myname));
    860     }
    861 
    862     /*
    863      * Don't allowlist clients that connect to backup MX addresses. Fail
    864      * "closed" on error.
    865      */
    866     if (addr_match_list_match(psc_allist_if, smtp_server_addr->buf) == 0) {
    867 	state->flags |= (PSC_STATE_FLAG_ALLIST_FAIL | PSC_STATE_FLAG_NOFORWARD);
    868 	msg_info("%sLIST VETO [%s]:%s", var_respectful_logging ?
    869 		 "ALLOW" : "WHITE", PSC_CLIENT_ADDR_PORT(state));
    870 	if (warn_compat_respectful_logging)
    871 	    psc_warn_compat_respectful_logging(state);
    872     }
    873 
    874     /*
    875      * Reply with 421 when we can't analyze more connections. That also means
    876      * no deep protocol tests when the noforward flag is raised.
    877      */
    878     if (var_psc_pre_queue_limit > 0
    879 	&& psc_check_queue_length - psc_post_queue_length
    880 	>= var_psc_pre_queue_limit) {
    881 	msg_info("reject: connect from [%s]:%s: all screening ports busy",
    882 		 state->smtp_client_addr, state->smtp_client_port);
    883 	PSC_DROP_SESSION_STATE(state,
    884 			       "421 4.3.2 All screening ports are busy\r\n");
    885 	return;
    886     }
    887 
    888     /*
    889      * If the client has no up-to-date results for some tests, do those tests
    890      * first. Otherwise, skip the tests and hand off the connection.
    891      */
    892     if (state->flags & PSC_STATE_MASK_EARLY_TODO)
    893 	psc_early_tests(state);
    894     else if (state->flags & (PSC_STATE_MASK_SMTPD_TODO | PSC_STATE_FLAG_NOFORWARD))
    895 	psc_smtpd_tests(state);
    896     else
    897 	psc_conclude(state);
    898 }
    899 
    900 /* psc_cache_validator - validate one cache entry */
    901 
    902 static int psc_cache_validator(const char *client_addr,
    903 			               const char *stamp_str,
    904 			               void *unused_context)
    905 {
    906     PSC_STATE dummy_state;
    907     PSC_CLIENT_INFO dummy_client_info;
    908 
    909     /*
    910      * This function is called by the cache cleanup pseudo thread.
    911      *
    912      * When an entry is removed from the cache, the client will be reported as
    913      * "NEW" in the next session where it passes all tests again. To avoid
    914      * silly logging we remove the cache entry only after all tests have
    915      * expired longer ago than the cache retention time.
    916      */
    917     dummy_state.client_info = &dummy_client_info;
    918     psc_parse_tests(&dummy_state, stamp_str, event_time() - var_psc_cache_ret);
    919     return ((dummy_state.flags & PSC_STATE_MASK_ANY_TODO) == 0);
    920 }
    921 
    922 /* pre_jail_init - pre-jail initialization */
    923 
    924 static void pre_jail_init(char *unused_name, char **unused_argv)
    925 {
    926     VSTRING *redirect;
    927 
    928     /*
    929      * Open read-only maps before dropping privilege, for consistency with
    930      * other Postfix daemons.
    931      */
    932     psc_acl_pre_jail_init(var_mynetworks, VAR_PSC_ACL);
    933     if (*var_psc_acl)
    934 	psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
    935     /* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */
    936     if (*var_psc_forbid_cmds)
    937 	psc_forbid_cmds = string_list_init(VAR_PSC_FORBID_CMDS,
    938 					   MATCH_FLAG_RETURN,
    939 					   var_psc_forbid_cmds);
    940     if (*var_psc_dnsbl_reply)
    941 	psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
    942 				    DICT_FLAG_DUP_WARN);
    943 
    944     /*
    945      * Never, ever, get killed by a master signal, as that would corrupt the
    946      * database when we're in the middle of an update.
    947      */
    948     if (setsid() < 0)
    949 	msg_warn("setsid: %m");
    950 
    951     /*
    952      * Security: don't create root-owned files that contain untrusted data.
    953      * And don't create Postfix-owned files in root-owned directories,
    954      * either. We want a correct relationship between (file or directory)
    955      * ownership and (file or directory) content. To open files before going
    956      * to jail, temporarily drop root privileges.
    957      */
    958     SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
    959     redirect = vstring_alloc(100);
    960 
    961     /*
    962      * Keep state in persistent external map. As a safety measure we sync the
    963      * database on each update. This hurts on LINUX file systems that sync
    964      * all dirty disk blocks whenever any application invokes fsync().
    965      *
    966      * Start the cache maintenance pseudo thread after dropping privileges.
    967      */
    968 #define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
    969 	    DICT_FLAG_OPEN_LOCK)
    970 
    971     if (*var_psc_cache_map)
    972 	psc_cache_map =
    973 	    dict_cache_open(data_redirect_map(redirect, var_psc_cache_map),
    974 			    O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS);
    975 
    976     /*
    977      * Clean up and restore privilege.
    978      */
    979     vstring_free(redirect);
    980     RESTORE_SAVED_EUGID();
    981 
    982     /*
    983      * Initialize the dummy SMTP engine.
    984      */
    985     psc_smtpd_pre_jail_init();
    986 }
    987 
    988 /* pre_accept - see if tables have changed */
    989 
    990 static void pre_accept(char *unused_name, char **unused_argv)
    991 {
    992     static time_t last_event_time;
    993     time_t  new_event_time;
    994     const char *name;
    995 
    996     /*
    997      * If some table has changed then stop accepting new connections. Don't
    998      * check the tables more than once a second.
    999      */
   1000     new_event_time = event_time();
   1001     if (new_event_time >= last_event_time + 1
   1002 	&& (name = dict_changed_name()) != 0) {
   1003 	msg_info("table %s has changed - finishing in the background", name);
   1004 	psc_drain(unused_name, unused_argv);
   1005     } else {
   1006 	last_event_time = new_event_time;
   1007     }
   1008 }
   1009 
   1010 /* contains_only_parameter - string contains $parameter or ${parameter} */
   1011 
   1012 static int contains_only_parameter(const char *str)
   1013 {
   1014     const char *last;
   1015     char   *tmp;
   1016     int     ret;
   1017 
   1018     if (*str != '$')
   1019 	return (0);
   1020     if (*++str != '{')
   1021 	return (mail_conf_lookup(str) != 0);
   1022     if (*(last = str + strlen(str) - 1) == '}') {
   1023 	tmp = mystrndup(str + 1, last - str - 1);
   1024 	ret = (mail_conf_lookup(tmp) != 0);
   1025 	myfree(tmp);
   1026 	return (ret);
   1027     }
   1028     return (0);
   1029 }
   1030 
   1031 /* post_jail_init - post-jail initialization */
   1032 
   1033 static void post_jail_init(char *unused_name, char **unused_argv)
   1034 {
   1035     const NAME_CODE actions[] = {
   1036 	PSC_NAME_ACT_DROP, PSC_ACT_DROP,
   1037 	PSC_NAME_ACT_ENFORCE, PSC_ACT_ENFORCE,
   1038 	PSC_NAME_ACT_IGNORE, PSC_ACT_IGNORE,
   1039 	PSC_NAME_ACT_CONT, PSC_ACT_IGNORE,	/* compatibility */
   1040 	0, -1,
   1041     };
   1042     int     cache_flags;
   1043     const char *tmp;
   1044 
   1045     /*
   1046      * This routine runs after the skeleton code has entered the chroot jail.
   1047      * Prevent automatic process suicide after a limited number of client
   1048      * requests. It is OK to terminate after a limited amount of idle time.
   1049      */
   1050     var_use_limit = 0;
   1051 
   1052     /*
   1053      * Workaround for parameters whose values may contain "$", and that have
   1054      * a default of "$parametername". Not sure if it would be a good idea to
   1055      * always do this in the mail_conf_raw(3) module.
   1056      */
   1057     if (contains_only_parameter(var_psc_rej_footer)) {
   1058 	tmp = mail_conf_eval_once(var_psc_rej_footer);
   1059 	myfree(var_psc_rej_footer);
   1060 	var_psc_rej_footer = mystrdup(tmp);
   1061     }
   1062     if (contains_only_parameter(var_psc_exp_filter)) {
   1063 	tmp = mail_conf_eval_once(var_psc_exp_filter);
   1064 	myfree(var_psc_exp_filter);
   1065 	var_psc_exp_filter = mystrdup(tmp);
   1066     }
   1067 
   1068     /*
   1069      * Other one-time initialization.
   1070      */
   1071     psc_temp = vstring_alloc(10);
   1072     vstring_sprintf(psc_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service);
   1073     psc_smtpd_service_name = mystrdup(STR(psc_temp));
   1074     psc_dnsbl_init();
   1075     psc_early_init();
   1076     psc_smtpd_init();
   1077 
   1078     if ((psc_dnlist_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1079 				       var_psc_dnlist_action)) < 0)
   1080 	msg_fatal("bad %s value: %s", VAR_PSC_DNLIST_ACTION,
   1081 		  var_psc_dnlist_action);
   1082     if ((psc_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1083 				      var_psc_dnsbl_action)) < 0)
   1084 	msg_fatal("bad %s value: %s", VAR_PSC_DNSBL_ACTION,
   1085 		  var_psc_dnsbl_action);
   1086     if ((psc_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1087 				      var_psc_pregr_action)) < 0)
   1088 	msg_fatal("bad %s value: %s", VAR_PSC_PREGR_ACTION,
   1089 		  var_psc_pregr_action);
   1090     if ((psc_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1091 				      var_psc_pipel_action)) < 0)
   1092 	msg_fatal("bad %s value: %s", VAR_PSC_PIPEL_ACTION,
   1093 		  var_psc_pipel_action);
   1094     if ((psc_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1095 				      var_psc_nsmtp_action)) < 0)
   1096 	msg_fatal("bad %s value: %s", VAR_PSC_NSMTP_ACTION,
   1097 		  var_psc_nsmtp_action);
   1098     if ((psc_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE,
   1099 				      var_psc_barlf_action)) < 0)
   1100 	msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION,
   1101 		  var_psc_barlf_action);
   1102     /* Fail "closed" on error. */
   1103     psc_allist_if = addr_match_list_init(VAR_PSC_ALLIST_IF, MATCH_FLAG_RETURN,
   1104 					 var_psc_allist_if);
   1105 
   1106     /*
   1107      * Start the cache maintenance pseudo thread last. Early cleanup makes
   1108      * verbose logging more informative (we get positive confirmation that
   1109      * the cleanup thread runs).
   1110      */
   1111     cache_flags = DICT_CACHE_FLAG_STATISTICS;
   1112     if (msg_verbose > 1)
   1113 	cache_flags |= DICT_CACHE_FLAG_VERBOSE;
   1114     if (psc_cache_map != 0 && var_psc_cache_scan > 0)
   1115 	dict_cache_control(psc_cache_map,
   1116 			   CA_DICT_CACHE_CTL_FLAGS(cache_flags),
   1117 			   CA_DICT_CACHE_CTL_INTERVAL(var_psc_cache_scan),
   1118 			   CA_DICT_CACHE_CTL_VALIDATOR(psc_cache_validator),
   1119 			   CA_DICT_CACHE_CTL_CONTEXT((void *) 0),
   1120 			   CA_DICT_CACHE_CTL_END);
   1121 
   1122     /*
   1123      * Pre-compute the minimal and maximal TTL.
   1124      */
   1125     psc_min_ttl =
   1126 	PSC_MIN(PSC_MIN(var_psc_pregr_ttl, var_psc_dnsbl_min_ttl),
   1127 		PSC_MIN(PSC_MIN(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
   1128 			var_psc_barlf_ttl));
   1129 
   1130     /*
   1131      * Pre-compute the stress and normal command time limits.
   1132      */
   1133     mail_conf_update(VAR_STRESS, "yes");
   1134     psc_stress_cmd_time_limit =
   1135 	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
   1136     psc_stress_greet_wait =
   1137 	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
   1138 
   1139     mail_conf_update(VAR_STRESS, "");
   1140     psc_normal_cmd_time_limit =
   1141 	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
   1142     psc_normal_greet_wait =
   1143 	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
   1144 
   1145     psc_lowat_check_queue_length = .7 * var_psc_pre_queue_limit;
   1146     psc_hiwat_check_queue_length = .9 * var_psc_pre_queue_limit;
   1147     if (msg_verbose)
   1148 	msg_info(VAR_PSC_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
   1149 		 psc_stress_cmd_time_limit, psc_normal_cmd_time_limit,
   1150 		 psc_lowat_check_queue_length, psc_hiwat_check_queue_length);
   1151 
   1152     if (psc_lowat_check_queue_length == 0)
   1153 	msg_panic("compiler error: 0.7 * %d = %d", var_psc_pre_queue_limit,
   1154 		  psc_lowat_check_queue_length);
   1155     if (psc_hiwat_check_queue_length == 0)
   1156 	msg_panic("compiler error: 0.9 * %d = %d", var_psc_pre_queue_limit,
   1157 		  psc_hiwat_check_queue_length);
   1158 
   1159     /*
   1160      * Per-client concurrency.
   1161      */
   1162     psc_client_concurrency = htable_create(var_psc_pre_queue_limit);
   1163 }
   1164 
   1165 MAIL_VERSION_STAMP_DECLARE;
   1166 
   1167 /* main - pass control to the multi-threaded skeleton */
   1168 
   1169 int     main(int argc, char **argv)
   1170 {
   1171 
   1172     /*
   1173      * List smtpd(8) parameters before any postscreen(8) parameters that have
   1174      * defaults dependencies on them.
   1175      */
   1176     static const CONFIG_STR_TABLE str_table[] = {
   1177 	VAR_SMTPD_SERVICE, DEF_SMTPD_SERVICE, &var_smtpd_service, 1, 0,
   1178 	VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
   1179 	VAR_SMTPD_FORBID_CMDS, DEF_SMTPD_FORBID_CMDS, &var_smtpd_forbid_cmds, 0, 0,
   1180 	VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
   1181 	VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
   1182 	VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0,
   1183 	VAR_SMTPD_CMD_FILTER, DEF_SMTPD_CMD_FILTER, &var_smtpd_cmd_filter, 0, 0,
   1184 	VAR_PSC_CACHE_MAP, DEF_PSC_CACHE_MAP, &var_psc_cache_map, 0, 0,
   1185 	VAR_PSC_PREGR_BANNER, DEF_PSC_PREGR_BANNER, &var_psc_pregr_banner, 0, 0,
   1186 	VAR_PSC_PREGR_ACTION, DEF_PSC_PREGR_ACTION, &var_psc_pregr_action, 1, 0,
   1187 	VAR_PSC_DNSBL_SITES, DEF_PSC_DNSBL_SITES, &var_psc_dnsbl_sites, 0, 0,
   1188 	VAR_PSC_DNSBL_ACTION, DEF_PSC_DNSBL_ACTION, &var_psc_dnsbl_action, 1, 0,
   1189 	VAR_PSC_PIPEL_ACTION, DEF_PSC_PIPEL_ACTION, &var_psc_pipel_action, 1, 0,
   1190 	VAR_PSC_NSMTP_ACTION, DEF_PSC_NSMTP_ACTION, &var_psc_nsmtp_action, 1, 0,
   1191 	VAR_PSC_BARLF_ACTION, DEF_PSC_BARLF_ACTION, &var_psc_barlf_action, 1, 0,
   1192 	VAR_PSC_ACL, DEF_PSC_ACL, &var_psc_acl, 0, 0,
   1193 	VAR_PSC_DNLIST_ACTION, DEF_PSC_DNLIST_ACTION, &var_psc_dnlist_action, 1, 0,
   1194 	VAR_PSC_FORBID_CMDS, DEF_PSC_FORBID_CMDS, &var_psc_forbid_cmds, 0, 0,
   1195 	VAR_PSC_EHLO_DIS_WORDS, DEF_PSC_EHLO_DIS_WORDS, &var_psc_ehlo_dis_words, 0, 0,
   1196 	VAR_PSC_EHLO_DIS_MAPS, DEF_PSC_EHLO_DIS_MAPS, &var_psc_ehlo_dis_maps, 0, 0,
   1197 	VAR_PSC_DNSBL_REPLY, DEF_PSC_DNSBL_REPLY, &var_psc_dnsbl_reply, 0, 0,
   1198 	VAR_PSC_TLS_LEVEL, DEF_PSC_TLS_LEVEL, &var_psc_tls_level, 0, 0,
   1199 	VAR_PSC_CMD_FILTER, DEF_PSC_CMD_FILTER, &var_psc_cmd_filter, 0, 0,
   1200 	VAR_DNSBLOG_SERVICE, DEF_DNSBLOG_SERVICE, &var_dnsblog_service, 1, 0,
   1201 	VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
   1202 	VAR_PSC_ALLIST_IF, DEF_PSC_ALLIST_IF, &var_psc_allist_if, 0, 0,
   1203 	VAR_PSC_UPROXY_PROTO, DEF_PSC_UPROXY_PROTO, &var_psc_uproxy_proto, 0, 0,
   1204 	VAR_PSC_REJ_FTR_MAPS, DEF_PSC_REJ_FTR_MAPS, &var_psc_rej_ftr_maps, 0, 0,
   1205 	0,
   1206     };
   1207     static const CONFIG_INT_TABLE int_table[] = {
   1208 	VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 1, 0,
   1209 	VAR_PSC_CMD_COUNT, DEF_PSC_CMD_COUNT, &var_psc_cmd_count, 1, 0,
   1210 	VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
   1211 	0,
   1212     };
   1213     static const CONFIG_NINT_TABLE nint_table[] = {
   1214 	VAR_PSC_POST_QLIMIT, DEF_PSC_POST_QLIMIT, &var_psc_post_queue_limit, 5, 0,
   1215 	VAR_PSC_PRE_QLIMIT, DEF_PSC_PRE_QLIMIT, &var_psc_pre_queue_limit, 10, 0,
   1216 	VAR_PSC_CCONN_LIMIT, DEF_PSC_CCONN_LIMIT, &var_psc_cconn_limit, 0, 0,
   1217 	VAR_PSC_DNSBL_ALTHRESH, DEF_PSC_DNSBL_ALTHRESH, &var_psc_dnsbl_althresh, 0, 0,
   1218 	0,
   1219     };
   1220     static const CONFIG_TIME_TABLE time_table[] = {
   1221 	VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0,
   1222 	VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, &var_psc_greet_wait, 1, 0,
   1223 	VAR_PSC_PREGR_TTL, DEF_PSC_PREGR_TTL, &var_psc_pregr_ttl, 1, 0,
   1224 	VAR_PSC_DNSBL_MIN_TTL, DEF_PSC_DNSBL_MIN_TTL, &var_psc_dnsbl_min_ttl, 1, 0,
   1225 	VAR_PSC_DNSBL_MAX_TTL, DEF_PSC_DNSBL_MAX_TTL, &var_psc_dnsbl_max_ttl, 1, 0,
   1226 	VAR_PSC_PIPEL_TTL, DEF_PSC_PIPEL_TTL, &var_psc_pipel_ttl, 1, 0,
   1227 	VAR_PSC_NSMTP_TTL, DEF_PSC_NSMTP_TTL, &var_psc_nsmtp_ttl, 1, 0,
   1228 	VAR_PSC_BARLF_TTL, DEF_PSC_BARLF_TTL, &var_psc_barlf_ttl, 1, 0,
   1229 	VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0,
   1230 	VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 0, 0,
   1231 	VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0,
   1232 	VAR_PSC_UPROXY_TMOUT, DEF_PSC_UPROXY_TMOUT, &var_psc_uproxy_tmout, 1, 0,
   1233 	VAR_PSC_DNSBL_TMOUT, DEF_PSC_DNSBL_TMOUT, &var_psc_dnsbl_tmout, 1, 0,
   1234 
   1235 	0,
   1236     };
   1237     static const CONFIG_BOOL_TABLE bool_table[] = {
   1238 	VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required,
   1239 	VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
   1240 	VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
   1241 	VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
   1242 	VAR_PSC_PIPEL_ENABLE, DEF_PSC_PIPEL_ENABLE, &var_psc_pipel_enable,
   1243 	VAR_PSC_NSMTP_ENABLE, DEF_PSC_NSMTP_ENABLE, &var_psc_nsmtp_enable,
   1244 	VAR_PSC_BARLF_ENABLE, DEF_PSC_BARLF_ENABLE, &var_psc_barlf_enable,
   1245 	0,
   1246     };
   1247     static const CONFIG_RAW_TABLE raw_table[] = {
   1248 	VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
   1249 	VAR_PSC_REJ_FOOTER, DEF_PSC_REJ_FOOTER, &var_psc_rej_footer, 0, 0,
   1250 	VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
   1251 	VAR_PSC_EXP_FILTER, DEF_PSC_EXP_FILTER, &var_psc_exp_filter, 1, 0,
   1252 	0,
   1253     };
   1254     static const CONFIG_NBOOL_TABLE nbool_table[] = {
   1255 	VAR_PSC_HELO_REQUIRED, DEF_PSC_HELO_REQUIRED, &var_psc_helo_required,
   1256 	VAR_PSC_DISABLE_VRFY, DEF_PSC_DISABLE_VRFY, &var_psc_disable_vrfy,
   1257 	VAR_PSC_USE_TLS, DEF_PSC_USE_TLS, &var_psc_use_tls,
   1258 	VAR_PSC_ENFORCE_TLS, DEF_PSC_ENFORCE_TLS, &var_psc_enforce_tls,
   1259 	0,
   1260     };
   1261 
   1262     /*
   1263      * Fingerprint executables and core dumps.
   1264      */
   1265     MAIL_VERSION_STAMP_ALLOCATE;
   1266 
   1267     event_server_main(argc, argv, psc_service,
   1268 		      CA_MAIL_SERVER_STR_TABLE(str_table),
   1269 		      CA_MAIL_SERVER_INT_TABLE(int_table),
   1270 		      CA_MAIL_SERVER_NINT_TABLE(nint_table),
   1271 		      CA_MAIL_SERVER_TIME_TABLE(time_table),
   1272 		      CA_MAIL_SERVER_BOOL_TABLE(bool_table),
   1273 		      CA_MAIL_SERVER_RAW_TABLE(raw_table),
   1274 		      CA_MAIL_SERVER_NBOOL_TABLE(nbool_table),
   1275 		      CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
   1276 		      CA_MAIL_SERVER_POST_INIT(post_jail_init),
   1277 		      CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
   1278 		      CA_MAIL_SERVER_SOLITARY,
   1279 		      CA_MAIL_SERVER_SLOW_EXIT(psc_drain),
   1280 		      CA_MAIL_SERVER_EXIT(psc_dump),
   1281 		      CA_MAIL_SERVER_WATCHDOG(&var_psc_watchdog),
   1282 		      0);
   1283 }
   1284