-TNAME_ASSIGNMENT
-TNAME_CODE
-TNAME_MASK
+-TNBBIO
-TPEER_NAME
-TPGSQL_NAME
-TPICKUP_INFO
-TPOSTMAP_KEY_STATE
-TPOST_MAIL_STATE
-TPRIVATE_STR_TABLE
--TPS_CALL_BACK_ENTRY
--TPS_DNSBL_HEAD
--TPS_DNSBL_SCORE
--TPS_DNSBL_SITE
--TPS_SMTPD_COMMAND
--TPS_STATE
+-TPSC_CALL_BACK_ENTRY
+-TPSC_DNSBL_HEAD
+-TPSC_DNSBL_SCORE
+-TPSC_DNSBL_SITE
+-TPSC_SMTPD_COMMAND
+-TPSC_STARTTLS
+-TPSC_STATE
-TQMGR_ENTRY
-TQMGR_FEEDBACK
-TQMGR_JOB
-TSTRING_TABLE
-TSYS_EXITS_DETAIL
-TTLSMGR_SCACHE
+-TTLSP_STATE
-TTLS_APPL_STATE
-TTLS_CLIENT_INIT_PROPS
-TTLS_CLIENT_START_PROPS
2821 (and 5321) is vague about the VRFY request format, but
spends lots of text on the reply format. File: smtpd/smtpd.c.
-20010117
+20100117
Cleanup: when a content_filter parameter or FILTER command
specifies an empty next-hop destination, the queue manager
This change eliminates an obscure bug where the SMTP server
would wait for another $smtpd_timeout seconds after sending
the "421 Error: timeout exceeded" message to the client.
+
+20101221
+
+ Cleanup: simplified the VSTREAM "large buffer" support by
+ dropping the Postfix 2.4 "binary compatibility" requirement.
+ Files: util/vstream.c, util/vstream.h.
+
+20101222
+
+ Cleanup: the SMTP client PIPELINING code did not account
+ for TLS protocol overhead. This could (only in theory)
+ result in deadlock when the remote SMTP server announces a
+ very small receive window after the client and server have
+ synchronized their SMTP state. Victor Duchovni. File:
+ smtp/smtp_proto.c.
+
+20101223
+
+ Feature: with "tls_preempt_cipherlist = yes" the Postfix
+ SMTP server will preempt the remote SMTP client's cipher
+ preference order. This requires OpenSSL 0.9.7 and later.
+ Victor Duchovni. Files: src/smtpd/smtpd.c, src/tls/tls_server.c,
+ proto/TLS_README.html, proto/postconf.proto.
+
+ Future proofing: specify "tls_disable_workarounds = a list
+ or bit-mask of OpenSSL bug work-arounds to disable". This
+ may become necessary when a bug workaround is found to cause
+ problems (security or interoperability). Victor Duchovni.
+ Files: tls/tls_misc.c, proto/TLS_README.html, proto/postconf.proto.
+
+ Infrastructure: extended name_mask module feature set with
+ extensive documentation and 32-bit regression tests. Victor
+ and Wietse. File: util/name_mask.[hc].
+
+20101224
+
+ Cleanup: sanitized the name_mask API so that errors will be
+ ignored only upon explicit request. Files: util/name_mask.[hc],
+ src/global/ehlo_mask.c, src/smtp/smtp_proto.c,
+ src/util/name_mask.c, src/xsasl/xsasl_dovecot_server.c.
+
+ Cleanup: more TLS overhead horrors for the SMTP client's
+ PIPELINING engine. Wietse and Victor. File: smtp/smtp_proto.c.
+
+20101226
+
+ Cleanup: the SMTP client logic for pipelining the "." and
+ "QUIT" commands was bogus - the pipelining engine could not
+ know how much unacknowledged data is pending in the local
+ TCP stack. We now ignore the buffer check for sending
+ "QUIT" after ".". Wietse and Victor. File: smtp/smtp_proto.c.
+
+20110101
+
+ Cleanup: the Postfix SMTP server now always refreshes the
+ SASL authentication mechanism list after STARTTLS. Some
+ Dovecot versions may change their responses when they know
+ that the SMTP connection is encrypted. File: smtpd/smtpd.c.
+
+ Cleanup: the smtpd_starttls_timeout default value is now
+ stress-dependent. Files: global/mail_params.h,
+ proto/postconf.proto.
+
+20110102
+
+ Feature: STARTTLS support for the postscreen(8) daemon.
+ With early testing feedback from Victor Duchovni and Ralf
+ Hildebrandt. Files: postscreen/postscreen_smtpd,
+ postscreen/postscreen_starttls.c.
+
+ Feature: event-driven tlsproxy(8) daemon that translates
+ TLS <=> plaintext for postscreen(8). One tlsproxy(8) process
+ can translate traffic for multiple remote SMTP clients.
+ With early testing feedback from Victor Duchovni and Christian
+ Roessner. Files: util/nbbio.c, tlsproxy/starttlsd.c,
+ tlsproxy/starttlsd_state.c.
src/postkick src/postlock src/postlog src/postmap src/postqueue \
src/postsuper src/qmqpd src/spawn src/flush src/verify \
src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
- src/postmulti src/postscreen src/dnsblog
+ src/postmulti src/postscreen src/dnsblog src/tlsproxy
MANDIRS = proto man html
LIBEXEC = libexec/post-install libexec/postfix-files libexec/postfix-script \
libexec/postfix-wrapper libexec/main.cf libexec/master.cf \
be queried in parallel with the reverse client IP address. This test is
disabled by default.
- CAUTION: when postscreen rejects mail, it's SMTP reply contains the DNSBL
+ CAUTION: when postscreen rejects mail, its SMTP reply contains the DNSBL
domain name. Use the postscreen_dnsbl_reply_map feature to hide "password"
information in DNSBL domain names.
limitation, postscreen(8) gives deep protocol tests a relatively long
expiration time.
- * postscreen(8)'s built-in SMTP engine does not implement the AUTH, STARTTLS,
- XCLIENT, and XFORWARD features. STARTTLS and AUTH support may be added in a
- future version. In the mean time, if you need to make these services
- available on port 25, then do not enable the tests after the 220 server
- greeting.
+ * postscreen(8)'s built-in SMTP engine does not implement the AUTH, XCLIENT,
+ and XFORWARD features. AUTH support may be added in a future version. In
+ the mean time, if you need to make these services available on port 25,
+ then do not enable the tests after the 220 server greeting.
End-user clients should connect directly to the submission service, so that
they never have to deal with postscreen(8)'s tests.
/etc/postfix/master.cf:
smtp inet n - n - 1 postscreen
- 4. Uncomment the new "dnsblog unix ... dnsblog" service in master.cf. This
+ 4. Uncomment the new "tlsproxy unix ... tlsproxy" service in master.cf. This
+ service implements STARTTLS support for postscreen(8).
+
+ /etc/postfix/master.cf:
+ tlsproxy unix - - n - 0 tlsproxy
+
+ 5. Uncomment the new "dnsblog unix ... dnsblog" service in master.cf. This
service does DNSBL lookups for postscreen(8) and logs results.
/etc/postfix/master.cf:
dnsblog unix - - n - 0 dnsblog
- 5. To enable DNSBL lookups, list some DNS blocklist sites in main.cf,
+ 6. To enable DNSBL lookups, list some DNS blocklist sites in main.cf,
separated by whitespace. Different sites can have different weights. For
example:
run postmap(1) before the file can be used, and that it does not detect
changes after the file is read. It is new with Postfix version 2.8.
- 6. Read the new configuration with "postfix reload".
+ 7. Read the new configuration with "postfix reload".
Notes:
When the good client comes back in a later session, it is allowed to talk
directly to a Postfix SMTP server. See "after_220 Tests after the 220 SMTP
- server greeting above for limitations with STARTTLS, AUTH and other
- features that clients may need.
+ server greeting above for limitations with AUTH and other features that
+ clients may need.
An unexpected benefit from "deep protocol tests" is that some "good"
clients don't return after the 4XX reply; these clients were not so good
#smtpd pass - - n - - smtpd
# -o parameter=value ...
- 4. Uncomment the "smtp inet ... smtpd" service in master.cf, including any "-
- o parameter=value" entries that follow.
+ 4. Comment out the "tlsproxy unix ... tlsproxy" service in master.cf,
+ including any "-o parameter=value" entries that follow.
/etc/postfix/master.cf:
- smtp inet n - n - - smtpd
+ #tlsproxy unix - - n - 0 tlsproxy
+ # -o parameter=value ...
+
+ 5. Uncomment the "smtp inet ... smtpd" service in master.cf, including any "-
+ o parameter=value" entries that may follow.
+
+ /etc/postfix/master.cf:
+ smtp inet n - n - - smtpd
-o parameter=value ...
- 5. Read the new configuration with "postfix reload".
+ 6. Read the new configuration with "postfix reload".
H\bHi\bis\bst\bto\bor\bri\bic\bca\bal\bl n\bno\bot\bte\bes\bs a\ban\bnd\bd c\bcr\bre\bed\bdi\bit\bts\bs
is written as carefully as Wietse's own code, every 1000 lines introduce one
additional bug into Postfix.
+At this time, you should no longer be using OpenSSL releases prior to the most
+recent 0.9.8 release unless all relevant security fixes have been backported to
+the earlier release by you or your O/S vendor. OpenSSL 0.9.7 and earlier are no
+longer maintained by the OpenSSL team.
+
W\bWh\bha\bat\bt P\bPo\bos\bst\btf\bfi\bix\bx T\bTL\bLS\bS s\bsu\bup\bpp\bpo\bor\brt\bt d\bdo\boe\bes\bs f\bfo\bor\br y\byo\bou\bu
Transport Layer Security (TLS, formerly called SSL) provides certificate-based
# Postfix >= 2.6:
smtpd_tls_eecdh_grade = strong
+Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS
+servers to preempt the TLS client's cipher preference list. This is only
+possible with SSLv3, as in SSLv2 the client chooses the cipher from a list
+supplied by the server.
+
+By default, the OpenSSL server selects the client's most preferred cipher that
+the server supports. With SSLv3 and later, the server may choose its own most
+preferred cipher that is supported (offered) by the client. Setting
+"tls_preempt_cipherlist = yes" enables server cipher preferences. The default
+OpenSSL behaviour applies with "tls_preempt_cipherlist = no".
+
+While server cipher selection may in some cases lead to a more secure or
+performant cipher choice, there is some risk of interoperability issues. In the
+past, some SSL clients have listed lower priority ciphers that they did not
+implement correctly. If the server chooses a cipher that the client prefers
+less, it may select a cipher whose client implementation is flawed.
+
M\bMi\bis\bsc\bce\bel\bll\bla\ban\bne\beo\bou\bus\bs s\bse\ber\brv\bve\ber\br c\bco\bon\bnt\btr\bro\bol\bls\bs
The smtpd_starttls_timeout parameter limits the time of Postfix SMTP server
/etc/postfix/main.cf:
smtpd_starttls_timeout = 300s
+With Postfix 2.8 and later, the tls_disable_workarounds parameter specifies a
+list or bit-mask of OpenSSL bug work-arounds to disable. This may be necessary
+if one of the work-arounds enabled by default in OpenSSL proves to pose a
+security risk, or introduces an unexpected interoperability issue. Some bug
+work-arounds known to be problematic are disabled in the default value of the
+parameter when linked with an OpenSSL library that could be vulnerable.
+
+Example:
+
+ /etc/postfix/main.cf:
+ tls_disable_workarounds = 0xFFFFFFFF
+ tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
+
+Note: Disabling LEGACY_SERVER_CONNECT is not wise at this time, lots of servers
+are still unpatched and Postfix is not significantly vulnerable to the
+renegotiation issue in the TLS protocol.
+
S\bSM\bMT\bTP\bP C\bCl\bli\bie\ben\bnt\bt s\bsp\bpe\bec\bci\bif\bfi\bic\bc s\bse\bet\btt\bti\bin\bng\bgs\bs
Topics covered in this section:
NOTE: Some postscreen parameters implement stress-dependent behavior.
This is supported only when the default value is stress-dependent
-(that is, the default looks like ${stress?XX}${stress:YY}). Other
-postscreen parameters always evaluate as if the stress value is
-equal to the empty string.
+(that is, the default looks like ${stress?XX}${stress:YY}, or it
+is the $name of an smtpd_xxx parameter with a stress-dependent
+default). Other postscreen parameters always evaluate as if the
+stress value is equal to the empty string.
+
+Incompatibility with snapshot 20110102
+======================================
+
+The smtpd_starttls_timeout default value is now stress-dependent.
+By default, TLS negotiations must now complete under overload in
+10s instead of 300s.
+
+The Postfix SMTP server now always re-computes the SASL mechanism
+list after successful completion of the STARTTLS command. Earlier
+versions only re-computed the mechanism list when the values of
+smtp_sasl_tls_security_options and smtp_sasl_security_options differ.
+This could produce incorrect results, because the Dovecot authentication
+server may change responses when the SMTP session is encrypted.
+
+Major changes with snapshot 20110102
+====================================
+
+STARTTLS support for the postscreen(8) daemon. This is implemented
+by a new tlsproxy(8) daemon that you will need to enable in master.cf
+(see POSTSCREEN_README for instructions). tlsproxy(8) implements
+its own tlsproxy_mumble versions of TLS-related smtpd_mumble
+parameters. This leaves no confusion about which parameters will
+affect tlsproxy(8) behavior, but it adds another 25 parameters to
+the documentation.
+
+Major changes with snapshot 20101223
+====================================
+
+The new tls_disable_workarounds parameter specifies a list or
+bit-mask of OpenSSL bug work-arounds to disable. This may be necessary
+if one of the work-arounds enabled by default in OpenSSL proves to
+pose a security risk, or introduces an unexpected interoperability
+issue. Some bug work-arounds known to be problematic are disabled
+in the default value of the parameter when linked with an OpenSSL
+library that could be vulnerable. See postconf(5) and TLS_README
+for details.
+
+With "tls_preempt_cipherlist = yes" the Postfix SMTP server will
+choose its most preferred cipher that is supported (offered) by the
+client. This can lead to a more secure or performant cipher choice,
+but may also introduce interoperability problems when a client
+announces support for a cipher that does not work. See postconf(5)
+and TLS_README for details.
+
+Major changes with snapshot 20101217
+====================================
+
+The lower-level code in the TLS engine was simplified by removing
+an unnecessary layer of data copying. OpenSSL now writes directly
+to the network. The difference in performance should be hardly
+noticeable.
Incompatibility with snapshot 20101206
======================================
anvil rate limit for sasl_username.
+ encapsulate nbbio buffer access and update by tlsproxy.
+
smtpd xclient option for sasl_username.
Use different ipc time limits for email message transactions
#smtp inet n - n - 1 postscreen
#smtpd pass - - n - - smtpd
#dnsblog unix - - n - 0 dnsblog
+#tlsproxy unix - - n - 0 tlsproxy
#submission inet n - n - - smtpd
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
EOF
}
+ # Postfix 2.8.
+ # Add tlsproxy (unix-domain) service to master.cf.
+
+ grep '^#*tlsproxy.*tlsproxy' $config_directory/master.cf >/dev/null || {
+ echo Editing $config_directory/master.cf, adding missing entry for tlsproxy unix-domain service
+ cat >>$config_directory/master.cf <<EOF || exit 1
+#tlsproxy unix - - n - 0 tlsproxy
+EOF
+ }
+
# Report (but do not remove) obsolete files.
test -n "$obsolete" && {
$daemon_directory/smtp:f:root:-:755
$daemon_directory/smtpd:f:root:-:755
$daemon_directory/spawn:f:root:-:755
+$daemon_directory/tlsproxy:f:root:-:755
$daemon_directory/tlsmgr:f:root:-:755
$daemon_directory/trivial-rewrite:f:root:-:755
$daemon_directory/verify:f:root:-:755
$manpage_directory/man8/smtp.8:f:root:-:644
$manpage_directory/man8/smtpd.8:f:root:-:644
$manpage_directory/man8/spawn.8:f:root:-:644
+$manpage_directory/man8/tlsproxy.8:f:root:-:644
$manpage_directory/man8/tlsmgr.8:f:root:-:644
$manpage_directory/man8/trace.8:f:root:-:644
$manpage_directory/man8/trivial-rewrite.8:f:root:-:644
$html_directory/smtp.8.html:h:$html_directory/lmtp.8.html:-:644
$html_directory/smtpd.8.html:f:root:-:644
$html_directory/spawn.8.html:f:root:-:644
+$html_directory/tlsproxy.8.html:f:root:-:644
$html_directory/tcp_table.5.html:f:root:-:644
$html_directory/trace.8.html:h:$html_directory/bounce.8.html:-:644
$html_directory/transport.5.html:f:root:-:644
oqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
trace.8.html verify.8.html proxymap.8.html anvil.8.html \
scache.8.html discard.8.html tlsmgr.8.html postscreen.8.html \
- dnsblog.8.html
+ dnsblog.8.html tlsproxy.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html postmulti.1.html \
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
+tlsproxy.8.html: ../src/tlsproxy/tlsproxy.c
+ PATH=../mantools:$$PATH; \
+ srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
+
virtual.8.html: ../src/virtual/virtual.c
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
<blockquote>
<p>
-CAUTION: when postscreen rejects mail, it's SMTP reply contains the
+CAUTION: when postscreen rejects mail, its SMTP reply contains the
DNSBL domain name. Use the <a href="postconf.5.html#postscreen_dnsbl_reply_map">postscreen_dnsbl_reply_map</a> feature to
hide "password" information in DNSBL domain names.
</p>
a relatively long expiration time. </p>
<li> <p> <a href="postscreen.8.html">postscreen(8)</a>'s built-in SMTP engine does not implement
-the AUTH, STARTTLS, XCLIENT, and XFORWARD features. STARTTLS and
-AUTH support may be added in a future version. In the mean time,
-if you need to make these services available on port 25, then do
-not enable the tests after the 220 server greeting. </p>
+the AUTH, XCLIENT, and XFORWARD features. AUTH support may be added
+in a future version. In the mean time, if you need to make these
+services available on port 25, then do not enable the tests after
+the 220 server greeting. </p>
</ul>
smtp inet n - n - 1 postscreen
</pre>
+<li> <p> Uncomment the new "<tt>tlsproxy unix ... tlsproxy</tt>"
+service in <a href="master.5.html">master.cf</a>. This service implements STARTTLS support for
+<a href="postscreen.8.html">postscreen(8)</a>. </p>
+
+<pre>
+/etc/postfix/<a href="master.5.html">master.cf</a>:
+ tlsproxy unix - - n - 0 tlsproxy
+</pre>
+
<li> <p> Uncomment the new "<tt>dnsblog unix ... dnsblog</tt>"
service in <a href="master.5.html">master.cf</a>. This service does DNSBL lookups for <a href="postscreen.8.html">postscreen(8)</a>
and logs results. </p>
<p> When the good client comes back in a later session, it is allowed
to talk directly to a Postfix SMTP server. See "after_220 <a
href="#after_220">Tests after the 220 SMTP server greeting</a> above
-for limitations with STARTTLS, AUTH and other features that clients
-may need. </p>
+for limitations with AUTH and other features that clients may need.
+</p>
<p> An unexpected benefit from "<a href="#after_220">deep protocol
tests</a>" is that some "good" clients don't return after the 4XX
# -o parameter=value ...
</pre>
+<li> <p> Comment out the "<tt>tlsproxy unix ... tlsproxy</tt>"
+service in <a href="master.5.html">master.cf</a>, including any "<tt>-o parameter=value</tt>"
+entries that follow. </p>
+
+<pre>
+/etc/postfix/<a href="master.5.html">master.cf</a>:
+ #tlsproxy unix - - n - 0 tlsproxy
+ # -o parameter=value ...
+</pre>
<li> <p> Uncomment the "<tt>smtp inet ... smtpd</tt>" service in
<a href="master.5.html">master.cf</a>, including any "<tt>-o parameter=value</tt>" entries that
-follow. </p>
+may follow. </p>
<pre>
/etc/postfix/<a href="master.5.html">master.cf</a>:
- smtp inet n - n - - smtpd
+ smtp inet n - n - - smtpd
-o parameter=value ...
</pre>
own code, every 1000 lines introduce one additional bug into
Postfix. </p>
+<p> At this time, you should no longer be using OpenSSL releases prior
+to the most recent 0.9.8 release unless all relevant security fixes have
+been backported to the earlier release by you or your O/S vendor. OpenSSL
+0.9.7 and earlier are no longer maintained by the OpenSSL team. </p>
+
<h2> What Postfix TLS support does for you </h2>
<p> Transport Layer Security (TLS, formerly called SSL) provides
</pre>
</blockquote>
+<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
+allows TLS servers to preempt the TLS client's cipher preference list.
+This is only possible with SSLv3, as in SSLv2 the client chooses the
+cipher from a list supplied by the server. </p>
+
+<p> By default, the OpenSSL server selects the client's most preferred
+cipher that the server supports. With SSLv3 and later, the server
+may choose its own most preferred cipher that is supported (offered)
+by the client. Setting "<a href="postconf.5.html#tls_preempts_cipherlist">tls_preempt_cipherlist</a> = yes" enables server
+cipher preferences. The default OpenSSL behaviour applies with
+"<a href="postconf.5.html#tls_preempts_cipherlist">tls_preempt_cipherlist</a> = no". </p>
+
+<p> While server cipher selection may in some cases lead to a more secure
+or performant cipher choice, there is some risk of interoperability
+issues. In the past, some SSL clients have listed lower priority ciphers
+that they did not implement correctly. If the server chooses a cipher
+that the client prefers less, it may select a cipher whose client
+implementation is flawed. </p>
+
<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
<p> The <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> parameter limits the time of Postfix
</pre>
</blockquote>
+<p> With Postfix 2.8 and later, the <a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> parameter
+specifies a list or bit-mask of OpenSSL bug work-arounds to disable. This
+may be necessary if one of the work-arounds enabled by default in
+OpenSSL proves to pose a security risk, or introduces an unexpected
+interoperability issue. Some bug work-arounds known to be problematic
+are disabled in the default value of the parameter when linked with
+an OpenSSL library that could be vulnerable. </p>
+
+<p> Example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> = 0xFFFFFFFF
+ <a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> = CVE-2010-4180, LEGACY_SERVER_CONNECT
+</pre>
+</blockquote>
+
+<p> Note: Disabling LEGACY_SERVER_CONNECT is not wise at this
+time, lots of servers are still unpatched and Postfix is <a
+href="http://www.postfix.org/wip.html#tls-renegotiation">not
+significantly vulnerable</a> to the renegotiation issue in the TLS
+protocol. </p>
+
<h2> <a name="client_tls">SMTP Client specific settings</a> </h2>
<p> Topics covered in this section: </p>
an attacker prepends malicious HELO, MAIL, RCPT,
DATA commands to a Postfix SMTP client TLS session.
+ Available in Postfix version 2.8 and later:
+
+ <b><a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> (see 'postconf -d' output)</b>
+ List or bit-mask of OpenSSL bug work-arounds to
+ disable.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
- The following configuration parameters exist for compati-
+ The following configuration parameters exist for compati-
bility with Postfix versions before 2.3. Support for these
will be removed in a future release.
<b><a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> (no)</b>
- Opportunistic mode: use TLS when a remote SMTP
- server announces STARTTLS support, otherwise send
+ Opportunistic mode: use TLS when a remote SMTP
+ server announces STARTTLS support, otherwise send
the mail in the clear.
<b><a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> (no)</b>
- Enforcement mode: require that remote SMTP servers
- use TLS encryption, and never send mail in the
+ Enforcement mode: require that remote SMTP servers
+ use TLS encryption, and never send mail in the
clear.
<b><a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> (yes)</b>
- With mandatory TLS encryption, require that the
+ With mandatory TLS encryption, require that the
remote SMTP server hostname matches the information
in the remote SMTP server certificate.
<b><a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> (empty)</b>
Optional lookup tables with the Postfix SMTP client
- TLS usage policy by next-hop destination and by
+ TLS usage policy by next-hop destination and by
remote SMTP server hostname.
<b><a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> (empty)</b>
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#smtp_destination_concurrency_limit">smtp_destination_concurrency_limit</a> ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destina</a>-</b>
<b><a href="postconf.5.html#default_destination_concurrency_limit">tion_concurrency_limit</a>)</b>
- The maximal number of parallel deliveries to the
- same destination via the smtp message delivery
+ The maximal number of parallel deliveries to the
+ same destination via the smtp message delivery
transport.
<b><a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a> ($<a href="postconf.5.html#default_destination_recipient_limit">default_destina</a>-</b>
<b><a href="postconf.5.html#default_destination_recipient_limit">tion_recipient_limit</a>)</b>
- The maximal number of recipients per message for
+ The maximal number of recipients per message for
the smtp message delivery transport.
<b><a href="postconf.5.html#smtp_connect_timeout">smtp_connect_timeout</a> (30s)</b>
- The SMTP client time limit for completing a TCP
+ The SMTP client time limit for completing a TCP
connection, or zero (use the operating system
built-in time limit).
<b><a href="postconf.5.html#smtp_helo_timeout">smtp_helo_timeout</a> (300s)</b>
- The SMTP client time limit for sending the HELO or
- EHLO command, and for receiving the initial server
+ The SMTP client time limit for sending the HELO or
+ EHLO command, and for receiving the initial server
response.
<b><a href="postconf.5.html#lmtp_lhlo_timeout">lmtp_lhlo_timeout</a> (300s)</b>
- The LMTP client time limit for sending the LHLO
+ The LMTP client time limit for sending the LHLO
command, and for receiving the initial server
response.
command, and for receiving the server response.
<b><a href="postconf.5.html#smtp_mail_timeout">smtp_mail_timeout</a> (300s)</b>
- The SMTP client time limit for sending the MAIL
- FROM command, and for receiving the server
+ The SMTP client time limit for sending the MAIL
+ FROM command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_rcpt_timeout">smtp_rcpt_timeout</a> (300s)</b>
- The SMTP client time limit for sending the SMTP
- RCPT TO command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ RCPT TO command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_data_init_timeout">smtp_data_init_timeout</a> (120s)</b>
- The SMTP client time limit for sending the SMTP
- DATA command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ DATA command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_data_xfer_timeout">smtp_data_xfer_timeout</a> (180s)</b>
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
message content.
<b><a href="postconf.5.html#smtp_data_done_timeout">smtp_data_done_timeout</a> (600s)</b>
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
".", and for receiving the server response.
<b><a href="postconf.5.html#smtp_quit_timeout">smtp_quit_timeout</a> (300s)</b>
- The SMTP client time limit for sending the QUIT
+ The SMTP client time limit for sending the QUIT
command, and for receiving the server response.
Available in Postfix version 2.1 and later:
lookups, or zero (no limit).
<b><a href="postconf.5.html#smtp_mx_session_limit">smtp_mx_session_limit</a> (2)</b>
- The maximal number of SMTP sessions per delivery
- request before giving up or delivering to a fall-
+ The maximal number of SMTP sessions per delivery
+ request before giving up or delivering to a fall-
back <a href="postconf.5.html#relayhost">relay host</a>, or zero (no limit).
<b><a href="postconf.5.html#smtp_rset_timeout">smtp_rset_timeout</a> (20s)</b>
- The SMTP client time limit for sending the RSET
+ The SMTP client time limit for sending the RSET
command, and for receiving the server response.
Available in Postfix version 2.2 and earlier:
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_connection_cache_destinations">smtp_connection_cache_destinations</a> (empty)</b>
- Permanently enable SMTP connection caching for the
+ Permanently enable SMTP connection caching for the
specified destinations.
<b><a href="postconf.5.html#smtp_connection_cache_on_demand">smtp_connection_cache_on_demand</a> (yes)</b>
- Temporarily enable SMTP connection caching while a
+ Temporarily enable SMTP connection caching while a
destination has a high volume of mail in the active
queue.
<b><a href="postconf.5.html#smtp_connection_cache_time_limit">smtp_connection_cache_time_limit</a> (2s)</b>
When SMTP connection caching is enabled, the amount
- of time that an unused SMTP client socket is kept
+ of time that an unused SMTP client socket is kept
open before it is closed.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#connection_cache_protocol_timeout">connection_cache_protocol_timeout</a> (5s)</b>
- Time limit for connection cache connect, send or
+ Time limit for connection cache connect, send or
receive operations.
<b>TROUBLE SHOOTING CONTROLS</b>
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
<b><a href="postconf.5.html#internal_mail_filter_classes">internal_mail_filter_classes</a> (empty)</b>
- What categories of Postfix-generated mail are sub-
- ject to before-queue content inspection by
+ What categories of Postfix-generated mail are sub-
+ ject to before-queue content inspection by
<a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a>, <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>.
<b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#best_mx_transport">best_mx_transport</a> (empty)</b>
- Where the Postfix SMTP client should deliver mail
+ Where the Postfix SMTP client should deliver mail
when it detects a "mail loops back to myself" error
condition.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
<b><a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a> (no)</b>
- Disable DNS lookups in the Postfix SMTP and LMTP
+ Disable DNS lookups in the Postfix SMTP and LMTP
clients.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
tem receives mail on.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#lmtp_assume_final">lmtp_assume_final</a> (no)</b>
- When an LMTP server announces no DSN support,
+ When an LMTP server announces no DSN support,
assume that the server performs final delivery, and
- send "delivered" delivery status notifications
+ send "delivered" delivery status notifications
instead of "relayed".
<b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a> (24)</b>
- The default TCP port that the Postfix LMTP client
+ The default TCP port that the Postfix LMTP client
connects to.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
<b><a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> (ipv6)</b>
The address type ("ipv6", "ipv4" or "any") that the
Postfix SMTP client will try first, when a destina-
- tion has IPv6 and IPv4 addresses with equal MX
+ tion has IPv6 and IPv4 addresses with equal MX
preference.
<b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
- An optional numerical network address that the
- Postfix SMTP client should bind to when making an
+ An optional numerical network address that the
+ Postfix SMTP client should bind to when making an
IPv4 connection.
<b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
- An optional numerical network address that the
- Postfix SMTP client should bind to when making an
+ An optional numerical network address that the
+ Postfix SMTP client should bind to when making an
IPv6 connection.
<b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The hostname to send in the SMTP EHLO or HELO com-
+ The hostname to send in the SMTP EHLO or HELO com-
mand.
<b><a href="postconf.5.html#lmtp_lhlo_name">lmtp_lhlo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The hostname to send in the LMTP LHLO command.
<b><a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a> (dns)</b>
- What mechanisms the Postfix SMTP client uses to
+ What mechanisms the Postfix SMTP client uses to
look up a host's IP address.
<b><a href="postconf.5.html#smtp_randomize_addresses">smtp_randomize_addresses</a> (yes)</b>
- Randomize the order of equal-preference MX host
+ Randomize the order of equal-preference MX host
addresses.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available with Postfix 2.2 and earlier:
<b><a href="postconf.5.html#fallback_relay">fallback_relay</a> (empty)</b>
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
Available with Postfix 2.3 and later:
<b><a href="postconf.5.html#smtp_fallback_relay">smtp_fallback_relay</a> ($<a href="postconf.5.html#fallback_relay">fallback_relay</a>)</b>
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
<b>SEE ALSO</b>
<a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<p> This feature is available in Postfix 2.8. </p>
+</DD>
+
+<DT><b><a name="postscreen_discard_ehlo_keyword_address_maps">postscreen_discard_ehlo_keyword_address_maps</a>
+(default: $<a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">smtpd_discard_ehlo_keyword_address_maps</a>)</b></DT><DD>
+
+<p> Lookup tables, indexed by the remote SMTP client address, with
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the <a href="postscreen.8.html">postscreen(8)</a> server will not send in the EHLO response
+to a remote SMTP client. See <a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_keywords</a> for details.
+The table is not searched by hostname for robustness reasons. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="postscreen_discard_ehlo_keywords">postscreen_discard_ehlo_keywords</a>
+(default: $<a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_keywords</a>)</b></DT><DD>
+
+<p> A case insensitive list of EHLO keywords (pipelining, starttls,
+auth, etc.) that the <a href="postscreen.8.html">postscreen(8)</a> server will not send in the EHLO
+response to a remote SMTP client. See <a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_keywords</a>
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
</DD>
<DT><b><a name="postscreen_dnsbl_action">postscreen_dnsbl_action</a>
<p> This feature is available in Postfix 2.8. </p>
+</DD>
+
+<DT><b><a name="postscreen_enforce_tls">postscreen_enforce_tls</a>
+(default: $<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b></DT><DD>
+
+<p> Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See smtpd_postscreen_enforce_tls
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later.
+Preferably, use <a href="postconf.5.html#postscreen_tls_security_level">postscreen_tls_security_level</a> instead. </p>
+
+
</DD>
<DT><b><a name="postscreen_forbidden_commands">postscreen_forbidden_commands</a>
<p> This feature is available in Postfix 2.8. </p>
+</DD>
+
+<DT><b><a name="postscreen_tls_security_level">postscreen_tls_security_level</a>
+(default: $<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b></DT><DD>
+
+<p> The SMTP TLS security level for the <a href="postscreen.8.html">postscreen(8)</a> server; when
+a non-empty value is specified, this overrides the obsolete parameters
+<a href="postconf.5.html#postscreen_use_tls">postscreen_use_tls</a> and <a href="postconf.5.html#postscreen_enforce_tls">postscreen_enforce_tls</a>. See <a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="postscreen_use_tls">postscreen_use_tls</a>
+(default: $<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b></DT><DD>
+
+<p> Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. </p>
+
+<p> This feature is available in Postfix 2.8 and later.
+Preferably, use <a href="postconf.5.html#postscreen_tls_security_level">postscreen_tls_security_level</a> instead. </p>
+
+
</DD>
<DT><b><a name="postscreen_watchdog_timeout">postscreen_watchdog_timeout</a>
</DD>
<DT><b><a name="smtpd_starttls_timeout">smtpd_starttls_timeout</a>
-(default: 300s)</b></DT><DD>
+(default: see "postconf -d" output)</b></DT><DD>
<p> The time limit for Postfix SMTP server write and read operations
-during TLS startup and shutdown handshake procedures. </p>
+during TLS startup and shutdown handshake procedures. The current
+default value is stress-dependent. Before Postfix version 2.8, it
+was fixed at 300s. </p>
<p> This feature is available in Postfix 2.2 and later. </p>
<p> This feature is available in Postfix 2.2 and later. </p>
+</DD>
+
+<DT><b><a name="tls_disable_workarounds">tls_disable_workarounds</a>
+(default: see "postconf -d" output)</b></DT><DD>
+
+<p> List or bit-mask of OpenSSL bug work-arounds to disable. </p>
+
+<p> The OpenSSL toolkit includes a set of work-arounds for buggy SSL/TLS
+implementations. Applications, such as Postfix, that want to maximize
+interoperability ask the OpenSSL library to enable the full set of
+recommended work-arounds. </p>
+
+<p> From time to time, it is discovered that a work-around creates a
+security issue, and should no longer be used. If upgrading OpenSSL
+to a fixed version is not an option or an upgrade is not available
+in a timely manner, or in closed environments where no buggy clients
+or servers exist, it may be appropriate to disable some or all of the
+OpenSSL interoperability work-arounds. This parameter specifies which
+bug work-arounds to disable. </p>
+
+<p> If the value of the parameter is a hexadecimal long integer starting
+with "0x", the bug work-arounds corresponding to the bits specified in
+its value are removed from the <b>SSL_OP_ALL</b> work-around bit-mask
+(see openssl/ssl.h and SSL_CTX_set_options(3)). You can specify more
+bits than are present in SSL_OP_ALL, excess bits are ignored. Specifying
+0xFFFFFFFF disables all bug-workarounds on a 32-bit system. This should
+also be sufficient on 64-bit systems, until OpenSSL abandons support
+for 32-bit systems and starts using the high 32 bits of a 64-bit
+bug-workaround mask. </p>
+
+<p> Otherwise, the parameter is a white-space or comma separated list
+of specific named bug work-arounds chosen from the list below. It
+is possible that your OpenSSL version includes new bug work-arounds
+added after your Postfix source code was last updated, in that case
+you can only disable one of these via the hexadecimal syntax above. </p>
+
+<dl>
+<dt><b>MICROSOFT_SESS_ID_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>NETSCAPE_CHALLENGE_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>LEGACY_SERVER_CONNECT</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b> also aliased as
+<b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.8q
+and OpenSSL 1.0.0c.</dt>
+<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>MICROSOFT_BIG_SSLV3_BUFFER</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>MSIE_SSLV2_RSA_PADDING</b> also aliased as
+<b>CVE-2005-2969</b>. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h
+and OpenSSL 0.9.8a.</dt>
+<dt><b>SSLEAY_080_CLIENT_DH_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_D5_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_BLOCK_PADDING_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_ROLLBACK_BUG</b>See SSL_CTX_set_options(3). This is disabled
+in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6! </dt>
+<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>CRYPTOPRO_TLSEXT_BUG</b>New with GOST support in OpenSSL 1.0.0.</dt>
+</dl>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
</DD>
<DT><b><a name="tls_eecdh_strong_curve">tls_eecdh_strong_curve</a>
<p> This feature is available in Postfix 2.3 and later. </p>
+</DD>
+
+<DT><b><a name="tls_preempt_cipherlist">tls_preempt_cipherlist</a>
+(default: no)</b></DT><DD>
+
+<p> With SSLv3 and later, use the server's cipher preference order
+instead of the client's cipher preference order. </p>
+
+<p> By default, the OpenSSL server selects the client's most preferred
+cipher that the server supports. With SSLv3 and later, the server may
+choose its own most preferred cipher that is supported (offered) by
+the client. Setting "<a href="postconf.5.html#tls_preempts_cipherlist">tls_preempt_cipherlist</a> = yes" enables server cipher
+preferences. </p>
+
+<p> While server cipher selection may in some cases lead to a more secure
+or performant cipher choice, there is some risk of interoperability
+issues. In the past, some SSL clients have listed lower priority ciphers
+that they did not implement correctly. If the server chooses a cipher
+that the client prefers less, it may select a cipher whose client
+implementation is flawed. </p>
+
+<p> This feature is available in Postfix 2.8 and later, in combination
+with OpenSSL 0.9.7 and later. </p>
+
+
</DD>
<DT><b><a name="tls_random_bytes">tls_random_bytes</a>
<p> This feature is available in Postfix 2.2 and later. </p>
+</DD>
+
+<DT><b><a name="tlsproxy_enforce_tls">tlsproxy_enforce_tls</a>
+(default: $<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b></DT><DD>
+
+<p> Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_CAfile">tlsproxy_tls_CAfile</a>
+(default: $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>)</b></DT><DD>
+
+<p> A file containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_CApath">tlsproxy_tls_CApath</a>
+(default: $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>)</b></DT><DD>
+
+<p> A directory containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_always_issue_session_ids">tlsproxy_tls_always_issue_session_ids</a>
+(default: $<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a>)</b></DT><DD>
+
+<p> Force the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server to issue a TLS session id,
+even when TLS session caching is turned off. See
+<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_ask_ccert">tlsproxy_tls_ask_ccert</a>
+(default: $<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>)</b></DT><DD>
+
+<p> Ask a remote SMTP client for a client certificate. See
+<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_ccert_verifydepth">tlsproxy_tls_ccert_verifydepth</a>
+(default: $<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a>)</b></DT><DD>
+
+<p> The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file. See <a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_cert_file">tlsproxy_tls_cert_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server RSA certificate in PEM
+format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+private RSA key. See <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_ciphers">tlsproxy_tls_ciphers</a>
+(default: $<a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a>)</b></DT><DD>
+
+<p> The minimum TLS cipher grade that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+will use with opportunistic TLS encryption. See <a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a>
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_dcert_file">tlsproxy_tls_dcert_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server DSA certificate in PEM
+format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+private DSA key. See <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> for further details.
+</p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_dh1024_param_file">tlsproxy_tls_dh1024_param_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>)</b></DT><DD>
+
+<p> File with DH parameters that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+should use with EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_dh512_param_file">tlsproxy_tls_dh512_param_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>)</b></DT><DD>
+
+<p> File with DH parameters that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+should use with EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_dkey_file">tlsproxy_tls_dkey_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server DSA private key in PEM
+format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a>
+server DSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>.
+See <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_eccert_file">tlsproxy_tls_eccert_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA certificate in
+PEM format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a>
+server private ECDSA key. See <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> for further
+details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_eckey_file">tlsproxy_tls_eckey_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA private key in
+PEM format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a>
+server ECDSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>.
+See <a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_eecdh_grade">tlsproxy_tls_eecdh_grade</a>
+(default: $<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a>)</b></DT><DD>
+
+<p> The Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server security grade for ephemeral
+elliptic-curve Diffie-Hellman (EECDH) key exchange. See
+<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_exclude_ciphers">tlsproxy_tls_exclude_ciphers</a>
+(default: $<a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a>)</b></DT><DD>
+
+<p> List of ciphers or cipher types to exclude from the <a href="tlsproxy.8.html">tlsproxy(8)</a>
+server cipher list at all TLS security levels. See
+<a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_fingerprint_digest">tlsproxy_tls_fingerprint_digest</a>
+(default: $<a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a>)</b></DT><DD>
+
+<p> The message digest algorithm used to construct client-certificate
+fingerprints. See <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> for further details.
+</p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_key_file">tlsproxy_tls_key_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a>)</b></DT><DD>
+
+<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server RSA private key in PEM
+format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a>
+server RSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>.
+See <a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_loglevel">tlsproxy_tls_loglevel</a>
+(default: $<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a>)</b></DT><DD>
+
+<p> Enable additional Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server logging of TLS
+activity. Each logging level also includes the information that
+is logged at a lower logging level. See <a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_mandatory_ciphers">tlsproxy_tls_mandatory_ciphers</a>
+(default: $<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a>)</b></DT><DD>
+
+<p> The minimum TLS cipher grade that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+will use with mandatory TLS encryption. See <a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a>
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_mandatory_exclude_ciphers">tlsproxy_tls_mandatory_exclude_ciphers</a>
+(default: $<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_mandatory_exclude_ciphers</a>)</b></DT><DD>
+
+<p> Additional list of ciphers or cipher types to exclude from the
+<a href="tlsproxy.8.html">tlsproxy(8)</a> server cipher list at mandatory TLS security levels.
+See <a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_mandatory_exclude_ciphers</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_mandatory_protocols">tlsproxy_tls_mandatory_protocols</a>
+(default: $<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a>)</b></DT><DD>
+
+<p> The SSL/TLS protocols accepted by the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
+with mandatory TLS encryption. If the list is empty, the server
+supports all available SSL/TLS protocol versions. See
+<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_protocols">tlsproxy_tls_protocols</a>
+(default: $<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a>)</b></DT><DD>
+
+<p> List of TLS protocols that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server will
+exclude or include with opportunistic TLS encryption. See
+<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_req_ccert">tlsproxy_tls_req_ccert</a>
+(default: $<a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a>)</b></DT><DD>
+
+<p> With mandatory TLS encryption, require a trusted remote SMTP
+client certificate in order to allow TLS connections to proceed.
+See <a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_security_level">tlsproxy_tls_security_level</a>
+(default: $<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b></DT><DD>
+
+<p> The SMTP TLS security level for the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server;
+when a non-empty value is specified, this overrides the obsolete
+parameters <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> and <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>. See
+<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_tls_session_cache_timeout">tlsproxy_tls_session_cache_timeout</a>
+(default: $<a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a>)</b></DT><DD>
+
+<p> The expiration time of Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server TLS session
+cache information. A cache cleanup is performed periodically every
+$<a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> seconds. See
+<a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_use_tls">tlsproxy_use_tls</a>
+(default: $<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b></DT><DD>
+
+<p> Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. See <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="tlsproxy_watchdog_timeout">tlsproxy_watchdog_timeout</a>
+(default: 10s)</b></DT><DD>
+
+<p> How much time a <a href="tlsproxy.8.html">tlsproxy(8)</a> process may take to process local
+or remote I/O before it is terminated by a built-in watchdog timer.
+This is a safety mechanism that prevents <a href="tlsproxy.8.html">tlsproxy(8)</a> from becoming
+non-responsive due to a bug in Postfix itself or in system software.
+To avoid false alarms and unnecessary cache corruption this limit
+cannot be set under 10s. </p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
+one-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
+
+<p> This feature is available in Postfix 2.8. </p>
+
+
</DD>
<DT><b><a name="trace_service_name">trace_service_name</a>
<li> <a href="pipe.8.html">pipe(8)</a>, deliver mail to non-Postfix command
-<li> <a href="postscreen.8.html">postscreen(8)</a>, Postfix SMTP triage server
+<li> <a href="postscreen.8.html">postscreen(8)</a>, Postfix zombie blocker
<li> <a href="proxymap.8.html">proxymap(8)</a>, Postfix lookup table proxy server
<li> <a href="tlsmgr.8.html">tlsmgr(8)</a>, Postfix TLS cache and randomness manager
+<li> <a href="tlsproxy.8.html">tlsproxy(8)</a>, Postfix TLS proxy server
+
<li> <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, Postfix address rewriting
<li> <a href="verify.8.html">verify(8)</a>, Postfix address verification
<a href="qmgr.8.html">oqmgr(8)</a>, old Postfix queue manager
<a href="pickup.8.html">pickup(8)</a>, Postfix local mail pickup
<a href="pipe.8.html">pipe(8)</a>, deliver mail to non-Postfix command
- <a href="postscreen.8.html">postscreen(8)</a>, Postfix SMTP triage server
+ <a href="postscreen.8.html">postscreen(8)</a>, Postfix zombie blocker
<a href="proxymap.8.html">proxymap(8)</a>, Postfix lookup table proxy server
<a href="qmgr.8.html">qmgr(8)</a>, Postfix queue manager
<a href="qmqpd.8.html">qmqpd(8)</a>, Postfix QMQP server
<a href="smtpd.8.html">smtpd(8)</a>, Postfix SMTP server
<a href="spawn.8.html">spawn(8)</a>, run non-Postfix server
<a href="tlsmgr.8.html">tlsmgr(8)</a>, Postfix TLS cache and randomness manager
+ <a href="tlsproxy.8.html">tlsproxy(8)</a>, Postfix TLS proxy server
<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, Postfix address rewriting
<a href="verify.8.html">verify(8)</a>, Postfix address verification
<a href="virtual.8.html">virtual(8)</a>, Postfix virtual delivery agent
POSTSCREEN(8) POSTSCREEN(8)
<b>NAME</b>
- postscreen - Postfix SMTP triage server
+ postscreen - Postfix zombie blocker
<b>SYNOPSIS</b>
<b>postscreen</b> [generic Postfix daemon options]
can be run chrooted at fixed low privilege.
<b>STANDARDS</b>
- <a href="http://tools.ietf.org/html/rfc5321">RFC 5321</a> (SMTP, including multi-line 220 greetings)
+ <a href="http://tools.ietf.org/html/rfc821">RFC 821</a> (SMTP protocol)
+ <a href="http://tools.ietf.org/html/rfc1123">RFC 1123</a> (Host requirements)
+ <a href="http://tools.ietf.org/html/rfc1652">RFC 1652</a> (8bit-MIME transport)
+ <a href="http://tools.ietf.org/html/rfc1869">RFC 1869</a> (SMTP service extensions)
+ <a href="http://tools.ietf.org/html/rfc1870">RFC 1870</a> (Message Size Declaration)
+ <a href="http://tools.ietf.org/html/rfc1985">RFC 1985</a> (ETRN command)
+ <a href="http://tools.ietf.org/html/rfc2034">RFC 2034</a> (SMTP Enhanced Error Codes)
+ <a href="http://tools.ietf.org/html/rfc2821">RFC 2821</a> (SMTP protocol)
<a href="http://tools.ietf.org/html/rfc2920">RFC 2920</a> (SMTP Pipelining)
+ <a href="http://tools.ietf.org/html/rfc3207">RFC 3207</a> (STARTTLS command)
+ <a href="http://tools.ietf.org/html/rfc3461">RFC 3461</a> (SMTP DSN Extension)
+ <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced Status Codes)
+ <a href="http://tools.ietf.org/html/rfc5321">RFC 5321</a> (SMTP protocol, including multi-line 220 greetings)
<b>DIAGNOSTICS</b>
Problems and transactions are logged to <b>syslogd</b>(8).
<b>BUGS</b>
The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> built-in SMTP protocol engine currently
- does not announce support for STARTTLS, AUTH, XCLIENT or
- XFORWARD. Support for STARTTLS and AUTH may be added in
- the future. In the mean time, if you need to make these
- services available on port 25, then do not enable the
- optional "after 220 server greeting" tests.
+ does not announce support for AUTH, XCLIENT or XFORWARD.
+ Support for AUTH may be added in the future. In the mean
+ time, if you need to make these services available on port
+ 25, then do not enable the optional "after 220 server
+ greeting" tests.
The optional "after 220 server greeting" tests involve
<a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol engine. When these
The text below provides only a parameter summary. See
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
- NOTE: Some <a href="postscreen.8.html"><b>postscreen</b>(8)</a> parameters implement stress-
+ NOTE: Some <a href="postscreen.8.html"><b>postscreen</b>(8)</a> parameters implement stress-
dependent behavior. This is supported only when the
- default value is stress-dependent (that is, it looks like
- ${stress?X}${stress:Y}). Other parameters always evaluate
- as if the stress value is the empty string.
+ default parameter value is stress-dependent (that is, it
+ looks like ${stress?X}${stress:Y}, or it is the $<i>name</i> of
+ an smtpd parameter with a stress-dependent default).
+ Other parameters always evaluate as if the <b>stress</b> parame-
+ ter value is the empty string.
+
+<b>COMPATIBILITY CONTROLS</b>
+ <b><a href="postconf.5.html#postscreen_discard_ehlo_keyword_address_maps">postscreen_discard_ehlo_keyword_address_maps</a> ($<a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">smtpd_dis</a>-</b>
+ <b><a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">card_ehlo_keyword_address_maps</a>)</b>
+ Lookup tables, indexed by the remote SMTP client
+ address, with case insensitive lists of EHLO key-
+ words (pipelining, starttls, auth, etc.) that the
+ <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server will not send in the EHLO
+ response to a remote SMTP client.
+
+ <b><a href="postconf.5.html#postscreen_discard_ehlo_keywords">postscreen_discard_ehlo_keywords</a> ($<a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_key</a>-</b>
+ <b><a href="postconf.5.html#smtpd_discard_ehlo_keywords">words</a>)</b>
+ A case insensitive list of EHLO keywords (pipelin-
+ ing, starttls, auth, etc.) that the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+ server will not send in the EHLO response to a
+ remote SMTP client.
<b>TRIAGE PARAMETERS</b>
<b><a href="postconf.5.html#postscreen_bare_newline_action">postscreen_bare_newline_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client sends a bare newline character, that is, a
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client sends a bare newline character, that is, a
newline not preceded by carriage return.
<b><a href="postconf.5.html#postscreen_bare_newline_enable">postscreen_bare_newline_enable</a> (no)</b>
- Enable "bare newline" SMTP protocol tests in the
+ Enable "bare newline" SMTP protocol tests in the
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
<b><a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client is permanently blacklisted with the
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client is permanently blacklisted with the
<a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter.
<b><a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> (empty)</b>
Network addresses that are permanently blacklisted;
- see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
+ see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
possible actions.
<b><a href="postconf.5.html#postscreen_disable_vrfy_command">postscreen_disable_vrfy_command</a> ($<a href="postconf.5.html#disable_vrfy_command">disable_vrfy_command</a>)</b>
- Disable the SMTP VRFY command in the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+ Disable the SMTP VRFY command in the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
daemon.
<b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
client's combined DNSBL score is equal to or
- greater than a threshold (as defined with the
+ greater than a threshold (as defined with the
<a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> and <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_thresh</a>-
<a href="postconf.5.html#postscreen_dnsbl_threshold">old</a> parameters).
<b><a href="postconf.5.html#postscreen_dnsbl_reply_map">postscreen_dnsbl_reply_map</a> (empty)</b>
- A mapping from actual DNSBL domain name which
- includes a secret password, to the DNSBL domain
+ A mapping from actual DNSBL domain name which
+ includes a secret password, to the DNSBL domain
name that postscreen will reply with when it
rejects mail.
weight factors.
<b><a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> (1)</b>
- The inclusive lower bound for blocking an SMTP
+ The inclusive lower bound for blocking an SMTP
client, based on its combined DNSBL score as
- defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
+ defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
<b><a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> ($<a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a>)</b>
List of commands that the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server con-
siders in violation of the SMTP protocol.
<b><a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
client speaks before its turn within the time spec-
ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter.
The <i>text</i> in the optional "220-<i>text</i>..." server
response that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends ahead of the real
Postfix SMTP server's "220 text..." response, in an
- attempt to confuse bad SMTP clients so that they
+ attempt to confuse bad SMTP clients so that they
speak before their turn (pre-greet).
<b><a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> (${stress?2}${stress:6}s)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will wait for
- an SMTP client to send a command before its turn,
- and for DNS blocklist lookup results to arrive
- (default: up to 2 seconds under stress, up to 6
+ an SMTP client to send a command before its turn,
+ and for DNS blocklist lookup results to arrive
+ (default: up to 2 seconds under stress, up to 6
seconds otherwise).
<b><a href="postconf.5.html#postscreen_helo_required">postscreen_helo_required</a> ($<a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a>)</b>
- Require that a remote SMTP client sends HELO or
+ Require that a remote SMTP client sends HELO or
EHLO before commencing a MAIL transaction.
<b><a href="postconf.5.html#postscreen_non_smtp_command_action">postscreen_non_smtp_command_action</a> (drop)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client sends non-SMTP commands as specified with
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client sends non-SMTP commands as specified with
the <a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> parameter.
<b><a href="postconf.5.html#postscreen_non_smtp_command_enable">postscreen_non_smtp_command_enable</a> (no)</b>
- Enable "non-SMTP command" tests in the
+ Enable "non-SMTP command" tests in the
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
<b><a href="postconf.5.html#postscreen_pipelining_action">postscreen_pipelining_action</a> (enforce)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client sends multiple commands instead of sending
- one command and waiting for the server to respond.
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client sends multiple commands instead of sending
+ one command and waiting for the server to respond.
<b><a href="postconf.5.html#postscreen_pipelining_enable">postscreen_pipelining_enable</a> (no)</b>
- Enable "pipelining" SMTP protocol tests in the
+ Enable "pipelining" SMTP protocol tests in the
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
<b><a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
Network addresses that are permanently whitelisted,
- and that will not be subjected to <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+ and that will not be subjected to <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
checks.
<b><a href="postconf.5.html#smtpd_service_name">smtpd_service_name</a> (smtpd)</b>
- The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
+ The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
allowed connections to.
<b>CACHE CONTROLS</b>
<b><a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> (12h)</b>
- The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
+ The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
cleanup runs.
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_cache)</b>
- Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
+ Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
decisions.
<b><a href="postconf.5.html#postscreen_cache_retention_time">postscreen_cache_retention_time</a> (7d)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache an
- expired temporary whitelist entry before it is
+ expired temporary whitelist entry before it is
removed.
<b><a href="postconf.5.html#postscreen_bare_newline_ttl">postscreen_bare_newline_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
- results from a successful "bare newline" SMTP pro-
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
+ results from a successful "bare newline" SMTP pro-
tocol test.
<b><a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a> (1h)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
results from a successful DNS blocklist test.
<b><a href="postconf.5.html#postscreen_greet_ttl">postscreen_greet_ttl</a> (1d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
results from a successful PREGREET test.
<b><a href="postconf.5.html#postscreen_non_smtp_command_ttl">postscreen_non_smtp_command_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
- results from a successful "non_smtp_command" SMTP
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
+ results from a successful "non_smtp_command" SMTP
protocol test.
<b><a href="postconf.5.html#postscreen_pipelining_ttl">postscreen_pipelining_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
- results from a successful "pipelining" SMTP proto-
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache
+ results from a successful "pipelining" SMTP proto-
col test.
<b>RESOURCE CONTROLS</b>
<b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
- Upon input, long lines are chopped up into pieces
- of at most this length; upon delivery, long lines
+ Upon input, long lines are chopped up into pieces
+ of at most this length; upon delivery, long lines
are reconstructed.
<b><a href="postconf.5.html#postscreen_client_connection_count_limit">postscreen_client_connection_count_limit</a></b>
<b>($<a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a>)</b>
- How many simultaneous connections any client is
+ How many simultaneous connections any client is
allowed to have with the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon.
<b><a href="postconf.5.html#postscreen_command_count_limit">postscreen_command_count_limit</a> (20)</b>
- The limit on the total number of commands per SMTP
- session for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol
+ The limit on the total number of commands per SMTP
+ session for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol
engine.
<b><a href="postconf.5.html#postscreen_command_time_limit">postscreen_command_time_limit</a> (${stress?10}${stress:300}s)</b>
- The command "read" time limit for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s
+ The command "read" time limit for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s
built-in SMTP protocol engine.
<b><a href="postconf.5.html#postscreen_post_queue_limit">postscreen_post_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
- The number of clients that can be waiting for ser-
+ The number of clients that can be waiting for ser-
vice from a real SMTP server process.
<b><a href="postconf.5.html#postscreen_pre_queue_limit">postscreen_pre_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
- The number of non-whitelisted clients that can be
- waiting for a decision whether they will receive
+ The number of non-whitelisted clients that can be
+ waiting for a decision whether they will receive
service from a real SMTP server process.
<b><a href="postconf.5.html#postscreen_watchdog_timeout">postscreen_watchdog_timeout</a> (10s)</b>
- How much time a <a href="postscreen.8.html"><b>postscreen</b>(8)</a> process may take to
- respond to an SMTP client command or to perform a
+ How much time a <a href="postscreen.8.html"><b>postscreen</b>(8)</a> process may take to
+ respond to an SMTP client command or to perform a
cache operation before it is terminated by a built-
in watchdog timer.
+<b>STARTTLS CONTROLS</b>
+ <b><a href="postconf.5.html#postscreen_tls_security_level">postscreen_tls_security_level</a> ($<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b>
+ The SMTP TLS security level for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+ server; when a non-empty value is specified, this
+ overrides the obsolete parameters
+ <a href="postconf.5.html#postscreen_use_tls">postscreen_use_tls</a> and <a href="postconf.5.html#postscreen_enforce_tls">postscreen_enforce_tls</a>.
+
+<b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
+ These parameters are supported for compatibility with
+ <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy parameters.
+
+ <b><a href="postconf.5.html#postscreen_use_tls">postscreen_use_tls</a> ($<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b>
+ Opportunistic TLS: announce STARTTLS support to
+ SMTP clients, but do not require that clients use
+ TLS encryption.
+
+ <b><a href="postconf.5.html#postscreen_enforce_tls">postscreen_enforce_tls</a> ($<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b>
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
+ tion.
+
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
<b>SEE ALSO</b>
<a href="smtpd.8.html">smtpd(8)</a>, Postfix SMTP server
+ <a href="tlsproxy.8.html">tlsproxy(8)</a>, Postfix TLS proxy server
<a href="dnsblog.8.html">dnsblog(8)</a>, temporary DNS helper
syslogd(8), system logging
<a href="POSTSCREEN_README.html">POSTSCREEN_README</a>, Postfix Postscreen Howto
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>HISTORY</b>
- Many ideas in <a href="postscreen.8.html"><b>postscreen</b>(8)</a> were explored in earlier work
- by Michael Tokarev, in OpenBSD spamd, and in MailChannels
+ Many ideas in <a href="postscreen.8.html"><b>postscreen</b>(8)</a> were explored in earlier work
+ by Michael Tokarev, in OpenBSD spamd, and in MailChannels
Traffic Control.
<b>AUTHOR(S)</b>
an attacker prepends malicious HELO, MAIL, RCPT,
DATA commands to a Postfix SMTP client TLS session.
+ Available in Postfix version 2.8 and later:
+
+ <b><a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> (see 'postconf -d' output)</b>
+ List or bit-mask of OpenSSL bug work-arounds to
+ disable.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
- The following configuration parameters exist for compati-
+ The following configuration parameters exist for compati-
bility with Postfix versions before 2.3. Support for these
will be removed in a future release.
<b><a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> (no)</b>
- Opportunistic mode: use TLS when a remote SMTP
- server announces STARTTLS support, otherwise send
+ Opportunistic mode: use TLS when a remote SMTP
+ server announces STARTTLS support, otherwise send
the mail in the clear.
<b><a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> (no)</b>
- Enforcement mode: require that remote SMTP servers
- use TLS encryption, and never send mail in the
+ Enforcement mode: require that remote SMTP servers
+ use TLS encryption, and never send mail in the
clear.
<b><a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> (yes)</b>
- With mandatory TLS encryption, require that the
+ With mandatory TLS encryption, require that the
remote SMTP server hostname matches the information
in the remote SMTP server certificate.
<b><a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> (empty)</b>
Optional lookup tables with the Postfix SMTP client
- TLS usage policy by next-hop destination and by
+ TLS usage policy by next-hop destination and by
remote SMTP server hostname.
<b><a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> (empty)</b>
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#smtp_destination_concurrency_limit">smtp_destination_concurrency_limit</a> ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destina</a>-</b>
<b><a href="postconf.5.html#default_destination_concurrency_limit">tion_concurrency_limit</a>)</b>
- The maximal number of parallel deliveries to the
- same destination via the smtp message delivery
+ The maximal number of parallel deliveries to the
+ same destination via the smtp message delivery
transport.
<b><a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a> ($<a href="postconf.5.html#default_destination_recipient_limit">default_destina</a>-</b>
<b><a href="postconf.5.html#default_destination_recipient_limit">tion_recipient_limit</a>)</b>
- The maximal number of recipients per message for
+ The maximal number of recipients per message for
the smtp message delivery transport.
<b><a href="postconf.5.html#smtp_connect_timeout">smtp_connect_timeout</a> (30s)</b>
- The SMTP client time limit for completing a TCP
+ The SMTP client time limit for completing a TCP
connection, or zero (use the operating system
built-in time limit).
<b><a href="postconf.5.html#smtp_helo_timeout">smtp_helo_timeout</a> (300s)</b>
- The SMTP client time limit for sending the HELO or
- EHLO command, and for receiving the initial server
+ The SMTP client time limit for sending the HELO or
+ EHLO command, and for receiving the initial server
response.
<b><a href="postconf.5.html#lmtp_lhlo_timeout">lmtp_lhlo_timeout</a> (300s)</b>
- The LMTP client time limit for sending the LHLO
+ The LMTP client time limit for sending the LHLO
command, and for receiving the initial server
response.
command, and for receiving the server response.
<b><a href="postconf.5.html#smtp_mail_timeout">smtp_mail_timeout</a> (300s)</b>
- The SMTP client time limit for sending the MAIL
- FROM command, and for receiving the server
+ The SMTP client time limit for sending the MAIL
+ FROM command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_rcpt_timeout">smtp_rcpt_timeout</a> (300s)</b>
- The SMTP client time limit for sending the SMTP
- RCPT TO command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ RCPT TO command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_data_init_timeout">smtp_data_init_timeout</a> (120s)</b>
- The SMTP client time limit for sending the SMTP
- DATA command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ DATA command, and for receiving the server
response.
<b><a href="postconf.5.html#smtp_data_xfer_timeout">smtp_data_xfer_timeout</a> (180s)</b>
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
message content.
<b><a href="postconf.5.html#smtp_data_done_timeout">smtp_data_done_timeout</a> (600s)</b>
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
".", and for receiving the server response.
<b><a href="postconf.5.html#smtp_quit_timeout">smtp_quit_timeout</a> (300s)</b>
- The SMTP client time limit for sending the QUIT
+ The SMTP client time limit for sending the QUIT
command, and for receiving the server response.
Available in Postfix version 2.1 and later:
lookups, or zero (no limit).
<b><a href="postconf.5.html#smtp_mx_session_limit">smtp_mx_session_limit</a> (2)</b>
- The maximal number of SMTP sessions per delivery
- request before giving up or delivering to a fall-
+ The maximal number of SMTP sessions per delivery
+ request before giving up or delivering to a fall-
back <a href="postconf.5.html#relayhost">relay host</a>, or zero (no limit).
<b><a href="postconf.5.html#smtp_rset_timeout">smtp_rset_timeout</a> (20s)</b>
- The SMTP client time limit for sending the RSET
+ The SMTP client time limit for sending the RSET
command, and for receiving the server response.
Available in Postfix version 2.2 and earlier:
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_connection_cache_destinations">smtp_connection_cache_destinations</a> (empty)</b>
- Permanently enable SMTP connection caching for the
+ Permanently enable SMTP connection caching for the
specified destinations.
<b><a href="postconf.5.html#smtp_connection_cache_on_demand">smtp_connection_cache_on_demand</a> (yes)</b>
- Temporarily enable SMTP connection caching while a
+ Temporarily enable SMTP connection caching while a
destination has a high volume of mail in the active
queue.
<b><a href="postconf.5.html#smtp_connection_cache_time_limit">smtp_connection_cache_time_limit</a> (2s)</b>
When SMTP connection caching is enabled, the amount
- of time that an unused SMTP client socket is kept
+ of time that an unused SMTP client socket is kept
open before it is closed.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#connection_cache_protocol_timeout">connection_cache_protocol_timeout</a> (5s)</b>
- Time limit for connection cache connect, send or
+ Time limit for connection cache connect, send or
receive operations.
<b>TROUBLE SHOOTING CONTROLS</b>
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
<b><a href="postconf.5.html#internal_mail_filter_classes">internal_mail_filter_classes</a> (empty)</b>
- What categories of Postfix-generated mail are sub-
- ject to before-queue content inspection by
+ What categories of Postfix-generated mail are sub-
+ ject to before-queue content inspection by
<a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a>, <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>.
<b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#best_mx_transport">best_mx_transport</a> (empty)</b>
- Where the Postfix SMTP client should deliver mail
+ Where the Postfix SMTP client should deliver mail
when it detects a "mail loops back to myself" error
condition.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
<b><a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a> (no)</b>
- Disable DNS lookups in the Postfix SMTP and LMTP
+ Disable DNS lookups in the Postfix SMTP and LMTP
clients.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
tem receives mail on.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#lmtp_assume_final">lmtp_assume_final</a> (no)</b>
- When an LMTP server announces no DSN support,
+ When an LMTP server announces no DSN support,
assume that the server performs final delivery, and
- send "delivered" delivery status notifications
+ send "delivered" delivery status notifications
instead of "relayed".
<b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a> (24)</b>
- The default TCP port that the Postfix LMTP client
+ The default TCP port that the Postfix LMTP client
connects to.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
<b><a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> (ipv6)</b>
The address type ("ipv6", "ipv4" or "any") that the
Postfix SMTP client will try first, when a destina-
- tion has IPv6 and IPv4 addresses with equal MX
+ tion has IPv6 and IPv4 addresses with equal MX
preference.
<b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
- An optional numerical network address that the
- Postfix SMTP client should bind to when making an
+ An optional numerical network address that the
+ Postfix SMTP client should bind to when making an
IPv4 connection.
<b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
- An optional numerical network address that the
- Postfix SMTP client should bind to when making an
+ An optional numerical network address that the
+ Postfix SMTP client should bind to when making an
IPv6 connection.
<b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The hostname to send in the SMTP EHLO or HELO com-
+ The hostname to send in the SMTP EHLO or HELO com-
mand.
<b><a href="postconf.5.html#lmtp_lhlo_name">lmtp_lhlo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The hostname to send in the LMTP LHLO command.
<b><a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a> (dns)</b>
- What mechanisms the Postfix SMTP client uses to
+ What mechanisms the Postfix SMTP client uses to
look up a host's IP address.
<b><a href="postconf.5.html#smtp_randomize_addresses">smtp_randomize_addresses</a> (yes)</b>
- Randomize the order of equal-preference MX host
+ Randomize the order of equal-preference MX host
addresses.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available with Postfix 2.2 and earlier:
<b><a href="postconf.5.html#fallback_relay">fallback_relay</a> (empty)</b>
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
Available with Postfix 2.3 and later:
<b><a href="postconf.5.html#smtp_fallback_relay">smtp_fallback_relay</a> ($<a href="postconf.5.html#fallback_relay">fallback_relay</a>)</b>
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
<b>SEE ALSO</b>
<a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
The elliptic curve used by the SMTP server for max-
imally strong ephemeral ECDH key exchange.
+ Available in Postfix version 2.8 and later:
+
+ <b><a href="postconf.5.html#tls_preempts_cipherlist">tls_preempt_cipherlist</a> (no)</b>
+ With SSLv3 and later, use the server's cipher pref-
+ erence order instead of the client's cipher prefer-
+ ence order.
+
+ <b><a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> (see 'postconf -d' output)</b>
+ List or bit-mask of OpenSSL bug work-arounds to
+ disable.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
- The following configuration parameters exist for compati-
+ The following configuration parameters exist for compati-
bility with Postfix versions before 2.3. Support for these
will be removed in a future release.
<b><a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> (no)</b>
- Opportunistic TLS: announce STARTTLS support to
- SMTP clients, but do not require that clients use
+ Opportunistic TLS: announce STARTTLS support to
+ SMTP clients, but do not require that clients use
TLS encryption.
<b><a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> (no)</b>
- Mandatory TLS: announce STARTTLS support to SMTP
- clients, and require that clients use TLS encryp-
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
tion.
<b><a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> (empty)</b>
server TLS cipher list.
<b>VERP SUPPORT CONTROLS</b>
- With VERP style delivery, each recipient of a message
+ With VERP style delivery, each recipient of a message
receives a customized copy of the message with his/her own
- recipient address encoded in the envelope sender address.
+ recipient address encoded in the envelope sender address.
The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
- details of Postfix support for variable envelope return
+ details of Postfix support for variable envelope return
path addresses. VERP style delivery is requested with the
- SMTP XVERP command or with the "sendmail -V" command-line
- option and is available in Postfix version 1.1 and later.
+ SMTP XVERP command or with the "sendmail -V" command-line
+ option and is available in Postfix version 1.1 and later.
<b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
The two default VERP delimiter characters.
<b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
- The characters Postfix accepts as VERP delimiter
- characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+ The characters Postfix accepts as VERP delimiter
+ characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
and in SMTP commands.
Available in Postfix version 1.1 and 2.0:
<b><a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_verp_clients">smtpd_authorized_verp_clients</a> ($<a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
<b>TROUBLE SHOOTING CONTROLS</b>
- The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
- the Postfix mail system. The methods vary from making the
- software log a lot of detail, to running some daemon pro-
+ The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
+ the Postfix mail system. The methods vary from making the
+ software log a lot of detail, to running some daemon pro-
cesses under control of a call tracer or debugger.
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
<b><a href="postconf.5.html#internal_mail_filter_classes">internal_mail_filter_classes</a> (empty)</b>
- What categories of Postfix-generated mail are sub-
- ject to before-queue content inspection by
+ What categories of Postfix-generated mail are sub-
+ ject to before-queue content inspection by
<a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a>, <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>.
<b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a> (empty)</b>
- What SMTP clients are allowed to use the XCLIENT
+ What SMTP clients are allowed to use the XCLIENT
feature.
<b>KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS</b>
- As of Postfix version 2.0, the SMTP server rejects mail
- for unknown recipients. This prevents the mail queue from
- clogging up with undeliverable MAILER-DAEMON messages.
- Additional information on this topic is in the
+ As of Postfix version 2.0, the SMTP server rejects mail
+ for unknown recipients. This prevents the mail queue from
+ clogging up with undeliverable MAILER-DAEMON messages.
+ Additional information on this topic is in the
<a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a> and <a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a> documents.
<b><a href="postconf.5.html#show_user_unknown_table_name">show_user_unknown_table_name</a> (yes)</b>
- Display the name of the recipient table in the
+ Display the name of the recipient table in the
"User unknown" responses.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for message
+ Optional address mapping lookup tables for message
headers and envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, local-</b>
<b>host)</b>
- The list of domains that are delivered via the
+ The list of domains that are delivered via the
$<a href="postconf.5.html#local_transport">local_transport</a> mail delivery transport.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
<b><a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> (<a href="proxymap.8.html">proxy</a>:unix:passwd.byname</b>
<b>$<a href="postconf.5.html#alias_maps">alias_maps</a>)</b>
- Lookup tables with all names or addresses of local
- recipients: a recipient address is local when its
- domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
+ Lookup tables with all names or addresses of local
+ recipients: a recipient address is local when its
+ domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
<b><a href="postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is local, and
- $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
+ The numerical Postfix SMTP server response code
+ when a recipient address is local, and
+ $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient.
- Parameters concerning known/unknown recipients of relay
+ Parameters concerning known/unknown recipients of relay
destinations:
<b><a href="postconf.5.html#relay_domains">relay_domains</a> ($<a href="postconf.5.html#mydestination">mydestination</a>)</b>
- What destination domains (and subdomains thereof)
+ What destination domains (and subdomains thereof)
this system will relay mail to.
<b><a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#unknown_relay_recipient_reject_code">unknown_relay_recipient_reject_code</a> (550)</b>
The numerical Postfix SMTP server reply code when a
- recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
- <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
+ recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
+ <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
alias domains:
<b><a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> ($<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)</b>
Postfix is final destination for the specified list
- of virtual alias domains, that is, domains for
- which all addresses are aliased to addresses in
+ of virtual alias domains, that is, domains for
+ which all addresses are aliased to addresses in
other local or remote domains.
<b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
- Optional lookup tables that alias specific mail
- addresses or domains to other local or remote
+ Optional lookup tables that alias specific mail
+ addresses or domains to other local or remote
address.
<b><a href="postconf.5.html#unknown_virtual_alias_reject_code">unknown_virtual_alias_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
- <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
+ matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
+ <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
mailbox domains:
<b><a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> ($<a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a>)</b>
Postfix is final destination for the specified list
- of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
+ of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
<a href="postconf.5.html#virtual_transport">tual_transport</a> mail delivery transport.
<b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
<b><a href="postconf.5.html#unknown_virtual_mailbox_reject_code">unknown_virtual_mailbox_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
+ matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
<a href="postconf.5.html#virtual_mailbox_maps">tual_mailbox_maps</a> specifies a list of lookup tables
that does not match the recipient address.
<b>RESOURCE AND RATE CONTROLS</b>
- The following parameters limit resource usage by the SMTP
+ The following parameters limit resource usage by the SMTP
server and/or control client request rates.
<b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
- Upon input, long lines are chopped up into pieces
- of at most this length; upon delivery, long lines
+ Upon input, long lines are chopped up into pieces
+ of at most this length; upon delivery, long lines
are reconstructed.
<b><a href="postconf.5.html#queue_minfree">queue_minfree</a> (0)</b>
- The minimal amount of free space in bytes in the
+ The minimal amount of free space in bytes in the
queue file system that is needed to receive mail.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
- The maximal size in bytes of a message, including
+ The maximal size in bytes of a message, including
envelope information.
<b><a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a> (1000)</b>
- The maximal number of recipients that the Postfix
+ The maximal number of recipients that the Postfix
SMTP server accepts per message delivery request.
<b><a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> (normal: 300s, overload: 10s)</b>
- The time limit for sending a Postfix SMTP server
- response and for receiving a remote SMTP client
+ The time limit for sending a Postfix SMTP server
+ response and for receiving a remote SMTP client
request.
<b><a href="postconf.5.html#smtpd_history_flush_threshold">smtpd_history_flush_threshold</a> (100)</b>
- The maximal number of lines in the Postfix SMTP
- server command history before it is flushed upon
+ The maximal number of lines in the Postfix SMTP
+ server command history before it is flushed upon
receipt of EHLO, RSET, or end of DATA.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_peername_lookup">smtpd_peername_lookup</a> (yes)</b>
Attempt to look up the remote SMTP client hostname,
- and verify that the name matches the client IP
+ and verify that the name matches the client IP
address.
The per SMTP client connection count and request rate lim-
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
- vice, and are available in Postfix version 2.2 and later.
+ vice, and are available in Postfix version 2.2 and later.
<b><a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> (50)</b>
- How many simultaneous connections any client is
+ How many simultaneous connections any client is
allowed to make to this service.
<b><a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a> (0)</b>
The maximal number of connection attempts any
- client is allowed to make to this service per time
+ client is allowed to make to this service per time
unit.
<b><a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a> (0)</b>
- The maximal number of message delivery requests
- that any client is allowed to make to this service
+ The maximal number of message delivery requests
+ that any client is allowed to make to this service
per time unit, regardless of whether or not Postfix
actually accepts those messages.
<b><a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a> (0)</b>
- The maximal number of recipient addresses that any
- client is allowed to send to this service per time
+ The maximal number of recipient addresses that any
+ client is allowed to send to this service per time
unit, regardless of whether or not Postfix actually
accepts those recipients.
<b><a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- Clients that are excluded from
+ Clients that are excluded from
smtpd_client_*_count/rate_limit restrictions.
Available in Postfix version 2.3 and later:
tiate with this service per time unit.
<b>TARPIT CONTROLS</b>
- When a remote SMTP client makes errors, the Postfix SMTP
- server can insert delays before responding. This can help
- to slow down run-away software. The behavior is con-
- trolled by an error counter that counts the number of
- errors within an SMTP session that a client makes without
+ When a remote SMTP client makes errors, the Postfix SMTP
+ server can insert delays before responding. This can help
+ to slow down run-away software. The behavior is con-
+ trolled by an error counter that counts the number of
+ errors within an SMTP session that a client makes without
delivering mail.
<b><a href="postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time</a> (1s)</b>
With Postfix version 2.1 and later: the SMTP server
- response delay after a client has made more than
- $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
- $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
+ response delay after a client has made more than
+ $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
+ $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
mail.
<b><a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> (10)</b>
- The number of errors a remote SMTP client is
- allowed to make without delivering mail before the
+ The number of errors a remote SMTP client is
+ allowed to make without delivering mail before the
Postfix SMTP server slows down all its responses.
<b><a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> (normal: 20, overload: 1)</b>
- The maximal number of errors a remote SMTP client
+ The maximal number of errors a remote SMTP client
is allowed to make without delivering mail.
<b><a href="postconf.5.html#smtpd_junk_command_limit">smtpd_junk_command_limit</a> (normal: 100, overload: 1)</b>
- The number of junk commands (NOOP, VRFY, ETRN or
+ The number of junk commands (NOOP, VRFY, ETRN or
RSET) that a remote SMTP client can send before the
- Postfix SMTP server starts to increment the error
+ Postfix SMTP server starts to increment the error
counter with each junk command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_recipient_overshoot_limit">smtpd_recipient_overshoot_limit</a> (1000)</b>
- The number of recipients that a remote SMTP client
- can send in excess of the limit specified with
+ The number of recipients that a remote SMTP client
+ can send in excess of the limit specified with
$<a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a>, before the Postfix SMTP
- server increments the per-session error count for
+ server increments the per-session error count for
each excess recipient.
<b>ACCESS POLICY DELEGATION CONTROLS</b>
- As of version 2.1, Postfix can be configured to delegate
- access policy decisions to an external server that runs
- outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
+ As of version 2.1, Postfix can be configured to delegate
+ access policy decisions to an external server that runs
+ outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
more information.
<b><a href="postconf.5.html#smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a> (300s)</b>
- The time after which an idle SMTPD policy service
+ The time after which an idle SMTPD policy service
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_max_ttl">smtpd_policy_service_max_ttl</a> (1000s)</b>
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (100s)</b>
- The time limit for connecting to, writing to or
+ The time limit for connecting to, writing to or
receiving from a delegated SMTPD policy server.
<b>ACCESS CONTROLS</b>
- The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
+ The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
all the SMTP server access control features.
<b><a href="postconf.5.html#smtpd_delay_reject">smtpd_delay_reject</a> (yes)</b>
- Wait until the RCPT TO command before evaluating
+ Wait until the RCPT TO command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a>, $smtpd_helo_restric-
tions and $<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a>, or wait until
- the ETRN command before evaluating
+ the ETRN command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and $smtpd_helo_restric-
tions.
- <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
+ <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b>put)</b>
What Postfix features match subdomains of
"domain.tld" automatically, instead of requiring an
explicit ".domain.tld" pattern.
<b><a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client SMTP connection request.
<b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
Require that a remote SMTP client introduces itself
- with the HELO or EHLO command before sending the
- MAIL command or other commands that require EHLO
+ with the HELO or EHLO command before sending the
+ MAIL command or other commands that require EHLO
negotiation.
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the SMTP HELO command.
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the MAIL FROM command.
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
The access restrictions that the Postfix SMTP
- server applies in the context of the RCPT TO com-
+ server applies in the context of the RCPT TO com-
mand.
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client ETRN request.
<b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
- Forward mail with sender-specified routing
- (user[@%!]remote[@%!]site) from untrusted clients
+ Forward mail with sender-specified routing
+ (user[@%!]remote[@%!]site) from untrusted clients
to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
- User-defined aliases for groups of access restric-
+ User-defined aliases for groups of access restric-
tions.
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b><><b>)</b>
- The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
+ The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
instead of the null sender address.
<b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP
- access feature to only domains whose primary MX
+ access feature to only domains whose primary MX
hosts match the listed networks.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
+ Optional access restrictions that the Postfix SMTP
server applies in the context of the SMTP DATA com-
mand.
<b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
- What characters are allowed in $name expansions of
+ What characters are allowed in $name expansions of
RBL reply templates.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
- Request that the Postfix SMTP server rejects mail
- from unknown sender addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
+ Request that the Postfix SMTP server rejects mail
+ from unknown sender addresses, even when no
+ explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
is specified.
<b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
- Request that the Postfix SMTP server rejects mail
+ Request that the Postfix SMTP server rejects mail
for unknown recipient addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
+ explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
tion is specified.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
- server applies in the context of the SMTP END-OF-
+ Optional access restrictions that the Postfix SMTP
+ server applies in the context of the SMTP END-OF-
DATA command.
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
- Postfix version 2.1 introduces sender and recipient
- address verification. This feature is implemented by
- sending probe email messages that are not actually deliv-
- ered. This feature is requested via the reject_unveri-
- fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
- restrictions. The status of verification probes is main-
+ Postfix version 2.1 introduces sender and recipient
+ address verification. This feature is implemented by
+ sending probe email messages that are not actually deliv-
+ ered. This feature is requested via the reject_unveri-
+ fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
+ restrictions. The status of verification probes is main-
tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>-
- <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
+ <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
and operate the Postfix sender/recipient address verifica-
tion service.
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (normal: 3, overload: 1)</b>
- How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
- the completion of an address verification request
+ How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
+ the completion of an address verification request
in progress.
<b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
- The delay between queries for the completion of an
+ The delay between queries for the completion of an
address verification request in progress.
<b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b>
- The sender address to use in address verification
+ The sender address to use in address verification
probes; prior to Postfix 2.5 the default was "post-
master".
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is rejected by the
+ The numerical Postfix SMTP server response code
+ when a recipient address is rejected by the
<a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
<b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response when a
+ The numerical Postfix SMTP server response when a
recipient address is rejected by the reject_unveri-
fied_recipient restriction.
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender address probe fails due to a tempo-
+ The numerical Postfix SMTP server response code
+ when a sender address probe fails due to a tempo-
rary error condition.
<b><a href="postconf.5.html#unverified_recipient_defer_code">unverified_recipient_defer_code</a> (450)</b>
- The numerical Postfix SMTP server response when a
- recipient address probe fails due to a temporary
+ The numerical Postfix SMTP server response when a
+ recipient address probe fails due to a temporary
error condition.
<b><a href="postconf.5.html#unverified_sender_reject_reason">unverified_sender_reject_reason</a> (empty)</b>
<b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unver</a>-
- <a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
+ <a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
tion.
<b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
dition.
<b>ACCESS CONTROL RESPONSES</b>
- The following parameters control numerical SMTP reply
+ The following parameters control numerical SMTP reply
codes and/or text responses.
<b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
an <a href="access.5.html"><b>access</b>(5)</a> map "reject" action.
<b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "defer" restriction.
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
- The numerical Postfix SMTP server response code
- when the client HELO or EHLO command parameter is
- rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
+ The numerical Postfix SMTP server response code
+ when the client HELO or EHLO command parameter is
+ rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
restriction.
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
<a href="postconf.5.html#reject_rhsbl_reverse_client">reject_rhsbl_reverse_client</a>, <a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
The numerical Postfix SMTP server reply code when a
- client request is rejected by the
+ client request is rejected by the
<a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
<a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
restriction.
<b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a request is rejected by the <b>reject_plain-</b>
+ The numerical Postfix SMTP server response code
+ when a request is rejected by the <b>reject_plain-</b>
<b>text_session</b> restriction.
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "reject" restriction.
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a client request is rejected by the
+ The numerical Postfix SMTP server response code
+ when a client request is rejected by the
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender or recipient address is rejected by
+ The numerical Postfix SMTP server response code
+ when a sender or recipient address is rejected by
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a client without valid address <=> name map-
+ The numerical Postfix SMTP server response code
+ when a client without valid address <=> name map-
ping is rejected by the reject_unknown_client_host-
name restriction.
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when the hostname specified with the HELO or EHLO
- command is rejected by the
+ The numerical Postfix SMTP server response code
+ when the hostname specified with the HELO or EHLO
+ command is rejected by the
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
- The default SMTP server response template for a
- request that is rejected by an RBL-based restric-
+ The default SMTP server response template for a
+ request that is rejected by an RBL-based restric-
tion.
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
<b><a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> (450)</b>
The numerical Postfix SMTP server response code for
- an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
+ an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
"<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or "<a href="postconf.5.html#defer_if_reject">defer_if_reject</a>".
<b><a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a> (<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>)</b>
The Postfix SMTP server's action when a reject-type
- restriction fails due to a temporary error condi-
+ restriction fails due to a temporary error condi-
tion.
<b><a href="postconf.5.html#unknown_helo_hostname_tempfail_action">unknown_helo_hostname_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
- The Postfix SMTP server's action when
+ The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> fails due to an tempo-
rary error condition.
<b><a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
- The Postfix SMTP server's action when
+ The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
- <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
+ <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
porary error condition.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
and most Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
The internet hostname of this mail system.
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
- The list of "trusted" SMTP clients that have more
+ The list of "trusted" SMTP clients that have more
privileges than "strangers".
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
sions (user+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
- The text that follows the 220 status code in the
+ The text that follows the 220 status code in the
SMTP greeting banner.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
List of commands that cause the Postfix SMTP server
- to immediately terminate the session with a 221
+ to immediately terminate the session with a 221
code.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b>
- Enable logging of the remote SMTP client port in
+ Enable logging of the remote SMTP client port in
addition to the hostname and IP address.
<b>SEE ALSO</b>
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title> Postfix manual - tlsproxy(8) </title>
+</head> <body> <pre>
+TLSPROXY(8) TLSPROXY(8)
+
+<b>NAME</b>
+ tlsproxy - Postfix TLS proxy
+
+<b>SYNOPSIS</b>
+ <b>tlsproxy</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+ The <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server implements a server-side TLS proxy.
+ Its primary use is to talk plaintext SMTP with
+ <a href="postscreen.8.html"><b>postscreen</b>(8)</a>, and to talk SMTP-over-TLS with remote SMTP
+ clients whose whitelist status has expired, but it should
+ also work for non-SMTP protocols.
+
+ Although one <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> process can serve multiple ses-
+ sions at the same time, it is a good idea to allow the
+ number of processes to increase with load, so that the
+ service remains available.
+
+<b>PROTOCOL EXAMPLE</b>
+ The example below involves <a href="postscreen.8.html"><b>postscreen</b>(8)</a>. However, the
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server is agnostic of the application proto-
+ col, and the example is easily adapted to other applica-
+ tions.
+
+ The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server sends the remote SMTP client end-
+ point string, the requested role (server), and the
+ requested timeout to <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>. <a href="postscreen.8.html"><b>postscreen</b>(8)</a> then
+ receives a "TLS available" indication from <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>.
+ If the TLS service is available, <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends the
+ remote SMTP client file descriptor to <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>, and
+ sends the plaintext 220 greeting to the remote SMTP
+ client. This triggers TLS negotiations between the remote
+ SMTP client and <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>. Upon completion of the TLS-
+ level handshake, <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> translates between plaintext
+ from/to <a href="postscreen.8.html"><b>postscreen</b>(8)</a> and ciphertext to/from the remote
+ SMTP client.
+
+<b>SECURITY</b>
+ The <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server is moderately security-sensitive.
+ It talks to untrusted clients on the network. The process
+ can be run chrooted at fixed low privilege.
+
+<b>DIAGNOSTICS</b>
+ Problems and transactions are logged to <b>syslogd</b>(8).
+
+<b>CONFIGURATION PARAMETERS</b>
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are not picked up automatically, as
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> processes may run for a long time depending on
+ mail server load. Use the command "<b>postfix reload</b>" to
+ speed up a change.
+
+ The text below provides only a parameter summary. See
+ <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
+
+<b>STARTTLS SUPPORT CONTROLS</b>
+ <b><a href="postconf.5.html#tlsproxy_tls_CAfile">tlsproxy_tls_CAfile</a> ($<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>)</b>
+ A file containing (PEM format) CA certificates of
+ root CAs trusted to sign either remote SMTP client
+ certificates or intermediate CA certificates.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_CApath">tlsproxy_tls_CApath</a> ($<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>)</b>
+ A directory containing (PEM format) CA certificates
+ of root CAs trusted to sign either remote SMTP
+ client certificates or intermediate CA certifi-
+ cates.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_always_issue_session_ids">tlsproxy_tls_always_issue_session_ids</a></b>
+ <b>($<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a>)</b>
+ Force the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server to issue a TLS
+ session id, even when TLS session caching is turned
+ off.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_ask_ccert">tlsproxy_tls_ask_ccert</a> ($<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>)</b>
+ Ask a remote SMTP client for a client certificate.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_ccert_verifydepth">tlsproxy_tls_ccert_verifydepth</a> ($<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verify</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_ccert_verifydepth">depth</a>)</b>
+ The verification depth for remote SMTP client cer-
+ tificates.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_cert_file">tlsproxy_tls_cert_file</a> ($<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA cer-
+ tificate in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_ciphers">tlsproxy_tls_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a>)</b>
+ The minimum TLS cipher grade that the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server will use with opportunistic TLS
+ encryption.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_dcert_file">tlsproxy_tls_dcert_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA cer-
+ tificate in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_dh1024_param_file">tlsproxy_tls_dh1024_param_file</a></b>
+ <b>($<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>)</b>
+ File with DH parameters that the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server should use with EDH ciphers.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_dh512_param_file">tlsproxy_tls_dh512_param_file</a></b>
+ <b>($<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>)</b>
+ File with DH parameters that the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server should use with EDH ciphers.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_dkey_file">tlsproxy_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA pri-
+ vate key in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_eccert_file">tlsproxy_tls_eccert_file</a> ($<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA cer-
+ tificate in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_eckey_file">tlsproxy_tls_eckey_file</a> ($<a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA pri-
+ vate key in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_eecdh_grade">tlsproxy_tls_eecdh_grade</a> ($<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a>)</b>
+ The Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server security grade for
+ ephemeral elliptic-curve Diffie-Hellman (EECDH) key
+ exchange.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_exclude_ciphers">tlsproxy_tls_exclude_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a>)</b>
+ List of ciphers or cipher types to exclude from the
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server cipher list at all TLS security
+ levels.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_fingerprint_digest">tlsproxy_tls_fingerprint_digest</a> ($<a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_finger</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_fingerprint_digest">print_digest</a>)</b>
+ The message digest algorithm used to construct
+ client-certificate fingerprints.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_key_file">tlsproxy_tls_key_file</a> ($<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a>)</b>
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA pri-
+ vate key in PEM format.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_loglevel">tlsproxy_tls_loglevel</a> ($<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a>)</b>
+ Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server log-
+ ging of TLS activity.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_mandatory_ciphers">tlsproxy_tls_mandatory_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_manda</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_mandatory_ciphers">tory_ciphers</a>)</b>
+ The minimum TLS cipher grade that the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server will use with mandatory TLS
+ encryption.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_mandatory_exclude_ciphers">tlsproxy_tls_mandatory_exclude_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_manda</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">tory_exclude_ciphers</a>)</b>
+ Additional list of ciphers or cipher types to
+ exclude from the <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server cipher list at
+ mandatory TLS security levels.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_mandatory_protocols">tlsproxy_tls_mandatory_protocols</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_manda</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_mandatory_protocols">tory_protocols</a>)</b>
+ The SSL/TLS protocols accepted by the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server with mandatory TLS encryption.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_protocols">tlsproxy_tls_protocols</a> ($<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a>)</b>
+ List of TLS protocols that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
+ server will exclude or include with opportunistic
+ TLS encryption.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_req_ccert">tlsproxy_tls_req_ccert</a> ($<a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a>)</b>
+ With mandatory TLS encryption, require a trusted
+ remote SMTP client certificate in order to allow
+ TLS connections to proceed.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> ($<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b>
+ The SMTP TLS security level for the Postfix
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server; when a non-empty value is spec-
+ ified, this overrides the obsolete parameters
+ <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> and <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>.
+
+ <b><a href="postconf.5.html#tlsproxy_tls_session_cache_timeout">tlsproxy_tls_session_cache_timeout</a> ($<a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_ses</a>-</b>
+ <b><a href="postconf.5.html#smtpd_tls_session_cache_timeout">sion_cache_timeout</a>)</b>
+ The expiration time of Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
+ TLS session cache information.
+
+<b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
+ These parameters are supported for compatibility with
+ <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy parameters.
+
+ <b><a href="postconf.5.html#tlsproxy_use_tls">tlsproxy_use_tls</a> ($<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b>
+ Opportunistic TLS: announce STARTTLS support to
+ SMTP clients, but do not require that clients use
+ TLS encryption.
+
+ <b><a href="postconf.5.html#tlsproxy_enforce_tls">tlsproxy_enforce_tls</a> ($<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b>
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
+ tion.
+
+<b>RESOURCE CONTROLS</b>
+ <b><a href="postconf.5.html#tlsproxy_watchdog_timeout">tlsproxy_watchdog_timeout</a> (10s)</b>
+ How much time a <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> process may take to
+ process local or remote I/O before it is terminated
+ by a built-in watchdog timer.
+
+<b>MISCELLANEOUS CONTROLS</b>
+ <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ <a href="master.5.html">master.cf</a> configuration files.
+
+ <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
+ The process ID of a Postfix command or daemon
+ process.
+
+ <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
+ The process name of a Postfix command or daemon
+ process.
+
+ <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
+ The syslog facility of Postfix logging.
+
+ <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
+ becomes, for example, "postfix/smtpd".
+
+<b>SEE ALSO</b>
+ <a href="postscreen.8.html">postscreen(8)</a>, Postfix zombie blocker
+ <a href="smtpd.8.html">smtpd(8)</a>, Postfix SMTP server
+ <a href="postconf.5.html">postconf(5)</a>, configuration parameters
+ syslogd(5), system logging
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this
+ software.
+
+<b>HISTORY</b>
+ This service was introduced with Postfix version 2.8.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ IBM T.J. Watson Research
+ P.O. Box 704
+ Yorktown Heights, NY 10598, USA
+
+ TLSPROXY(8)
+</pre> </body> </html>
man8/oqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \
man8/verify.8 man8/trace.8 man8/proxymap.8 man8/anvil.8 \
man8/scache.8 man8/discard.8 man8/tlsmgr.8 man8/postscreen.8 \
- man8/dnsblog.8
+ man8/dnsblog.8 man8/tlsproxy.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/postmulti.1 man1/postqueue.1 man1/postsuper.1 \
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman $? >$@
+man8/tlsproxy.8: ../src/tlsproxy/tlsproxy.c
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman $? >$@
+
man8/virtual.8: ../src/virtual/virtual.c
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
oqmgr(8), old Postfix queue manager
pickup(8), Postfix local mail pickup
pipe(8), deliver mail to non-Postfix command
-postscreen(8), Postfix SMTP triage server
+postscreen(8), Postfix zombie blocker
proxymap(8), Postfix lookup table proxy server
qmgr(8), Postfix queue manager
qmqpd(8), Postfix QMQP server
smtpd(8), Postfix SMTP server
spawn(8), run non-Postfix server
tlsmgr(8), Postfix TLS cache and randomness manager
+tlsproxy(8), Postfix TLS proxy server
trivial-rewrite(8), Postfix address rewriting
verify(8), Postfix address verification
virtual(8), Postfix virtual delivery agent
disable_vrfy_command for details.
.PP
This feature is available in Postfix 2.8.
+.SH postscreen_discard_ehlo_keyword_address_maps (default: $smtpd_discard_ehlo_keyword_address_maps)
+Lookup tables, indexed by the remote SMTP client address, with
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO response
+to a remote SMTP client. See smtpd_discard_ehlo_keywords for details.
+The table is not searched by hostname for robustness reasons.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH postscreen_discard_ehlo_keywords (default: $smtpd_discard_ehlo_keywords)
+A case insensitive list of EHLO keywords (pipelining, starttls,
+auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
+response to a remote SMTP client. See smtpd_discard_ehlo_keywords
+for details.
+.PP
+This feature is available in Postfix 2.8 and later.
.SH postscreen_dnsbl_action (default: ignore)
The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
DNSBL score is equal to or greater than a threshold (as defined
(seconds), m (minutes), h (hours), d (days), w (weeks).
.PP
This feature is available in Postfix 2.8.
+.SH postscreen_enforce_tls (default: $smtpd_enforce_tls)
+Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See smtpd_postscreen_enforce_tls
+for details.
+.PP
+This feature is available in Postfix 2.8 and later.
+Preferably, use postscreen_tls_security_level instead.
.SH postscreen_forbidden_commands (default: $smtpd_forbidden_commands)
List of commands that the \fBpostscreen\fR(8) server considers in
violation of the SMTP protocol. See smtpd_forbidden_commands for
receive a 421 reponse.
.PP
This feature is available in Postfix 2.8.
+.SH postscreen_tls_security_level (default: $smtpd_tls_security_level)
+The SMTP TLS security level for the \fBpostscreen\fR(8) server; when
+a non-empty value is specified, this overrides the obsolete parameters
+postscreen_use_tls and postscreen_enforce_tls. See smtpd_tls_security_level
+for details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH postscreen_use_tls (default: $smtpd_use_tls)
+Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption.
+.PP
+This feature is available in Postfix 2.8 and later.
+Preferably, use postscreen_tls_security_level instead.
.SH postscreen_watchdog_timeout (default: 10s)
How much time a \fBpostscreen\fR(8) process may take to respond to
an SMTP client command or to perform a cache operation before it
.IP \(bu
With Postfix versions 2.0 and earlier, the Postfix SMTP
server delays all responses by (number of errors) seconds.
-.SH smtpd_starttls_timeout (default: 300s)
+.SH smtpd_starttls_timeout (default: see "postconf -d" output)
The time limit for Postfix SMTP server write and read operations
-during TLS startup and shutdown handshake procedures.
+during TLS startup and shutdown handshake procedures. The current
+default value is stress-dependent. Before Postfix version 2.8, it
+was fixed at 300s.
.PP
This feature is available in Postfix 2.2 and later.
.SH smtpd_timeout (default: normal: 300s, overload: 10s)
(or 168bit) session key.
.PP
This feature is available in Postfix 2.2 and later.
+.SH tls_disable_workarounds (default: see "postconf -d" output)
+List or bit-mask of OpenSSL bug work-arounds to disable.
+.PP
+The OpenSSL toolkit includes a set of work-arounds for buggy SSL/TLS
+implementations. Applications, such as Postfix, that want to maximize
+interoperability ask the OpenSSL library to enable the full set of
+recommended work-arounds.
+.PP
+From time to time, it is discovered that a work-around creates a
+security issue, and should no longer be used. If upgrading OpenSSL
+to a fixed version is not an option or an upgrade is not available
+in a timely manner, or in closed environments where no buggy clients
+or servers exist, it may be appropriate to disable some or all of the
+OpenSSL interoperability work-arounds. This parameter specifies which
+bug work-arounds to disable.
+.PP
+If the value of the parameter is a hexadecimal long integer starting
+with "0x", the bug work-arounds corresponding to the bits specified in
+its value are removed from the \fBSSL_OP_ALL\fR work-around bit-mask
+(see openssl/ssl.h and SSL_CTX_\fBset_options\fR(3)). You can specify more
+bits than are present in SSL_OP_ALL, excess bits are ignored. Specifying
+0xFFFFFFFF disables all bug-workarounds on a 32-bit system. This should
+also be sufficient on 64-bit systems, until OpenSSL abandons support
+for 32-bit systems and starts using the high 32 bits of a 64-bit
+bug-workaround mask.
+.PP
+Otherwise, the parameter is a white-space or comma separated list
+of specific named bug work-arounds chosen from the list below. It
+is possible that your OpenSSL version includes new bug work-arounds
+added after your Postfix source code was last updated, in that case
+you can only disable one of these via the hexadecimal syntax above.
+.IP "\fBMICROSOFT_SESS_ID_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBNETSCAPE_CHALLENGE_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBLEGACY_SERVER_CONNECT\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBNETSCAPE_REUSE_CIPHER_CHANGE_BUG\fR also aliased as
+\fBCVE-2010-4180\fR. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.8q
+and OpenSSL 1.0.0c."
+.IP "\fBSSLREF2_REUSE_CERT_TYPE_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBMICROSOFT_BIG_SSLV3_BUFFER\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBMSIE_SSLV2_RSA_PADDING\fR also aliased as
+\fBCVE-2005-2969\fR. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h
+and OpenSSL 0.9.8a."
+.IP "\fBSSLEAY_080_CLIENT_DH_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBTLS_D5_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBTLS_BLOCK_PADDING_BUG\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBTLS_ROLLBACK_BUG\fRSee SSL_CTX_\fBset_options\fR(3). This is disabled
+in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6!"
+.IP "\fBDONT_INSERT_EMPTY_FRAGMENTS\fRSee SSL_CTX_\fBset_options\fR(3)"
+.IP "\fBCRYPTOPRO_TLSEXT_BUG\fRNew with GOST support in OpenSSL 1.0.0."
+This feature is available in Postfix 2.8 and later.
.SH tls_eecdh_strong_curve (default: prime256v1)
The elliptic curve used by the SMTP server for sensibly strong
ephemeral ECDH key exchange. This curve is used by the Postfix SMTP
change this setting.
.PP
This feature is available in Postfix 2.3 and later.
+.SH tls_preempt_cipherlist (default: no)
+With SSLv3 and later, use the server's cipher preference order
+instead of the client's cipher preference order.
+.PP
+By default, the OpenSSL server selects the client's most preferred
+cipher that the server supports. With SSLv3 and later, the server may
+choose its own most preferred cipher that is supported (offered) by
+the client. Setting "tls_preempt_cipherlist = yes" enables server cipher
+preferences.
+.PP
+While server cipher selection may in some cases lead to a more secure
+or performant cipher choice, there is some risk of interoperability
+issues. In the past, some SSL clients have listed lower priority ciphers
+that they did not implement correctly. If the server chooses a cipher
+that the client prefers less, it may select a cipher whose client
+implementation is flawed.
+.PP
+This feature is available in Postfix 2.8 and later, in combination
+with OpenSSL 0.9.7 and later.
.SH tls_random_bytes (default: 32)
The number of bytes that \fBtlsmgr\fR(8) reads from $tls_random_source
when (re)seeding the in-memory pseudo random number generator (PRNG)
gives timeout errors.
.PP
This feature is available in Postfix 2.2 and later.
+.SH tlsproxy_enforce_tls (default: $smtpd_enforce_tls)
+Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See smtpd_enforce_tls for
+further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_CAfile (default: $smtpd_tls_CAfile)
+A file containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See smtpd_tls_CAfile for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_CApath (default: $smtpd_tls_CApath)
+A directory containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See smtpd_tls_CApath for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_always_issue_session_ids (default: $smtpd_tls_always_issue_session_ids)
+Force the Postfix \fBtlsproxy\fR(8) server to issue a TLS session id,
+even when TLS session caching is turned off. See
+smtpd_tls_always_issue_session_ids for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_ask_ccert (default: $smtpd_tls_ask_ccert)
+Ask a remote SMTP client for a client certificate. See
+smtpd_tls_ask_ccert for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_ccert_verifydepth (default: $smtpd_tls_ccert_verifydepth)
+The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file. See smtpd_tls_ccert_verifydepth for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_cert_file (default: $smtpd_tls_cert_file)
+File with the Postfix \fBtlsproxy\fR(8) server RSA certificate in PEM
+format. This file may also contain the Postfix \fBtlsproxy\fR(8) server
+private RSA key. See smtpd_tls_cert_file for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_ciphers (default: $smtpd_tls_ciphers)
+The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+will use with opportunistic TLS encryption. See smtpd_tls_ciphers
+for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_dcert_file (default: $smtpd_tls_dcert_file)
+File with the Postfix \fBtlsproxy\fR(8) server DSA certificate in PEM
+format. This file may also contain the Postfix \fBtlsproxy\fR(8) server
+private DSA key. See smtpd_tls_dcert_file for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_dh1024_param_file (default: $smtpd_tls_dh1024_param_file)
+File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+should use with EDH ciphers. See smtpd_tls_dh1024_param_file for
+further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_dh512_param_file (default: $smtpd_tls_dh512_param_file)
+File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+should use with EDH ciphers. See smtpd_tls_dh512_param_file for
+further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_dkey_file (default: $smtpd_tls_dkey_file)
+File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM
+format. This file may be combined with the Postfix \fBtlsproxy\fR(8)
+server DSA certificate file specified with $smtpd_tls_dcert_file.
+See smtpd_tls_dkey_file for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_eccert_file (default: $smtpd_tls_eccert_file)
+File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in
+PEM format. This file may also contain the Postfix \fBtlsproxy\fR(8)
+server private ECDSA key. See smtpd_tls_eccert_file for further
+details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_eckey_file (default: $smtpd_tls_eckey_file)
+File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in
+PEM format. This file may be combined with the Postfix \fBtlsproxy\fR(8)
+server ECDSA certificate file specified with $smtpd_tls_eccert_file.
+See smtpd_tls_eckey_file for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_eecdh_grade (default: $smtpd_tls_eecdh_grade)
+The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral
+elliptic-curve Diffie-Hellman (EECDH) key exchange. See
+smtpd_tls_eecdh_grade for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_exclude_ciphers (default: $smtpd_tls_exclude_ciphers)
+List of ciphers or cipher types to exclude from the \fBtlsproxy\fR(8)
+server cipher list at all TLS security levels. See
+smtpd_tls_exclude_ciphers for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_fingerprint_digest (default: $smtpd_tls_fingerprint_digest)
+The message digest algorithm used to construct client-certificate
+fingerprints. See smtpd_tls_fingerprint_digest for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_key_file (default: $smtpd_tls_key_file)
+File with the Postfix \fBtlsproxy\fR(8) server RSA private key in PEM
+format. This file may be combined with the Postfix \fBtlsproxy\fR(8)
+server RSA certificate file specified with $smtpd_tls_cert_file.
+See smtpd_tls_key_file for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_loglevel (default: $smtpd_tls_loglevel)
+Enable additional Postfix \fBtlsproxy\fR(8) server logging of TLS
+activity. Each logging level also includes the information that
+is logged at a lower logging level. See smtpd_tls_loglevel for
+further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_mandatory_ciphers (default: $smtpd_tls_mandatory_ciphers)
+The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+will use with mandatory TLS encryption. See smtpd_tls_mandatory_ciphers
+for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_mandatory_exclude_ciphers (default: $smtpd_tls_mandatory_exclude_ciphers)
+Additional list of ciphers or cipher types to exclude from the
+\fBtlsproxy\fR(8) server cipher list at mandatory TLS security levels.
+See smtpd_tls_mandatory_exclude_ciphers for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_mandatory_protocols (default: $smtpd_tls_mandatory_protocols)
+The SSL/TLS protocols accepted by the Postfix \fBtlsproxy\fR(8) server
+with mandatory TLS encryption. If the list is empty, the server
+supports all available SSL/TLS protocol versions. See
+smtpd_tls_mandatory_protocols for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_protocols (default: $smtpd_tls_protocols)
+List of TLS protocols that the Postfix \fBtlsproxy\fR(8) server will
+exclude or include with opportunistic TLS encryption. See
+smtpd_tls_protocols for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_req_ccert (default: $smtpd_tls_req_ccert)
+With mandatory TLS encryption, require a trusted remote SMTP
+client certificate in order to allow TLS connections to proceed.
+See smtpd_tls_req_ccert for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_security_level (default: $smtpd_tls_security_level)
+The SMTP TLS security level for the Postfix \fBtlsproxy\fR(8) server;
+when a non-empty value is specified, this overrides the obsolete
+parameters smtpd_use_tls and smtpd_enforce_tls. See
+smtpd_tls_security_level for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_session_cache_timeout (default: $smtpd_tls_session_cache_timeout)
+The expiration time of Postfix \fBtlsproxy\fR(8) server TLS session
+cache information. A cache cleanup is performed periodically every
+$smtpd_tls_session_cache_timeout seconds. See
+smtpd_tls_session_cache_timeout for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_use_tls (default: $smtpd_use_tls)
+Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. See smtpd_use_tls
+for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_watchdog_timeout (default: 10s)
+How much time a \fBtlsproxy\fR(8) process may take to process local
+or remote I/O before it is terminated by a built-in watchdog timer.
+This is a safety mechanism that prevents \fBtlsproxy\fR(8) from becoming
+non-responsive due to a bug in Postfix itself or in system software.
+To avoid false alarms and unnecessary cache corruption this limit
+cannot be set under 10s.
+.PP
+Specify a non-zero time value (an integral value plus an optional
+one-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks).
+.PP
+This feature is available in Postfix 2.8.
.SH trace_service_name (default: trace)
The name of the trace service. This service is implemented by the
\fBbounce\fR(8) daemon and maintains a record
.SH NAME
postscreen
\-
-Postfix SMTP triage server
+Postfix zombie blocker
.SH "SYNOPSIS"
.na
.nf
.SH "STANDARDS"
.na
.nf
-RFC 5321 (SMTP, including multi-line 220 greetings)
+RFC 821 (SMTP protocol)
+RFC 1123 (Host requirements)
+RFC 1652 (8bit-MIME transport)
+RFC 1869 (SMTP service extensions)
+RFC 1870 (Message Size Declaration)
+RFC 1985 (ETRN command)
+RFC 2034 (SMTP Enhanced Error Codes)
+RFC 2821 (SMTP protocol)
RFC 2920 (SMTP Pipelining)
+RFC 3207 (STARTTLS command)
+RFC 3461 (SMTP DSN Extension)
+RFC 3463 (Enhanced Status Codes)
+RFC 5321 (SMTP protocol, including multi-line 220 greetings)
.SH DIAGNOSTICS
.ad
.fi
.ad
.fi
The \fBpostscreen\fR(8) built-in SMTP protocol engine
-currently does not announce support for STARTTLS, AUTH,
-XCLIENT or XFORWARD.
-Support for STARTTLS and AUTH may be added in the future.
+currently does not announce support for AUTH, XCLIENT or
+XFORWARD.
+Support for AUTH may be added in the future.
In the mean time, if you need to make these services available
on port 25, then do not enable the optional "after 220
server greeting" tests.
The text below provides only a parameter summary. See
\fBpostconf\fR(5) for more details including examples.
-NOTE: Some \fBpostscreen\fR(8) parameters implement
+NOTE: Some \fBpostscreen\fR(8) parameters implement
stress-dependent behavior. This is supported only when the
-default value is stress-dependent (that is, it looks like
-${stress?X}${stress:Y}). Other parameters always evaluate
-as if the stress value is the empty string.
+default parameter value is stress-dependent (that is, it
+looks like ${stress?X}${stress:Y}, or it is the $\fIname\fR
+of an smtpd parameter with a stress-dependent default).
+Other parameters always evaluate as if the \fBstress\fR
+parameter value is the empty string.
+.SH "COMPATIBILITY CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBpostscreen_discard_ehlo_keyword_address_maps ($smtpd_discard_ehlo_keyword_address_maps)\fR"
+Lookup tables, indexed by the remote SMTP client address, with
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO response
+to a remote SMTP client.
+.IP "\fBpostscreen_discard_ehlo_keywords ($smtpd_discard_ehlo_keywords)\fR"
+A case insensitive list of EHLO keywords (pipelining, starttls,
+auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
+response to a remote SMTP client.
.SH "TRIAGE PARAMETERS"
.na
.nf
How much time a \fBpostscreen\fR(8) process may take to respond to
an SMTP client command or to perform a cache operation before it
is terminated by a built-in watchdog timer.
+.SH "STARTTLS CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBpostscreen_tls_security_level ($smtpd_tls_security_level)\fR"
+The SMTP TLS security level for the \fBpostscreen\fR(8) server; when
+a non-empty value is specified, this overrides the obsolete parameters
+postscreen_use_tls and postscreen_enforce_tls.
+.SH "OBSOLETE STARTTLS SUPPORT CONTROLS"
+.na
+.nf
+.ad
+.fi
+These parameters are supported for compatibility with
+\fBsmtpd\fR(8) legacy parameters.
+.IP "\fBpostscreen_use_tls ($smtpd_use_tls)\fR"
+Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption.
+.IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
+Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption.
.SH "MISCELLANEOUS CONTROLS"
.na
.nf
.na
.nf
smtpd(8), Postfix SMTP server
+tlsproxy(8), Postfix TLS proxy server
dnsblog(8), temporary DNS helper
syslogd(8), system logging
.SH "README FILES"
Try to detect a mail hijacking attack based on a TLS protocol
vulnerability (CVE-2009-3555), where an attacker prepends malicious
HELO, MAIL, RCPT, DATA commands to a Postfix SMTP client TLS session.
+.PP
+Available in Postfix version 2.8 and later:
+.IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
+List or bit-mask of OpenSSL bug work-arounds to disable.
.SH "OBSOLETE STARTTLS CONTROLS"
.na
.nf
.IP "\fBtls_eecdh_ultra_curve (secp384r1)\fR"
The elliptic curve used by the SMTP server for maximally strong
ephemeral ECDH key exchange.
+.PP
+Available in Postfix version 2.8 and later:
+.IP "\fBtls_preempt_cipherlist (no)\fR"
+With SSLv3 and later, use the server's cipher preference order
+instead of the client's cipher preference order.
+.IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
+List or bit-mask of OpenSSL bug work-arounds to disable.
.SH "OBSOLETE STARTTLS CONTROLS"
.na
.nf
--- /dev/null
+.TH TLSPROXY 8
+.ad
+.fi
+.SH NAME
+tlsproxy
+\-
+Postfix TLS proxy
+.SH "SYNOPSIS"
+.na
+.nf
+\fBtlsproxy\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+The \fBtlsproxy\fR(8) server implements a server-side TLS
+proxy. Its primary use is to talk plaintext SMTP with
+\fBpostscreen\fR(8), and to talk SMTP-over-TLS with remote
+SMTP clients whose whitelist status has expired, but it
+should also work for non-SMTP protocols.
+
+Although one \fBtlsproxy\fR(8) process can serve multiple
+sessions at the same time, it is a good idea to allow the
+number of processes to increase with load, so that the
+service remains available.
+.SH "PROTOCOL EXAMPLE"
+.na
+.nf
+.ad
+.fi
+The example below involves \fBpostscreen\fR(8). However,
+the \fBtlsproxy\fR(8) server is agnostic of the application
+protocol, and the example is easily adapted to other
+applications.
+
+The \fBpostscreen\fR(8) server sends the remote SMTP client
+endpoint string, the requested role (server), and the
+requested timeout to \fBtlsproxy\fR(8). \fBpostscreen\fR(8)
+then receives a "TLS available" indication from \fBtlsproxy\fR(8).
+If the TLS service is available, \fBpostscreen\fR(8) sends
+the remote SMTP client file descriptor to \fBtlsproxy\fR(8),
+and sends the plaintext 220 greeting to the remote SMTP
+client. This triggers TLS negotiations between the remote
+SMTP client and \fBtlsproxy\fR(8). Upon completion of the
+TLS-level handshake, \fBtlsproxy\fR(8) translates between
+plaintext from/to \fBpostscreen\fR(8) and ciphertext to/from
+the remote SMTP client.
+.SH "SECURITY"
+.na
+.nf
+.ad
+.fi
+The \fBtlsproxy\fR(8) server is moderately security-sensitive.
+It talks to untrusted clients on the network. The process
+can be run chrooted at fixed low privilege.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems and transactions are logged to \fBsyslogd\fR(8).
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+Changes to \fBmain.cf\fR are not picked up automatically,
+as \fBtlsproxy\fR(8) processes may run for a long time
+depending on mail server load. Use the command "\fBpostfix
+reload\fR" to speed up a change.
+
+The text below provides only a parameter summary. See
+\fBpostconf\fR(5) for more details including examples.
+.SH "STARTTLS SUPPORT CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBtlsproxy_tls_CAfile ($smtpd_tls_CAfile)\fR"
+A file containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates.
+.IP "\fBtlsproxy_tls_CApath ($smtpd_tls_CApath)\fR"
+A directory containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates.
+.IP "\fBtlsproxy_tls_always_issue_session_ids ($smtpd_tls_always_issue_session_ids)\fR"
+Force the Postfix \fBtlsproxy\fR(8) server to issue a TLS session id,
+even when TLS session caching is turned off.
+.IP "\fBtlsproxy_tls_ask_ccert ($smtpd_tls_ask_ccert)\fR"
+Ask a remote SMTP client for a client certificate.
+.IP "\fBtlsproxy_tls_ccert_verifydepth ($smtpd_tls_ccert_verifydepth)\fR"
+The verification depth for remote SMTP client certificates.
+.IP "\fBtlsproxy_tls_cert_file ($smtpd_tls_cert_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server RSA certificate in PEM
+format.
+.IP "\fBtlsproxy_tls_ciphers ($smtpd_tls_ciphers)\fR"
+The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+will use with opportunistic TLS encryption.
+.IP "\fBtlsproxy_tls_dcert_file ($smtpd_tls_dcert_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server DSA certificate in PEM
+format.
+.IP "\fBtlsproxy_tls_dh1024_param_file ($smtpd_tls_dh1024_param_file)\fR"
+File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+should use with EDH ciphers.
+.IP "\fBtlsproxy_tls_dh512_param_file ($smtpd_tls_dh512_param_file)\fR"
+File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+should use with EDH ciphers.
+.IP "\fBtlsproxy_tls_dkey_file ($smtpd_tls_dkey_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM
+format.
+.IP "\fBtlsproxy_tls_eccert_file ($smtpd_tls_eccert_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in
+PEM format.
+.IP "\fBtlsproxy_tls_eckey_file ($smtpd_tls_eckey_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in
+PEM format.
+.IP "\fBtlsproxy_tls_eecdh_grade ($smtpd_tls_eecdh_grade)\fR"
+The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral
+elliptic-curve Diffie-Hellman (EECDH) key exchange.
+.IP "\fBtlsproxy_tls_exclude_ciphers ($smtpd_tls_exclude_ciphers)\fR"
+List of ciphers or cipher types to exclude from the \fBtlsproxy\fR(8)
+server cipher list at all TLS security levels.
+.IP "\fBtlsproxy_tls_fingerprint_digest ($smtpd_tls_fingerprint_digest)\fR"
+The message digest algorithm used to construct client-certificate
+fingerprints.
+.IP "\fBtlsproxy_tls_key_file ($smtpd_tls_key_file)\fR"
+File with the Postfix \fBtlsproxy\fR(8) server RSA private key in PEM
+format.
+.IP "\fBtlsproxy_tls_loglevel ($smtpd_tls_loglevel)\fR"
+Enable additional Postfix \fBtlsproxy\fR(8) server logging of TLS
+activity.
+.IP "\fBtlsproxy_tls_mandatory_ciphers ($smtpd_tls_mandatory_ciphers)\fR"
+The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+will use with mandatory TLS encryption.
+.IP "\fBtlsproxy_tls_mandatory_exclude_ciphers ($smtpd_tls_mandatory_exclude_ciphers)\fR"
+Additional list of ciphers or cipher types to exclude from the
+\fBtlsproxy\fR(8) server cipher list at mandatory TLS security levels.
+.IP "\fBtlsproxy_tls_mandatory_protocols ($smtpd_tls_mandatory_protocols)\fR"
+The SSL/TLS protocols accepted by the Postfix \fBtlsproxy\fR(8) server
+with mandatory TLS encryption.
+.IP "\fBtlsproxy_tls_protocols ($smtpd_tls_protocols)\fR"
+List of TLS protocols that the Postfix \fBtlsproxy\fR(8) server will
+exclude or include with opportunistic TLS encryption.
+.IP "\fBtlsproxy_tls_req_ccert ($smtpd_tls_req_ccert)\fR"
+With mandatory TLS encryption, require a trusted remote SMTP
+client certificate in order to allow TLS connections to proceed.
+.IP "\fBtlsproxy_tls_security_level ($smtpd_tls_security_level)\fR"
+The SMTP TLS security level for the Postfix \fBtlsproxy\fR(8) server;
+when a non-empty value is specified, this overrides the obsolete
+parameters smtpd_use_tls and smtpd_enforce_tls.
+.IP "\fBtlsproxy_tls_session_cache_timeout ($smtpd_tls_session_cache_timeout)\fR"
+The expiration time of Postfix \fBtlsproxy\fR(8) server TLS session
+cache information.
+.SH "OBSOLETE STARTTLS SUPPORT CONTROLS"
+.na
+.nf
+.ad
+.fi
+These parameters are supported for compatibility with
+\fBsmtpd\fR(8) legacy parameters.
+.IP "\fBtlsproxy_use_tls ($smtpd_use_tls)\fR"
+Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption.
+.IP "\fBtlsproxy_enforce_tls ($smtpd_enforce_tls)\fR"
+Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption.
+.SH "RESOURCE CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBtlsproxy_watchdog_timeout (10s)\fR"
+How much time a \fBtlsproxy\fR(8) process may take to process local
+or remote I/O before it is terminated by a built-in watchdog timer.
+.SH "MISCELLANEOUS CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+The default location of the Postfix main.cf and master.cf
+configuration files.
+.IP "\fBprocess_id (read-only)\fR"
+The process ID of a Postfix command or daemon process.
+.IP "\fBprocess_name (read-only)\fR"
+The process name of a Postfix command or daemon process.
+.IP "\fBsyslog_facility (mail)\fR"
+The syslog facility of Postfix logging.
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+The mail system name that is prepended to the process name in syslog
+records, so that "smtpd" becomes, for example, "postfix/smtpd".
+.SH "SEE ALSO"
+.na
+.nf
+postscreen(8), Postfix zombie blocker
+smtpd(8), Postfix SMTP server
+postconf(5), configuration parameters
+syslogd(5), system logging
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH "HISTORY"
+.na
+.nf
+.ad
+.fi
+This service was introduced with Postfix version 2.8.
+.SH "AUTHOR(S)"
+.na
+.nf
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
s;\bsmtpd_data_restrictions\b;<a href="postconf.5.html#smtpd_data_restrictions">$&</a>;g;
s;\bsmtpd_delay_open_until_valid_rcpt\b;<a href="postconf.5.html#smtpd_delay_open_until_valid_rcpt">$&</a>;g;
s;\bsmtpd_delay_reject\b;<a href="postconf.5.html#smtpd_delay_reject">$&</a>;g;
- s;\bsmtpd_discard_ehlo_keyword_address_maps\b;<a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">$&</a>;g;
- s;\bsmtpd_discard_ehlo_keywords\b;<a href="postconf.5.html#smtpd_discard_ehlo_keywords">$&</a>;g;
+ s;\bsmtpd_dis[-</bB>]*\n* *[<bB>]*card_ehlo_key[-</bB>]*\n* *[<bB>]*word_address_maps\b;<a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">$&</a>;g;
+ s;\bsmtpd_dis[-</bB>]*\n* *[<bB>]*card_ehlo_key[-</bB>]*\n* *[<bB>]*words\b;<a href="postconf.5.html#smtpd_discard_ehlo_keywords">$&</a>;g;
s;\bsmtpd_end_of_data_restrictions\b;<a href="postconf.5.html#smtpd_end_of_data_restrictions">$&</a>;g;
s;\bsmtpd_error_sleep_time\b;<a href="postconf.5.html#smtpd_error_sleep_time">$&</a>;g;
s;\bsmtpd_etrn_restrictions\b;<a href="postconf.5.html#smtpd_etrn_restrictions">$&</a>;g;
s;\bsmtpd_tls_CApath\b;<a href="postconf.5.html#smtpd_tls_CApath">$&</a>;g;
s;\bsmtpd_tls_ask_ccert\b;<a href="postconf.5.html#smtpd_tls_ask_ccert">$&</a>;g;
s;\bsmtpd_tls_auth_only\b;<a href="postconf.5.html#smtpd_tls_auth_only">$&</a>;g;
- s;\bsmtpd_tls_ccert_verifydepth\b;<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">$&</a>;g;
+ s;\bsmtpd_tls_ccert_verify[-</bB>]*\n*[ <bB>]*depth\b;<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">$&</a>;g;
s;\bsmtpd_tls_cert_file\b;<a href="postconf.5.html#smtpd_tls_cert_file">$&</a>;g;
s;\bsmtpd_tls_cipherlist\b;<a href="postconf.5.html#smtpd_tls_cipherlist">$&</a>;g;
s;\bsmtpd_tls_exclude_ciphers\b;<a href="postconf.5.html#smtpd_tls_exclude_ciphers">$&</a>;g;
- s;\bsmtpd_tls_fingerprint_digest\b;<a href="postconf.5.html#smtpd_tls_fingerprint_digest">$&</a>;g;
+ s;\bsmtpd_tls_finger[-</bB>]*\n*[ <bB>]*print_digest\b;<a href="postconf.5.html#smtpd_tls_fingerprint_digest">$&</a>;g;
s;\bsmtpd_tls_protocols\b;<a href="postconf.5.html#smtpd_tls_protocols">$&</a>;g;
s;\bsmtpd_tls_ciphers\b;<a href="postconf.5.html#smtpd_tls_ciphers">$&</a>;g;
- s;\bsmtpd_tls_mandatory_ciphers\b;<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">$&</a>;g;
- s;\bsmtpd_tls_mandatory_exclude_ciphers\b;<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">$&</a>;g;
+ s;\bsmtpd_tls_manda[-</bB>]*\n*[ <bB>]*tory_ciphers\b;<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">$&</a>;g;
+ s;\bsmtpd_tls_manda[-</bB>]*\n*[ <bB>]*tory_exclude_ciphers\b;<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">$&</a>;g;
s;\bsmtpd_tls_dcert_file\b;<a href="postconf.5.html#smtpd_tls_dcert_file">$&</a>;g;
s;\bsmtpd_tls_eccert_file\b;<a href="postconf.5.html#smtpd_tls_eccert_file">$&</a>;g;
s;\bsmtpd_tls_eckey_file\b;<a href="postconf.5.html#smtpd_tls_eckey_file">$&</a>;g;
s;\bsmtpd_tls_key_file\b;<a href="postconf.5.html#smtpd_tls_key_file">$&</a>;g;
s;\bsmtpd_tls_security_level\b;<a href="postconf.5.html#smtpd_tls_security_level">$&</a>;g;
s;\bsmtpd_tls_loglevel\b;<a href="postconf.5.html#smtpd_tls_loglevel">$&</a>;g;
- s;\bsmtpd_tls_mandatory_protocols\b;<a href="postconf.5.html#smtpd_tls_mandatory_protocols">$&</a>;g;
+ s;\bsmtpd_tls_manda[-</bB>]*\n*[ <bB>]*tory_protocols\b;<a href="postconf.5.html#smtpd_tls_mandatory_protocols">$&</a>;g;
s;\bsmtpd_tls_received_header\b;<a href="postconf.5.html#smtpd_tls_received_header">$&</a>;g;
s;\bsmtpd_tls_req_ccert\b;<a href="postconf.5.html#smtpd_tls_req_ccert">$&</a>;g;
- s;\bsmtpd_tls_session_cache_database\b;<a href="postconf.5.html#smtpd_tls_session_cache_database">$&</a>;g;
- s;\bsmtpd_tls_session_cache_timeout\b;<a href="postconf.5.html#smtpd_tls_session_cache_timeout">$&</a>;g;
+ s;\bsmtpd_tls_ses[-</bB>]*\n*[ <bB>]*sion_cache_database\b;<a href="postconf.5.html#smtpd_tls_session_cache_database">$&</a>;g;
+ s;\bsmtpd_tls_ses[-</bB>]*\n*[ <bB>]*sion_cache_timeout\b;<a href="postconf.5.html#smtpd_tls_session_cache_timeout">$&</a>;g;
s;\bsmtpd_tls_always_issue_session_ids\b;<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">$&</a>;g;
s;\bsmtpd_tls_wrappermode\b;<a href="postconf.5.html#smtpd_tls_wrappermode">$&</a>;g;
s;\bsmtpd_use_tls\b;<a href="postconf.5.html#smtpd_use_tls">$&</a>;g;
s;\btls_null_cipherlist\b;<a href="postconf.5.html#tls_null_cipherlist">$&</a>;g;
s;\btls_eecdh_strong_curve\b;<a href="postconf.5.html#tls_eecdh_strong_curve">$&</a>;g;
s;\btls_eecdh_ultra_curve\b;<a href="postconf.5.html#tls_eecdh_ultra_curve">$&</a>;g;
+ s;\btls_preempt_cipherlist\b;<a href="postconf.5.html#tls_preempts_cipherlist">$&</a>;g;
+ s;\btls_disable_workarounds\b;<a href="postconf.5.html#tls_disable_workarounds">$&</a>;g;
s;\btls_append_default_CA\b;<a href="postconf.5.html#tls_append_default_CA">$&</a>;g;
s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
s/[<bB>]*smtp[<\/bB>]*\(8\)/<a href="smtp.8.html">$&<\/a>/g;
s/[<bB>]*smtpd[<\/bB>]*\(8\)/<a href="smtpd.8.html">$&<\/a>/g;
s/[<bB>]*spawn[<\/bB>]*\(8\)/<a href="spawn.8.html">$&<\/a>/g;
+ s/[<bB>]*tlsproxy[<\/bB>]*\(8\)/<a href="tlsproxy.8.html">$&<\/a>/g;
s/[<bB>]*tlsmgr[<\/bB>]*\(8\)/<a href="tlsmgr.8.html">$&<\/a>/g;
s/[<bB>]*trace[<\/bB>]*\(8\)/<a href="trace.8.html">$&<\/a>/g;
s/[<bB>]*trivial- *<br> *rewrite[<\/bB>]*\(8\)/<a href="trivial-rewrite.8.html">$&<\/a>/g;
s;\bpostscreen_black[-</bB>]*\n*[ <bB>]*list_networks\b;<a href="postconf.5.html#postscreen_blacklist_networks">$&</a>;g;
s;\bpostscreen_black[-</bB>]*\n*[ <bB>]*list_action\b;<a href="postconf.5.html#postscreen_blacklist_action">$&</a>;g;
s;\bpostscreen_client_connection_count_limit\b;<a href="postconf.5.html#postscreen_client_connection_count_limit">$&</a>;g;
+ s;\bpostscreen_tls_security_level\b;<a href="postconf.5.html#postscreen_tls_security_level">$&</a>;g;
+ s;\bpostscreen_enforce_tls\b;<a href="postconf.5.html#postscreen_enforce_tls">$&</a>;g;
+ s;\bpostscreen_use_tls\b;<a href="postconf.5.html#postscreen_use_tls">$&</a>;g;
+ s;\bpostscreen_discard_ehlo_keyword_address_maps\b;<a href="postconf.5.html#postscreen_discard_ehlo_keyword_address_maps">$&</a>;g;
+ s;\bpostscreen_discard_ehlo_keywords\b;<a href="postconf.5.html#postscreen_discard_ehlo_keywords">$&</a>;g;
+
+ s;\btlsproxy_watchdog_timeout\b;<a href="postconf.5.html#tlsproxy_watchdog_timeout">$&</a>;g;
+ s;\btlsproxy_enforce_tls\b;<a href="postconf.5.html#tlsproxy_enforce_tls">$&</a>;g;
+ s;\btlsproxy_tls_CAfile\b;<a href="postconf.5.html#tlsproxy_tls_CAfile">$&</a>;g;
+ s;\btlsproxy_tls_CApath\b;<a href="postconf.5.html#tlsproxy_tls_CApath">$&</a>;g;
+ s;\btlsproxy_tls_always_issue_session_ids\b;<a href="postconf.5.html#tlsproxy_tls_always_issue_session_ids">$&</a>;g;
+ s;\btlsproxy_tls_ask_ccert\b;<a href="postconf.5.html#tlsproxy_tls_ask_ccert">$&</a>;g;
+ s;\btlsproxy_tls_ccert_verifydepth\b;<a href="postconf.5.html#tlsproxy_tls_ccert_verifydepth">$&</a>;g;
+ s;\btlsproxy_tls_cert_file\b;<a href="postconf.5.html#tlsproxy_tls_cert_file">$&</a>;g;
+ s;\btlsproxy_tls_ciphers\b;<a href="postconf.5.html#tlsproxy_tls_ciphers">$&</a>;g;
+ s;\btlsproxy_tls_dcert_file\b;<a href="postconf.5.html#tlsproxy_tls_dcert_file">$&</a>;g;
+ s;\btlsproxy_tls_dh1024_param_file\b;<a href="postconf.5.html#tlsproxy_tls_dh1024_param_file">$&</a>;g;
+ s;\btlsproxy_tls_dh512_param_file\b;<a href="postconf.5.html#tlsproxy_tls_dh512_param_file">$&</a>;g;
+ s;\btlsproxy_tls_dkey_file\b;<a href="postconf.5.html#tlsproxy_tls_dkey_file">$&</a>;g;
+ s;\btlsproxy_tls_eccert_file\b;<a href="postconf.5.html#tlsproxy_tls_eccert_file">$&</a>;g;
+ s;\btlsproxy_tls_eckey_file\b;<a href="postconf.5.html#tlsproxy_tls_eckey_file">$&</a>;g;
+ s;\btlsproxy_tls_eecdh_grade\b;<a href="postconf.5.html#tlsproxy_tls_eecdh_grade">$&</a>;g;
+ s;\btlsproxy_tls_exclude_ciphers\b;<a href="postconf.5.html#tlsproxy_tls_exclude_ciphers">$&</a>;g;
+ s;\btlsproxy_tls_fingerprint_digest\b;<a href="postconf.5.html#tlsproxy_tls_fingerprint_digest">$&</a>;g;
+ s;\btlsproxy_tls_key_file\b;<a href="postconf.5.html#tlsproxy_tls_key_file">$&</a>;g;
+ s;\btlsproxy_tls_loglevel\b;<a href="postconf.5.html#tlsproxy_tls_loglevel">$&</a>;g;
+ s;\btlsproxy_tls_mandatory_ciphers\b;<a href="postconf.5.html#tlsproxy_tls_mandatory_ciphers">$&</a>;g;
+ s;\btlsproxy_tls_mandatory_exclude_ciphers\b;<a href="postconf.5.html#tlsproxy_tls_mandatory_exclude_ciphers">$&</a>;g;
+ s;\btlsproxy_tls_mandatory_protocols\b;<a href="postconf.5.html#tlsproxy_tls_mandatory_protocols">$&</a>;g;
+ s;\btlsproxy_tls_protocols\b;<a href="postconf.5.html#tlsproxy_tls_protocols">$&</a>;g;
+ s;\btlsproxy_tls_req_ccert\b;<a href="postconf.5.html#tlsproxy_tls_req_ccert">$&</a>;g;
+ s;\btlsproxy_tls_security_level\b;<a href="postconf.5.html#tlsproxy_tls_security_level">$&</a>;g;
+ s;\btlsproxy_tls_session_cache_timeout\b;<a href="postconf.5.html#tlsproxy_tls_session_cache_timeout">$&</a>;g;
+ s;\btlsproxy_use_tls\b;<a href="postconf.5.html#tlsproxy_use_tls">$&</a>;g;
# Hyperlink URLs and RFC documents
<blockquote>
<p>
-CAUTION: when postscreen rejects mail, it's SMTP reply contains the
+CAUTION: when postscreen rejects mail, its SMTP reply contains the
DNSBL domain name. Use the postscreen_dnsbl_reply_map feature to
hide "password" information in DNSBL domain names.
</p>
a relatively long expiration time. </p>
<li> <p> postscreen(8)'s built-in SMTP engine does not implement
-the AUTH, STARTTLS, XCLIENT, and XFORWARD features. STARTTLS and
-AUTH support may be added in a future version. In the mean time,
-if you need to make these services available on port 25, then do
-not enable the tests after the 220 server greeting. </p>
+the AUTH, XCLIENT, and XFORWARD features. AUTH support may be added
+in a future version. In the mean time, if you need to make these
+services available on port 25, then do not enable the tests after
+the 220 server greeting. </p>
</ul>
smtp inet n - n - 1 postscreen
</pre>
+<li> <p> Uncomment the new "<tt>tlsproxy unix ... tlsproxy</tt>"
+service in master.cf. This service implements STARTTLS support for
+postscreen(8). </p>
+
+<pre>
+/etc/postfix/master.cf:
+ tlsproxy unix - - n - 0 tlsproxy
+</pre>
+
<li> <p> Uncomment the new "<tt>dnsblog unix ... dnsblog</tt>"
service in master.cf. This service does DNSBL lookups for postscreen(8)
and logs results. </p>
<p> When the good client comes back in a later session, it is allowed
to talk directly to a Postfix SMTP server. See "after_220 <a
href="#after_220">Tests after the 220 SMTP server greeting</a> above
-for limitations with STARTTLS, AUTH and other features that clients
-may need. </p>
+for limitations with AUTH and other features that clients may need.
+</p>
<p> An unexpected benefit from "<a href="#after_220">deep protocol
tests</a>" is that some "good" clients don't return after the 4XX
# -o parameter=value ...
</pre>
+<li> <p> Comment out the "<tt>tlsproxy unix ... tlsproxy</tt>"
+service in master.cf, including any "<tt>-o parameter=value</tt>"
+entries that follow. </p>
+
+<pre>
+/etc/postfix/master.cf:
+ #tlsproxy unix - - n - 0 tlsproxy
+ # -o parameter=value ...
+</pre>
<li> <p> Uncomment the "<tt>smtp inet ... smtpd</tt>" service in
master.cf, including any "<tt>-o parameter=value</tt>" entries that
-follow. </p>
+may follow. </p>
<pre>
/etc/postfix/master.cf:
- smtp inet n - n - - smtpd
+ smtp inet n - n - - smtpd
-o parameter=value ...
</pre>
own code, every 1000 lines introduce one additional bug into
Postfix. </p>
+<p> At this time, you should no longer be using OpenSSL releases prior
+to the most recent 0.9.8 release unless all relevant security fixes have
+been backported to the earlier release by you or your O/S vendor. OpenSSL
+0.9.7 and earlier are no longer maintained by the OpenSSL team. </p>
+
<h2> What Postfix TLS support does for you </h2>
<p> Transport Layer Security (TLS, formerly called SSL) provides
</pre>
</blockquote>
+<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
+allows TLS servers to preempt the TLS client's cipher preference list.
+This is only possible with SSLv3, as in SSLv2 the client chooses the
+cipher from a list supplied by the server. </p>
+
+<p> By default, the OpenSSL server selects the client's most preferred
+cipher that the server supports. With SSLv3 and later, the server
+may choose its own most preferred cipher that is supported (offered)
+by the client. Setting "tls_preempt_cipherlist = yes" enables server
+cipher preferences. The default OpenSSL behaviour applies with
+"tls_preempt_cipherlist = no". </p>
+
+<p> While server cipher selection may in some cases lead to a more secure
+or performant cipher choice, there is some risk of interoperability
+issues. In the past, some SSL clients have listed lower priority ciphers
+that they did not implement correctly. If the server chooses a cipher
+that the client prefers less, it may select a cipher whose client
+implementation is flawed. </p>
+
<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
<p> The smtpd_starttls_timeout parameter limits the time of Postfix
</pre>
</blockquote>
+<p> With Postfix 2.8 and later, the tls_disable_workarounds parameter
+specifies a list or bit-mask of OpenSSL bug work-arounds to disable. This
+may be necessary if one of the work-arounds enabled by default in
+OpenSSL proves to pose a security risk, or introduces an unexpected
+interoperability issue. Some bug work-arounds known to be problematic
+are disabled in the default value of the parameter when linked with
+an OpenSSL library that could be vulnerable. </p>
+
+<p> Example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+ tls_disable_workarounds = 0xFFFFFFFF
+ tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
+</pre>
+</blockquote>
+
+<p> Note: Disabling LEGACY_SERVER_CONNECT is not wise at this
+time, lots of servers are still unpatched and Postfix is <a
+href="http://www.postfix.org/wip.html#tls-renegotiation">not
+significantly vulnerable</a> to the renegotiation issue in the TLS
+protocol. </p>
+
<h2> <a name="client_tls">SMTP Client specific settings</a> </h2>
<p> Topics covered in this section: </p>
<p>This feature is available with Postfix version 2.2.</p>
-%PARAM smtpd_starttls_timeout 300s
+%PARAM smtpd_starttls_timeout see "postconf -d" output
<p> The time limit for Postfix SMTP server write and read operations
-during TLS startup and shutdown handshake procedures. </p>
+during TLS startup and shutdown handshake procedures. The current
+default value is stress-dependent. Before Postfix version 2.8, it
+was fixed at 300s. </p>
<p> This feature is available in Postfix 2.2 and later. </p>
The default time unit is s (seconds).
</p>
+%PARAM tls_preempt_cipherlist no
+
+<p> With SSLv3 and later, use the server's cipher preference order
+instead of the client's cipher preference order. </p>
+
+<p> By default, the OpenSSL server selects the client's most preferred
+cipher that the server supports. With SSLv3 and later, the server may
+choose its own most preferred cipher that is supported (offered) by
+the client. Setting "tls_preempt_cipherlist = yes" enables server cipher
+preferences. </p>
+
+<p> While server cipher selection may in some cases lead to a more secure
+or performant cipher choice, there is some risk of interoperability
+issues. In the past, some SSL clients have listed lower priority ciphers
+that they did not implement correctly. If the server chooses a cipher
+that the client prefers less, it may select a cipher whose client
+implementation is flawed. </p>
+
+<p> This feature is available in Postfix 2.8 and later, in combination
+with OpenSSL 0.9.7 and later. </p>
+
+%PARAM tls_disable_workarounds see "postconf -d" output
+
+<p> List or bit-mask of OpenSSL bug work-arounds to disable. </p>
+
+<p> The OpenSSL toolkit includes a set of work-arounds for buggy SSL/TLS
+implementations. Applications, such as Postfix, that want to maximize
+interoperability ask the OpenSSL library to enable the full set of
+recommended work-arounds. </p>
+
+<p> From time to time, it is discovered that a work-around creates a
+security issue, and should no longer be used. If upgrading OpenSSL
+to a fixed version is not an option or an upgrade is not available
+in a timely manner, or in closed environments where no buggy clients
+or servers exist, it may be appropriate to disable some or all of the
+OpenSSL interoperability work-arounds. This parameter specifies which
+bug work-arounds to disable. </p>
+
+<p> If the value of the parameter is a hexadecimal long integer starting
+with "0x", the bug work-arounds corresponding to the bits specified in
+its value are removed from the <b>SSL_OP_ALL</b> work-around bit-mask
+(see openssl/ssl.h and SSL_CTX_set_options(3)). You can specify more
+bits than are present in SSL_OP_ALL, excess bits are ignored. Specifying
+0xFFFFFFFF disables all bug-workarounds on a 32-bit system. This should
+also be sufficient on 64-bit systems, until OpenSSL abandons support
+for 32-bit systems and starts using the high 32 bits of a 64-bit
+bug-workaround mask. </p>
+
+<p> Otherwise, the parameter is a white-space or comma separated list
+of specific named bug work-arounds chosen from the list below. It
+is possible that your OpenSSL version includes new bug work-arounds
+added after your Postfix source code was last updated, in that case
+you can only disable one of these via the hexadecimal syntax above. </p>
+
+<dl>
+<dt><b>MICROSOFT_SESS_ID_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>NETSCAPE_CHALLENGE_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>LEGACY_SERVER_CONNECT</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b> also aliased as
+<b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.8q
+and OpenSSL 1.0.0c.</dt>
+<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>MICROSOFT_BIG_SSLV3_BUFFER</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>MSIE_SSLV2_RSA_PADDING</b> also aliased as
+<b>CVE-2005-2969</b>. Postfix 2.8 disables this work-around by default
+with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h
+and OpenSSL 0.9.8a.</dt>
+<dt><b>SSLEAY_080_CLIENT_DH_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_D5_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_BLOCK_PADDING_BUG</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>TLS_ROLLBACK_BUG</b>See SSL_CTX_set_options(3). This is disabled
+in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6! </dt>
+<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b>See SSL_CTX_set_options(3)</dt>
+<dt><b>CRYPTOPRO_TLSEXT_BUG</b>New with GOST support in OpenSSL 1.0.0.</dt>
+</dl>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_watchdog_timeout 10s
+
+<p> How much time a tlsproxy(8) process may take to process local
+or remote I/O before it is terminated by a built-in watchdog timer.
+This is a safety mechanism that prevents tlsproxy(8) from becoming
+non-responsive due to a bug in Postfix itself or in system software.
+To avoid false alarms and unnecessary cache corruption this limit
+cannot be set under 10s. </p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
+one-letter suffix that specifies the time unit). Time units: s
+(seconds), m (minutes), h (hours), d (days), w (weeks). </p>
+
+<p> This feature is available in Postfix 2.8. </p>
+
+%PARAM postscreen_discard_ehlo_keywords $smtpd_discard_ehlo_keywords
+
+<p> A case insensitive list of EHLO keywords (pipelining, starttls,
+auth, etc.) that the postscreen(8) server will not send in the EHLO
+response to a remote SMTP client. See smtpd_discard_ehlo_keywords
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM postscreen_discard_ehlo_keyword_address_maps $smtpd_discard_ehlo_keyword_address_maps
+
+<p> Lookup tables, indexed by the remote SMTP client address, with
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the postscreen(8) server will not send in the EHLO response
+to a remote SMTP client. See smtpd_discard_ehlo_keywords for details.
+The table is not searched by hostname for robustness reasons. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM postscreen_use_tls $smtpd_use_tls
+
+<p> Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. </p>
+
+<p> This feature is available in Postfix 2.8 and later.
+Preferably, use postscreen_tls_security_level instead. </p>
+
+%PARAM postscreen_enforce_tls $smtpd_enforce_tls
+
+<p> Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See smtpd_postscreen_enforce_tls
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later.
+Preferably, use postscreen_tls_security_level instead. </p>
+
+%PARAM postscreen_tls_security_level $smtpd_tls_security_level
+
+<p> The SMTP TLS security level for the postscreen(8) server; when
+a non-empty value is specified, this overrides the obsolete parameters
+postscreen_use_tls and postscreen_enforce_tls. See smtpd_tls_security_level
+for details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_enforce_tls $smtpd_enforce_tls
+
+<p> Mandatory TLS: announce STARTTLS support to SMTP clients, and
+require that clients use TLS encryption. See smtpd_enforce_tls for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_CAfile $smtpd_tls_CAfile
+
+<p> A file containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See smtpd_tls_CAfile for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_CApath $smtpd_tls_CApath
+
+<p> A directory containing (PEM format) CA certificates of root CAs
+trusted to sign either remote SMTP client certificates or intermediate
+CA certificates. See smtpd_tls_CApath for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_always_issue_session_ids $smtpd_tls_always_issue_session_ids
+
+<p> Force the Postfix tlsproxy(8) server to issue a TLS session id,
+even when TLS session caching is turned off. See
+smtpd_tls_always_issue_session_ids for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_ask_ccert $smtpd_tls_ask_ccert
+
+<p> Ask a remote SMTP client for a client certificate. See
+smtpd_tls_ask_ccert for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_ccert_verifydepth $smtpd_tls_ccert_verifydepth
+
+<p> The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file. See smtpd_tls_ccert_verifydepth for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_cert_file $smtpd_tls_cert_file
+
+<p> File with the Postfix tlsproxy(8) server RSA certificate in PEM
+format. This file may also contain the Postfix tlsproxy(8) server
+private RSA key. See smtpd_tls_cert_file for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_ciphers $smtpd_tls_ciphers
+
+<p> The minimum TLS cipher grade that the Postfix tlsproxy(8) server
+will use with opportunistic TLS encryption. See smtpd_tls_ciphers
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_dcert_file $smtpd_tls_dcert_file
+
+<p> File with the Postfix tlsproxy(8) server DSA certificate in PEM
+format. This file may also contain the Postfix tlsproxy(8) server
+private DSA key. See smtpd_tls_dcert_file for further details.
+</p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_dh1024_param_file $smtpd_tls_dh1024_param_file
+
+<p> File with DH parameters that the Postfix tlsproxy(8) server
+should use with EDH ciphers. See smtpd_tls_dh1024_param_file for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_dh512_param_file $smtpd_tls_dh512_param_file
+
+<p> File with DH parameters that the Postfix tlsproxy(8) server
+should use with EDH ciphers. See smtpd_tls_dh512_param_file for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_dkey_file $smtpd_tls_dkey_file
+
+<p> File with the Postfix tlsproxy(8) server DSA private key in PEM
+format. This file may be combined with the Postfix tlsproxy(8)
+server DSA certificate file specified with $smtpd_tls_dcert_file.
+See smtpd_tls_dkey_file for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_eccert_file $smtpd_tls_eccert_file
+
+<p> File with the Postfix tlsproxy(8) server ECDSA certificate in
+PEM format. This file may also contain the Postfix tlsproxy(8)
+server private ECDSA key. See smtpd_tls_eccert_file for further
+details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_eckey_file $smtpd_tls_eckey_file
+
+<p> File with the Postfix tlsproxy(8) server ECDSA private key in
+PEM format. This file may be combined with the Postfix tlsproxy(8)
+server ECDSA certificate file specified with $smtpd_tls_eccert_file.
+See smtpd_tls_eckey_file for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_eecdh_grade $smtpd_tls_eecdh_grade
+
+<p> The Postfix tlsproxy(8) server security grade for ephemeral
+elliptic-curve Diffie-Hellman (EECDH) key exchange. See
+smtpd_tls_eecdh_grade for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_exclude_ciphers $smtpd_tls_exclude_ciphers
+
+<p> List of ciphers or cipher types to exclude from the tlsproxy(8)
+server cipher list at all TLS security levels. See
+smtpd_tls_exclude_ciphers for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_fingerprint_digest $smtpd_tls_fingerprint_digest
+
+<p> The message digest algorithm used to construct client-certificate
+fingerprints. See smtpd_tls_fingerprint_digest for further details.
+</p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_key_file $smtpd_tls_key_file
+
+<p> File with the Postfix tlsproxy(8) server RSA private key in PEM
+format. This file may be combined with the Postfix tlsproxy(8)
+server RSA certificate file specified with $smtpd_tls_cert_file.
+See smtpd_tls_key_file for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_loglevel $smtpd_tls_loglevel
+
+<p> Enable additional Postfix tlsproxy(8) server logging of TLS
+activity. Each logging level also includes the information that
+is logged at a lower logging level. See smtpd_tls_loglevel for
+further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_mandatory_ciphers $smtpd_tls_mandatory_ciphers
+
+<p> The minimum TLS cipher grade that the Postfix tlsproxy(8) server
+will use with mandatory TLS encryption. See smtpd_tls_mandatory_ciphers
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_mandatory_exclude_ciphers $smtpd_tls_mandatory_exclude_ciphers
+
+<p> Additional list of ciphers or cipher types to exclude from the
+tlsproxy(8) server cipher list at mandatory TLS security levels.
+See smtpd_tls_mandatory_exclude_ciphers for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_mandatory_protocols $smtpd_tls_mandatory_protocols
+
+<p> The SSL/TLS protocols accepted by the Postfix tlsproxy(8) server
+with mandatory TLS encryption. If the list is empty, the server
+supports all available SSL/TLS protocol versions. See
+smtpd_tls_mandatory_protocols for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_protocols $smtpd_tls_protocols
+
+<p> List of TLS protocols that the Postfix tlsproxy(8) server will
+exclude or include with opportunistic TLS encryption. See
+smtpd_tls_protocols for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_req_ccert $smtpd_tls_req_ccert
+
+<p> With mandatory TLS encryption, require a trusted remote SMTP
+client certificate in order to allow TLS connections to proceed.
+See smtpd_tls_req_ccert for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_security_level $smtpd_tls_security_level
+
+<p> The SMTP TLS security level for the Postfix tlsproxy(8) server;
+when a non-empty value is specified, this overrides the obsolete
+parameters smtpd_use_tls and smtpd_enforce_tls. See
+smtpd_tls_security_level for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_tls_session_cache_timeout $smtpd_tls_session_cache_timeout
+
+<p> The expiration time of Postfix tlsproxy(8) server TLS session
+cache information. A cache cleanup is performed periodically every
+$smtpd_tls_session_cache_timeout seconds. See
+smtpd_tls_session_cache_timeout for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM tlsproxy_use_tls $smtpd_use_tls
+
+<p> Opportunistic TLS: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. See smtpd_use_tls
+for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
* can switch between Postfix versions without trouble.
*/
return (name_mask_opt("ehlo string mask", ehlo_mask_table,
- mask_str, NAME_MASK_ANY_CASE));
+ mask_str, NAME_MASK_ANY_CASE | NAME_MASK_IGNORE));
}
/* str_ehlo_mask - mask to string */
extern int var_smtpd_tmout;
#define VAR_SMTPD_STARTTLS_TMOUT "smtpd_starttls_timeout"
-#define DEF_SMTPD_STARTTLS_TMOUT "300s"
+#define DEF_SMTPD_STARTTLS_TMOUT "${stress?10}${stress:300}s"
extern int var_smtpd_starttls_tmout;
#define VAR_SMTPD_RCPT_LIMIT "smtpd_recipient_limit"
#define DEF_TLS_EECDH_ULTRA "secp384r1"
extern char *var_tls_eecdh_ultra;
+#define VAR_TLS_PREEMPT_CLIST "tls_preempt_cipherlist"
+#define DEF_TLS_PREEMPT_CLIST 0
+extern bool var_tls_preempt_clist;
+
+#ifdef USE_TLS
+
+ /*
+ * The tweak for CVE-2005-2969 is needed in some versions prior to 1.0.0
+ */
+#if (OPENSSL_VERSION_NUMBER < 0x1000000fL)
+#define TLS_BUG_TWEAK_A " CVE-2005-2969"
+#else
+#define TLS_BUG_TWEAK_A ""
+#endif
+
+ /*
+ * The tweak for CVE-2010-4180 is needed in some versions prior to 1.0.1
+ */
+#if (OPENSSL_VERSION_NUMBER < 0x1000100fL)
+#define TLS_BUG_TWEAK_B " CVE-2010-4180"
+#else
+#define TLS_BUG_TWEAK_B " "
+#endif
+
+#else /* USE_TLS */
+#define TLS_BUG_TWEAK_A ""
+#define TLS_BUG_TWEAK_B " "
+#endif /* USE_TLS */
+
+#define VAR_TLS_BUG_TWEAKS "tls_disable_workarounds"
+#define DEF_TLS_BUG_TWEAKS ((TLS_BUG_TWEAK_A TLS_BUG_TWEAK_B)+1)
+extern char *var_tls_bug_tweaks;
+
/*
* Sendmail-style mail filter support.
*/
/*
* postscreen(8)
*/
-#define VAR_PS_CACHE_MAP "postscreen_cache_map"
-#define DEF_PS_CACHE_MAP "btree:$data_directory/ps_cache"
-extern char *var_ps_cache_map;
+#define VAR_PSC_CACHE_MAP "postscreen_cache_map"
+#define DEF_PSC_CACHE_MAP "btree:$data_directory/psc_cache"
+extern char *var_psc_cache_map;
#define VAR_SMTPD_SERVICE "smtpd_service"
#define DEF_SMTPD_SERVICE "smtpd"
extern char *var_smtpd_service;
-#define VAR_PS_POST_QLIMIT "postscreen_post_queue_limit"
-#define DEF_PS_POST_QLIMIT "$" VAR_PROC_LIMIT
-extern int var_ps_post_queue_limit;
+#define VAR_PSC_POST_QLIMIT "postscreen_post_queue_limit"
+#define DEF_PSC_POST_QLIMIT "$" VAR_PROC_LIMIT
+extern int var_psc_post_queue_limit;
+
+#define VAR_PSC_PRE_QLIMIT "postscreen_pre_queue_limit"
+#define DEF_PSC_PRE_QLIMIT "$" VAR_PROC_LIMIT
+extern int var_psc_pre_queue_limit;
+
+#define VAR_PSC_CACHE_RET "postscreen_cache_retention_time"
+#define DEF_PSC_CACHE_RET "7d"
+extern int var_psc_cache_ret;
+
+#define VAR_PSC_CACHE_SCAN "postscreen_cache_cleanup_interval"
+#define DEF_PSC_CACHE_SCAN "12h"
+extern int var_psc_cache_scan;
-#define VAR_PS_PRE_QLIMIT "postscreen_pre_queue_limit"
-#define DEF_PS_PRE_QLIMIT "$" VAR_PROC_LIMIT
-extern int var_ps_pre_queue_limit;
+#define VAR_PSC_GREET_WAIT "postscreen_greet_wait"
+#define DEF_PSC_GREET_WAIT "${stress?2}${stress:6}s"
+extern int var_psc_greet_wait;
-#define VAR_PS_CACHE_RET "postscreen_cache_retention_time"
-#define DEF_PS_CACHE_RET "7d"
-extern int var_ps_cache_ret;
+#define VAR_PSC_PREGR_BANNER "postscreen_greet_banner"
+#define DEF_PSC_PREGR_BANNER "$" VAR_SMTPD_BANNER
+extern char *var_psc_pregr_banner;
-#define VAR_PS_CACHE_SCAN "postscreen_cache_cleanup_interval"
-#define DEF_PS_CACHE_SCAN "12h"
-extern int var_ps_cache_scan;
+#define VAR_PSC_PREGR_ENABLE "postscreen_greet_enable"
+#define DEF_PSC_PREGR_ENABLE no
+extern char *var_psc_pregr_enable;
-#define VAR_PS_GREET_WAIT "postscreen_greet_wait"
-#define DEF_PS_GREET_WAIT "${stress?2}${stress:6}s"
-extern int var_ps_greet_wait;
+#define VAR_PSC_PREGR_ACTION "postscreen_greet_action"
+#define DEF_PSC_PREGR_ACTION "ignore"
+extern char *var_psc_pregr_action;
-#define VAR_PS_PREGR_BANNER "postscreen_greet_banner"
-#define DEF_PS_PREGR_BANNER "$" VAR_SMTPD_BANNER
-extern char *var_ps_pregr_banner;
+#define VAR_PSC_PREGR_TTL "postscreen_greet_ttl"
+#define DEF_PSC_PREGR_TTL "1d"
+extern int var_psc_pregr_ttl;
-#define VAR_PS_PREGR_ENABLE "postscreen_greet_enable"
-#define DEF_PS_PREGR_ENABLE no
-extern char *var_ps_pregr_enable;
+#define VAR_PSC_DNSBL_SITES "postscreen_dnsbl_sites"
+#define DEF_PSC_DNSBL_SITES ""
+extern char *var_psc_dnsbl_sites;
-#define VAR_PS_PREGR_ACTION "postscreen_greet_action"
-#define DEF_PS_PREGR_ACTION "ignore"
-extern char *var_ps_pregr_action;
+#define VAR_PSC_DNSBL_THRESH "postscreen_dnsbl_threshold"
+#define DEF_PSC_DNSBL_THRESH 1
+extern int var_psc_dnsbl_thresh;
-#define VAR_PS_PREGR_TTL "postscreen_greet_ttl"
-#define DEF_PS_PREGR_TTL "1d"
-extern int var_ps_pregr_ttl;
+#define VAR_PSC_DNSBL_ENABLE "postscreen_dnsbl_enable"
+#define DEF_PSC_DNSBL_ENABLE 0
+extern char *var_psc_dnsbl_enable;
-#define VAR_PS_DNSBL_SITES "postscreen_dnsbl_sites"
-#define DEF_PS_DNSBL_SITES ""
-extern char *var_ps_dnsbl_sites;
+#define VAR_PSC_DNSBL_ACTION "postscreen_dnsbl_action"
+#define DEF_PSC_DNSBL_ACTION "ignore"
+extern char *var_psc_dnsbl_action;
-#define VAR_PS_DNSBL_THRESH "postscreen_dnsbl_threshold"
-#define DEF_PS_DNSBL_THRESH 1
-extern int var_ps_dnsbl_thresh;
+#define VAR_PSC_DNSBL_TTL "postscreen_dnsbl_ttl"
+#define DEF_PSC_DNSBL_TTL "1h"
+extern int var_psc_dnsbl_ttl;
-#define VAR_PS_DNSBL_ENABLE "postscreen_dnsbl_enable"
-#define DEF_PS_DNSBL_ENABLE 0
-extern char *var_ps_dnsbl_enable;
+#define VAR_PSC_DNSBL_REPLY "postscreen_dnsbl_reply_map"
+#define DEF_PSC_DNSBL_REPLY ""
+extern char *var_psc_dnsbl_reply;
-#define VAR_PS_DNSBL_ACTION "postscreen_dnsbl_action"
-#define DEF_PS_DNSBL_ACTION "ignore"
-extern char *var_ps_dnsbl_action;
+#define VAR_PSC_PIPEL_ENABLE "postscreen_pipelining_enable"
+#define DEF_PSC_PIPEL_ENABLE 0
+extern bool var_psc_pipel_enable;
-#define VAR_PS_DNSBL_TTL "postscreen_dnsbl_ttl"
-#define DEF_PS_DNSBL_TTL "1h"
-extern int var_ps_dnsbl_ttl;
+#define VAR_PSC_PIPEL_ACTION "postscreen_pipelining_action"
+#define DEF_PSC_PIPEL_ACTION "enforce"
+extern char *var_psc_pipel_action;
-#define VAR_PS_DNSBL_REPLY "postscreen_dnsbl_reply_map"
-#define DEF_PS_DNSBL_REPLY ""
-extern char *var_ps_dnsbl_reply;
+#define VAR_PSC_PIPEL_TTL "postscreen_pipelining_ttl"
+#define DEF_PSC_PIPEL_TTL "30d"
+extern int var_psc_pipel_ttl;
-#define VAR_PS_PIPEL_ENABLE "postscreen_pipelining_enable"
-#define DEF_PS_PIPEL_ENABLE 0
-extern bool var_ps_pipel_enable;
+#define VAR_PSC_NSMTP_ENABLE "postscreen_non_smtp_command_enable"
+#define DEF_PSC_NSMTP_ENABLE 0
+extern bool var_psc_nsmtp_enable;
-#define VAR_PS_PIPEL_ACTION "postscreen_pipelining_action"
-#define DEF_PS_PIPEL_ACTION "enforce"
-extern char *var_ps_pipel_action;
+#define VAR_PSC_NSMTP_ACTION "postscreen_non_smtp_command_action"
+#define DEF_PSC_NSMTP_ACTION "drop"
+extern char *var_psc_nsmtp_action;
-#define VAR_PS_PIPEL_TTL "postscreen_pipelining_ttl"
-#define DEF_PS_PIPEL_TTL "30d"
-extern int var_ps_pipel_ttl;
+#define VAR_PSC_NSMTP_TTL "postscreen_non_smtp_command_ttl"
+#define DEF_PSC_NSMTP_TTL "30d"
+extern int var_psc_nsmtp_ttl;
-#define VAR_PS_NSMTP_ENABLE "postscreen_non_smtp_command_enable"
-#define DEF_PS_NSMTP_ENABLE 0
-extern bool var_ps_nsmtp_enable;
+#define VAR_PSC_BARLF_ENABLE "postscreen_bare_newline_enable"
+#define DEF_PSC_BARLF_ENABLE 0
+extern bool var_psc_barlf_enable;
-#define VAR_PS_NSMTP_ACTION "postscreen_non_smtp_command_action"
-#define DEF_PS_NSMTP_ACTION "drop"
-extern char *var_ps_nsmtp_action;
+#define VAR_PSC_BARLF_ACTION "postscreen_bare_newline_action"
+#define DEF_PSC_BARLF_ACTION "ignore"
+extern char *var_psc_barlf_action;
-#define VAR_PS_NSMTP_TTL "postscreen_non_smtp_command_ttl"
-#define DEF_PS_NSMTP_TTL "30d"
-extern int var_ps_nsmtp_ttl;
+#define VAR_PSC_BARLF_TTL "postscreen_bare_newline_ttl"
+#define DEF_PSC_BARLF_TTL "30d"
+extern int var_psc_barlf_ttl;
-#define VAR_PS_BARLF_ENABLE "postscreen_bare_newline_enable"
-#define DEF_PS_BARLF_ENABLE 0
-extern bool var_ps_barlf_enable;
+#define VAR_PSC_WLIST_NETS "postscreen_whitelist_networks"
+#define DEF_PSC_WLIST_NETS "$" VAR_MYNETWORKS
+extern char *var_psc_wlist_nets;
-#define VAR_PS_BARLF_ACTION "postscreen_bare_newline_action"
-#define DEF_PS_BARLF_ACTION "ignore"
-extern char *var_ps_barlf_action;
+#define VAR_PSC_BLIST_NETS "postscreen_blacklist_networks"
+#define DEF_PSC_BLIST_NETS ""
+extern char *var_psc_blist_nets;
-#define VAR_PS_BARLF_TTL "postscreen_bare_newline_ttl"
-#define DEF_PS_BARLF_TTL "30d"
-extern int var_ps_barlf_ttl;
+#define VAR_PSC_BLIST_ACTION "postscreen_blacklist_action"
+#define DEF_PSC_BLIST_ACTION "ignore"
+extern char *var_psc_blist_nets;
-#define VAR_PS_WLIST_NETS "postscreen_whitelist_networks"
-#define DEF_PS_WLIST_NETS "$" VAR_MYNETWORKS
-extern char *var_ps_wlist_nets;
+#define VAR_PSC_CMD_COUNT "postscreen_command_count_limit"
+#define DEF_PSC_CMD_COUNT 20
+extern int var_psc_cmd_count;
-#define VAR_PS_BLIST_NETS "postscreen_blacklist_networks"
-#define DEF_PS_BLIST_NETS ""
-extern char *var_ps_blist_nets;
+#define VAR_PSC_CMD_TIME "postscreen_command_time_limit"
+#define DEF_PSC_CMD_TIME DEF_SMTPD_TMOUT
+extern char *var_psc_cmd_time;
-#define VAR_PS_BLIST_ACTION "postscreen_blacklist_action"
-#define DEF_PS_BLIST_ACTION "ignore"
-extern char *var_ps_blist_nets;
+#define VAR_PSC_WATCHDOG "postscreen_watchdog_timeout"
+#define DEF_PSC_WATCHDOG "10s"
+extern int var_psc_watchdog;
-#define VAR_PS_CMD_COUNT "postscreen_command_count_limit"
-#define DEF_PS_CMD_COUNT 20
-extern int var_ps_cmd_count;
+#define VAR_PSC_EHLO_DIS_WORDS "postscreen_discard_ehlo_keywords"
+#define DEF_PSC_EHLO_DIS_WORDS "$" VAR_SMTPD_EHLO_DIS_WORDS
+extern char *var_psc_ehlo_dis_words;
-#define VAR_PS_CMD_TIME "postscreen_command_time_limit"
-#define DEF_PS_CMD_TIME DEF_SMTPD_TMOUT
-extern char *var_ps_cmd_time;
+#define VAR_PSC_EHLO_DIS_MAPS "postscreen_discard_ehlo_keyword_address_maps"
+#define DEF_PSC_EHLO_DIS_MAPS "$" VAR_SMTPD_EHLO_DIS_MAPS
+extern char *var_psc_ehlo_dis_maps;
-#define VAR_PS_WATCHDOG "postscreen_watchdog_timeout"
-#define DEF_PS_WATCHDOG "10s"
-extern int var_ps_watchdog;
+#define VAR_PSC_TLS_LEVEL "postscreen_tls_security_level"
+#define DEF_PSC_TLS_LEVEL "$" VAR_SMTPD_TLS_LEVEL
+extern char *var_psc_tls_level;
-#define VAR_PS_FORBID_CMDS "postscreen_forbidden_commands"
-#define DEF_PS_FORBID_CMDS "$" VAR_SMTPD_FORBID_CMDS
-extern char *var_ps_forbid_cmds;
+#define VAR_PSC_USE_TLS "postscreen_use_tls"
+#define DEF_PSC_USE_TLS "$" VAR_SMTPD_USE_TLS
+extern bool var_psc_use_tls;
-#define VAR_PS_HELO_REQUIRED "postscreen_helo_required"
-#define DEF_PS_HELO_REQUIRED "$" VAR_HELO_REQUIRED
-extern bool var_ps_helo_required;
+#define VAR_PSC_ENFORCE_TLS "postscreen_enforce_tls"
+#define DEF_PSC_ENFORCE_TLS "$" VAR_SMTPD_ENFORCE_TLS
+extern bool var_psc_enforce_tls;
-#define VAR_PS_DISABLE_VRFY "postscreen_disable_vrfy_command"
-#define DEF_PS_DISABLE_VRFY "$" VAR_DISABLE_VRFY_CMD
-extern bool var_ps_disable_vrfy;
+#define VAR_PSC_FORBID_CMDS "postscreen_forbidden_commands"
+#define DEF_PSC_FORBID_CMDS "$" VAR_SMTPD_FORBID_CMDS
+extern char *var_psc_forbid_cmds;
-#define VAR_PS_CCONN_LIMIT "postscreen_client_connection_count_limit"
-#define DEF_PS_CCONN_LIMIT "$" VAR_SMTPD_CCONN_LIMIT
-extern int var_ps_cconn_limit;
+#define VAR_PSC_HELO_REQUIRED "postscreen_helo_required"
+#define DEF_PSC_HELO_REQUIRED "$" VAR_HELO_REQUIRED
+extern bool var_psc_helo_required;
+
+#define VAR_PSC_DISABLE_VRFY "postscreen_disable_vrfy_command"
+#define DEF_PSC_DISABLE_VRFY "$" VAR_DISABLE_VRFY_CMD
+extern bool var_psc_disable_vrfy;
+
+#define VAR_PSC_CCONN_LIMIT "postscreen_client_connection_count_limit"
+#define DEF_PSC_CCONN_LIMIT "$" VAR_SMTPD_CCONN_LIMIT
+extern int var_psc_cconn_limit;
#define VAR_DNSBLOG_DELAY "dnsblog_reply_delay"
#define DEF_DNSBLOG_DELAY "0s"
extern int var_dnsblog_delay;
+#define VAR_TLSP_WATCHDOG "tlsproxy_watchdog_timeout"
+#define DEF_TLSP_WATCHDOG "10s"
+extern int var_tlsp_watchdog;
+
+#define VAR_TLSP_TLS_LEVEL "tlsproxy_tls_security_level"
+#define DEF_TLSP_TLS_LEVEL "$" VAR_SMTPD_TLS_LEVEL
+extern char *var_tlsp_tls_level;
+
+#define VAR_TLSP_USE_TLS "tlsproxy_use_tls"
+#define DEF_TLSP_USE_TLS "$" VAR_SMTPD_USE_TLS
+extern bool var_tlsp_use_tls;
+
+#define VAR_TLSP_ENFORCE_TLS "tlsproxy_enforce_tls"
+#define DEF_TLSP_ENFORCE_TLS "$" VAR_SMTPD_ENFORCE_TLS
+extern bool var_tlsp_enforce_tls;
+
+#define VAR_TLSP_TLS_ACERT "tlsproxy_tls_ask_ccert"
+#define DEF_TLSP_TLS_ACERT "$" VAR_SMTPD_TLS_ACERT
+extern bool var_tlsp_tls_ask_ccert;
+
+#define VAR_TLSP_TLS_RCERT "tlsproxy_tls_req_ccert"
+#define DEF_TLSP_TLS_RCERT "$" VAR_SMTPD_TLS_RCERT
+extern bool var_tlsp_tls_req_ccert;
+
+#define VAR_TLSP_TLS_CCERT_VD "tlsproxy_tls_ccert_verifydepth"
+#define DEF_TLSP_TLS_CCERT_VD "$" VAR_SMTPD_TLS_CCERT_VD
+extern int var_tlsp_tls_ccert_vd;
+
+#define VAR_TLSP_TLS_CERT_FILE "tlsproxy_tls_cert_file"
+#define DEF_TLSP_TLS_CERT_FILE "$" VAR_SMTPD_TLS_CERT_FILE
+extern char *var_tlsp_tls_cert_file;
+
+#define VAR_TLSP_TLS_KEY_FILE "tlsproxy_tls_key_file"
+#define DEF_TLSP_TLS_KEY_FILE "$" VAR_SMTPD_TLS_KEY_FILE
+extern char *var_tlsp_tls_key_file;
+
+#define VAR_TLSP_TLS_DCERT_FILE "tlsproxy_tls_dcert_file"
+#define DEF_TLSP_TLS_DCERT_FILE "$" VAR_SMTPD_TLS_DCERT_FILE
+extern char *var_tlsp_tls_dcert_file;
+
+#define VAR_TLSP_TLS_DKEY_FILE "tlsproxy_tls_dkey_file"
+#define DEF_TLSP_TLS_DKEY_FILE "$" VAR_SMTPD_TLS_DKEY_FILE
+extern char *var_tlsp_tls_dkey_file;
+
+#define VAR_TLSP_TLS_ECCERT_FILE "tlsproxy_tls_eccert_file"
+#define DEF_TLSP_TLS_ECCERT_FILE "$" VAR_SMTPD_TLS_ECCERT_FILE
+extern char *var_tlsp_tls_eccert_file;
+
+#define VAR_TLSP_TLS_ECKEY_FILE "tlsproxy_tls_eckey_file"
+#define DEF_TLSP_TLS_ECKEY_FILE "$" VAR_SMTPD_TLS_ECKEY_FILE
+extern char *var_tlsp_tls_eckey_file;
+
+#define DEF_TLSP_TLS_ECKEY_FILE "$" VAR_SMTPD_TLS_ECKEY_FILE
+extern char *var_tlsp_tls_eckey_file;
+
+#define VAR_TLSP_TLS_CA_FILE "tlsproxy_tls_CAfile"
+#define DEF_TLSP_TLS_CA_FILE "$" VAR_SMTPD_TLS_CA_FILE
+extern char *var_tlsp_tls_CAfile;
+
+#define VAR_TLSP_TLS_CA_PATH "tlsproxy_tls_CApath"
+#define DEF_TLSP_TLS_CA_PATH "$" VAR_SMTPD_TLS_CA_PATH
+extern char *var_tlsp_tls_CApath;
+
+#define VAR_TLSP_TLS_PROTO "tlsproxy_tls_protocols"
+#define DEF_TLSP_TLS_PROTO "$" VAR_SMTPD_TLS_PROTO
+extern char *var_tlsp_tls_proto;
+
+#define VAR_TLSP_TLS_MAND_PROTO "tlsproxy_tls_mandatory_protocols"
+#define DEF_TLSP_TLS_MAND_PROTO "$" VAR_SMTPD_TLS_MAND_PROTO
+extern char *var_tlsp_tls_mand_proto;
+
+#define VAR_TLSP_TLS_CIPH "tlsproxy_tls_ciphers"
+#define DEF_TLSP_TLS_CIPH "$" VAR_SMTPD_TLS_CIPH
+extern char *var_tlsp_tls_ciph;
+
+#define VAR_TLSP_TLS_MAND_CIPH "tlsproxy_tls_mandatory_ciphers"
+#define DEF_TLSP_TLS_MAND_CIPH "$" VAR_SMTPD_TLS_MAND_CIPH
+extern char *var_tlsp_tls_mand_ciph;
+
+#define VAR_TLSP_TLS_EXCL_CIPH "tlsproxy_tls_exclude_ciphers"
+#define DEF_TLSP_TLS_EXCL_CIPH "$" VAR_SMTPD_TLS_EXCL_CIPH
+extern char *var_tlsp_tls_excl_ciph;
+
+#define VAR_TLSP_TLS_MAND_EXCL "tlsproxy_tls_mandatory_exclude_ciphers"
+#define DEF_TLSP_TLS_MAND_EXCL "$" VAR_SMTPD_TLS_MAND_EXCL
+extern char *var_tlsp_tls_mand_excl;
+
+#define VAR_TLSP_TLS_FPT_DGST "tlsproxy_tls_fingerprint_digest"
+#define DEF_TLSP_TLS_FPT_DGST "$" VAR_SMTPD_TLS_FPT_DGST
+extern char *var_tlsp_tls_fpt_dgst;
+
+#define VAR_TLSP_TLS_512_FILE "tlsproxy_tls_dh512_param_file"
+#define DEF_TLSP_TLS_512_FILE "$" VAR_SMTPD_TLS_512_FILE
+extern char *var_tlsp_tls_dh512_param_file;
+
+#define VAR_TLSP_TLS_1024_FILE "tlsproxy_tls_dh1024_param_file"
+#define DEF_TLSP_TLS_1024_FILE "$" VAR_SMTPD_TLS_1024_FILE
+extern char *var_tlsp_tls_dh1024_param_file;
+
+#define VAR_TLSP_TLS_EECDH "tlsproxy_tls_eecdh_grade"
+#ifdef SNAPSHOT
+#define DEF_TLSP_TLS_EECDH "$" VAR_SMTPD_TLS_EECDH
+#else
+#define DEF_TLSP_TLS_EECDH "$" VAR_SMTPD_TLS_EECDH
+#endif
+extern char *var_tlsp_tls_eecdh;
+
+#define VAR_TLSP_TLS_LOGLEVEL "tlsproxy_tls_loglevel"
+#define DEF_TLSP_TLS_LOGLEVEL "$" VAR_SMTPD_TLS_LOGLEVEL
+extern int var_tlsp_tls_loglevel;
+
+#define VAR_TLSP_TLS_RECHEAD "tlsproxy_tls_received_header"
+#define DEF_TLSP_TLS_RECHEAD "$" VAR_SMTPD_TLS_RECHEAD
+extern bool var_tlsp_tls_received_header;
+
+#define VAR_TLSP_TLS_SCACHE_DB "tlsproxy_tls_session_cache_database"
+#define DEF_TLSP_TLS_SCACHE_DB "$" VAR_SMTPD_TLS_SCACHE_DB
+extern char *var_tlsp_tls_scache_db;
+
+#define VAR_TLSP_TLS_SCACHTIME "tlsproxy_tls_session_cache_timeout"
+#define DEF_TLSP_TLS_SCACHTIME "$" VAR_SMTPD_TLS_SCACHTIME
+extern int var_tlsp_tls_scache_timeout;
+
+#define VAR_TLSP_TLS_SET_SESSID "tlsproxy_tls_always_issue_session_ids"
+#define DEF_TLSP_TLS_SET_SESSID "$" VAR_SMTPD_TLS_SET_SESSID
+extern bool var_tlsp_tls_set_sessid;
+
/* LICENSE
/* .ad
/* .fi
#define MAIL_ATTR_DSN_NOTIFY "notify_flags" /* dsn notify flags */
#define MAIL_ATTR_DSN_ORCPT "dsn_orig_rcpt" /* dsn original recipient */
+ /*
+ * PROXY support.
+ */
+#define MAIL_ATTR_REMOTE_ENDPT "remote_endpoint" /* name[addr]:port */
+#define MAIL_ATTR_ROLE "role" /* requested role */
+#define MAIL_ATTR_ROLE_SERVER "server"
+#define MAIL_ATTR_ROLE_CLIENT "client"
+#define MAIL_ATTR_TIMEOUT "timeout"
+
/* LICENSE
/* .ad
/* .fi
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20101217"
+#define MAIL_RELEASE_DATE "20110102"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
/* oqmgr(8), old Postfix queue manager
/* pickup(8), Postfix local mail pickup
/* pipe(8), deliver mail to non-Postfix command
-/* postscreen(8), Postfix SMTP triage server
+/* postscreen(8), Postfix zombie blocker
/* proxymap(8), Postfix lookup table proxy server
/* qmgr(8), Postfix queue manager
/* qmqpd(8), Postfix QMQP server
/* smtpd(8), Postfix SMTP server
/* spawn(8), run non-Postfix server
/* tlsmgr(8), Postfix TLS cache and randomness manager
+/* tlsproxy(8), Postfix TLS proxy server
/* trivial-rewrite(8), Postfix address rewriting
/* verify(8), Postfix address verification
/* virtual(8), Postfix virtual delivery agent
SHELL = /bin/sh
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c \
postscreen_early.c postscreen_smtpd.c postscreen_misc.c \
- postscreen_state.c postscreen_tests.c postscreen_send.c
+ postscreen_state.c postscreen_tests.c postscreen_send.c \
+ postscreen_starttls.c
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o \
postscreen_early.o postscreen_smtpd.o postscreen_misc.o \
- postscreen_state.o postscreen_tests.o postscreen_send.o
+ postscreen_state.o postscreen_tests.o postscreen_send.o \
+ postscreen_starttls.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
TESTPROG=
PROG = postscreen
INC_DIR = ../../include
-LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
+LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libglobal.a \
+ ../../lib/libutil.a
.c.o:; $(CC) $(CFLAGS) -c $*.c
postscreen_smtpd.o: ../../include/attr.h
postscreen_smtpd.o: ../../include/dict.h
postscreen_smtpd.o: ../../include/dict_cache.h
+postscreen_smtpd.o: ../../include/ehlo_mask.h
postscreen_smtpd.o: ../../include/events.h
postscreen_smtpd.o: ../../include/htable.h
postscreen_smtpd.o: ../../include/iostuff.h
postscreen_smtpd.o: ../../include/is_header.h
postscreen_smtpd.o: ../../include/mail_params.h
postscreen_smtpd.o: ../../include/mail_proto.h
+postscreen_smtpd.o: ../../include/maps.h
postscreen_smtpd.o: ../../include/match_list.h
postscreen_smtpd.o: ../../include/match_ops.h
postscreen_smtpd.o: ../../include/msg.h
postscreen_smtpd.o: ../../include/mymalloc.h
+postscreen_smtpd.o: ../../include/name_code.h
+postscreen_smtpd.o: ../../include/name_mask.h
postscreen_smtpd.o: ../../include/string_list.h
postscreen_smtpd.o: ../../include/stringops.h
postscreen_smtpd.o: ../../include/sys_defs.h
+postscreen_smtpd.o: ../../include/tls.h
postscreen_smtpd.o: ../../include/vbuf.h
postscreen_smtpd.o: ../../include/vstream.h
postscreen_smtpd.o: ../../include/vstring.h
postscreen_smtpd.o: postscreen.h
postscreen_smtpd.o: postscreen_smtpd.c
+postscreen_starttls.o: ../../include/addr_match_list.h
+postscreen_starttls.o: ../../include/argv.h
+postscreen_starttls.o: ../../include/attr.h
+postscreen_starttls.o: ../../include/connect.h
+postscreen_starttls.o: ../../include/dict.h
+postscreen_starttls.o: ../../include/dict_cache.h
+postscreen_starttls.o: ../../include/events.h
+postscreen_starttls.o: ../../include/htable.h
+postscreen_starttls.o: ../../include/iostuff.h
+postscreen_starttls.o: ../../include/mail_params.h
+postscreen_starttls.o: ../../include/mail_proto.h
+postscreen_starttls.o: ../../include/match_list.h
+postscreen_starttls.o: ../../include/match_ops.h
+postscreen_starttls.o: ../../include/msg.h
+postscreen_starttls.o: ../../include/mymalloc.h
+postscreen_starttls.o: ../../include/string_list.h
+postscreen_starttls.o: ../../include/stringops.h
+postscreen_starttls.o: ../../include/sys_defs.h
+postscreen_starttls.o: ../../include/vbuf.h
+postscreen_starttls.o: ../../include/vstream.h
+postscreen_starttls.o: ../../include/vstring.h
+postscreen_starttls.o: postscreen.h
+postscreen_starttls.o: postscreen_starttls.c
postscreen_state.o: ../../include/addr_match_list.h
postscreen_state.o: ../../include/argv.h
postscreen_state.o: ../../include/attr.h
/* NAME
/* postscreen 8
/* SUMMARY
-/* Postfix SMTP triage server
+/* Postfix zombie blocker
/* SYNOPSIS
/* \fBpostscreen\fR [generic Postfix daemon options]
/* DESCRIPTION
/* It talks to untrusted clients on the network. The process
/* can be run chrooted at fixed low privilege.
/* STANDARDS
-/* RFC 5321 (SMTP, including multi-line 220 greetings)
+/* RFC 821 (SMTP protocol)
+/* RFC 1123 (Host requirements)
+/* RFC 1652 (8bit-MIME transport)
+/* RFC 1869 (SMTP service extensions)
+/* RFC 1870 (Message Size Declaration)
+/* RFC 1985 (ETRN command)
+/* RFC 2034 (SMTP Enhanced Error Codes)
+/* RFC 2821 (SMTP protocol)
/* RFC 2920 (SMTP Pipelining)
+/* RFC 3207 (STARTTLS command)
+/* RFC 3461 (SMTP DSN Extension)
+/* RFC 3463 (Enhanced Status Codes)
+/* RFC 5321 (SMTP protocol, including multi-line 220 greetings)
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
/* The \fBpostscreen\fR(8) built-in SMTP protocol engine
-/* currently does not announce support for STARTTLS, AUTH,
-/* XCLIENT or XFORWARD.
-/* Support for STARTTLS and AUTH may be added in the future.
+/* currently does not announce support for AUTH, XCLIENT or
+/* XFORWARD.
+/* Support for AUTH may be added in the future.
/* In the mean time, if you need to make these services available
/* on port 25, then do not enable the optional "after 220
/* server greeting" tests.
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
/*
-/* NOTE: Some \fBpostscreen\fR(8) parameters implement
+/* NOTE: Some \fBpostscreen\fR(8) parameters implement
/* stress-dependent behavior. This is supported only when the
-/* default value is stress-dependent (that is, it looks like
-/* ${stress?X}${stress:Y}). Other parameters always evaluate
-/* as if the stress value is the empty string.
+/* default parameter value is stress-dependent (that is, it
+/* looks like ${stress?X}${stress:Y}, or it is the $\fIname\fR
+/* of an smtpd parameter with a stress-dependent default).
+/* Other parameters always evaluate as if the \fBstress\fR
+/* parameter value is the empty string.
+/* COMPATIBILITY CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBpostscreen_discard_ehlo_keyword_address_maps ($smtpd_discard_ehlo_keyword_address_maps)\fR"
+/* Lookup tables, indexed by the remote SMTP client address, with
+/* case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+/* etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO response
+/* to a remote SMTP client.
+/* .IP "\fBpostscreen_discard_ehlo_keywords ($smtpd_discard_ehlo_keywords)\fR"
+/* A case insensitive list of EHLO keywords (pipelining, starttls,
+/* auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
+/* response to a remote SMTP client.
/* TRIAGE PARAMETERS
/* .ad
/* .fi
/* How much time a \fBpostscreen\fR(8) process may take to respond to
/* an SMTP client command or to perform a cache operation before it
/* is terminated by a built-in watchdog timer.
+/* STARTTLS CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBpostscreen_tls_security_level ($smtpd_tls_security_level)\fR"
+/* The SMTP TLS security level for the \fBpostscreen\fR(8) server; when
+/* a non-empty value is specified, this overrides the obsolete parameters
+/* postscreen_use_tls and postscreen_enforce_tls.
+/* OBSOLETE STARTTLS SUPPORT CONTROLS
+/* .ad
+/* .fi
+/* These parameters are supported for compatibility with
+/* \fBsmtpd\fR(8) legacy parameters.
+/* .IP "\fBpostscreen_use_tls ($smtpd_use_tls)\fR"
+/* Opportunistic TLS: announce STARTTLS support to SMTP clients,
+/* but do not require that clients use TLS encryption.
+/* .IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
+/* Mandatory TLS: announce STARTTLS support to SMTP clients, and
+/* require that clients use TLS encryption.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
/* SEE ALSO
/* smtpd(8), Postfix SMTP server
+/* tlsproxy(8), Postfix TLS proxy server
/* dnsblog(8), temporary DNS helper
/* syslogd(8), system logging
/* README FILES
int var_proc_limit;
char *var_smtpd_service;
char *var_smtpd_banner;
-char *var_smtpd_forbid_cmds;
bool var_disable_vrfy_cmd;
bool var_helo_required;
-char *var_ps_forbid_cmds;
-
-bool var_ps_disable_vrfy;
-bool var_ps_helo_required;
-
-char *var_ps_cache_map;
-int var_ps_cache_scan;
-int var_ps_cache_ret;
-int var_ps_post_queue_limit;
-int var_ps_pre_queue_limit;
-int var_ps_watchdog;
-
-char *var_ps_wlist_nets;
-char *var_ps_blist_nets;
-char *var_ps_blist_action;
-
-char *var_ps_greet_ttl;
-int var_ps_greet_wait;
-
-char *var_ps_pregr_banner;
-char *var_ps_pregr_action;
-int var_ps_pregr_ttl;
-
-char *var_ps_dnsbl_sites;
-char *var_ps_dnsbl_reply;
-int var_ps_dnsbl_thresh;
-char *var_ps_dnsbl_action;
-int var_ps_dnsbl_ttl;
-
-bool var_ps_pipel_enable;
-char *var_ps_pipel_action;
-int var_ps_pipel_ttl;
-
-bool var_ps_nsmtp_enable;
-char *var_ps_nsmtp_action;
-int var_ps_nsmtp_ttl;
-
-bool var_ps_barlf_enable;
-char *var_ps_barlf_action;
-int var_ps_barlf_ttl;
-
-int var_ps_cmd_count;
-char *var_ps_cmd_time;
+char *var_smtpd_forbid_cmds;
+char *var_psc_forbid_cmds;
+
+char *var_smtpd_ehlo_dis_words;
+char *var_smtpd_ehlo_dis_maps;
+char *var_psc_ehlo_dis_words;
+char *var_psc_ehlo_dis_maps;
+
+char *var_smtpd_tls_level;
+bool var_smtpd_use_tls;
+bool var_smtpd_enforce_tls;
+char *var_psc_tls_level;
+bool var_psc_use_tls;
+bool var_psc_enforce_tls;
+
+bool var_psc_disable_vrfy;
+bool var_psc_helo_required;
+
+char *var_psc_cache_map;
+int var_psc_cache_scan;
+int var_psc_cache_ret;
+int var_psc_post_queue_limit;
+int var_psc_pre_queue_limit;
+int var_psc_watchdog;
+
+char *var_psc_wlist_nets;
+char *var_psc_blist_nets;
+char *var_psc_blist_action;
+
+char *var_psc_greet_ttl;
+int var_psc_greet_wait;
+
+char *var_psc_pregr_banner;
+char *var_psc_pregr_action;
+int var_psc_pregr_ttl;
+
+char *var_psc_dnsbl_sites;
+char *var_psc_dnsbl_reply;
+int var_psc_dnsbl_thresh;
+char *var_psc_dnsbl_action;
+int var_psc_dnsbl_ttl;
+
+bool var_psc_pipel_enable;
+char *var_psc_pipel_action;
+int var_psc_pipel_ttl;
+
+bool var_psc_nsmtp_enable;
+char *var_psc_nsmtp_action;
+int var_psc_nsmtp_ttl;
+
+bool var_psc_barlf_enable;
+char *var_psc_barlf_action;
+int var_psc_barlf_ttl;
+
+int var_psc_cmd_count;
+char *var_psc_cmd_time;
int var_smtpd_cconn_limit;
-int var_ps_cconn_limit;
+int var_psc_cconn_limit;
/*
* Global variables.
*/
-int ps_check_queue_length; /* connections being checked */
-int ps_post_queue_length; /* being sent to real SMTPD */
-DICT_CACHE *ps_cache_map; /* cache table handle */
-VSTRING *ps_temp; /* scratchpad */
-char *ps_smtpd_service_name; /* path to real SMTPD */
-int ps_pregr_action; /* PS_ACT_DROP/ENFORCE/etc */
-int ps_dnsbl_action; /* PS_ACT_DROP/ENFORCE/etc */
-int ps_pipel_action; /* PS_ACT_DROP/ENFORCE/etc */
-int ps_nsmtp_action; /* PS_ACT_DROP/ENFORCE/etc */
-int ps_barlf_action; /* PS_ACT_DROP/ENFORCE/etc */
-int ps_min_ttl; /* Update with new tests! */
-int ps_max_ttl; /* Update with new tests! */
-STRING_LIST *ps_forbid_cmds; /* CONNECT GET POST */
-int ps_stress_greet_wait; /* stressed greet wait */
-int ps_normal_greet_wait; /* stressed greet wait */
-int ps_stress_cmd_time_limit; /* stressed command limit */
-int ps_normal_cmd_time_limit; /* normal command time limit */
-int ps_stress; /* stress level */
-int ps_check_queue_length_lowat; /* stress low-water mark */
-int ps_check_queue_length_hiwat; /* stress high-water mark */
-DICT *ps_dnsbl_reply; /* DNSBL name mapper */
-HTABLE *ps_client_concurrency; /* per-client concurrency */
+int psc_check_queue_length; /* connections being checked */
+int psc_post_queue_length; /* being sent to real SMTPD */
+DICT_CACHE *psc_cache_map; /* cache table handle */
+VSTRING *psc_temp; /* scratchpad */
+char *psc_smtpd_service_name; /* path to real SMTPD */
+int psc_pregr_action; /* PSC_ACT_DROP/ENFORCE/etc */
+int psc_dnsbl_action; /* PSC_ACT_DROP/ENFORCE/etc */
+int psc_pipel_action; /* PSC_ACT_DROP/ENFORCE/etc */
+int psc_nsmtp_action; /* PSC_ACT_DROP/ENFORCE/etc */
+int psc_barlf_action; /* PSC_ACT_DROP/ENFORCE/etc */
+int psc_min_ttl; /* Update with new tests! */
+int psc_max_ttl; /* Update with new tests! */
+STRING_LIST *psc_forbid_cmds; /* CONNECT GET POST */
+int psc_stress_greet_wait; /* stressed greet wait */
+int psc_normal_greet_wait; /* stressed greet wait */
+int psc_stress_cmd_time_limit; /* stressed command limit */
+int psc_normal_cmd_time_limit; /* normal command time limit */
+int psc_stress; /* stress level */
+int psc_check_queue_length_lowat; /* stress low-water mark */
+int psc_check_queue_length_hiwat; /* stress high-water mark */
+DICT *psc_dnsbl_reply; /* DNSBL name mapper */
+HTABLE *psc_client_concurrency; /* per-client concurrency */
/*
* Local variables.
*/
-static ADDR_MATCH_LIST *ps_wlist_nets; /* permanently whitelisted networks */
-static ADDR_MATCH_LIST *ps_blist_nets; /* permanently blacklisted networks */
-static int ps_blist_action; /* PS_ACT_DROP/ENFORCE/etc */
+static ADDR_MATCH_LIST *psc_wlist_nets; /* permanently whitelisted networks */
+static ADDR_MATCH_LIST *psc_blist_nets; /* permanently blacklisted networks */
+static int psc_blist_action; /* PSC_ACT_DROP/ENFORCE/etc */
-/* ps_dump - dump some statistics before exit */
+/* psc_dump - dump some statistics before exit */
-static void ps_dump(void)
+static void psc_dump(void)
{
/*
* distinguish between "postfix reload" (we should restart) or "maximal
* idle time reached" (we could finish the cache cleanup first).
*/
- if (ps_cache_map) {
- dict_cache_close(ps_cache_map);
- ps_cache_map = 0;
+ if (psc_cache_map) {
+ dict_cache_close(psc_cache_map);
+ psc_cache_map = 0;
}
}
-/* ps_drain - delayed exit after "postfix reload" */
+/* psc_drain - delayed exit after "postfix reload" */
-static void ps_drain(char *unused_service, char **unused_argv)
+static void psc_drain(char *unused_service, char **unused_argv)
{
int count;
* XXX Some Berkeley DB versions break with close-after-fork. Every new
* version is an improvement over its predecessor.
*/
- if (ps_cache_map != 0) {
- dict_cache_close(ps_cache_map);
- ps_cache_map = 0;
+ if (psc_cache_map != 0) {
+ dict_cache_close(psc_cache_map);
+ psc_cache_map = 0;
}
for (count = 0; /* see below */ ; count++) {
if (count >= 5) {
}
}
-/* ps_service - handle new client connection */
+/* psc_service - handle new client connection */
-static void ps_service(VSTREAM *smtp_client_stream,
- char *unused_service,
- char **unused_argv)
+static void psc_service(VSTREAM *smtp_client_stream,
+ char *unused_service,
+ char **unused_argv)
{
- const char *myname = "ps_service";
- PS_STATE *state;
+ const char *myname = "psc_service";
+ PSC_STATE *state;
struct sockaddr_storage addr_storage;
SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
MAI_HOSTADDR_STR smtp_client_addr;
* connections so we have to invoke getpeername() to find out the remote
* address and port.
*/
-#define PS_SERVICE_DISCONNECT_AND_RETURN(stream) do { \
+#define PSC_SERVICE_DISCONNECT_AND_RETURN(stream) do { \
event_server_disconnect(stream); \
return; \
} while (0);
if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
& addr_storage, &addr_storage_len) < 0) {
msg_warn("getpeername: %m -- dropping this connection");
- ps_send_reply(vstream_fileno(smtp_client_stream),
- "unknown_address", "unknown_port",
- "421 4.3.2 No system resources\r\n");
- PS_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
+ psc_send_reply(vstream_fileno(smtp_client_stream),
+ "unknown_address", "unknown_port",
+ "421 4.3.2 No system resources\r\n");
+ PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
}
/*
msg_warn("cannot convert client address/port to string: %s"
" -- dropping this connection",
MAI_STRERROR(aierr));
- ps_send_reply(vstream_fileno(smtp_client_stream),
- "unknown_address", "unknown_port",
- "421 4.3.2 No system resources\r\n");
- PS_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
+ psc_send_reply(vstream_fileno(smtp_client_stream),
+ "unknown_address", "unknown_port",
+ "421 4.3.2 No system resources\r\n");
+ PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream);
}
if (strncasecmp("::ffff:", smtp_client_addr.buf, 7) == 0)
memmove(smtp_client_addr.buf, smtp_client_addr.buf + 7,
sizeof(smtp_client_addr.buf) - 7);
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
smtp_client_addr.buf, smtp_client_port.buf);
msg_info("CONNECT from [%s]:%s", smtp_client_addr.buf, smtp_client_port.buf);
* Bundle up all the loose session pieces. This zeroes all flags and time
* stamps.
*/
- state = ps_new_session_state(smtp_client_stream, smtp_client_addr.buf,
- smtp_client_port.buf);
+ state = psc_new_session_state(smtp_client_stream, smtp_client_addr.buf,
+ smtp_client_port.buf);
/*
* Reply with 421 when the client has too many open connections.
*/
- if (var_ps_cconn_limit > 0
- && state->client_concurrency > var_ps_cconn_limit) {
+ if (var_psc_cconn_limit > 0
+ && state->client_concurrency > var_psc_cconn_limit) {
msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
state->smtp_client_addr, state->smtp_client_port);
- PS_DROP_SESSION_STATE(state,
- "421 4.7.0 Error: too many connections\r\n");
+ PSC_DROP_SESSION_STATE(state,
+ "421 4.7.0 Error: too many connections\r\n");
return;
}
/*
* Reply with 421 when we can't forward more connections.
*/
- if (var_ps_post_queue_limit > 0
- && ps_post_queue_length >= var_ps_post_queue_limit) {
+ if (var_psc_post_queue_limit > 0
+ && psc_post_queue_length >= var_psc_post_queue_limit) {
msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: all server ports busy",
state->smtp_client_addr, state->smtp_client_port);
- PS_DROP_SESSION_STATE(state,
- "421 4.3.2 All server ports are busy\r\n");
+ PSC_DROP_SESSION_STATE(state,
+ "421 4.3.2 All server ports are busy\r\n");
return;
}
* The permanent whitelist has highest precedence (never block mail from
* whitelisted sites, and never run tests against those sites).
*/
- if (ps_wlist_nets != 0
- && ps_addr_match_list_match(ps_wlist_nets, state->smtp_client_addr)) {
- msg_info("WHITELISTED [%s]:%s", PS_CLIENT_ADDR_PORT(state));
- ps_conclude(state);
+ if (psc_wlist_nets != 0
+ && psc_addr_match_list_match(psc_wlist_nets, state->smtp_client_addr)) {
+ msg_info("WHITELISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ psc_conclude(state);
return;
}
* permanently blacklisted, send some generic reply and hang up
* immediately, or run more tests for logging purposes.
*/
- if (ps_blist_nets != 0
- && ps_addr_match_list_match(ps_blist_nets, state->smtp_client_addr)) {
- msg_info("BLACKLISTED [%s]:%s", PS_CLIENT_ADDR_PORT(state));
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_BLIST_FAIL);
- switch (ps_blist_action) {
- case PS_ACT_DROP:
- PS_DROP_SESSION_STATE(state,
+ if (psc_blist_nets != 0
+ && psc_addr_match_list_match(psc_blist_nets, state->smtp_client_addr)) {
+ msg_info("BLACKLISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
+ switch (psc_blist_action) {
+ case PSC_ACT_DROP:
+ PSC_DROP_SESSION_STATE(state,
"521 5.3.2 Service currently unavailable\r\n");
return;
- case PS_ACT_ENFORCE:
- PS_ENFORCE_SESSION_STATE(state,
+ case PSC_ACT_ENFORCE:
+ PSC_ENFORCE_SESSION_STATE(state,
"550 5.3.2 Service currently unavailable\r\n");
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state, PS_STATE_FLAG_BLIST_FAIL);
- /* Not: PS_PASS_SESSION_STATE. Repeat this test the next time. */
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
+ /* Not: PSC_PASS_SESSION_STATE. Repeat this test the next time. */
break;
default:
msg_panic("%s: unknown blacklist action value %d",
- myname, ps_blist_action);
+ myname, psc_blist_action);
}
}
* tests. Whitelist the client when all enabled test results are still
* valid.
*/
- if ((state->flags & PS_STATE_MASK_ANY_FAIL) == 0
- && ps_cache_map != 0
- && (stamp_str = ps_cache_lookup(ps_cache_map, state->smtp_client_addr)) != 0) {
+ if ((state->flags & PSC_STATE_MASK_ANY_FAIL) == 0
+ && psc_cache_map != 0
+ && (stamp_str = psc_cache_lookup(psc_cache_map, state->smtp_client_addr)) != 0) {
saved_flags = state->flags;
- ps_parse_tests(state, stamp_str, event_time());
+ psc_parse_tests(state, stamp_str, event_time());
state->flags |= saved_flags;
if (msg_verbose)
msg_info("%s: cached + recent flags: %s",
- myname, ps_print_state_flags(state->flags, myname));
- if ((state->flags & PS_STATE_MASK_ANY_TODO_FAIL) == 0) {
- msg_info("PASS OLD [%s]:%s", PS_CLIENT_ADDR_PORT(state));
- ps_conclude(state);
+ myname, psc_print_state_flags(state->flags, myname));
+ if ((state->flags & PSC_STATE_MASK_ANY_TODO_FAIL) == 0) {
+ msg_info("PASS OLD [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ psc_conclude(state);
return;
}
} else {
saved_flags = state->flags;
- ps_new_tests(state);
+ psc_new_tests(state);
state->flags |= saved_flags;
if (msg_verbose)
msg_info("%s: new + recent flags: %s",
- myname, ps_print_state_flags(state->flags, myname));
+ myname, psc_print_state_flags(state->flags, myname));
}
/*
* Reply with 421 when we can't analyze more connections.
*/
- if (var_ps_pre_queue_limit > 0
- && ps_check_queue_length - ps_post_queue_length >= var_ps_pre_queue_limit) {
+ if (var_psc_pre_queue_limit > 0
+ && psc_check_queue_length - psc_post_queue_length
+ >= var_psc_pre_queue_limit) {
msg_info("reject: connect from [%s]:%s: all screening ports busy",
state->smtp_client_addr, state->smtp_client_port);
- PS_DROP_SESSION_STATE(state,
- "421 4.3.2 All screening ports are busy\r\n");
+ PSC_DROP_SESSION_STATE(state,
+ "421 4.3.2 All screening ports are busy\r\n");
return;
}
* If the client has no up-to-date results for some tests, do those tests
* first. Otherwise, skip the tests and hand off the connection.
*/
- if (state->flags & PS_STATE_MASK_EARLY_TODO)
- ps_early_tests(state);
- else if (state->flags & (PS_STATE_MASK_SMTPD_TODO | PS_STATE_FLAG_NOFORWARD))
- ps_smtpd_tests(state);
+ if (state->flags & PSC_STATE_MASK_EARLY_TODO)
+ psc_early_tests(state);
+ else if (state->flags & (PSC_STATE_MASK_SMTPD_TODO | PSC_STATE_FLAG_NOFORWARD))
+ psc_smtpd_tests(state);
else
- ps_conclude(state);
+ psc_conclude(state);
}
-/* ps_cache_validator - validate one cache entry */
+/* psc_cache_validator - validate one cache entry */
-static int ps_cache_validator(const char *client_addr,
- const char *stamp_str,
- char *unused_context)
+static int psc_cache_validator(const char *client_addr,
+ const char *stamp_str,
+ char *unused_context)
{
- PS_STATE dummy;
+ PSC_STATE dummy;
/*
* This function is called by the cache cleanup pseudo thread.
* silly logging we remove the cache entry only after all tests have
* expired longer ago than the cache retention time.
*/
- ps_parse_tests(&dummy, stamp_str, event_time() - var_ps_cache_ret);
- return ((dummy.flags & PS_STATE_MASK_ANY_TODO) == 0);
+ psc_parse_tests(&dummy, stamp_str, event_time() - var_psc_cache_ret);
+ return ((dummy.flags & PSC_STATE_MASK_ANY_TODO) == 0);
}
/* pre_jail_init - pre-jail initialization */
* Open read-only maps before dropping privilege, for consistency with
* other Postfix daemons.
*/
- if (*var_ps_wlist_nets)
- ps_wlist_nets = addr_match_list_init(MATCH_FLAG_NONE, var_ps_wlist_nets);
-
- if (*var_ps_blist_nets)
- ps_blist_nets = addr_match_list_init(MATCH_FLAG_NONE, var_ps_blist_nets);
- if (*var_ps_forbid_cmds)
- ps_forbid_cmds = string_list_init(MATCH_FLAG_NONE, var_ps_forbid_cmds);
- if (*var_ps_dnsbl_reply)
- ps_dnsbl_reply = dict_open(var_ps_dnsbl_reply, O_RDONLY,
- DICT_FLAG_DUP_WARN);
+ if (*var_psc_wlist_nets)
+ psc_wlist_nets =
+ addr_match_list_init(MATCH_FLAG_NONE, var_psc_wlist_nets);
+
+ if (*var_psc_blist_nets)
+ psc_blist_nets = addr_match_list_init(MATCH_FLAG_NONE,
+ var_psc_blist_nets);
+ if (*var_psc_forbid_cmds)
+ psc_forbid_cmds = string_list_init(MATCH_FLAG_NONE,
+ var_psc_forbid_cmds);
+ if (*var_psc_dnsbl_reply)
+ psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
+ DICT_FLAG_DUP_WARN);
/*
* Never, ever, get killed by a master signal, as that would corrupt the
*
* Start the cache maintenance pseudo thread after dropping privileges.
*/
-#define PS_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
+#define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
- if (*var_ps_cache_map)
- ps_cache_map =
- dict_cache_open(data_redirect_map(redirect, var_ps_cache_map),
- O_CREAT | O_RDWR, PS_DICT_OPEN_FLAGS);
+ if (*var_psc_cache_map)
+ psc_cache_map =
+ dict_cache_open(data_redirect_map(redirect, var_psc_cache_map),
+ O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS);
/*
* Clean up and restore privilege.
*/
vstring_free(redirect);
RESTORE_SAVED_EUGID();
+
+ /*
+ * Initialize the dummy SMTP engine.
+ */
+ psc_smtpd_pre_jail_init();
+}
+
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(char *unused_name, char **unused_argv)
+{
+ static time_t last_event_time;
+ time_t new_event_time;
+ const char *name;
+
+ /*
+ * If some table has changed then stop accepting new connections. Don't
+ * check the tables more than once a second.
+ */
+ new_event_time = event_time();
+ if (new_event_time >= last_event_time + 1
+ && (name = dict_changed_name()) != 0) {
+ msg_info("table %s has changed - finishing in the background", name);
+ event_server_drain();
+ } else {
+ last_event_time = new_event_time;
+ }
}
/* post_jail_init - post-jail initialization */
static void post_jail_init(char *unused_name, char **unused_argv)
{
const NAME_CODE actions[] = {
- PS_NAME_ACT_DROP, PS_ACT_DROP,
- PS_NAME_ACT_ENFORCE, PS_ACT_ENFORCE,
- PS_NAME_ACT_IGNORE, PS_ACT_IGNORE,
- PS_NAME_ACT_CONT, PS_ACT_IGNORE,/* compatibility */
+ PSC_NAME_ACT_DROP, PSC_ACT_DROP,
+ PSC_NAME_ACT_ENFORCE, PSC_ACT_ENFORCE,
+ PSC_NAME_ACT_IGNORE, PSC_ACT_IGNORE,
+ PSC_NAME_ACT_CONT, PSC_ACT_IGNORE, /* compatibility */
0, -1,
};
int cache_flags;
/*
* Other one-time initialization.
*/
- ps_temp = vstring_alloc(10);
- vstring_sprintf(ps_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service);
- ps_smtpd_service_name = mystrdup(STR(ps_temp));
- ps_dnsbl_init();
- ps_early_init();
- ps_smtpd_init();
-
- if ((ps_blist_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_blist_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_BLIST_ACTION, var_ps_blist_action);
- if ((ps_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_dnsbl_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_DNSBL_ACTION, var_ps_dnsbl_action);
- if ((ps_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_pregr_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_PREGR_ACTION, var_ps_pregr_action);
- if ((ps_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_pipel_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_PIPEL_ACTION, var_ps_pipel_action);
- if ((ps_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_nsmtp_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_NSMTP_ACTION, var_ps_nsmtp_action);
- if ((ps_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE,
- var_ps_barlf_action)) < 0)
- msg_fatal("bad %s value: %s", VAR_PS_BARLF_ACTION, var_ps_barlf_action);
+ psc_temp = vstring_alloc(10);
+ vstring_sprintf(psc_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service);
+ psc_smtpd_service_name = mystrdup(STR(psc_temp));
+ psc_dnsbl_init();
+ psc_early_init();
+ psc_smtpd_init();
+
+ if ((psc_blist_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_blist_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_BLIST_ACTION,
+ var_psc_blist_action);
+ if ((psc_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_dnsbl_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_DNSBL_ACTION,
+ var_psc_dnsbl_action);
+ if ((psc_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_pregr_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_PREGR_ACTION,
+ var_psc_pregr_action);
+ if ((psc_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_pipel_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_PIPEL_ACTION,
+ var_psc_pipel_action);
+ if ((psc_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_nsmtp_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_NSMTP_ACTION,
+ var_psc_nsmtp_action);
+ if ((psc_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE,
+ var_psc_barlf_action)) < 0)
+ msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION,
+ var_psc_barlf_action);
/*
* Start the cache maintenance pseudo thread last. Early cleanup makes
cache_flags = DICT_CACHE_FLAG_STATISTICS;
if (msg_verbose > 1)
cache_flags |= DICT_CACHE_FLAG_VERBOSE;
- if (ps_cache_map != 0 && var_ps_cache_scan > 0)
- dict_cache_control(ps_cache_map,
+ if (psc_cache_map != 0 && var_psc_cache_scan > 0)
+ dict_cache_control(psc_cache_map,
DICT_CACHE_CTL_FLAGS, cache_flags,
- DICT_CACHE_CTL_INTERVAL, var_ps_cache_scan,
- DICT_CACHE_CTL_VALIDATOR, ps_cache_validator,
+ DICT_CACHE_CTL_INTERVAL, var_psc_cache_scan,
+ DICT_CACHE_CTL_VALIDATOR, psc_cache_validator,
DICT_CACHE_CTL_CONTEXT, (char *) 0,
DICT_CACHE_CTL_END);
/*
* Pre-compute the minimal and maximal TTL.
*/
- ps_min_ttl =
- PS_MIN(PS_MIN(var_ps_pregr_ttl, var_ps_dnsbl_ttl),
- PS_MIN(PS_MIN(var_ps_pipel_ttl, var_ps_nsmtp_ttl),
- var_ps_barlf_ttl));
- ps_max_ttl =
- PS_MAX(PS_MAX(var_ps_pregr_ttl, var_ps_dnsbl_ttl),
- PS_MAX(PS_MAX(var_ps_pipel_ttl, var_ps_nsmtp_ttl),
- var_ps_barlf_ttl));
+ psc_min_ttl =
+ PSC_MIN(PSC_MIN(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
+ PSC_MIN(PSC_MIN(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
+ var_psc_barlf_ttl));
+ psc_max_ttl =
+ PSC_MAX(PSC_MAX(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
+ PSC_MAX(PSC_MAX(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
+ var_psc_barlf_ttl));
/*
* Pre-compute the stress and normal command time limits.
*/
mail_conf_update(VAR_STRESS, "yes");
- ps_stress_cmd_time_limit =
- get_mail_conf_time(VAR_PS_CMD_TIME, DEF_PS_CMD_TIME, 1, 0);
- ps_stress_greet_wait =
- get_mail_conf_time(VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, 1, 0);
+ psc_stress_cmd_time_limit =
+ get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
+ psc_stress_greet_wait =
+ get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
mail_conf_update(VAR_STRESS, "");
- ps_normal_cmd_time_limit =
- get_mail_conf_time(VAR_PS_CMD_TIME, DEF_PS_CMD_TIME, 1, 0);
- ps_normal_greet_wait =
- get_mail_conf_time(VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, 1, 0);
+ psc_normal_cmd_time_limit =
+ get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
+ psc_normal_greet_wait =
+ get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);
- ps_check_queue_length_lowat = .7 * var_ps_pre_queue_limit;
- ps_check_queue_length_hiwat = .9 * var_ps_pre_queue_limit;
+ psc_check_queue_length_lowat = .7 * var_psc_pre_queue_limit;
+ psc_check_queue_length_hiwat = .9 * var_psc_pre_queue_limit;
if (msg_verbose)
- msg_info(VAR_PS_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
- ps_stress_cmd_time_limit, ps_normal_cmd_time_limit,
- ps_check_queue_length_lowat, ps_check_queue_length_hiwat);
+ msg_info(VAR_PSC_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
+ psc_stress_cmd_time_limit, psc_normal_cmd_time_limit,
+ psc_check_queue_length_lowat, psc_check_queue_length_hiwat);
/*
* Per-client concurrency.
*/
- ps_client_concurrency = htable_create(var_ps_pre_queue_limit);
+ psc_client_concurrency = htable_create(var_psc_pre_queue_limit);
}
MAIL_VERSION_STAMP_DECLARE;
VAR_SMTPD_SERVICE, DEF_SMTPD_SERVICE, &var_smtpd_service, 1, 0,
VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
VAR_SMTPD_FORBID_CMDS, DEF_SMTPD_FORBID_CMDS, &var_smtpd_forbid_cmds, 0, 0,
- VAR_PS_CACHE_MAP, DEF_PS_CACHE_MAP, &var_ps_cache_map, 0, 0,
- VAR_PS_PREGR_BANNER, DEF_PS_PREGR_BANNER, &var_ps_pregr_banner, 0, 0,
- VAR_PS_PREGR_ACTION, DEF_PS_PREGR_ACTION, &var_ps_pregr_action, 1, 0,
- VAR_PS_DNSBL_SITES, DEF_PS_DNSBL_SITES, &var_ps_dnsbl_sites, 0, 0,
- VAR_PS_DNSBL_ACTION, DEF_PS_DNSBL_ACTION, &var_ps_dnsbl_action, 1, 0,
- VAR_PS_PIPEL_ACTION, DEF_PS_PIPEL_ACTION, &var_ps_pipel_action, 1, 0,
- VAR_PS_NSMTP_ACTION, DEF_PS_NSMTP_ACTION, &var_ps_nsmtp_action, 1, 0,
- VAR_PS_BARLF_ACTION, DEF_PS_BARLF_ACTION, &var_ps_barlf_action, 1, 0,
- VAR_PS_WLIST_NETS, DEF_PS_WLIST_NETS, &var_ps_wlist_nets, 0, 0,
- VAR_PS_BLIST_NETS, DEF_PS_BLIST_NETS, &var_ps_blist_nets, 0, 0,
- VAR_PS_BLIST_ACTION, DEF_PS_BLIST_ACTION, &var_ps_blist_action, 1, 0,
- VAR_PS_FORBID_CMDS, DEF_PS_FORBID_CMDS, &var_ps_forbid_cmds, 0, 0,
- VAR_PS_DNSBL_REPLY, DEF_PS_DNSBL_REPLY, &var_ps_dnsbl_reply, 0, 0,
+ VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
+ VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
+ VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0,
+ VAR_PSC_CACHE_MAP, DEF_PSC_CACHE_MAP, &var_psc_cache_map, 0, 0,
+ VAR_PSC_PREGR_BANNER, DEF_PSC_PREGR_BANNER, &var_psc_pregr_banner, 0, 0,
+ VAR_PSC_PREGR_ACTION, DEF_PSC_PREGR_ACTION, &var_psc_pregr_action, 1, 0,
+ VAR_PSC_DNSBL_SITES, DEF_PSC_DNSBL_SITES, &var_psc_dnsbl_sites, 0, 0,
+ VAR_PSC_DNSBL_ACTION, DEF_PSC_DNSBL_ACTION, &var_psc_dnsbl_action, 1, 0,
+ VAR_PSC_PIPEL_ACTION, DEF_PSC_PIPEL_ACTION, &var_psc_pipel_action, 1, 0,
+ VAR_PSC_NSMTP_ACTION, DEF_PSC_NSMTP_ACTION, &var_psc_nsmtp_action, 1, 0,
+ VAR_PSC_BARLF_ACTION, DEF_PSC_BARLF_ACTION, &var_psc_barlf_action, 1, 0,
+ VAR_PSC_WLIST_NETS, DEF_PSC_WLIST_NETS, &var_psc_wlist_nets, 0, 0,
+ VAR_PSC_BLIST_NETS, DEF_PSC_BLIST_NETS, &var_psc_blist_nets, 0, 0,
+ VAR_PSC_BLIST_ACTION, DEF_PSC_BLIST_ACTION, &var_psc_blist_action, 1, 0,
+ VAR_PSC_FORBID_CMDS, DEF_PSC_FORBID_CMDS, &var_psc_forbid_cmds, 0, 0,
+ VAR_PSC_EHLO_DIS_WORDS, DEF_PSC_EHLO_DIS_WORDS, &var_psc_ehlo_dis_words, 0, 0,
+ VAR_PSC_EHLO_DIS_MAPS, DEF_PSC_EHLO_DIS_MAPS, &var_psc_ehlo_dis_maps, 0, 0,
+ VAR_PSC_DNSBL_REPLY, DEF_PSC_DNSBL_REPLY, &var_psc_dnsbl_reply, 0, 0,
+ VAR_PSC_TLS_LEVEL, DEF_PSC_TLS_LEVEL, &var_psc_tls_level, 0, 0,
0,
};
static const CONFIG_INT_TABLE int_table[] = {
VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
- VAR_PS_DNSBL_THRESH, DEF_PS_DNSBL_THRESH, &var_ps_dnsbl_thresh, 0, 0,
- VAR_PS_CMD_COUNT, DEF_PS_CMD_COUNT, &var_ps_cmd_count, 1, 0,
+ VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 0, 0,
+ VAR_PSC_CMD_COUNT, DEF_PSC_CMD_COUNT, &var_psc_cmd_count, 1, 0,
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
0,
};
static const CONFIG_NINT_TABLE nint_table[] = {
- VAR_PS_POST_QLIMIT, DEF_PS_POST_QLIMIT, &var_ps_post_queue_limit, 5, 0,
- VAR_PS_PRE_QLIMIT, DEF_PS_PRE_QLIMIT, &var_ps_pre_queue_limit, 10, 0,
- VAR_PS_CCONN_LIMIT, DEF_PS_CCONN_LIMIT, &var_ps_cconn_limit, 0, 0,
+ VAR_PSC_POST_QLIMIT, DEF_PSC_POST_QLIMIT, &var_psc_post_queue_limit, 5, 0,
+ VAR_PSC_PRE_QLIMIT, DEF_PSC_PRE_QLIMIT, &var_psc_pre_queue_limit, 10, 0,
+ VAR_PSC_CCONN_LIMIT, DEF_PSC_CCONN_LIMIT, &var_psc_cconn_limit, 0, 0,
0,
};
static const CONFIG_TIME_TABLE time_table[] = {
- VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, &var_ps_greet_wait, 1, 0,
- VAR_PS_PREGR_TTL, DEF_PS_PREGR_TTL, &var_ps_pregr_ttl, 1, 0,
- VAR_PS_DNSBL_TTL, DEF_PS_DNSBL_TTL, &var_ps_dnsbl_ttl, 1, 0,
- VAR_PS_PIPEL_TTL, DEF_PS_PIPEL_TTL, &var_ps_pipel_ttl, 1, 0,
- VAR_PS_NSMTP_TTL, DEF_PS_NSMTP_TTL, &var_ps_nsmtp_ttl, 1, 0,
- VAR_PS_BARLF_TTL, DEF_PS_BARLF_TTL, &var_ps_barlf_ttl, 1, 0,
- VAR_PS_CACHE_RET, DEF_PS_CACHE_RET, &var_ps_cache_ret, 1, 0,
- VAR_PS_CACHE_SCAN, DEF_PS_CACHE_SCAN, &var_ps_cache_scan, 1, 0,
- VAR_PS_WATCHDOG, DEF_PS_WATCHDOG, &var_ps_watchdog, 10, 0,
+ VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, &var_psc_greet_wait, 1, 0,
+ VAR_PSC_PREGR_TTL, DEF_PSC_PREGR_TTL, &var_psc_pregr_ttl, 1, 0,
+ VAR_PSC_DNSBL_TTL, DEF_PSC_DNSBL_TTL, &var_psc_dnsbl_ttl, 1, 0,
+ VAR_PSC_PIPEL_TTL, DEF_PSC_PIPEL_TTL, &var_psc_pipel_ttl, 1, 0,
+ VAR_PSC_NSMTP_TTL, DEF_PSC_NSMTP_TTL, &var_psc_nsmtp_ttl, 1, 0,
+ VAR_PSC_BARLF_TTL, DEF_PSC_BARLF_TTL, &var_psc_barlf_ttl, 1, 0,
+ VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0,
+ VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 1, 0,
+ VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0,
0,
};
static const CONFIG_BOOL_TABLE bool_table[] = {
VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required,
VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd,
- VAR_PS_PIPEL_ENABLE, DEF_PS_PIPEL_ENABLE, &var_ps_pipel_enable,
- VAR_PS_NSMTP_ENABLE, DEF_PS_NSMTP_ENABLE, &var_ps_nsmtp_enable,
- VAR_PS_BARLF_ENABLE, DEF_PS_BARLF_ENABLE, &var_ps_barlf_enable,
+ VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
+ VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
+ VAR_PSC_PIPEL_ENABLE, DEF_PSC_PIPEL_ENABLE, &var_psc_pipel_enable,
+ VAR_PSC_NSMTP_ENABLE, DEF_PSC_NSMTP_ENABLE, &var_psc_nsmtp_enable,
+ VAR_PSC_BARLF_ENABLE, DEF_PSC_BARLF_ENABLE, &var_psc_barlf_enable,
0,
};
static const CONFIG_RAW_TABLE raw_table[] = {
- VAR_PS_CMD_TIME, DEF_PS_CMD_TIME, &var_ps_cmd_time, 1, 0,
+ VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0,
0,
};
static const CONFIG_NBOOL_TABLE nbool_table[] = {
- VAR_PS_HELO_REQUIRED, DEF_PS_HELO_REQUIRED, &var_ps_helo_required,
- VAR_PS_DISABLE_VRFY, DEF_PS_DISABLE_VRFY, &var_ps_disable_vrfy,
+ VAR_PSC_HELO_REQUIRED, DEF_PSC_HELO_REQUIRED, &var_psc_helo_required,
+ VAR_PSC_DISABLE_VRFY, DEF_PSC_DISABLE_VRFY, &var_psc_disable_vrfy,
+ VAR_PSC_USE_TLS, DEF_PSC_USE_TLS, &var_psc_use_tls,
+ VAR_PSC_ENFORCE_TLS, DEF_PSC_ENFORCE_TLS, &var_psc_enforce_tls,
0,
};
*/
MAIL_VERSION_STAMP_ALLOCATE;
- event_server_main(argc, argv, ps_service,
+ event_server_main(argc, argv, psc_service,
MAIL_SERVER_STR_TABLE, str_table,
MAIL_SERVER_INT_TABLE, int_table,
MAIL_SERVER_NINT_TABLE, nint_table,
MAIL_SERVER_NBOOL_TABLE, nbool_table,
MAIL_SERVER_PRE_INIT, pre_jail_init,
MAIL_SERVER_POST_INIT, post_jail_init,
+ MAIL_SERVER_PRE_ACCEPT, pre_accept,
MAIL_SERVER_SOLITARY,
- MAIL_SERVER_SLOW_EXIT, ps_drain,
- MAIL_SERVER_EXIT, ps_dump,
- MAIL_SERVER_WATCHDOG, &var_ps_watchdog,
+ MAIL_SERVER_SLOW_EXIT, psc_drain,
+ MAIL_SERVER_EXIT, psc_dump,
+ MAIL_SERVER_WATCHDOG, &var_psc_watchdog,
0);
}
/*
* Preliminary stuff, to be fixed.
*/
-#define PS_READ_BUF_SIZE 1024
+#define PSC_READ_BUF_SIZE 1024
/*
* Per-session state.
char *sender; /* MAIL FROM */
VSTRING *cmd_buffer; /* command read buffer */
int read_state; /* command read state machine */
-} PS_STATE;
-
-#define PS_TIME_STAMP_NEW (0) /* test was never passed */
-#define PS_TIME_STAMP_DISABLED (1) /* never passed but disabled */
-#define PS_TIME_STAMP_INVALID (-1) /* must not be cached */
-
-#define PS_STATE_FLAG_NOFORWARD (1<<0) /* don't forward this session */
-#define PS_STATE_FLAG_UNUSED1 (1<<1) /* use me! */
-#define PS_STATE_FLAG_UNUSED2 (1<<2) /* use me! */
-#define PS_STATE_FLAG_NEW (1<<3) /* some test was never passed */
-#define PS_STATE_FLAG_BLIST_FAIL (1<<4) /* blacklisted */
-#define PS_STATE_FLAG_HANGUP (1<<5) /* NOT a test failure */
-#define PS_STATE_FLAG_CACHE_EXPIRED (1<<6) /* cache retention expired */
+ /* smtpd(8) compatibility */
+ int ehlo_discard_mask; /* EHLO filter */
+} PSC_STATE;
+
+#define PSC_TIME_STAMP_NEW (0) /* test was never passed */
+#define PSC_TIME_STAMP_DISABLED (1) /* never passed but disabled */
+#define PSC_TIME_STAMP_INVALID (-1) /* must not be cached */
+
+#define PSC_STATE_FLAG_NOFORWARD (1<<0) /* don't forward this session */
+#define PSC_STATE_FLAG_USING_TLS (1<<1) /* using the TLS proxy */
+#define PSC_STATE_FLAG_UNUSED2 (1<<2) /* use me! */
+#define PSC_STATE_FLAG_NEW (1<<3) /* some test was never passed */
+#define PSC_STATE_FLAG_BLIST_FAIL (1<<4) /* blacklisted */
+#define PSC_STATE_FLAG_HANGUP (1<<5) /* NOT a test failure */
+#define PSC_STATE_FLAG_CACHE_EXPIRED (1<<6) /* cache retention expired */
/*
* Important: every MUMBLE_TODO flag must have a MUMBLE_PASS flag, such that
- * MUMBLE_PASS == PS_STATE_FLAGS_TODO_TO_PASS(MUMBLE_TODO).
+ * MUMBLE_PASS == PSC_STATE_FLAGS_TODO_TO_PASS(MUMBLE_TODO).
*
* MUMBLE_TODO flags must not be cleared once raised. The _TODO_TO_PASS and
* _TODO_TO_DONE macros depend on this to decide that a group of tests is
* We use MUMBLE_SKIP to indicate that a decision was either "fail" or
* forced "pass".
*/
-#define PS_STATE_FLAGS_TODO_TO_PASS(todo_flags) ((todo_flags) >> 1)
-#define PS_STATE_FLAGS_TODO_TO_DONE(todo_flags) ((todo_flags) << 1)
+#define PSC_STATE_FLAGS_TODO_TO_PASS(todo_flags) ((todo_flags) >> 1)
+#define PSC_STATE_FLAGS_TODO_TO_DONE(todo_flags) ((todo_flags) << 1)
-#define PS_STATE_FLAG_PENAL_UPDATE (1<<6) /* save new penalty */
-#define PS_STATE_FLAG_PENAL_FAIL (1<<7) /* penalty is active */
+#define PSC_STATE_FLAG_PENAL_UPDATE (1<<6) /* save new penalty */
+#define PSC_STATE_FLAG_PENAL_FAIL (1<<7) /* penalty is active */
-#define PS_STATE_FLAG_PREGR_FAIL (1<<8) /* failed pregreet test */
-#define PS_STATE_FLAG_PREGR_PASS (1<<9) /* passed pregreet test */
-#define PS_STATE_FLAG_PREGR_TODO (1<<10) /* pregreet test expired */
-#define PS_STATE_FLAG_PREGR_DONE (1<<11) /* decision is final */
+#define PSC_STATE_FLAG_PREGR_FAIL (1<<8) /* failed pregreet test */
+#define PSC_STATE_FLAG_PREGR_PASS (1<<9) /* passed pregreet test */
+#define PSC_STATE_FLAG_PREGR_TODO (1<<10) /* pregreet test expired */
+#define PSC_STATE_FLAG_PREGR_DONE (1<<11) /* decision is final */
-#define PS_STATE_FLAG_DNSBL_FAIL (1<<12) /* failed DNSBL test */
-#define PS_STATE_FLAG_DNSBL_PASS (1<<13) /* passed DNSBL test */
-#define PS_STATE_FLAG_DNSBL_TODO (1<<14) /* DNSBL test expired */
-#define PS_STATE_FLAG_DNSBL_DONE (1<<15) /* decision is final */
+#define PSC_STATE_FLAG_DNSBL_FAIL (1<<12) /* failed DNSBL test */
+#define PSC_STATE_FLAG_DNSBL_PASS (1<<13) /* passed DNSBL test */
+#define PSC_STATE_FLAG_DNSBL_TODO (1<<14) /* DNSBL test expired */
+#define PSC_STATE_FLAG_DNSBL_DONE (1<<15) /* decision is final */
/* Room here for one more after-handshake test. */
-#define PS_STATE_FLAG_PIPEL_FAIL (1<<20) /* failed pipelining test */
-#define PS_STATE_FLAG_PIPEL_PASS (1<<21) /* passed pipelining test */
-#define PS_STATE_FLAG_PIPEL_TODO (1<<22) /* pipelining test expired */
-#define PS_STATE_FLAG_PIPEL_SKIP (1<<23) /* action is already logged */
+#define PSC_STATE_FLAG_PIPEL_FAIL (1<<20) /* failed pipelining test */
+#define PSC_STATE_FLAG_PIPEL_PASS (1<<21) /* passed pipelining test */
+#define PSC_STATE_FLAG_PIPEL_TODO (1<<22) /* pipelining test expired */
+#define PSC_STATE_FLAG_PIPEL_SKIP (1<<23) /* action is already logged */
-#define PS_STATE_FLAG_NSMTP_FAIL (1<<24) /* failed non-SMTP test */
-#define PS_STATE_FLAG_NSMTP_PASS (1<<25) /* passed non-SMTP test */
-#define PS_STATE_FLAG_NSMTP_TODO (1<<26) /* non-SMTP test expired */
-#define PS_STATE_FLAG_NSMTP_SKIP (1<<27) /* action is already logged */
+#define PSC_STATE_FLAG_NSMTP_FAIL (1<<24) /* failed non-SMTP test */
+#define PSC_STATE_FLAG_NSMTP_PASS (1<<25) /* passed non-SMTP test */
+#define PSC_STATE_FLAG_NSMTP_TODO (1<<26) /* non-SMTP test expired */
+#define PSC_STATE_FLAG_NSMTP_SKIP (1<<27) /* action is already logged */
-#define PS_STATE_FLAG_BARLF_FAIL (1<<28) /* failed bare newline test */
-#define PS_STATE_FLAG_BARLF_PASS (1<<29) /* passed bare newline test */
-#define PS_STATE_FLAG_BARLF_TODO (1<<30) /* bare newline test expired */
-#define PS_STATE_FLAG_BARLF_SKIP (1<<31) /* action is already logged */
+#define PSC_STATE_FLAG_BARLF_FAIL (1<<28) /* failed bare newline test */
+#define PSC_STATE_FLAG_BARLF_PASS (1<<29) /* passed bare newline test */
+#define PSC_STATE_FLAG_BARLF_TODO (1<<30) /* bare newline test expired */
+#define PSC_STATE_FLAG_BARLF_SKIP (1<<31) /* action is already logged */
/*
* Aggregates for individual tests.
*/
-#define PS_STATE_MASK_PREGR_TODO_FAIL \
- (PS_STATE_FLAG_PREGR_TODO | PS_STATE_FLAG_PREGR_FAIL)
-#define PS_STATE_MASK_DNSBL_TODO_FAIL \
- (PS_STATE_FLAG_DNSBL_TODO | PS_STATE_FLAG_DNSBL_FAIL)
-#define PS_STATE_MASK_PIPEL_TODO_FAIL \
- (PS_STATE_FLAG_PIPEL_TODO | PS_STATE_FLAG_PIPEL_FAIL)
-#define PS_STATE_MASK_NSMTP_TODO_FAIL \
- (PS_STATE_FLAG_NSMTP_TODO | PS_STATE_FLAG_NSMTP_FAIL)
-#define PS_STATE_MASK_BARLF_TODO_FAIL \
- (PS_STATE_FLAG_BARLF_TODO | PS_STATE_FLAG_BARLF_FAIL)
-
-#define PS_STATE_MASK_PIPEL_TODO_SKIP \
- (PS_STATE_FLAG_PIPEL_TODO | PS_STATE_FLAG_PIPEL_SKIP)
-#define PS_STATE_MASK_NSMTP_TODO_SKIP \
- (PS_STATE_FLAG_NSMTP_TODO | PS_STATE_FLAG_NSMTP_SKIP)
-#define PS_STATE_MASK_BARLF_TODO_SKIP \
- (PS_STATE_FLAG_BARLF_TODO | PS_STATE_FLAG_BARLF_SKIP)
-
-#define PS_STATE_MASK_PIPEL_TODO_PASS_FAIL \
- (PS_STATE_MASK_PIPEL_TODO_FAIL | PS_STATE_FLAG_PIPEL_PASS)
-#define PS_STATE_MASK_NSMTP_TODO_PASS_FAIL \
- (PS_STATE_MASK_NSMTP_TODO_FAIL | PS_STATE_FLAG_NSMTP_PASS)
-#define PS_STATE_MASK_BARLF_TODO_PASS_FAIL \
- (PS_STATE_MASK_BARLF_TODO_FAIL | PS_STATE_FLAG_BARLF_PASS)
+#define PSC_STATE_MASK_PREGR_TODO_FAIL \
+ (PSC_STATE_FLAG_PREGR_TODO | PSC_STATE_FLAG_PREGR_FAIL)
+#define PSC_STATE_MASK_DNSBL_TODO_FAIL \
+ (PSC_STATE_FLAG_DNSBL_TODO | PSC_STATE_FLAG_DNSBL_FAIL)
+#define PSC_STATE_MASK_PIPEL_TODO_FAIL \
+ (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_PIPEL_FAIL)
+#define PSC_STATE_MASK_NSMTP_TODO_FAIL \
+ (PSC_STATE_FLAG_NSMTP_TODO | PSC_STATE_FLAG_NSMTP_FAIL)
+#define PSC_STATE_MASK_BARLF_TODO_FAIL \
+ (PSC_STATE_FLAG_BARLF_TODO | PSC_STATE_FLAG_BARLF_FAIL)
+
+#define PSC_STATE_MASK_PIPEL_TODO_SKIP \
+ (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_PIPEL_SKIP)
+#define PSC_STATE_MASK_NSMTP_TODO_SKIP \
+ (PSC_STATE_FLAG_NSMTP_TODO | PSC_STATE_FLAG_NSMTP_SKIP)
+#define PSC_STATE_MASK_BARLF_TODO_SKIP \
+ (PSC_STATE_FLAG_BARLF_TODO | PSC_STATE_FLAG_BARLF_SKIP)
+
+#define PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL \
+ (PSC_STATE_MASK_PIPEL_TODO_FAIL | PSC_STATE_FLAG_PIPEL_PASS)
+#define PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL \
+ (PSC_STATE_MASK_NSMTP_TODO_FAIL | PSC_STATE_FLAG_NSMTP_PASS)
+#define PSC_STATE_MASK_BARLF_TODO_PASS_FAIL \
+ (PSC_STATE_MASK_BARLF_TODO_FAIL | PSC_STATE_FLAG_BARLF_PASS)
/*
* Separate aggregates for early tests and deep tests.
*/
-#define PS_STATE_MASK_EARLY_DONE \
- (PS_STATE_FLAG_PREGR_DONE | PS_STATE_FLAG_DNSBL_DONE)
-#define PS_STATE_MASK_EARLY_TODO \
- (PS_STATE_FLAG_PREGR_TODO | PS_STATE_FLAG_DNSBL_TODO)
-#define PS_STATE_MASK_EARLY_PASS \
- (PS_STATE_FLAG_PREGR_PASS | PS_STATE_FLAG_DNSBL_PASS)
-#define PS_STATE_MASK_EARLY_FAIL \
- (PS_STATE_FLAG_PREGR_FAIL | PS_STATE_FLAG_DNSBL_FAIL)
-
-#define PS_STATE_MASK_SMTPD_TODO \
- (PS_STATE_FLAG_PIPEL_TODO | PS_STATE_FLAG_NSMTP_TODO | \
- PS_STATE_FLAG_BARLF_TODO)
-#define PS_STATE_MASK_SMTPD_PASS \
- (PS_STATE_FLAG_PIPEL_PASS | PS_STATE_FLAG_NSMTP_PASS | \
- PS_STATE_FLAG_BARLF_PASS)
-#define PS_STATE_MASK_SMTPD_FAIL \
- (PS_STATE_FLAG_PIPEL_FAIL | PS_STATE_FLAG_NSMTP_FAIL | \
- PS_STATE_FLAG_BARLF_FAIL)
+#define PSC_STATE_MASK_EARLY_DONE \
+ (PSC_STATE_FLAG_PREGR_DONE | PSC_STATE_FLAG_DNSBL_DONE)
+#define PSC_STATE_MASK_EARLY_TODO \
+ (PSC_STATE_FLAG_PREGR_TODO | PSC_STATE_FLAG_DNSBL_TODO)
+#define PSC_STATE_MASK_EARLY_PASS \
+ (PSC_STATE_FLAG_PREGR_PASS | PSC_STATE_FLAG_DNSBL_PASS)
+#define PSC_STATE_MASK_EARLY_FAIL \
+ (PSC_STATE_FLAG_PREGR_FAIL | PSC_STATE_FLAG_DNSBL_FAIL)
+
+#define PSC_STATE_MASK_SMTPD_TODO \
+ (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_NSMTP_TODO | \
+ PSC_STATE_FLAG_BARLF_TODO)
+#define PSC_STATE_MASK_SMTPD_PASS \
+ (PSC_STATE_FLAG_PIPEL_PASS | PSC_STATE_FLAG_NSMTP_PASS | \
+ PSC_STATE_FLAG_BARLF_PASS)
+#define PSC_STATE_MASK_SMTPD_FAIL \
+ (PSC_STATE_FLAG_PIPEL_FAIL | PSC_STATE_FLAG_NSMTP_FAIL | \
+ PSC_STATE_FLAG_BARLF_FAIL)
/*
* Super-aggregates for all tests combined.
*/
-#define PS_STATE_MASK_ANY_FAIL \
- (PS_STATE_FLAG_BLIST_FAIL | PS_STATE_FLAG_PENAL_FAIL | \
- PS_STATE_MASK_EARLY_FAIL | PS_STATE_MASK_SMTPD_FAIL)
+#define PSC_STATE_MASK_ANY_FAIL \
+ (PSC_STATE_FLAG_BLIST_FAIL | PSC_STATE_FLAG_PENAL_FAIL | \
+ PSC_STATE_MASK_EARLY_FAIL | PSC_STATE_MASK_SMTPD_FAIL)
-#define PS_STATE_MASK_ANY_PASS \
- (PS_STATE_MASK_EARLY_PASS | PS_STATE_MASK_SMTPD_PASS)
+#define PSC_STATE_MASK_ANY_PASS \
+ (PSC_STATE_MASK_EARLY_PASS | PSC_STATE_MASK_SMTPD_PASS)
-#define PS_STATE_MASK_ANY_TODO \
- (PS_STATE_MASK_EARLY_TODO | PS_STATE_MASK_SMTPD_TODO)
+#define PSC_STATE_MASK_ANY_TODO \
+ (PSC_STATE_MASK_EARLY_TODO | PSC_STATE_MASK_SMTPD_TODO)
-#define PS_STATE_MASK_ANY_TODO_FAIL \
- (PS_STATE_MASK_ANY_TODO | PS_STATE_MASK_ANY_FAIL)
+#define PSC_STATE_MASK_ANY_TODO_FAIL \
+ (PSC_STATE_MASK_ANY_TODO | PSC_STATE_MASK_ANY_FAIL)
-#define PS_STATE_MASK_ANY_UPDATE \
- (PS_STATE_MASK_ANY_PASS | PS_STATE_FLAG_PENAL_UPDATE)
+#define PSC_STATE_MASK_ANY_UPDATE \
+ (PSC_STATE_MASK_ANY_PASS | PSC_STATE_FLAG_PENAL_UPDATE)
/*
* See log_adhoc.c for discussion.
int dt_usec; /* make sure it's signed */
} DELTA_TIME;
-#define PS_CALC_DELTA(x, y, z) \
+#define PSC_CALC_DELTA(x, y, z) \
do { \
(x).dt_sec = (y).tv_sec - (z).tv_sec; \
(x).dt_usec = (y).tv_usec - (z).tv_usec; \
* Event management.
*/
-/* PS_READ_EVENT_REQUEST - prepare for transition to next state */
+/* PSC_READ_EVENT_REQUEST - prepare for transition to next state */
-#define PS_READ_EVENT_REQUEST(fd, action, context, timeout) do { \
+#define PSC_READ_EVENT_REQUEST(fd, action, context, timeout) do { \
if (msg_verbose > 1) \
msg_info("%s: read-request fd=%d", myname, (fd)); \
event_enable_read((fd), (action), (context)); \
event_request_timer((action), (context), (timeout)); \
} while (0)
-#define PS_READ_EVENT_REQUEST2(fd, read_act, time_act, context, timeout) do { \
+#define PSC_READ_EVENT_REQUEST2(fd, read_act, time_act, context, timeout) do { \
if (msg_verbose > 1) \
msg_info("%s: read-request fd=%d", myname, (fd)); \
event_enable_read((fd), (read_act), (context)); \
event_request_timer((time_act), (context), (timeout)); \
} while (0)
-/* PS_CLEAR_EVENT_REQUEST - complete state transition */
+/* PSC_CLEAR_EVENT_REQUEST - complete state transition */
-#define PS_CLEAR_EVENT_REQUEST(fd, time_act, context) do { \
+#define PSC_CLEAR_EVENT_REQUEST(fd, time_act, context) do { \
if (msg_verbose > 1) \
msg_info("%s: clear-request fd=%d", myname, (fd)); \
event_disable_readwrite(fd); \
/*
* Failure enforcement policies.
*/
-#define PS_NAME_ACT_DROP "drop"
-#define PS_NAME_ACT_ENFORCE "enforce"
-#define PS_NAME_ACT_IGNORE "ignore"
-#define PS_NAME_ACT_CONT "continue"
+#define PSC_NAME_ACT_DROP "drop"
+#define PSC_NAME_ACT_ENFORCE "enforce"
+#define PSC_NAME_ACT_IGNORE "ignore"
+#define PSC_NAME_ACT_CONT "continue"
-#define PS_ACT_DROP 1
-#define PS_ACT_ENFORCE 2
-#define PS_ACT_IGNORE 3
+#define PSC_ACT_DROP 1
+#define PSC_ACT_ENFORCE 2
+#define PSC_ACT_IGNORE 3
/*
* Global variables.
*/
-extern int ps_check_queue_length; /* connections being checked */
-extern int ps_post_queue_length; /* being sent to real SMTPD */
-extern DICT_CACHE *ps_cache_map; /* cache table handle */
-extern VSTRING *ps_temp; /* scratchpad */
-extern char *ps_smtpd_service_name; /* path to real SMTPD */
-extern int ps_pregr_action; /* PS_ACT_DROP etc. */
-extern int ps_dnsbl_action; /* PS_ACT_DROP etc. */
-extern int ps_pipel_action; /* PS_ACT_DROP etc. */
-extern int ps_nsmtp_action; /* PS_ACT_DROP etc. */
-extern int ps_barlf_action; /* PS_ACT_DROP etc. */
-extern int ps_min_ttl; /* Update with new tests! */
-extern int ps_max_ttl; /* Update with new tests! */
-extern STRING_LIST *ps_forbid_cmds; /* CONNECT GET POST */
-extern int ps_stress_greet_wait; /* stressed greet wait */
-extern int ps_normal_greet_wait; /* stressed greet wait */
-extern int ps_stress_cmd_time_limit; /* stressed command limit */
-extern int ps_normal_cmd_time_limit; /* normal command time limit */
-extern int ps_stress; /* stress level */
-extern int ps_check_queue_length_lowat; /* stress low-water mark */
-extern int ps_check_queue_length_hiwat; /* stress high-water mark */
-extern DICT *ps_dnsbl_reply; /* DNSBL name mapper */
-extern HTABLE *ps_client_concurrency; /* per-client concurrency */
-
-#define PS_EFF_GREET_WAIT \
- (ps_stress ? ps_stress_greet_wait : ps_normal_greet_wait)
-#define PS_EFF_CMD_TIME_LIMIT \
- (ps_stress ? ps_stress_cmd_time_limit : ps_normal_cmd_time_limit)
+extern int psc_check_queue_length; /* connections being checked */
+extern int psc_post_queue_length; /* being sent to real SMTPD */
+extern DICT_CACHE *psc_cache_map; /* cache table handle */
+extern VSTRING *psc_temp; /* scratchpad */
+extern char *psc_smtpd_service_name; /* path to real SMTPD */
+extern int psc_pregr_action; /* PSC_ACT_DROP etc. */
+extern int psc_dnsbl_action; /* PSC_ACT_DROP etc. */
+extern int psc_pipel_action; /* PSC_ACT_DROP etc. */
+extern int psc_nsmtp_action; /* PSC_ACT_DROP etc. */
+extern int psc_barlf_action; /* PSC_ACT_DROP etc. */
+extern int psc_min_ttl; /* Update with new tests! */
+extern int psc_max_ttl; /* Update with new tests! */
+extern STRING_LIST *psc_forbid_cmds; /* CONNECT GET POST */
+extern int psc_stress_greet_wait; /* stressed greet wait */
+extern int psc_normal_greet_wait; /* stressed greet wait */
+extern int psc_stress_cmd_time_limit; /* stressed command limit */
+extern int psc_normal_cmd_time_limit; /* normal command time limit */
+extern int psc_stress; /* stress level */
+extern int psc_check_queue_length_lowat;/* stress low-water mark */
+extern int psc_check_queue_length_hiwat;/* stress high-water mark */
+extern DICT *psc_dnsbl_reply; /* DNSBL name mapper */
+extern HTABLE *psc_client_concurrency; /* per-client concurrency */
+
+#define PSC_EFF_GREET_WAIT \
+ (psc_stress ? psc_stress_greet_wait : psc_normal_greet_wait)
+#define PSC_EFF_CMD_TIME_LIMIT \
+ (psc_stress ? psc_stress_cmd_time_limit : psc_normal_cmd_time_limit)
/*
* String plumbing macros.
*/
-#define PS_STRING_UPDATE(str, text) do { \
+#define PSC_STRING_UPDATE(str, text) do { \
if (str) myfree(str); \
(str) = ((text) ? mystrdup(text) : 0); \
} while (0)
-#define PS_STRING_RESET(str) do { \
+#define PSC_STRING_RESET(str) do { \
if (str) { \
myfree(str); \
(str) = 0; \
/*
* postscreen_state.c
*/
-#define PS_CLIENT_ADDR_PORT(state) \
+#define PSC_CLIENT_ADDR_PORT(state) \
(state)->smtp_client_addr, (state)->smtp_client_port
-#define PS_PASS_SESSION_STATE(state, what, bits) do { \
+#define PSC_PASS_SESSION_STATE(state, what, bits) do { \
if (msg_verbose) \
- msg_info("PASS %s [%s]:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("PASS %s [%s]:%s", (what), PSC_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
-#define PS_FAIL_SESSION_STATE(state, bits) do { \
+#define PSC_FAIL_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("FAIL [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("FAIL [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
-#define PS_SKIP_SESSION_STATE(state, what, bits) do { \
+#define PSC_SKIP_SESSION_STATE(state, what, bits) do { \
if (msg_verbose) \
- msg_info("SKIP %s [%s]:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("SKIP %s [%s]:%s", (what), PSC_CLIENT_ADDR_PORT(state)); \
(state)->flags |= (bits); \
} while (0)
-#define PS_DROP_SESSION_STATE(state, reply) do { \
+#define PSC_DROP_SESSION_STATE(state, reply) do { \
if (msg_verbose) \
- msg_info("DROP [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
- (state)->flags |= PS_STATE_FLAG_NOFORWARD; \
+ msg_info("DROP [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \
+ (state)->flags |= PSC_STATE_FLAG_NOFORWARD; \
(state)->final_reply = (reply); \
- ps_conclude(state); \
+ psc_conclude(state); \
} while (0)
-#define PS_ENFORCE_SESSION_STATE(state, reply) do { \
+#define PSC_ENFORCE_SESSION_STATE(state, reply) do { \
if (msg_verbose) \
- msg_info("ENFORCE [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("ENFORCE [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \
(state)->rcpt_reply = (reply); \
- (state)->flags |= PS_STATE_FLAG_NOFORWARD; \
+ (state)->flags |= PSC_STATE_FLAG_NOFORWARD; \
} while (0)
-#define PS_UNPASS_SESSION_STATE(state, bits) do { \
+#define PSC_UNPASS_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("UNPASS [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("UNPASS [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \
(state)->flags &= ~(bits); \
} while (0)
-#define PS_UNFAIL_SESSION_STATE(state, bits) do { \
+#define PSC_UNFAIL_SESSION_STATE(state, bits) do { \
if (msg_verbose) \
- msg_info("UNFAIL [%s]:%s", PS_CLIENT_ADDR_PORT(state)); \
+ msg_info("UNFAIL [%s]:%s", PSC_CLIENT_ADDR_PORT(state)); \
(state)->flags &= ~(bits); \
} while (0)
-#define PS_ADD_SERVER_STATE(state, fd) do { \
+#define PSC_ADD_SERVER_STATE(state, fd) do { \
(state)->smtp_server_fd = (fd); \
- ps_post_queue_length++; \
+ psc_post_queue_length++; \
} while (0)
-#define PS_DEL_CLIENT_STATE(state) do { \
+#define PSC_DEL_CLIENT_STATE(state) do { \
event_server_disconnect((state)->smtp_client_stream); \
(state)->smtp_client_stream = 0; \
- ps_check_queue_length--; \
+ psc_check_queue_length--; \
} while (0)
-extern PS_STATE *ps_new_session_state(VSTREAM *, const char *, const char *);
-extern void ps_free_session_state(PS_STATE *);
-extern const char *ps_print_state_flags(int, const char *);
+extern PSC_STATE *psc_new_session_state(VSTREAM *, const char *, const char *);
+extern void psc_free_session_state(PSC_STATE *);
+extern const char *psc_print_state_flags(int, const char *);
/*
* postscreen_dict.c
*/
-extern int ps_addr_match_list_match(ADDR_MATCH_LIST *, const char *);
-extern const char *ps_cache_lookup(DICT_CACHE *, const char *);
-extern void ps_cache_update(DICT_CACHE *, const char *, const char *);
+extern int psc_addr_match_list_match(ADDR_MATCH_LIST *, const char *);
+extern const char *psc_cache_lookup(DICT_CACHE *, const char *);
+extern void psc_cache_update(DICT_CACHE *, const char *, const char *);
/*
* postscreen_dnsbl.c
*/
-extern void ps_dnsbl_init(void);
-extern int ps_dnsbl_retrieve(const char *, const char **, int);
-extern int ps_dnsbl_request(const char *, void (*) (int, char *), char *);
+extern void psc_dnsbl_init(void);
+extern int psc_dnsbl_retrieve(const char *, const char **, int);
+extern int psc_dnsbl_request(const char *, void (*) (int, char *), char *);
/*
* postscreen_tests.c
*/
-#define PS_INIT_TESTS(dst) do { \
+#define PSC_INIT_TESTS(dst) do { \
(dst)->flags = 0; \
- (dst)->pregr_stamp = PS_TIME_STAMP_INVALID; \
- (dst)->dnsbl_stamp = PS_TIME_STAMP_INVALID; \
- (dst)->pipel_stamp = PS_TIME_STAMP_INVALID; \
- (dst)->barlf_stamp = PS_TIME_STAMP_INVALID; \
- (dst)->penal_stamp = PS_TIME_STAMP_INVALID; \
+ (dst)->pregr_stamp = PSC_TIME_STAMP_INVALID; \
+ (dst)->dnsbl_stamp = PSC_TIME_STAMP_INVALID; \
+ (dst)->pipel_stamp = PSC_TIME_STAMP_INVALID; \
+ (dst)->barlf_stamp = PSC_TIME_STAMP_INVALID; \
+ (dst)->penal_stamp = PSC_TIME_STAMP_INVALID; \
} while (0)
-#define PS_BEGIN_TESTS(state, name) do { \
+#define PSC_BEGIN_TESTS(state, name) do { \
(state)->test_name = (name); \
GETTIMEOFDAY(&(state)->start_time); \
} while (0)
-extern void ps_new_tests(PS_STATE *);
-extern void ps_parse_tests(PS_STATE *, const char *, time_t);
-extern char *ps_print_tests(VSTRING *, PS_STATE *);
-extern char *ps_print_grey_key(VSTRING *, const char *, const char *, const char *, const char *);
+extern void psc_new_tests(PSC_STATE *);
+extern void psc_parse_tests(PSC_STATE *, const char *, time_t);
+extern char *psc_print_tests(VSTRING *, PSC_STATE *);
+extern char *psc_print_grey_key(VSTRING *, const char *, const char *,
+ const char *, const char *);
-#define PS_MIN(x, y) ((x) < (y) ? (x) : (y))
-#define PS_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define PSC_MIN(x, y) ((x) < (y) ? (x) : (y))
+#define PSC_MAX(x, y) ((x) > (y) ? (x) : (y))
/*
* postscreen_early.c
*/
-extern void ps_early_tests(PS_STATE *);
-extern void ps_early_init(void);
+extern void psc_early_tests(PSC_STATE *);
+extern void psc_early_init(void);
/*
* postscreen_smtpd.c
*/
-extern void ps_smtpd_tests(PS_STATE *);
-extern void ps_smtpd_init(void);
+extern void psc_smtpd_tests(PSC_STATE *);
+extern void psc_smtpd_init(void);
+extern void psc_smtpd_pre_jail_init(void);
/*
* postscreen_misc.c
*/
-extern char *ps_format_delta_time(VSTRING *, struct timeval, DELTA_TIME *);
-extern void ps_conclude(PS_STATE *);
-extern void ps_hangup_event(PS_STATE *);
+extern char *psc_format_delta_time(VSTRING *, struct timeval, DELTA_TIME *);
+extern void psc_conclude(PSC_STATE *);
+extern void psc_hangup_event(PSC_STATE *);
/*
* postscreen_send.c
*/
-#define PS_SEND_REPLY(state, text) \
- ps_send_reply(vstream_fileno((state)->smtp_client_stream), \
+#define PSC_SEND_REPLY(state, text) \
+ psc_send_reply(vstream_fileno((state)->smtp_client_stream), \
(state)->smtp_client_addr, \
(state)->smtp_client_port, \
(text))
-extern int ps_send_reply(int, const char *, const char *, const char *);
-extern void ps_send_socket(PS_STATE *);
+extern int psc_send_reply(int, const char *, const char *, const char *);
+extern void psc_send_socket(PSC_STATE *);
+
+ /*
+ * postscreen_starttls.c
+ */
+extern void psc_starttls_open(PSC_STATE *, EVENT_NOTIFY_FN);
/* LICENSE
/* .ad
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* int ps_addr_match_list_match(match_list, client_addr)
+/* int psc_addr_match_list_match(match_list, client_addr)
/* ADDR_MATCH_LIST *match_list;
/* const char *client_addr;
/*
-/* const char *ps_cache_lookup(DICT_CACHE *cache, const char *key)
+/* const char *psc_cache_lookup(DICT_CACHE *cache, const char *key)
/* DICT_CACHE *cache;
/* const char *key;
/*
-/* void ps_cache_update(cache, key, value)
+/* void psc_cache_update(cache, key, value)
/* DICT_CACHE *cache;
/* const char *key;
/* const char *value;
/* access functions. The functions log a warning when table
/* access takes a non-trivial amount of time.
/*
-/* ps_addr_match_list_match() is a wrapper around
+/* psc_addr_match_list_match() is a wrapper around
/* addr_match_list_match().
/*
-/* ps_cache_lookup() and ps_cache_update() are wrappers around
+/* psc_cache_lookup() and psc_cache_update() are wrappers around
/* the corresponding dict_cache() methods.
/* LICENSE
/* .ad
/*
* Monitor time-critical operations.
*/
-#define PS_GET_TIME_BEFORE_LOOKUP \
+#define PSC_GET_TIME_BEFORE_LOOKUP \
struct timeval _before, _after; \
DELTA_TIME _delta; \
GETTIMEOFDAY(&_before);
-#define PS_DELTA_MS(d) ((d).dt_sec * 1000 + (d).dt_usec / 1000)
+#define PSC_DELTA_MS(d) ((d).dt_sec * 1000 + (d).dt_usec / 1000)
-#define PS_CHECK_TIME_AFTER_LOOKUP(table, action) \
+#define PSC_CHECK_TIME_AFTER_LOOKUP(table, action) \
GETTIMEOFDAY(&_after); \
- PS_CALC_DELTA(_delta, _after, _before); \
+ PSC_CALC_DELTA(_delta, _after, _before); \
if (_delta.dt_sec > 1 || _delta.dt_usec > 100000) \
msg_warn("%s: %s %s took %d ms", \
- myname, (table), (action), PS_DELTA_MS(_delta));
+ myname, (table), (action), PSC_DELTA_MS(_delta));
-/* ps_addr_match_list_match - time-critical address list lookup */
+/* psc_addr_match_list_match - time-critical address list lookup */
-int ps_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
- const char *addr_str)
+int psc_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
+ const char *addr_str)
{
- const char *myname = "ps_addr_match_list_match";
+ const char *myname = "psc_addr_match_list_match";
int result;
- PS_GET_TIME_BEFORE_LOOKUP;
+ PSC_GET_TIME_BEFORE_LOOKUP;
result = addr_match_list_match(addr_list, addr_str);
- PS_CHECK_TIME_AFTER_LOOKUP("address list", "lookup");
+ PSC_CHECK_TIME_AFTER_LOOKUP("address list", "lookup");
return (result);
}
-/* ps_cache_lookup - time-critical cache lookup */
+/* psc_cache_lookup - time-critical cache lookup */
-const char *ps_cache_lookup(DICT_CACHE *cache, const char *key)
+const char *psc_cache_lookup(DICT_CACHE *cache, const char *key)
{
- const char *myname = "ps_cache_lookup";
+ const char *myname = "psc_cache_lookup";
const char *result;
- PS_GET_TIME_BEFORE_LOOKUP;
+ PSC_GET_TIME_BEFORE_LOOKUP;
result = dict_cache_lookup(cache, key);
- PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
+ PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
return (result);
}
-/* ps_cache_update - time-critical cache update */
+/* psc_cache_update - time-critical cache update */
-void ps_cache_update(DICT_CACHE *cache, const char *key, const char *value)
+void psc_cache_update(DICT_CACHE *cache, const char *key, const char *value)
{
- const char *myname = "ps_cache_update";
+ const char *myname = "psc_cache_update";
- PS_GET_TIME_BEFORE_LOOKUP;
+ PSC_GET_TIME_BEFORE_LOOKUP;
dict_cache_update(cache, key, value);
- PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
+ PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
}
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* void ps_dnsbl_init(void)
+/* void psc_dnsbl_init(void)
/*
-/* int ps_dnsbl_request(client_addr, callback, context)
+/* int psc_dnsbl_request(client_addr, callback, context)
/* char *client_addr;
/* void (*callback)(int, char *);
/* char *context;
/*
-/* int ps_dnsbl_retrieve(client_addr, dnsbl_name, dnsbl_index)
+/* int psc_dnsbl_retrieve(client_addr, dnsbl_name, dnsbl_index)
/* char *client_addr;
/* const char **dnsbl_name;
/* int dnsbl_index;
/* Multiple requests for the same information are handled with
/* reference counts.
/*
-/* ps_dnsbl_init() initializes this module, and must be called
+/* psc_dnsbl_init() initializes this module, and must be called
/* once before any of the other functions in this module.
/*
-/* ps_dnsbl_request() requests a blocklist score for the
+/* psc_dnsbl_request() requests a blocklist score for the
/* specified client IP address and increments the reference
/* count. The request completes in the background. The client
/* IP address must be in inet_ntop(3) output format. The
/* on to the callback function. The callback should ignore its
/* first argument (it exists for compatibility with Postfix
/* generic event infrastructure).
-/* The result value is the index for the ps_dnsbl_retrieve()
+/* The result value is the index for the psc_dnsbl_retrieve()
/* call.
/*
-/* ps_dnsbl_retrieve() retrieves the result score requested with
-/* ps_dnsbl_request() and decrements the reference count. It
+/* psc_dnsbl_retrieve() retrieves the result score requested with
+/* psc_dnsbl_request() and decrements the reference count. It
/* is an error to retrieve a score without requesting it first.
/* LICENSE
/* .ad
typedef struct {
const char *safe_dnsbl; /* from postscreen_dnsbl_reply_map */
- struct PS_DNSBL_SITE *first; /* list of (filter, weight) tuples */
-} PS_DNSBL_HEAD;
+ struct PSC_DNSBL_SITE *first; /* list of (filter, weight) tuples */
+} PSC_DNSBL_HEAD;
-typedef struct PS_DNSBL_SITE {
+typedef struct PSC_DNSBL_SITE {
char *filter; /* printable filter (default: null) */
char *byte_codes; /* encoded filter (default: null) */
int weight; /* reply weight (default: 1) */
- struct PS_DNSBL_SITE *next; /* linked list */
-} PS_DNSBL_SITE;
+ struct PSC_DNSBL_SITE *next; /* linked list */
+} PSC_DNSBL_SITE;
/*
* Per-client DNSBL scores.
typedef struct {
void (*callback) (int, char *); /* generic call-back routine */
char *context; /* generic call-back argument */
-} PS_CALL_BACK_ENTRY;
+} PSC_CALL_BACK_ENTRY;
typedef struct {
const char *dnsbl; /* one contributing DNSBL */
/* Call-back table support. */
int index; /* next table index */
int limit; /* last valid index */
- PS_CALL_BACK_ENTRY table[1]; /* actually a bunch */
-} PS_DNSBL_SCORE;
+ PSC_CALL_BACK_ENTRY table[1]; /* actually a bunch */
+} PSC_DNSBL_SCORE;
-#define PS_CALL_BACK_INIT(sp) do { \
+#define PSC_CALL_BACK_INIT(sp) do { \
(sp)->limit = 0; \
(sp)->index = 0; \
} while (0)
-#define PS_CALL_BACK_INDEX_OF_LAST(sp) ((sp)->index - 1)
+#define PSC_CALL_BACK_INDEX_OF_LAST(sp) ((sp)->index - 1)
-#define PS_CALL_BACK_CANCEL(sp, idx) do { \
- PS_CALL_BACK_ENTRY *_cb_; \
+#define PSC_CALL_BACK_CANCEL(sp, idx) do { \
+ PSC_CALL_BACK_ENTRY *_cb_; \
if ((idx) < 0 || (idx) >= (sp)->index) \
msg_panic("%s: index %d must be >= 0 and < %d", \
myname, (idx), (sp)->index); \
_cb_->context = 0; \
} while (0)
-#define PS_CALL_BACK_EXTEND(hp, sp) do { \
+#define PSC_CALL_BACK_EXTEND(hp, sp) do { \
if ((sp)->index >= (sp)->limit) { \
int _count_ = ((sp)->limit ? (sp)->limit * 2 : 5); \
(hp)->value = myrealloc((char *) (sp), sizeof(*(sp)) + \
_count_ * sizeof((sp)->table)); \
- (sp) = (PS_DNSBL_SCORE *) (hp)->value; \
+ (sp) = (PSC_DNSBL_SCORE *) (hp)->value; \
(sp)->limit = _count_; \
} \
} while (0)
-#define PS_CALL_BACK_ENTER(sp, fn, ctx) do { \
- PS_CALL_BACK_ENTRY *_cb_ = (sp)->table + (sp)->index++; \
+#define PSC_CALL_BACK_ENTER(sp, fn, ctx) do { \
+ PSC_CALL_BACK_ENTRY *_cb_ = (sp)->table + (sp)->index++; \
_cb_->callback = (fn); \
_cb_->context = (ctx); \
} while (0)
-#define PS_CALL_BACK_NOTIFY(sp, ev) do { \
- PS_CALL_BACK_ENTRY *_cb_; \
+#define PSC_CALL_BACK_NOTIFY(sp, ev) do { \
+ PSC_CALL_BACK_ENTRY *_cb_; \
for (_cb_ = (sp)->table; _cb_ < (sp)->table + (sp)->index; _cb_++) \
if (_cb_->callback != 0) \
_cb_->callback((ev), _cb_->context); \
} while (0)
-#define PS_NULL_EVENT (0)
+#define PSC_NULL_EVENT (0)
/*
* Per-request state.
static VSTRING *reply_dnsbl; /* domain in DNSBLOG reply */
static VSTRING *reply_addr; /* adress list in DNSBLOG reply */
-/* ps_dnsbl_add_site - add DNSBL site information */
+/* psc_dnsbl_add_site - add DNSBL site information */
-static void ps_dnsbl_add_site(const char *site)
+static void psc_dnsbl_add_site(const char *site)
{
- const char *myname = "ps_dnsbl_add_site";
+ const char *myname = "psc_dnsbl_add_site";
char *saved_site = mystrdup(site);
VSTRING *byte_codes = 0;
- PS_DNSBL_HEAD *head;
- PS_DNSBL_SITE *new_site;
+ PSC_DNSBL_HEAD *head;
+ PSC_DNSBL_SITE *new_site;
char junk;
const char *weight_text;
char *pattern_text;
* Look up or create the (filter, weight) list head for this DNSBL domain
* name.
*/
- if ((head = (PS_DNSBL_HEAD *)
+ if ((head = (PSC_DNSBL_HEAD *)
htable_find(dnsbl_site_cache, saved_site)) == 0) {
- head = (PS_DNSBL_HEAD *) mymalloc(sizeof(*head));
+ head = (PSC_DNSBL_HEAD *) mymalloc(sizeof(*head));
ht = htable_enter(dnsbl_site_cache, saved_site, (char *) head);
/* Translate the DNSBL name into a safe name if available. */
- if (ps_dnsbl_reply == 0
- || (head->safe_dnsbl = dict_get(ps_dnsbl_reply, saved_site)) == 0)
+ if (psc_dnsbl_reply == 0
+ || (head->safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0)
head->safe_dnsbl = ht->key;
head->first = 0;
}
* Append the new (filter, weight) node to the list for this DNSBL domain
* name.
*/
- new_site = (PS_DNSBL_SITE *) mymalloc(sizeof(*new_site));
+ new_site = (PSC_DNSBL_SITE *) mymalloc(sizeof(*new_site));
new_site->filter = (pattern_text ? mystrdup(pattern_text) : 0);
new_site->byte_codes = (byte_codes ? ip_match_save(byte_codes) : 0);
new_site->weight = weight;
vstring_free(byte_codes);
}
-/* ps_dnsbl_match - match DNSBL reply filter */
+/* psc_dnsbl_match - match DNSBL reply filter */
-static int ps_dnsbl_match(const char *filter, ARGV *reply)
+static int psc_dnsbl_match(const char *filter, ARGV *reply)
{
char addr_buf[MAI_HOSTADDR_STRSIZE];
char **cpp;
return (0);
}
-/* ps_dnsbl_retrieve - retrieve blocklist score, decrement reference count */
+/* psc_dnsbl_retrieve - retrieve blocklist score, decrement reference count */
-int ps_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name,
- int dnsbl_index)
+int psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name,
+ int dnsbl_index)
{
- const char *myname = "ps_dnsbl_retrieve";
- PS_DNSBL_SCORE *score;
+ const char *myname = "psc_dnsbl_retrieve";
+ PSC_DNSBL_SCORE *score;
int result_score;
/*
* Sanity check.
*/
- if ((score = (PS_DNSBL_SCORE *)
+ if ((score = (PSC_DNSBL_SCORE *)
htable_find(dnsbl_score_cache, client_addr)) == 0)
msg_panic("%s: no blocklist score for %s", myname, client_addr);
/*
* Disable callbacks.
*/
- PS_CALL_BACK_CANCEL(score, dnsbl_index);
+ PSC_CALL_BACK_CANCEL(score, dnsbl_index);
/*
* Reads are destructive.
return (result_score);
}
-/* ps_dnsbl_receive - receive DNSBL reply, update blocklist score */
+/* psc_dnsbl_receive - receive DNSBL reply, update blocklist score */
-static void ps_dnsbl_receive(int event, char *context)
+static void psc_dnsbl_receive(int event, char *context)
{
- const char *myname = "ps_dnsbl_receive";
+ const char *myname = "psc_dnsbl_receive";
VSTREAM *stream = (VSTREAM *) context;
- PS_DNSBL_SCORE *score;
- PS_DNSBL_HEAD *head;
- PS_DNSBL_SITE *site;
+ PSC_DNSBL_SCORE *score;
+ PSC_DNSBL_HEAD *head;
+ PSC_DNSBL_SITE *site;
ARGV *reply_argv;
- PS_CLEAR_EVENT_REQUEST(vstream_fileno(stream), ps_dnsbl_receive, context);
+ PSC_CLEAR_EVENT_REQUEST(vstream_fileno(stream), psc_dnsbl_receive, context);
/*
* Receive the DNSBL lookup result.
*/
if (event == EVENT_READ
&& attr_scan(stream,
- ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
+ ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, reply_dnsbl,
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, reply_client,
ATTR_TYPE_STR, MAIL_ATTR_RBL_ADDR, reply_addr,
ATTR_TYPE_END) == 3
- && (score = (PS_DNSBL_SCORE *)
+ && (score = (PSC_DNSBL_SCORE *)
htable_find(dnsbl_score_cache, STR(reply_client))) != 0) {
/*
myname, STR(reply_client), score->total,
STR(reply_dnsbl), STR(reply_addr));
if (*STR(reply_addr) != 0) {
- head = (PS_DNSBL_HEAD *)
+ head = (PSC_DNSBL_HEAD *)
htable_find(dnsbl_site_cache, STR(reply_dnsbl));
- site = (head ? head->first : (PS_DNSBL_SITE *) 0);
+ site = (head ? head->first : (PSC_DNSBL_SITE *) 0);
for (reply_argv = 0; site != 0; site = site->next) {
if (site->byte_codes == 0
- || ps_dnsbl_match(site->byte_codes, reply_argv ? reply_argv :
+ || psc_dnsbl_match(site->byte_codes, reply_argv ? reply_argv :
(reply_argv = argv_split(STR(reply_addr), " ")))) {
if (score->dnsbl == 0)
score->dnsbl = head->safe_dnsbl;
*/
score->pending_lookups -= 1;
if (score->pending_lookups == 0)
- PS_CALL_BACK_NOTIFY(score, PS_NULL_EVENT);
+ PSC_CALL_BACK_NOTIFY(score, PSC_NULL_EVENT);
}
/* Here, score may be a null pointer. */
vstream_fclose(stream);
}
-/* ps_dnsbl_request - send dnsbl query, increment reference count */
+/* psc_dnsbl_request - send dnsbl query, increment reference count */
-int ps_dnsbl_request(const char *client_addr,
- void (*callback) (int, char *),
- char *context)
+int psc_dnsbl_request(const char *client_addr,
+ void (*callback) (int, char *),
+ char *context)
{
- const char *myname = "ps_dnsbl_request";
+ const char *myname = "psc_dnsbl_request";
int fd;
VSTREAM *stream;
HTABLE_INFO **ht;
- PS_DNSBL_SCORE *score;
+ PSC_DNSBL_SCORE *score;
HTABLE_INFO *hash_node;
/*
* a zero-delay timer request and call the notification function from
* there.
*
- * ps_dnsbl_request() could instead return a result value to indicate that
+ * psc_dnsbl_request() could instead return a result value to indicate that
* the DNSBL score is already available, but that would complicate the
* caller with two different notification code paths: one asynchronous
* code path via the callback invocation, and one synchronous code path
- * via the ps_dnsbl_request() result value. That would be a source of
+ * via the psc_dnsbl_request() result value. That would be a source of
* future bugs.
*/
if ((hash_node = htable_locate(dnsbl_score_cache, client_addr)) != 0) {
- score = (PS_DNSBL_SCORE *) hash_node->value;
+ score = (PSC_DNSBL_SCORE *) hash_node->value;
score->refcount += 1;
- PS_CALL_BACK_EXTEND(hash_node, score);
- PS_CALL_BACK_ENTER(score, callback, context);
+ PSC_CALL_BACK_EXTEND(hash_node, score);
+ PSC_CALL_BACK_ENTER(score, callback, context);
if (msg_verbose > 1)
msg_info("%s: reuse blocklist score for %s refcount=%d pending=%d",
myname, client_addr, score->refcount,
score->pending_lookups);
if (score->pending_lookups == 0)
event_request_timer(callback, context, EVENT_NULL_DELAY);
- return (PS_CALL_BACK_INDEX_OF_LAST(score));
+ return (PSC_CALL_BACK_INDEX_OF_LAST(score));
}
if (msg_verbose > 1)
msg_info("%s: create blocklist score for %s", myname, client_addr);
- score = (PS_DNSBL_SCORE *) mymalloc(sizeof(*score));
+ score = (PSC_DNSBL_SCORE *) mymalloc(sizeof(*score));
score->dnsbl = 0;
score->total = 0;
score->refcount = 1;
score->pending_lookups = 0;
- PS_CALL_BACK_INIT(score);
- PS_CALL_BACK_ENTER(score, callback, context);
+ PSC_CALL_BACK_INIT(score);
+ PSC_CALL_BACK_ENTER(score, callback, context);
(void) htable_enter(dnsbl_score_cache, client_addr, (char *) score);
/*
vstream_fclose(stream);
continue;
}
- PS_READ_EVENT_REQUEST(vstream_fileno(stream), ps_dnsbl_receive,
- (char *) stream, DNSBLOG_TIMEOUT);
+ PSC_READ_EVENT_REQUEST(vstream_fileno(stream), psc_dnsbl_receive,
+ (char *) stream, DNSBLOG_TIMEOUT);
score->pending_lookups += 1;
}
- return (PS_CALL_BACK_INDEX_OF_LAST(score));
+ return (PSC_CALL_BACK_INDEX_OF_LAST(score));
}
-/* ps_dnsbl_init - initialize */
+/* psc_dnsbl_init - initialize */
-void ps_dnsbl_init(void)
+void psc_dnsbl_init(void)
{
- const char *myname = "ps_dnsbl_init";
- ARGV *dnsbl_site = argv_split(var_ps_dnsbl_sites, ", \t\r\n");
+ const char *myname = "psc_dnsbl_init";
+ ARGV *dnsbl_site = argv_split(var_psc_dnsbl_sites, ", \t\r\n");
char **cpp;
/*
*/
dnsbl_site_cache = htable_create(13);
for (cpp = dnsbl_site->argv; *cpp; cpp++)
- ps_dnsbl_add_site(*cpp);
+ psc_dnsbl_add_site(*cpp);
argv_free(dnsbl_site);
dnsbl_site_list = htable_list(dnsbl_site_cache);
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* void ps_early_init(void)
+/* void psc_early_init(void)
/*
-/* void ps_early_tests(state)
-/* PS_STATE *state;
+/* void psc_early_tests(state)
+/* PSC_STATE *state;
/* DESCRIPTION
-/* ps_early_tests() performs protocol tests before the SMTP
+/* psc_early_tests() performs protocol tests before the SMTP
/* handshake: the pregreet test and the DNSBL test. Control
-/* is passed to the ps_smtpd_tests() routine as appropriate.
+/* is passed to the psc_smtpd_tests() routine as appropriate.
/*
-/* ps_early_init() performs one-time initialization.
+/* psc_early_init() performs one-time initialization.
/* LICENSE
/* .ad
/* .fi
#include <postscreen.h>
-static char *ps_teaser_greeting;
+static char *psc_teaser_greeting;
-/* ps_early_event - handle pre-greet, EOF, and DNSBL results. */
+/* psc_early_event - handle pre-greet, EOF, and DNSBL results. */
-static void ps_early_event(int event, char *context)
+static void psc_early_event(int event, char *context)
{
- const char *myname = "ps_early_event";
- PS_STATE *state = (PS_STATE *) context;
- char read_buf[PS_READ_BUF_SIZE];
+ const char *myname = "psc_early_event";
+ PSC_STATE *state = (PSC_STATE *) context;
+ char read_buf[PSC_READ_BUF_SIZE];
int read_count;
int dnsbl_score;
DELTA_TIME elapsed;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
- ps_print_state_flags(state->flags, myname));
+ psc_print_state_flags(state->flags, myname));
- PS_CLEAR_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
- ps_early_event, context);
+ PSC_CLEAR_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
+ psc_early_event, context);
/*
* XXX Be sure to empty the DNSBL lookup buffer otherwise we have a
* memory leak.
*
* XXX We can avoid "forgetting" to do this by keeping a pointer to the
- * DNSBL lookup buffer in the PS_STATE structure. This also allows us to
+ * DNSBL lookup buffer in the PSC_STATE structure. This also allows us to
* shave off a hash table lookup when retrieving the DNSBL result.
*/
switch (event) {
/*
* Check if the SMTP client spoke before its turn.
*/
- if ((state->flags & PS_STATE_MASK_PREGR_TODO_FAIL)
- == PS_STATE_FLAG_PREGR_TODO) {
- state->pregr_stamp = event_time() + var_ps_pregr_ttl;
- PS_PASS_SESSION_STATE(state, "pregreet test",
- PS_STATE_FLAG_PREGR_PASS);
+ if ((state->flags & PSC_STATE_MASK_PREGR_TODO_FAIL)
+ == PSC_STATE_FLAG_PREGR_TODO) {
+ state->pregr_stamp = event_time() + var_psc_pregr_ttl;
+ PSC_PASS_SESSION_STATE(state, "pregreet test",
+ PSC_STATE_FLAG_PREGR_PASS);
}
- if ((state->flags & PS_STATE_FLAG_PREGR_FAIL)
- && ps_pregr_action == PS_ACT_IGNORE) {
- PS_UNFAIL_SESSION_STATE(state, PS_STATE_FLAG_PREGR_FAIL);
- /* Not: PS_PASS_SESSION_STATE. Repeat this test the next time. */
+ if ((state->flags & PSC_STATE_FLAG_PREGR_FAIL)
+ && psc_pregr_action == PSC_ACT_IGNORE) {
+ PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_PREGR_FAIL);
+ /* Not: PSC_PASS_SESSION_STATE. Repeat this test the next time. */
}
/*
* If the client is DNS blocklisted, drop the connection, send the
* client to a dummy protocol engine, or continue to the next test.
*/
-#define PS_DNSBL_FORMAT \
+#define PSC_DNSBL_FORMAT \
"%s 5.7.1 Service unavailable; client [%s] blocked using %s\r\n"
- if (state->flags & PS_STATE_FLAG_DNSBL_TODO) {
+ if (state->flags & PSC_STATE_FLAG_DNSBL_TODO) {
dnsbl_score =
- ps_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
- state->dnsbl_index);
- if (dnsbl_score < var_ps_dnsbl_thresh) {
- state->dnsbl_stamp = event_time() + var_ps_dnsbl_ttl;
- PS_PASS_SESSION_STATE(state, "dnsbl test",
- PS_STATE_FLAG_DNSBL_PASS);
+ psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
+ state->dnsbl_index);
+ if (dnsbl_score < var_psc_dnsbl_thresh) {
+ state->dnsbl_stamp = event_time() + var_psc_dnsbl_ttl;
+ PSC_PASS_SESSION_STATE(state, "dnsbl test",
+ PSC_STATE_FLAG_DNSBL_PASS);
} else {
msg_info("DNSBL rank %d for [%s]:%s",
- dnsbl_score, PS_CLIENT_ADDR_PORT(state));
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_DNSBL_FAIL);
- switch (ps_dnsbl_action) {
- case PS_ACT_DROP:
+ dnsbl_score, PSC_CLIENT_ADDR_PORT(state));
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_DNSBL_FAIL);
+ switch (psc_dnsbl_action) {
+ case PSC_ACT_DROP:
state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
- PS_DNSBL_FORMAT, "521",
+ PSC_DNSBL_FORMAT, "521",
state->smtp_client_addr, dnsbl_name);
- PS_DROP_SESSION_STATE(state, STR(state->dnsbl_reply));
+ PSC_DROP_SESSION_STATE(state, STR(state->dnsbl_reply));
return;
- case PS_ACT_ENFORCE:
+ case PSC_ACT_ENFORCE:
state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
- PS_DNSBL_FORMAT, "550",
+ PSC_DNSBL_FORMAT, "550",
state->smtp_client_addr, dnsbl_name);
- PS_ENFORCE_SESSION_STATE(state, STR(state->dnsbl_reply));
+ PSC_ENFORCE_SESSION_STATE(state, STR(state->dnsbl_reply));
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state, PS_STATE_FLAG_DNSBL_FAIL);
- /* Not: PS_PASS_SESSION_STATE. Repeat this test. */
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_DNSBL_FAIL);
+ /* Not: PSC_PASS_SESSION_STATE. Repeat this test. */
break;
default:
msg_panic("%s: unknown dnsbl action value %d",
- myname, ps_dnsbl_action);
+ myname, psc_dnsbl_action);
}
}
* Pass the connection to a real SMTP server, or enter the dummy
* engine for deep tests.
*/
- if (state->flags & (PS_STATE_FLAG_NOFORWARD | PS_STATE_MASK_SMTPD_TODO))
- ps_smtpd_tests(state);
+ if (state->flags & (PSC_STATE_FLAG_NOFORWARD | PSC_STATE_MASK_SMTPD_TODO))
+ psc_smtpd_tests(state);
else
- ps_conclude(state);
+ psc_conclude(state);
return;
/*
* EOF, or the client spoke before its turn. We simply drop the
* connection, or we continue waiting and allow DNS replies to
* trickle in.
- *
- * XXX Reset the pregreet timer when the DNS results are complete.
*/
default:
if ((read_count = recv(vstream_fileno(state->smtp_client_stream),
read_buf, sizeof(read_buf) - 1, MSG_PEEK)) <= 0) {
/* Avoid memory leak. */
- if (state->flags & PS_STATE_FLAG_DNSBL_TODO)
- (void) ps_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
- state->dnsbl_index);
+ if (state->flags & PSC_STATE_FLAG_DNSBL_TODO)
+ (void) psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
+ state->dnsbl_index);
/* XXX Wait for DNS replies to come in. */
- ps_hangup_event(state);
+ psc_hangup_event(state);
return;
}
read_buf[read_count] = 0;
msg_info("PREGREET %d after %s from [%s]:%s: %.100s", read_count,
- ps_format_delta_time(ps_temp, state->start_time, &elapsed),
- PS_CLIENT_ADDR_PORT(state), printable(read_buf, '?'));
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_PREGR_FAIL);
- switch (ps_pregr_action) {
- case PS_ACT_DROP:
+ psc_format_delta_time(psc_temp, state->start_time, &elapsed),
+ PSC_CLIENT_ADDR_PORT(state), printable(read_buf, '?'));
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PREGR_FAIL);
+ switch (psc_pregr_action) {
+ case PSC_ACT_DROP:
/* Avoid memory leak. */
- if (state->flags & PS_STATE_FLAG_DNSBL_TODO)
- (void) ps_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
- state->dnsbl_index);
- PS_DROP_SESSION_STATE(state, "521 5.5.1 Protocol error\r\n");
+ if (state->flags & PSC_STATE_FLAG_DNSBL_TODO)
+ (void) psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
+ state->dnsbl_index);
+ PSC_DROP_SESSION_STATE(state, "521 5.5.1 Protocol error\r\n");
return;
- case PS_ACT_ENFORCE:
- /* We call ps_dnsbl_retrieve() when the timer expires. */
- PS_ENFORCE_SESSION_STATE(state, "550 5.5.1 Protocol error\r\n");
+ case PSC_ACT_ENFORCE:
+ /* We call psc_dnsbl_retrieve() when the timer expires. */
+ PSC_ENFORCE_SESSION_STATE(state, "550 5.5.1 Protocol error\r\n");
break;
- case PS_ACT_IGNORE:
- /* We call ps_dnsbl_retrieve() when the timer expires. */
+ case PSC_ACT_IGNORE:
+ /* We call psc_dnsbl_retrieve() when the timer expires. */
/* We must handle this case after the timer expires. */
break;
default:
msg_panic("%s: unknown pregreet action value %d",
- myname, ps_pregr_action);
+ myname, psc_pregr_action);
}
/*
* Terminate the greet delay if we're just waiting for the pregreet
- * test to complete. It is safe to call ps_early_event directly,
+ * test to complete. It is safe to call psc_early_event directly,
* since we are already in that function.
*
* XXX After this code passes all tests, swap around the two blocks in
* this switch statement and fall through from EVENT_READ into
- * EVENT_TIME, instead of calling ps_early_event recursively.
+ * EVENT_TIME, instead of calling psc_early_event recursively.
*/
- state->flags |= PS_STATE_FLAG_PREGR_DONE;
- if (elapsed.dt_sec >= PS_EFF_GREET_WAIT
- || ((state->flags & PS_STATE_MASK_EARLY_DONE)
- == PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_MASK_EARLY_TODO)))
- ps_early_event(EVENT_TIME, context);
+ state->flags |= PSC_STATE_FLAG_PREGR_DONE;
+ if (elapsed.dt_sec >= PSC_EFF_GREET_WAIT
+ || ((state->flags & PSC_STATE_MASK_EARLY_DONE)
+ == PSC_STATE_FLAGS_TODO_TO_DONE(state->flags & PSC_STATE_MASK_EARLY_TODO)))
+ psc_early_event(EVENT_TIME, context);
else
- event_request_timer(ps_early_event, context,
- PS_EFF_GREET_WAIT - elapsed.dt_sec);
+ event_request_timer(psc_early_event, context,
+ PSC_EFF_GREET_WAIT - elapsed.dt_sec);
return;
}
}
-/* ps_early_dnsbl_event - cancel pregreet timer if waiting for DNS only */
+/* psc_early_dnsbl_event - cancel pregreet timer if waiting for DNS only */
-static void ps_early_dnsbl_event(int unused_event, char *context)
+static void psc_early_dnsbl_event(int unused_event, char *context)
{
- const char *myname = "ps_early_dnsbl_event";
- PS_STATE *state = (PS_STATE *) context;
+ const char *myname = "psc_early_dnsbl_event";
+ PSC_STATE *state = (PSC_STATE *) context;
if (msg_verbose)
- msg_info("%s: notify [%s]:%s", myname, PS_CLIENT_ADDR_PORT(state));
+ msg_info("%s: notify [%s]:%s", myname, PSC_CLIENT_ADDR_PORT(state));
/*
* Terminate the greet delay if we're just waiting for DNSBL lookup to
- * complete. Don't call ps_early_event directly, that would result in a
+ * complete. Don't call psc_early_event directly, that would result in a
* dangling pointer.
*/
- state->flags |= PS_STATE_FLAG_DNSBL_DONE;
- if ((state->flags & PS_STATE_MASK_EARLY_DONE)
- == PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_MASK_EARLY_TODO))
- event_request_timer(ps_early_event, context, EVENT_NULL_DELAY);
+ state->flags |= PSC_STATE_FLAG_DNSBL_DONE;
+ if ((state->flags & PSC_STATE_MASK_EARLY_DONE)
+ == PSC_STATE_FLAGS_TODO_TO_DONE(state->flags & PSC_STATE_MASK_EARLY_TODO))
+ event_request_timer(psc_early_event, context, EVENT_NULL_DELAY);
}
-/* ps_early_tests - start the early (before protocol) tests */
+/* psc_early_tests - start the early (before protocol) tests */
-void ps_early_tests(PS_STATE *state)
+void psc_early_tests(PSC_STATE *state)
{
- const char *myname = "ps_early_tests";
+ const char *myname = "psc_early_tests";
/*
* Report errors and progress in the context of this test.
*/
- PS_BEGIN_TESTS(state, "tests before SMTP handshake");
+ PSC_BEGIN_TESTS(state, "tests before SMTP handshake");
/*
* Run a PREGREET test. Send half the greeting banner, by way of teaser,
* then wait briefly to see if the client speaks before its turn.
*/
- if ((state->flags & PS_STATE_FLAG_PREGR_TODO) != 0
- && ps_teaser_greeting != 0
- && PS_SEND_REPLY(state, ps_teaser_greeting) != 0) {
- ps_hangup_event(state);
+ if ((state->flags & PSC_STATE_FLAG_PREGR_TODO) != 0
+ && psc_teaser_greeting != 0
+ && PSC_SEND_REPLY(state, psc_teaser_greeting) != 0) {
+ psc_hangup_event(state);
return;
}
/*
* Run a DNS blocklist query.
*/
- if ((state->flags & PS_STATE_FLAG_DNSBL_TODO) != 0)
+ if ((state->flags & PSC_STATE_FLAG_DNSBL_TODO) != 0)
state->dnsbl_index =
- ps_dnsbl_request(state->smtp_client_addr, ps_early_dnsbl_event,
- (char *) state);
+ psc_dnsbl_request(state->smtp_client_addr, psc_early_dnsbl_event,
+ (char *) state);
else
state->dnsbl_index = -1;
/*
* Wait for the client to respond or for DNS lookup to complete.
*/
- if ((state->flags & PS_STATE_FLAG_PREGR_TODO) != 0)
- PS_READ_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
- ps_early_event, (char *) state, PS_EFF_GREET_WAIT);
+ if ((state->flags & PSC_STATE_FLAG_PREGR_TODO) != 0)
+ PSC_READ_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
+ psc_early_event, (char *) state, PSC_EFF_GREET_WAIT);
else
- event_request_timer(ps_early_event, (char *) state, PS_EFF_GREET_WAIT);
+ event_request_timer(psc_early_event, (char *) state, PSC_EFF_GREET_WAIT);
}
-/* ps_early_init - initialize early tests */
+/* psc_early_init - initialize early tests */
-void ps_early_init(void)
+void psc_early_init(void)
{
- if (*var_ps_pregr_banner) {
- vstring_sprintf(ps_temp, "220-%s\r\n", var_ps_pregr_banner);
- ps_teaser_greeting = mystrdup(STR(ps_temp));
+ if (*var_psc_pregr_banner) {
+ vstring_sprintf(psc_temp, "220-%s\r\n", var_psc_pregr_banner);
+ psc_teaser_greeting = mystrdup(STR(psc_temp));
}
}
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* char *ps_format_delta_time(buf, tv, delta)
+/* char *psc_format_delta_time(buf, tv, delta)
/* VSTRING *buf;
/* struct timeval tv;
/* DELTA_TIME *delta;
/*
-/* void ps_conclude(state)
-/* PS_STATE *state;
+/* void psc_conclude(state)
+/* PSC_STATE *state;
/*
-/* void ps_hangup_event(state)
-/* PS_STATE *state;
+/* void psc_hangup_event(state)
+/* PSC_STATE *state;
/* DESCRIPTION
-/* ps_format_delta_time() computes the time difference between
+/* psc_format_delta_time() computes the time difference between
/* tv (past) and the present, formats the time difference with
/* sub-second resolution in a human-readable way, and returns
/* the integer time difference in seconds through the delta
/* argument.
/*
-/* ps_conclude() logs when a client passes all necessary tests,
+/* psc_conclude() logs when a client passes all necessary tests,
/* updates the postscreen cache for any testes that were passed,
/* and either forwards the connection to a real SMTP server or
/* replies with the text in state->error_reply and hangs up the
/* connection (by default, state->error_reply is set to a
/* default 421 reply).
/*
-/* ps_hangup_event() cleans up after a client connection breaks
+/* psc_hangup_event() cleans up after a client connection breaks
/* unexpectedly. If logs the test where the break happened,
/* and how much time as spent in that test before the connection
/* broke.
#include <postscreen.h>
-/* ps_format_delta_time - pretty-formatted delta time */
+/* psc_format_delta_time - pretty-formatted delta time */
-char *ps_format_delta_time(VSTRING *buf, struct timeval tv, DELTA_TIME *delta)
+char *psc_format_delta_time(VSTRING *buf, struct timeval tv,
+ DELTA_TIME *delta)
{
DELTA_TIME pdelay;
struct timeval now;
GETTIMEOFDAY(&now);
- PS_CALC_DELTA(pdelay, now, tv);
+ PSC_CALC_DELTA(pdelay, now, tv);
VSTRING_RESET(buf);
format_tv(buf, pdelay.dt_sec, pdelay.dt_usec, SIG_DIGS, var_delay_max_res);
*delta = pdelay;
return (STR(buf));
}
-/* ps_conclude - bring this session to a conclusion */
+/* psc_conclude - bring this session to a conclusion */
-void ps_conclude(PS_STATE *state)
+void psc_conclude(PSC_STATE *state)
{
- const char *myname = "ps_conclude";
+ const char *myname = "psc_conclude";
if (msg_verbose)
msg_info("flags for %s: %s",
- myname, ps_print_state_flags(state->flags, myname));
+ myname, psc_print_state_flags(state->flags, myname));
/*
* Handle clients that passed at least one test other than permanent
* blacklisting. There may still be unfinished tests; those tests will
* need to be completed when the client returns in a later session.
*/
- if (state->flags & PS_STATE_MASK_ANY_FAIL)
- state->flags &= ~PS_STATE_MASK_ANY_PASS;
+ if (state->flags & PSC_STATE_MASK_ANY_FAIL)
+ state->flags &= ~PSC_STATE_MASK_ANY_PASS;
/*
* Log our final blessing when all unfinished tests were completed.
*/
- if ((state->flags & PS_STATE_MASK_ANY_PASS) != 0
- && (state->flags & PS_STATE_MASK_ANY_PASS) ==
- PS_STATE_FLAGS_TODO_TO_PASS(state->flags & PS_STATE_MASK_ANY_TODO))
- msg_info("PASS %s [%s]:%s", (state->flags & PS_STATE_FLAG_NEW) == 0 ?
- "OLD" : "NEW", PS_CLIENT_ADDR_PORT(state));
+ if ((state->flags & PSC_STATE_MASK_ANY_PASS) != 0
+ && (state->flags & PSC_STATE_MASK_ANY_PASS) ==
+ PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_ANY_TODO))
+ msg_info("PASS %s [%s]:%s", (state->flags & PSC_STATE_FLAG_NEW) == 0 ?
+ "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state));
/*
* Update the postscreen cache. This still supports a scenario where a
* client gets whitelisted in the course of multiple sessions, as long as
* that client does not "fail" any test.
*/
- if ((state->flags & PS_STATE_MASK_ANY_UPDATE) != 0
- && ps_cache_map != 0) {
- ps_print_tests(ps_temp, state);
- ps_cache_update(ps_cache_map, state->smtp_client_addr, STR(ps_temp));
+ if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0
+ && psc_cache_map != 0) {
+ psc_print_tests(psc_temp, state);
+ psc_cache_update(psc_cache_map, state->smtp_client_addr, STR(psc_temp));
}
/*
* Either hand off the socket to a real SMTP engine, or say bye-bye.
*/
- if ((state->flags & PS_STATE_FLAG_NOFORWARD) == 0) {
- ps_send_socket(state);
+ if ((state->flags & PSC_STATE_FLAG_NOFORWARD) == 0) {
+ psc_send_socket(state);
} else {
- if ((state->flags & PS_STATE_FLAG_HANGUP) == 0)
- (void) PS_SEND_REPLY(state, state->final_reply);
- msg_info("DISCONNECT [%s]:%s", PS_CLIENT_ADDR_PORT(state));
- ps_free_session_state(state);
+ if ((state->flags & PSC_STATE_FLAG_HANGUP) == 0)
+ (void) PSC_SEND_REPLY(state, state->final_reply);
+ msg_info("DISCONNECT [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ psc_free_session_state(state);
}
}
-/* ps_hangup_event - handle unexpected disconnect */
+/* psc_hangup_event - handle unexpected disconnect */
-void ps_hangup_event(PS_STATE *state)
+void psc_hangup_event(PSC_STATE *state)
{
DELTA_TIME elapsed;
* Log the current test phase, and the elapsed time after the start of that
* phase.
*/
- state->flags |= PS_STATE_FLAG_HANGUP;
+ state->flags |= PSC_STATE_FLAG_HANGUP;
msg_info("HANGUP after %s from [%s]:%s in %s",
- ps_format_delta_time(ps_temp, state->start_time, &elapsed),
- PS_CLIENT_ADDR_PORT(state), state->test_name);
- state->flags |= PS_STATE_FLAG_NOFORWARD;
- ps_conclude(state);
+ psc_format_delta_time(psc_temp, state->start_time, &elapsed),
+ PSC_CLIENT_ADDR_PORT(state), state->test_name);
+ state->flags |= PSC_STATE_FLAG_NOFORWARD;
+ psc_conclude(state);
}
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* int ps_send_reply(client_fd, client_addr, client_port, text)
+/* int psc_send_reply(client_fd, client_addr, client_port, text)
/* int client_fd;
/* const char *client_addr;
/* const char *client_port;
/* const char *text;
/*
-/* int PS_SEND_REPLY(state, text)
+/* int PSC_SEND_REPLY(state, text)
/* const char *text;
/*
-/* void ps_send_socket(state)
-/* PS_STATE *state;
+/* void psc_send_socket(state)
+/* PSC_STATE *state;
/* DESCRIPTION
-/* ps_send_reply() sends the specified text to the specified
+/* psc_send_reply() sends the specified text to the specified
/* remote SMTP client. In case of an immediate error, it logs
/* a warning (except EPIPE) with the client address and port,
/* and returns a non-zero result (all errors including EPIPE).
/*
-/* PS_SEND_REPLY() is a convenience wrapper for ps_send_reply().
+/* PSC_SEND_REPLY() is a convenience wrapper for psc_send_reply().
/* It is an unsafe macro that evaluates its arguments multiple
/* times.
/*
-/* ps_send_socket() sends the specified socket to the real
+/* psc_send_socket() sends the specified socket to the real
/* Postfix SMTP server. The socket is delivered in the background.
/* This function must be called after all other session-related
/* work is finished including postscreen cache updates.
/*
-/* In case of an immediate error, ps_send_socket() sends a 421
+/* In case of an immediate error, psc_send_socket() sends a 421
/* reply to the remote SMTP client and closes the connection.
/* LICENSE
/* .ad
* This program screens all inbound SMTP connections, so it better not waste
* time.
*/
-#define PS_SEND_SOCK_CONNECT_TIMEOUT 1
-#define PS_SEND_SOCK_NOTIFY_TIMEOUT 100
-#define PS_SEND_TEXT_TIMEOUT 1
+#define PSC_SEND_SOCK_CONNECT_TIMEOUT 1
+#define PSC_SEND_SOCK_NOTIFY_TIMEOUT 100
+#define PSC_SEND_TEXT_TIMEOUT 1
-/* ps_send_reply - send reply to remote SMTP client */
+/* psc_send_reply - send reply to remote SMTP client */
-int ps_send_reply(int smtp_client_fd, const char *smtp_client_addr,
- const char *smtp_client_port, const char *text)
+int psc_send_reply(int smtp_client_fd, const char *smtp_client_addr,
+ const char *smtp_client_port, const char *text)
{
int ret;
* response, so that a nasty client can't cause this process to block.
*/
ret = (write_buf(smtp_client_fd, text, strlen(text),
- PS_SEND_TEXT_TIMEOUT) < 0);
+ PSC_SEND_TEXT_TIMEOUT) < 0);
if (ret != 0 && errno != EPIPE)
msg_warn("write [%s]:%s: %m", smtp_client_addr, smtp_client_port);
return (ret);
}
-/* ps_send_socket_close_event - file descriptor has arrived or timeout */
+/* psc_send_socket_close_event - file descriptor has arrived or timeout */
-static void ps_send_socket_close_event(int event, char *context)
+static void psc_send_socket_close_event(int event, char *context)
{
- const char *myname = "ps_send_socket_close_event";
- PS_STATE *state = (PS_STATE *) context;
+ const char *myname = "psc_send_socket_close_event";
+ PSC_STATE *state = (PSC_STATE *) context;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d event %d on send socket %d from [%s]:%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
event, state->smtp_server_fd, state->smtp_client_addr,
state->smtp_client_port);
* possible that the real SMTP server will receive the socket so we
* should not interfere.
*/
- PS_CLEAR_EVENT_REQUEST(state->smtp_server_fd, ps_send_socket_close_event,
- context);
+ PSC_CLEAR_EVENT_REQUEST(state->smtp_server_fd, psc_send_socket_close_event,
+ context);
if (event == EVENT_TIME)
msg_warn("timeout sending connection to service %s",
- ps_smtpd_service_name);
- ps_free_session_state(state);
+ psc_smtpd_service_name);
+ psc_free_session_state(state);
}
-/* ps_send_socket - send socket to real SMTP server process */
+/* psc_send_socket - send socket to real SMTP server process */
-void ps_send_socket(PS_STATE *state)
+void psc_send_socket(PSC_STATE *state)
{
- const char *myname = "ps_send_socket";
+ const char *myname = "psc_send_socket";
int server_fd;
int window_size;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d send socket %d from [%s]:%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port);
* Postfix-specific.
*/
if ((server_fd =
- LOCAL_CONNECT(ps_smtpd_service_name, NON_BLOCKING,
- PS_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
- msg_warn("cannot connect to service %s: %m", ps_smtpd_service_name);
- PS_SEND_REPLY(state, "421 4.3.2 All server ports are busy\r\n");
- ps_free_session_state(state);
+ LOCAL_CONNECT(psc_smtpd_service_name, NON_BLOCKING,
+ PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
+ msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name);
+ PSC_SEND_REPLY(state, "421 4.3.2 All server ports are busy\r\n");
+ psc_free_session_state(state);
return;
}
- PS_ADD_SERVER_STATE(state, server_fd);
+ PSC_ADD_SERVER_STATE(state, server_fd);
if (LOCAL_SEND_FD(state->smtp_server_fd,
vstream_fileno(state->smtp_client_stream)) < 0) {
msg_warn("cannot pass connection to service %s: %m",
- ps_smtpd_service_name);
- PS_SEND_REPLY(state, "421 4.3.2 No system resources\r\n");
- ps_free_session_state(state);
+ psc_smtpd_service_name);
+ PSC_SEND_REPLY(state, "421 4.3.2 No system resources\r\n");
+ psc_free_session_state(state);
return;
} else {
* it has already received the real SMTP server's 220 greeting!
*/
#if 0
- PS_DEL_CLIENT_STATE(state);
+ PSC_DEL_CLIENT_STATE(state);
#endif
- PS_READ_EVENT_REQUEST(state->smtp_server_fd, ps_send_socket_close_event,
- (char *) state, PS_SEND_SOCK_NOTIFY_TIMEOUT);
+ PSC_READ_EVENT_REQUEST(state->smtp_server_fd, psc_send_socket_close_event,
+ (char *) state, PSC_SEND_SOCK_NOTIFY_TIMEOUT);
return;
}
}
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* void ps_smtpd_init(void)
+/* void psc_smtpd_pre_jail_init(void)
/*
-/* void ps_smtpd_tests(state)
-/* PS_STATE *state;
+/* void psc_smtpd_init(void)
+/*
+/* void psc_smtpd_tests(state)
+/* PSC_STATE *state;
/* DESCRIPTION
-/* ps_smtpd_init() performs one-time per-process initialization.
+/* psc_smtpd_pre_jail_init() performs one-time per-process
+/* initialization during the "before chroot" execution phase.
+/*
+/* psc_smtpd_init() performs one-time per-process initialization.
/*
-/* ps_smtpd_tests() starts up an SMTP server engine for deep
+/* psc_smtpd_tests() starts up an SMTP server engine for deep
/* protocol tests and for collecting helo/sender/recipient
/* information.
/*
/* their commands anyway. To pass this test, the client has
/* to speak SMTP all the way to the RCPT TO command.
/*
-/* No support is announced for AUTH, STARTTLS, XCLIENT or
-/* XFORWARD. Clients that need this should be whitelisted or
-/* should talk directly to the submission service. Support
-/* for STARTTLS may be added later.
+/* No support is announced for AUTH, XCLIENT or XFORWARD.
+/* Clients that need this should be whitelisted or should talk
+/* directly to the submission service.
/*
/* The engine rejects RCPT TO and VRFY commands with the
/* state->rcpt_reply response which depends on program history,
#include <mail_proto.h>
#include <is_header.h>
#include <string_list.h>
+#include <maps.h>
+#include <ehlo_mask.h>
+
+/* TLS library. */
+
+#include <tls.h>
/* Application-specific. */
* per-session push-back except for the single-character push-back that
* VSTREAM guarantees after we read one character.
*/
-#define PS_SMTPD_HAVE_PUSH_BACK(state) (0)
-#define PS_SMTPD_PUSH_BACK_CHAR(state, ch) \
+#define PSC_SMTPD_HAVE_PUSH_BACK(state) (0)
+#define PSC_SMTPD_PUSH_BACK_CHAR(state, ch) \
vstream_ungetc((state)->smtp_client_stream, (ch))
-#define PS_SMTPD_NEXT_CHAR(state) \
+#define PSC_SMTPD_NEXT_CHAR(state) \
VSTREAM_GETC((state)->smtp_client_stream)
/*
* Dynamic reply strings. To minimize overhead we format these once.
*/
-static char *ps_smtpd_greeting; /* smtp banner */
-static char *ps_smtpd_helo_reply; /* helo reply */
-static char *ps_smtpd_ehlo_reply; /* multi-line ehlo reply */
-static char *ps_smtpd_timeout_reply; /* timeout reply */
-static char *ps_smtpd_421_reply; /* generic final_reply value */
+static char *psc_smtpd_greeting; /* smtp banner */
+static char *psc_smtpd_helo_reply; /* helo reply */
+static char *psc_smtpd_ehlo_reply_plain;/* multi-line ehlo reply, non-TLS */
+static char *psc_smtpd_ehlo_reply_tls; /* multi-line ehlo reply, with TLS */
+static char *psc_smtpd_timeout_reply; /* timeout reply */
+static char *psc_smtpd_421_reply; /* generic final_reply value */
/*
- * Forward declaration, needed by PS_CLEAR_EVENT_REQUEST.
+ * Forward declaration, needed by PSC_CLEAR_EVENT_REQUEST.
*/
-static void ps_smtpd_time_event(int, char *);
+static void psc_smtpd_time_event(int, char *);
+static void psc_smtpd_read_event(int, char *);
+
+ /*
+ * Encapsulation. The STARTTLS, EHLO and AUTH command handlers temporarily
+ * suspend SMTP command events, send an asynchronous proxy request, and
+ * resume SMTP command events after receiving the asynchrounous proxy
+ * response.
+ */
+#define PSC_RESUME_SMTP_CMD_EVENTS(state) \
+ PSC_READ_EVENT_REQUEST2(vstream_fileno((state)->smtp_client_stream), \
+ psc_smtpd_read_event, psc_smtpd_time_event, \
+ (char *) (state), PSC_EFF_CMD_TIME_LIMIT)
+
+#define PSC_SUSPEND_SMTP_CMD_EVENTS(state) \
+ PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
+ psc_smtpd_time_event, (char *) (state));
/*
* Command parser support.
*/
-#define PS_SMTPD_NEXT_TOKEN(ptr) mystrtok(&(ptr), " ")
+#define PSC_SMTPD_NEXT_TOKEN(ptr) mystrtok(&(ptr), " ")
+
+ /*
+ * EHLO keyword filter
+ */
+static MAPS *psc_ehlo_discard_maps;
+static int psc_ehlo_discard_mask;
+
+ /*
+ * STARTTLS support. Note the complete absence of #ifdef USE_TLS throughout
+ * the postscreen(8) source code. If Postfix is built without TLS support,
+ * then the TLS proxy will simply report that TLS is not available, and
+ * conventional error handling will take care of the issue.
+ */
+static int psc_tls_use_tls;
+static int psc_tls_enforce_tls;
+
+#ifdef TODO_USE_SASL_AUTH
+static int psc_tls_auth_only;
+
+#endif
/*
* Encapsulation. We must not forget turn off input/timer events when we
* with the Postfix smtp-source and smtp-sink tools shows that this would
* noticeably increase the run-time cost.
*/
-#define PS_CLEAR_EVENT_DROP_SESSION_STATE(state, event, reply) do { \
- PS_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
+#define PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, event, reply) do { \
+ PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
(event), (char *) (state)); \
- PS_DROP_SESSION_STATE((state), (reply)); \
+ PSC_DROP_SESSION_STATE((state), (reply)); \
} while (0);
-#define PS_CLEAR_EVENT_HANGUP(state, event) do { \
- PS_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
+#define PSC_CLEAR_EVENT_HANGUP(state, event) do { \
+ PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
(event), (char *) (state)); \
- ps_hangup_event(state); \
+ psc_hangup_event(state); \
} while (0);
-/* ps_helo_cmd - record HELO and respond */
+/* psc_helo_cmd - record HELO and respond */
-static int ps_helo_cmd(PS_STATE *state, char *args)
+static int psc_helo_cmd(PSC_STATE *state, char *args)
{
- char *helo_name = PS_SMTPD_NEXT_TOKEN(args);
+ char *helo_name = PSC_SMTPD_NEXT_TOKEN(args);
/*
* smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them.
*/
if (helo_name == 0)
- return (PS_SEND_REPLY(state, "501 Syntax: HELO hostname\r\n"));
+ return (PSC_SEND_REPLY(state, "501 Syntax: HELO hostname\r\n"));
- PS_STRING_UPDATE(state->helo_name, helo_name);
- PS_STRING_RESET(state->sender);
+ PSC_STRING_UPDATE(state->helo_name, helo_name);
+ PSC_STRING_RESET(state->sender);
/* Don't downgrade state->protocol, in case some test depends on this. */
- return (PS_SEND_REPLY(state, ps_smtpd_helo_reply));
+ return (PSC_SEND_REPLY(state, psc_smtpd_helo_reply));
+}
+
+/* psc_smtpd_format_ehlo_reply - format EHLO response */
+
+static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask)
+{
+ const char *myname = "psc_smtpd_format_ehlo_reply";
+ int saved_len = 0;
+
+ if (msg_verbose)
+ msg_info("%s: discard_mask %s", myname, str_ehlo_mask(discard_mask));
+
+#define PSC_EHLO_APPEND(save, buf, fmt) do { \
+ (save) = LEN(buf); \
+ vstring_sprintf_append((buf), (fmt)); \
+ } while (0)
+
+#define PSC_EHLO_APPEND1(save, buf, fmt, arg1) do { \
+ (save) = LEN(buf); \
+ vstring_sprintf_append((buf), (fmt), (arg1)); \
+ } while (0)
+
+ vstring_sprintf(psc_temp, "250-%s\r\n", var_myhostname);
+ if ((discard_mask & EHLO_MASK_SIZE) == 0) {
+ if (var_message_limit)
+ PSC_EHLO_APPEND1(saved_len, psc_temp, "250-SIZE %lu\r\n",
+ (unsigned long) var_message_limit);
+ else
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-SIZE\r\n");
+ }
+ if ((discard_mask & EHLO_MASK_VRFY) == 0 && var_disable_vrfy_cmd == 0)
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-VRFY\r\n");
+ if ((discard_mask & EHLO_MASK_ETRN) == 0)
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-ETRN\r\n");
+ if ((discard_mask & EHLO_MASK_STARTTLS) == 0
+ && (psc_tls_use_tls || psc_tls_enforce_tls))
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-STARTTLS\r\n");
+#ifdef TODO_SASL_AUTH
+ if ((discard_mask & EHLO_MASK_AUTH) == 0 && sasl_mechanism_list
+ && (psc_tls_auth_only == 0 || (discard_mask & EHLO_MASK_STARTTLS))) {
+ PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH %s", sasl_mechanism_list);
+ if (var_broken_auth_clients)
+ PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH=%s", sasl_mechanism_list);
+ }
+#endif
+ if ((discard_mask & EHLO_MASK_ENHANCEDSTATUSCODES) == 0)
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-ENHANCEDSTATUSCODES\r\n");
+ if ((discard_mask & EHLO_MASK_8BITMIME) == 0)
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-8BITMIME\r\n");
+ if ((discard_mask & EHLO_MASK_DSN) == 0)
+ PSC_EHLO_APPEND(saved_len, psc_temp, "250-DSN\r\n");
+ STR(psc_temp)[saved_len + 3] = ' ';
}
-/* ps_ehlo_cmd - record EHLO and respond */
+/* psc_ehlo_cmd - record EHLO and respond */
-static int ps_ehlo_cmd(PS_STATE *state, char *args)
+static int psc_ehlo_cmd(PSC_STATE *state, char *args)
{
- char *helo_name = PS_SMTPD_NEXT_TOKEN(args);
+ char *helo_name = PSC_SMTPD_NEXT_TOKEN(args);
+ const char *ehlo_words;
+ int discard_mask;
+ char *reply;
/*
* smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them.
*/
if (helo_name == 0)
- return (PS_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
+ return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
- PS_STRING_UPDATE(state->helo_name, helo_name);
- PS_STRING_RESET(state->sender);
+ PSC_STRING_UPDATE(state->helo_name, helo_name);
+ PSC_STRING_RESET(state->sender);
state->protocol = MAIL_PROTO_ESMTP;
- return (PS_SEND_REPLY(state, ps_smtpd_ehlo_reply));
+
+ /*
+ * smtpd(8) compatibility: dynamic reply filtering.
+ */
+ if (psc_ehlo_discard_maps != 0
+ && (ehlo_words = maps_find(psc_ehlo_discard_maps,
+ state->smtp_client_addr, 0)) != 0
+ && (discard_mask = ehlo_mask(ehlo_words)) != psc_ehlo_discard_mask) {
+ if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
+ msg_info("[%s]%s: discarding EHLO keywords: %s",
+ PSC_CLIENT_ADDR_PORT(state), str_ehlo_mask(discard_mask));
+ if (state->flags & PSC_STATE_FLAG_USING_TLS)
+ discard_mask |= EHLO_MASK_STARTTLS;
+ psc_smtpd_format_ehlo_reply(psc_temp, discard_mask);
+ reply = STR(psc_temp);
+ state->ehlo_discard_mask = discard_mask;
+ } else if (state->flags & PSC_STATE_FLAG_USING_TLS) {
+ reply = psc_smtpd_ehlo_reply_tls;
+ state->ehlo_discard_mask = psc_ehlo_discard_mask | EHLO_MASK_STARTTLS;
+ } else {
+ reply = psc_smtpd_ehlo_reply_plain;
+ state->ehlo_discard_mask = psc_ehlo_discard_mask;
+ }
+ return (PSC_SEND_REPLY(state, reply));
+}
+
+/* psc_starttls_resume - resume the SMTP protocol after tlsproxy activation */
+
+static void psc_starttls_resume(int unused_event, char *context)
+{
+ const char *myname = "psc_starttls_resume";
+ PSC_STATE *state = (PSC_STATE *) context;
+
+ /*
+ * Reset SMTP server state if STARTTLS was successful. Todo: reset SASL
+ * AUTH state. Dovecot responses may change when it knows that a
+ * connection is encrypted.
+ */
+ if (state->flags & PSC_STATE_FLAG_USING_TLS) {
+ PSC_STRING_RESET(state->helo_name);
+ PSC_STRING_RESET(state->sender);
+ }
+
+ /*
+ * Wait for the client to respond.
+ */
+ PSC_RESUME_SMTP_CMD_EVENTS(state);
+}
+
+/* psc_starttls_cmd - activate the tlsproxy server */
+
+static int psc_starttls_cmd(PSC_STATE *state, char *args)
+{
+ const char *myname = "psc_starttls_cmd";
+
+ /*
+ * smtpd(8) incompatibility: we can't send a 4XX reply that TLS is
+ * unavailable when tlsproxy(8) detects the problem too late.
+ */
+ if (PSC_SMTPD_NEXT_TOKEN(args) != 0)
+ return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
+ if (state->flags & PSC_STATE_FLAG_USING_TLS)
+ return (PSC_SEND_REPLY(state,
+ "554 5.5.1 Error: TLS already active\r\n"));
+ if (psc_tls_use_tls == 0 || (state->ehlo_discard_mask & EHLO_MASK_STARTTLS))
+ return (PSC_SEND_REPLY(state,
+ "502 5.5.1 Error: command not implemented\r\n"));
+
+ /*
+ * Suspend the SMTP protocol until psc_starttls_resume() is called.
+ */
+ PSC_SUSPEND_SMTP_CMD_EVENTS(state);
+ psc_starttls_open(state, psc_starttls_resume);
+ return (0);
}
-/* ps_extract_addr - extract MAIL/RCPT address, unquoted form */
+/* psc_extract_addr - extract MAIL/RCPT address, unquoted form */
-static char *ps_extract_addr(VSTRING *result, const char *string)
+static char *psc_extract_addr(VSTRING *result, const char *string)
{
const unsigned char *cp = (const unsigned char *) string;
int stop_at;
return (STR(result));
}
-/* ps_mail_cmd - record MAIL and respond */
+/* psc_mail_cmd - record MAIL and respond */
-static int ps_mail_cmd(PS_STATE *state, char *args)
+static int psc_mail_cmd(PSC_STATE *state, char *args)
{
char *colon;
char *addr;
* smtpd(8) incompatibility: we never reject the sender, and we ignore
* additional arguments.
*/
- if (var_ps_helo_required && state->helo_name == 0)
- return (PS_SEND_REPLY(state,
- "503 5.5.1 Error: send HELO/EHLO first\r\n"));
+ if (var_psc_helo_required && state->helo_name == 0)
+ return (PSC_SEND_REPLY(state,
+ "503 5.5.1 Error: send HELO/EHLO first\r\n"));
if (state->sender != 0)
- return (PS_SEND_REPLY(state,
- "503 5.5.1 Error: nested MAIL command\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "503 5.5.1 Error: nested MAIL command\r\n"));
if (args == 0 || (colon = strchr(args, ':')) == 0)
- return (PS_SEND_REPLY(state,
- "501 5.5.4 Syntax: MAIL FROM:<address>\r\n"));
- if ((addr = ps_extract_addr(ps_temp, colon + 1)) == 0)
- return (PS_SEND_REPLY(state,
- "501 5.1.7 Bad sender address syntax\r\n"));
- PS_STRING_UPDATE(state->sender, addr);
- return (PS_SEND_REPLY(state, "250 2.1.0 Ok\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "501 5.5.4 Syntax: MAIL FROM:<address>\r\n"));
+ if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0)
+ return (PSC_SEND_REPLY(state,
+ "501 5.1.7 Bad sender address syntax\r\n"));
+ PSC_STRING_UPDATE(state->sender, addr);
+ return (PSC_SEND_REPLY(state, "250 2.1.0 Ok\r\n"));
}
-/* ps_rcpt_cmd record RCPT and respond */
+/* psc_rcpt_cmd record RCPT and respond */
-static int ps_rcpt_cmd(PS_STATE *state, char *args)
+static int psc_rcpt_cmd(PSC_STATE *state, char *args)
{
char *colon;
char *addr;
* additional arguments.
*/
if (state->sender == 0)
- return (PS_SEND_REPLY(state,
- "503 5.5.1 Error: need MAIL command\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "503 5.5.1 Error: need MAIL command\r\n"));
if (args == 0 || (colon = strchr(args, ':')) == 0)
- return (PS_SEND_REPLY(state,
- "501 5.5.4 Syntax: RCPT TO:<address>\r\n"));
- if ((addr = ps_extract_addr(ps_temp, colon + 1)) == 0)
- return (PS_SEND_REPLY(state,
- "501 5.1.3 Bad recipient address syntax\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "501 5.5.4 Syntax: RCPT TO:<address>\r\n"));
+ if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0)
+ return (PSC_SEND_REPLY(state,
+ "501 5.1.3 Bad recipient address syntax\r\n"));
msg_info("NOQUEUE: reject: RCPT from [%s]:%s: %.*s; "
"from=<%s>, to=<%s>, proto=%s, helo=<%s>",
- PS_CLIENT_ADDR_PORT(state),
+ PSC_CLIENT_ADDR_PORT(state),
(int) strlen(state->rcpt_reply) - 2, state->rcpt_reply,
state->sender, addr, state->protocol,
state->helo_name ? state->helo_name : "");
- return (PS_SEND_REPLY(state, state->rcpt_reply));
+ return (PSC_SEND_REPLY(state, state->rcpt_reply));
}
-/* ps_data_cmd - respond to DATA and disconnect */
+/* psc_data_cmd - respond to DATA and disconnect */
-static int ps_data_cmd(PS_STATE *state, char *args)
+static int psc_data_cmd(PSC_STATE *state, char *args)
{
/*
* smtpd(8) incompatibility: we reject all requests.
*/
- if (PS_SMTPD_NEXT_TOKEN(args) != 0)
- return (PS_SEND_REPLY(state,
- "501 5.5.4 Syntax: DATA\r\n"));
+ if (PSC_SMTPD_NEXT_TOKEN(args) != 0)
+ return (PSC_SEND_REPLY(state,
+ "501 5.5.4 Syntax: DATA\r\n"));
if (state->sender == 0)
- return (PS_SEND_REPLY(state,
- "503 5.5.1 Error: need RCPT command\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "503 5.5.1 Error: need RCPT command\r\n"));
/*
* We really would like to hang up the connection as early as possible,
*
* If we proceed into the data phase, enforce over-all DATA time limit.
*/
- return (PS_SEND_REPLY(state,
- "554 5.5.1 Error: no valid recipients\r\n"));
+ return (PSC_SEND_REPLY(state,
+ "554 5.5.1 Error: no valid recipients\r\n"));
}
-/* ps_rset_cmd - reset, send 250 OK */
+/* psc_rset_cmd - reset, send 250 OK */
-static int ps_rset_cmd(PS_STATE *state, char *unused_args)
+static int psc_rset_cmd(PSC_STATE *state, char *unused_args)
{
- PS_STRING_RESET(state->sender);
- return (PS_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
+ PSC_STRING_RESET(state->sender);
+ return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
}
-/* ps_noop_cmd - respond to something */
+/* psc_noop_cmd - respond to something */
-static int ps_noop_cmd(PS_STATE *state, char *unused_args)
+static int psc_noop_cmd(PSC_STATE *state, char *unused_args)
{
- return (PS_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
+ return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
}
-/* ps_vrfy_cmd - respond to VRFY */
+/* psc_vrfy_cmd - respond to VRFY */
-static int ps_vrfy_cmd(PS_STATE *state, char *args)
+static int psc_vrfy_cmd(PSC_STATE *state, char *args)
{
/*
* smtpd(8) incompatibility: we reject all requests, and ignore
* additional arguments.
*/
- if (PS_SMTPD_NEXT_TOKEN(args) == 0)
- return (PS_SEND_REPLY(state,
- "501 5.5.4 Syntax: VRFY address\r\n"));
- if (var_ps_disable_vrfy)
- return (PS_SEND_REPLY(state,
- "502 5.5.1 VRFY command is disabled\r\n"));
- return (PS_SEND_REPLY(state, state->rcpt_reply));
+ if (PSC_SMTPD_NEXT_TOKEN(args) == 0)
+ return (PSC_SEND_REPLY(state,
+ "501 5.5.4 Syntax: VRFY address\r\n"));
+ if (var_psc_disable_vrfy)
+ return (PSC_SEND_REPLY(state,
+ "502 5.5.1 VRFY command is disabled\r\n"));
+ return (PSC_SEND_REPLY(state, state->rcpt_reply));
}
-/* ps_etrn_cmd - reset, send 250 OK */
+/* psc_etrn_cmd - reset, send 250 OK */
-static int ps_etrn_cmd(PS_STATE *state, char *args)
+static int psc_etrn_cmd(PSC_STATE *state, char *args)
{
/*
* smtpd(8) incompatibility: we reject all requests, and ignore
* additional arguments.
*/
- if (var_ps_helo_required && state->helo_name == 0)
- return (PS_SEND_REPLY(state,
- "503 5.5.1 Error: send HELO/EHLO first\r\n"));
- if (PS_SMTPD_NEXT_TOKEN(args) == 0)
- return (PS_SEND_REPLY(state,
- "500 Syntax: ETRN domain\r\n"));
- return (PS_SEND_REPLY(state, "458 Unable to queue messages\r\n"));
+ if (var_psc_helo_required && state->helo_name == 0)
+ return (PSC_SEND_REPLY(state,
+ "503 5.5.1 Error: send HELO/EHLO first\r\n"));
+ if (PSC_SMTPD_NEXT_TOKEN(args) == 0)
+ return (PSC_SEND_REPLY(state,
+ "500 Syntax: ETRN domain\r\n"));
+ return (PSC_SEND_REPLY(state, "458 Unable to queue messages\r\n"));
}
-/* ps_quit_cmd - respond to QUIT and disconnect */
+/* psc_quit_cmd - respond to QUIT and disconnect */
-static int ps_quit_cmd(PS_STATE *state, char *unused_args)
+static int psc_quit_cmd(PSC_STATE *state, char *unused_args)
{
- const char *myname = "ps_quit_cmd";
+ const char *myname = "psc_quit_cmd";
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
- "221 2.0.0 Bye\r\n");
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
+ "221 2.0.0 Bye\r\n");
/* Caution: state is now a dangling pointer. */
return (0);
}
-/* ps_smtpd_time_event - handle per-session time limit */
+/* psc_smtpd_time_event - handle per-session time limit */
-static void ps_smtpd_time_event(int event, char *context)
+static void psc_smtpd_time_event(int event, char *context)
{
- const char *myname = "ps_smtpd_time_event";
- PS_STATE *state = (PS_STATE *) context;
+ const char *myname = "psc_smtpd_time_event";
+ PSC_STATE *state = (PSC_STATE *) context;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
- ps_print_state_flags(state->flags, myname));
+ psc_print_state_flags(state->flags, myname));
- msg_info("COMMAND TIME LIMIT from [%s]:%s", PS_CLIENT_ADDR_PORT(state));
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
- ps_smtpd_timeout_reply);
+ msg_info("COMMAND TIME LIMIT from [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
+ psc_smtpd_timeout_reply);
}
/*
*/
typedef struct {
const char *name;
- int (*action) (PS_STATE *, char *);
+ int (*action) (PSC_STATE *, char *);
int flags; /* see below */
-} PS_SMTPD_COMMAND;
-
-#define PS_SMTPD_CMD_FLAG_NONE (0) /* no flags (i.e. disabled) */
-#define PS_SMTPD_CMD_FLAG_ENABLE (1<<0) /* command is enabled */
-#define PS_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */
-
-static const PS_SMTPD_COMMAND command_table[] = {
- "HELO", ps_helo_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "EHLO", ps_ehlo_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "XCLIENT", ps_noop_cmd, PS_SMTPD_CMD_FLAG_NONE,
- "XFORWARD", ps_noop_cmd, PS_SMTPD_CMD_FLAG_NONE,
- "AUTH", ps_noop_cmd, PS_SMTPD_CMD_FLAG_NONE,
- "MAIL", ps_mail_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "RCPT", ps_rcpt_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "DATA", ps_data_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- /* ".", ps_dot_cmd, PS_SMTPD_CMD_FLAG_NONE, */
- "RSET", ps_rset_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "NOOP", ps_noop_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "VRFY", ps_vrfy_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "ETRN", ps_etrn_cmd, PS_SMTPD_CMD_FLAG_ENABLE,
- "QUIT", ps_quit_cmd, PS_SMTPD_CMD_FLAG_ENABLE | PS_SMTPD_CMD_FLAG_DESTROY,
+} PSC_SMTPD_COMMAND;
+
+#define PSC_SMTPD_CMD_FLAG_NONE (0) /* no flags (i.e. disabled) */
+#define PSC_SMTPD_CMD_FLAG_ENABLE (1<<0) /* command is enabled */
+#define PSC_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */
+#define PSC_SMTPD_CMD_FLAG_PRE_TLS (1<<2) /* allowed with mandatory TLS */
+
+static const PSC_SMTPD_COMMAND command_table[] = {
+ "HELO", psc_helo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
+ "EHLO", psc_ehlo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
+ "STARTTLS", psc_starttls_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
+ "XCLIENT", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
+ "XFORWARD", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
+ "AUTH", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
+ "MAIL", psc_mail_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ "RCPT", psc_rcpt_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ "DATA", psc_data_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ /* ".", psc_dot_cmd, PSC_SMTPD_CMD_FLAG_NONE, */
+ "RSET", psc_rset_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ "NOOP", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
+ "VRFY", psc_vrfy_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ "ETRN", psc_etrn_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
+ "QUIT", psc_quit_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_DESTROY | PSC_SMTPD_CMD_FLAG_PRE_TLS,
0,
};
-/* ps_smtpd_read_event - pseudo responder */
+/* psc_smtpd_read_event - pseudo responder */
-static void ps_smtpd_read_event(int event, char *context)
+static void psc_smtpd_read_event(int event, char *context)
{
- const char *myname = "ps_smtpd_read_event";
- PS_STATE *state = (PS_STATE *) context;
+ const char *myname = "psc_smtpd_read_event";
+ PSC_STATE *state = (PSC_STATE *) context;
int ch;
struct cmd_trans {
int state;
int next_state;
};
-#define PS_SMTPD_CMD_ST_ANY 0
-#define PS_SMTPD_CMD_ST_CR 1
-#define PS_SMTPD_CMD_ST_CR_LF 2
+#define PSC_SMTPD_CMD_ST_ANY 0
+#define PSC_SMTPD_CMD_ST_CR 1
+#define PSC_SMTPD_CMD_ST_CR_LF 2
static const struct cmd_trans cmd_trans[] = {
- PS_SMTPD_CMD_ST_ANY, '\r', PS_SMTPD_CMD_ST_CR,
- PS_SMTPD_CMD_ST_CR, '\n', PS_SMTPD_CMD_ST_CR_LF,
+ PSC_SMTPD_CMD_ST_ANY, '\r', PSC_SMTPD_CMD_ST_CR,
+ PSC_SMTPD_CMD_ST_CR, '\n', PSC_SMTPD_CMD_ST_CR_LF,
0, 0, 0,
};
const struct cmd_trans *transp;
char *cmd_buffer_ptr;
char *command;
- const PS_SMTPD_COMMAND *cmdp;
+ const PSC_SMTPD_COMMAND *cmdp;
int write_stat;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
- myname, ps_post_queue_length, ps_check_queue_length,
+ myname, psc_post_queue_length, psc_check_queue_length,
event, vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port,
- ps_print_state_flags(state->flags, myname));
+ psc_print_state_flags(state->flags, myname));
/*
* Basic liveness requirements.
* Don't try to read input before it has arrived, otherwise we would starve
* the pseudo threads of other sessions. Get out of here as soon as the
* VSTREAM read buffer dries up. Do not look for more input in kernel
- * buffers. That input wasn't likely there when ps_smtpd_read_event() was
- * called. Also, yielding the pseudo thread will improve fairness for
+ * buffers. That input wasn't likely there when psc_smtpd_read_event()
+ * was called. Also, yielding the pseudo thread will improve fairness for
* other pseudo threads.
*/
-#define PS_SMTPD_BUFFER_EMPTY(state) \
- (!PS_SMTPD_HAVE_PUSH_BACK(state) \
+#define PSC_SMTPD_BUFFER_EMPTY(state) \
+ (!PSC_SMTPD_HAVE_PUSH_BACK(state) \
&& vstream_peek(state->smtp_client_stream) <= 0)
/*
*/
for (;;) {
- if ((ch = PS_SMTPD_NEXT_CHAR(state)) == VSTREAM_EOF) {
- PS_CLEAR_EVENT_HANGUP(state, ps_smtpd_time_event);
+ if ((ch = PSC_SMTPD_NEXT_CHAR(state)) == VSTREAM_EOF) {
+ PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event);
return;
}
/*
* Sanity check. We don't want to store infinitely long commands.
*/
- if (state->read_state == PS_SMTPD_CMD_ST_ANY
+ if (state->read_state == PSC_SMTPD_CMD_ST_ANY
&& VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
msg_info("COMMAND LENGTH LIMIT from [%s]:%s",
- PS_CLIENT_ADDR_PORT(state));
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
- ps_smtpd_421_reply);
+ PSC_CLIENT_ADDR_PORT(state));
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
+ psc_smtpd_421_reply);
return;
}
VSTRING_ADDCH(state->cmd_buffer, ch);
else if (ch == cmd_trans[0].want)
state->read_state = cmd_trans[0].next_state;
else
- state->read_state = PS_SMTPD_CMD_ST_ANY;
- if (state->read_state == PS_SMTPD_CMD_ST_CR_LF) {
+ state->read_state = PSC_SMTPD_CMD_ST_ANY;
+ if (state->read_state == PSC_SMTPD_CMD_ST_CR_LF) {
vstring_truncate(state->cmd_buffer,
VSTRING_LEN(state->cmd_buffer) - 2);
break;
* Bare newline test.
*/
if (ch == '\n') {
- if ((state->flags & PS_STATE_MASK_BARLF_TODO_SKIP)
- == PS_STATE_FLAG_BARLF_TODO) {
+ if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP)
+ == PSC_STATE_FLAG_BARLF_TODO) {
msg_info("BARE NEWLINE from [%s]:%s",
- PS_CLIENT_ADDR_PORT(state));
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_BARLF_FAIL);
- PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_BARLF_PASS);
- state->barlf_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
+ PSC_CLIENT_ADDR_PORT(state));
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_FAIL);
+ PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_PASS);
+ state->barlf_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */
/* Skip this test for the remainder of this session. */
- PS_SKIP_SESSION_STATE(state, "bare newline test",
- PS_STATE_FLAG_BARLF_SKIP);
- switch (ps_barlf_action) {
- case PS_ACT_DROP:
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state,
- ps_smtpd_time_event,
+ PSC_SKIP_SESSION_STATE(state, "bare newline test",
+ PSC_STATE_FLAG_BARLF_SKIP);
+ switch (psc_barlf_action) {
+ case PSC_ACT_DROP:
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state,
+ psc_smtpd_time_event,
"521 5.5.1 Protocol error\r\n");
return;
- case PS_ACT_ENFORCE:
- PS_ENFORCE_SESSION_STATE(state,
+ case PSC_ACT_ENFORCE:
+ PSC_ENFORCE_SESSION_STATE(state,
"550 5.5.1 Protocol error\r\n");
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state,
- PS_STATE_FLAG_BARLF_FAIL);
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state,
+ PSC_STATE_FLAG_BARLF_FAIL);
/* Temporarily whitelist until something expires. */
- PS_PASS_SESSION_STATE(state, "bare newline test",
- PS_STATE_FLAG_BARLF_PASS);
- state->barlf_stamp = event_time() + ps_min_ttl;
+ PSC_PASS_SESSION_STATE(state, "bare newline test",
+ PSC_STATE_FLAG_BARLF_PASS);
+ state->barlf_stamp = event_time() + psc_min_ttl;
break;
default:
msg_panic("%s: unknown bare_newline action value %d",
- myname, ps_barlf_action);
+ myname, psc_barlf_action);
}
}
vstring_truncate(state->cmd_buffer,
* XXX Do not reset the read timeout. The entire command must be
* received within the time limit.
*/
- if (PS_SMTPD_BUFFER_EMPTY(state))
+ if (PSC_SMTPD_BUFFER_EMPTY(state))
return;
}
* this to work as expected, VSTRING_RESET() must be non-destructive.
*/
VSTRING_TERMINATE(state->cmd_buffer);
- state->read_state = PS_SMTPD_CMD_ST_ANY;
+ state->read_state = PSC_SMTPD_CMD_ST_ANY;
VSTRING_RESET(state->cmd_buffer);
/*
state->smtp_client_port, cmd_buffer_ptr);
/* Parse the command name. */
- if ((command = PS_SMTPD_NEXT_TOKEN(cmd_buffer_ptr)) == 0)
+ if ((command = PSC_SMTPD_NEXT_TOKEN(cmd_buffer_ptr)) == 0)
command = "";
/*
break;
/* Non-SMTP command test. */
- if ((state->flags & PS_STATE_MASK_NSMTP_TODO_SKIP)
- == PS_STATE_FLAG_NSMTP_TODO && cmdp->name == 0
+ if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_SKIP)
+ == PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0
&& (is_header(command)
- || (*var_ps_forbid_cmds
- && string_list_match(ps_forbid_cmds, command)))) {
+ || (*var_psc_forbid_cmds
+ && string_list_match(psc_forbid_cmds, command)))) {
printable(command, '?');
msg_info("NON-SMTP COMMAND from [%s]:%s %.100s",
- PS_CLIENT_ADDR_PORT(state), command);
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_NSMTP_FAIL);
- PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_NSMTP_PASS);
- state->nsmtp_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
+ PSC_CLIENT_ADDR_PORT(state), command);
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_FAIL);
+ PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_PASS);
+ state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */
/* Skip this test for the remainder of this SMTP session. */
- PS_SKIP_SESSION_STATE(state, "non-smtp test",
- PS_STATE_FLAG_NSMTP_SKIP);
- switch (ps_nsmtp_action) {
- case PS_ACT_DROP:
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state,
- ps_smtpd_time_event,
+ PSC_SKIP_SESSION_STATE(state, "non-smtp test",
+ PSC_STATE_FLAG_NSMTP_SKIP);
+ switch (psc_nsmtp_action) {
+ case PSC_ACT_DROP:
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state,
+ psc_smtpd_time_event,
"521 5.7.0 Error: I can break rules, too. Goodbye.\r\n");
return;
- case PS_ACT_ENFORCE:
- PS_ENFORCE_SESSION_STATE(state,
- "550 5.5.1 Protocol error\r\n");
+ case PSC_ACT_ENFORCE:
+ PSC_ENFORCE_SESSION_STATE(state,
+ "550 5.5.1 Protocol error\r\n");
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state,
- PS_STATE_FLAG_NSMTP_FAIL);
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state,
+ PSC_STATE_FLAG_NSMTP_FAIL);
/* Temporarily whitelist until something else expires. */
- PS_PASS_SESSION_STATE(state, "non-smtp test",
- PS_STATE_FLAG_NSMTP_PASS);
- state->nsmtp_stamp = event_time() + ps_min_ttl;
+ PSC_PASS_SESSION_STATE(state, "non-smtp test",
+ PSC_STATE_FLAG_NSMTP_PASS);
+ state->nsmtp_stamp = event_time() + psc_min_ttl;
break;
default:
msg_panic("%s: unknown non_smtp_command action value %d",
- myname, ps_nsmtp_action);
+ myname, psc_nsmtp_action);
}
}
/* Command PIPELINING test. */
- if ((state->flags & PS_STATE_MASK_PIPEL_TODO_SKIP)
- == PS_STATE_FLAG_PIPEL_TODO && !PS_SMTPD_BUFFER_EMPTY(state)) {
+ if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_SKIP)
+ == PSC_STATE_FLAG_PIPEL_TODO && !PSC_SMTPD_BUFFER_EMPTY(state)) {
printable(command, '?');
msg_info("COMMAND PIPELINING from [%s]:%s after %.100s",
- PS_CLIENT_ADDR_PORT(state), command);
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_PIPEL_FAIL);
- PS_UNPASS_SESSION_STATE(state, PS_STATE_FLAG_PIPEL_PASS);
- state->pipel_stamp = PS_TIME_STAMP_DISABLED; /* XXX */
+ PSC_CLIENT_ADDR_PORT(state), command);
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_FAIL);
+ PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_PASS);
+ state->pipel_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */
/* Skip this test for the remainder of this SMTP session. */
- PS_SKIP_SESSION_STATE(state, "pipelining test",
- PS_STATE_FLAG_PIPEL_SKIP);
- switch (ps_pipel_action) {
- case PS_ACT_DROP:
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state,
- ps_smtpd_time_event,
+ PSC_SKIP_SESSION_STATE(state, "pipelining test",
+ PSC_STATE_FLAG_PIPEL_SKIP);
+ switch (psc_pipel_action) {
+ case PSC_ACT_DROP:
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state,
+ psc_smtpd_time_event,
"521 5.5.1 Protocol error\r\n");
return;
- case PS_ACT_ENFORCE:
- PS_ENFORCE_SESSION_STATE(state,
- "550 5.5.1 Protocol error\r\n");
+ case PSC_ACT_ENFORCE:
+ PSC_ENFORCE_SESSION_STATE(state,
+ "550 5.5.1 Protocol error\r\n");
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state,
- PS_STATE_FLAG_PIPEL_FAIL);
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state,
+ PSC_STATE_FLAG_PIPEL_FAIL);
/* Temporarily whitelist until something else expires. */
- PS_PASS_SESSION_STATE(state, "pipelining test",
- PS_STATE_FLAG_PIPEL_PASS);
- state->pipel_stamp = event_time() + ps_min_ttl;
+ PSC_PASS_SESSION_STATE(state, "pipelining test",
+ PSC_STATE_FLAG_PIPEL_PASS);
+ state->pipel_stamp = event_time() + psc_min_ttl;
break;
default:
msg_panic("%s: unknown pipelining action value %d",
- myname, ps_pipel_action);
+ myname, psc_pipel_action);
}
}
* to the RCPT TO command. However, the client can still fail these
* tests with some later command.
*/
- if (cmdp->action == ps_rcpt_cmd) {
- if ((state->flags & PS_STATE_MASK_BARLF_TODO_PASS_FAIL)
- == PS_STATE_FLAG_BARLF_TODO) {
- PS_PASS_SESSION_STATE(state, "bare newline test",
- PS_STATE_FLAG_BARLF_PASS);
- /* XXX Reset to PS_TIME_STAMP_DISABLED on failure. */
- state->barlf_stamp = event_time() + var_ps_barlf_ttl;
+ if (cmdp->action == psc_rcpt_cmd) {
+ if ((state->flags & PSC_STATE_MASK_BARLF_TODO_PASS_FAIL)
+ == PSC_STATE_FLAG_BARLF_TODO) {
+ PSC_PASS_SESSION_STATE(state, "bare newline test",
+ PSC_STATE_FLAG_BARLF_PASS);
+ /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
+ state->barlf_stamp = event_time() + var_psc_barlf_ttl;
}
- if ((state->flags & PS_STATE_MASK_NSMTP_TODO_PASS_FAIL)
- == PS_STATE_FLAG_NSMTP_TODO) {
- PS_PASS_SESSION_STATE(state, "non-smtp test",
- PS_STATE_FLAG_NSMTP_PASS);
- /* XXX Reset to PS_TIME_STAMP_DISABLED on failure. */
- state->nsmtp_stamp = event_time() + var_ps_nsmtp_ttl;
+ if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL)
+ == PSC_STATE_FLAG_NSMTP_TODO) {
+ PSC_PASS_SESSION_STATE(state, "non-smtp test",
+ PSC_STATE_FLAG_NSMTP_PASS);
+ /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
+ state->nsmtp_stamp = event_time() + var_psc_nsmtp_ttl;
}
- if ((state->flags & PS_STATE_MASK_PIPEL_TODO_PASS_FAIL)
- == PS_STATE_FLAG_PIPEL_TODO) {
- PS_PASS_SESSION_STATE(state, "pipelining test",
- PS_STATE_FLAG_PIPEL_PASS);
- /* XXX Reset to PS_TIME_STAMP_DISABLED on failure. */
- state->pipel_stamp = event_time() + var_ps_pipel_ttl;
+ if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL)
+ == PSC_STATE_FLAG_PIPEL_TODO) {
+ PSC_PASS_SESSION_STATE(state, "pipelining test",
+ PSC_STATE_FLAG_PIPEL_PASS);
+ /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
+ state->pipel_stamp = event_time() + var_psc_pipel_ttl;
}
}
/* Command COUNT limit test. */
- if (++state->command_count > var_ps_cmd_count
- && cmdp->action != ps_quit_cmd) {
+ if (++state->command_count > var_psc_cmd_count
+ && cmdp->action != psc_quit_cmd) {
msg_info("COMMAND COUNT LIMIT from [%s]:%s",
- PS_CLIENT_ADDR_PORT(state));
- PS_CLEAR_EVENT_DROP_SESSION_STATE(state, ps_smtpd_time_event,
- ps_smtpd_421_reply);
+ PSC_CLIENT_ADDR_PORT(state));
+ PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
+ psc_smtpd_421_reply);
return;
}
/* Finally, execute the command. */
- if (cmdp->name == 0 || (cmdp->flags & PS_SMTPD_CMD_FLAG_ENABLE) == 0) {
- write_stat = PS_SEND_REPLY(state,
+ if (cmdp->name == 0 || (cmdp->flags & PSC_SMTPD_CMD_FLAG_ENABLE) == 0) {
+ write_stat = PSC_SEND_REPLY(state,
"502 5.5.2 Error: command not recognized\r\n");
+ } else if (psc_tls_enforce_tls
+ && (state->flags & PSC_STATE_FLAG_USING_TLS) == 0
+ && (cmdp->flags & PSC_SMTPD_CMD_FLAG_PRE_TLS) == 0) {
+ write_stat = PSC_SEND_REPLY(state,
+ "530 5.7.0 Must issue a STARTTLS command first\r\n");
} else {
write_stat = cmdp->action(state, cmd_buffer_ptr);
- if (cmdp->flags & PS_SMTPD_CMD_FLAG_DESTROY)
+ if (cmdp->flags & PSC_SMTPD_CMD_FLAG_DESTROY)
return;
}
* Terminate the session after a write error.
*/
if (write_stat < 0) {
- PS_CLEAR_EVENT_HANGUP(state, ps_smtpd_time_event);
+ PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event);
return;
}
/*
* Reset the command read timeout before reading the next command.
*/
- event_request_timer(ps_smtpd_time_event, (char *) state,
- PS_EFF_CMD_TIME_LIMIT);
+ event_request_timer(psc_smtpd_time_event, (char *) state,
+ PSC_EFF_CMD_TIME_LIMIT);
/*
* Yield this pseudo thread when the VSTREAM buffer is empty.
*/
- if (PS_SMTPD_BUFFER_EMPTY(state))
+ if (PSC_SMTPD_BUFFER_EMPTY(state))
return;
}
}
-/* ps_smtpd_tests - per-session deep protocol test initialization */
+/* psc_smtpd_tests - per-session deep protocol test initialization */
-void ps_smtpd_tests(PS_STATE *state)
+void psc_smtpd_tests(PSC_STATE *state)
{
- static char *myname = "ps_smtpd_tests";
+ static char *myname = "psc_smtpd_tests";
/*
* Report errors and progress in the context of this test.
*/
- PS_BEGIN_TESTS(state, "tests after SMTP handshake");
+ PSC_BEGIN_TESTS(state, "tests after SMTP handshake");
/*
* Initialize per-session state that is used only by the dummy engine:
* the command read buffer and the command read state machine.
*/
state->cmd_buffer = vstring_alloc(100);
- state->read_state = PS_SMTPD_CMD_ST_ANY;
+ state->read_state = PSC_SMTPD_CMD_ST_ANY;
/*
* Opportunistically make postscreen more useful by turning on the
*
* XXX Make "opportunistically" configurable for each test.
*/
- state->flags |= (PS_STATE_FLAG_PIPEL_TODO | PS_STATE_FLAG_NSMTP_TODO | \
- PS_STATE_FLAG_BARLF_TODO);
+ state->flags |= (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_NSMTP_TODO | \
+ PSC_STATE_FLAG_BARLF_TODO);
/*
* Send no SMTP banner to pregreeting clients. This eliminates a lot of
* "NON-SMTP COMMAND" events, and improves sender/recipient logging.
*/
- if ((state->flags & PS_STATE_FLAG_PREGR_FAIL) == 0
- && PS_SEND_REPLY(state, ps_smtpd_greeting) != 0) {
- ps_hangup_event(state);
+ if ((state->flags & PSC_STATE_FLAG_PREGR_FAIL) == 0
+ && PSC_SEND_REPLY(state, psc_smtpd_greeting) != 0) {
+ psc_hangup_event(state);
return;
}
/*
* Wait for the client to respond.
*/
- PS_READ_EVENT_REQUEST2(vstream_fileno(state->smtp_client_stream),
- ps_smtpd_read_event, ps_smtpd_time_event,
- (char *) state, PS_EFF_CMD_TIME_LIMIT);
+ PSC_READ_EVENT_REQUEST2(vstream_fileno(state->smtp_client_stream),
+ psc_smtpd_read_event, psc_smtpd_time_event,
+ (char *) state, PSC_EFF_CMD_TIME_LIMIT);
}
-/* ps_smtpd_init - per-process deep protocol test initialization */
+/* psc_smtpd_init - per-process deep protocol test initialization */
-void ps_smtpd_init(void)
+void psc_smtpd_init(void)
{
/*
* Initialize the server banner.
*/
- vstring_sprintf(ps_temp, "220 %s\r\n", var_smtpd_banner);
- ps_smtpd_greeting = mystrdup(STR(ps_temp));
+ vstring_sprintf(psc_temp, "220 %s\r\n", var_smtpd_banner);
+ psc_smtpd_greeting = mystrdup(STR(psc_temp));
/*
* Initialize the HELO reply.
*/
- vstring_sprintf(ps_temp, "250 %s\r\n", var_myhostname);
- ps_smtpd_helo_reply = mystrdup(STR(ps_temp));
+ vstring_sprintf(psc_temp, "250 %s\r\n", var_myhostname);
+ psc_smtpd_helo_reply = mystrdup(STR(psc_temp));
/*
- * Initialize the EHLO reply.
+ * Legacy code copied from smtpd(8). The pre-fabricated EHLO reply
+ * depends on this.
*/
- vstring_sprintf(ps_temp,
- "250-%s\r\n", /* NOT: PIPELINING */
- var_myhostname);
- if (var_message_limit)
- vstring_sprintf_append(ps_temp,
- "250-SIZE %lu\r\n",
- (unsigned long) var_message_limit);
- else
- vstring_sprintf_append(ps_temp,
- "250-SIZE\r\n");
- if (var_disable_vrfy_cmd == 0)
- vstring_sprintf_append(ps_temp,
- "250-VRFY\r\n");
- vstring_sprintf_append(ps_temp,
- "250-ETRN\r\n"
- "250-ENHANCEDSTATUSCODES\r\n"
- "250-8BITMIME\r\n"
- "250 DSN\r\n");
- ps_smtpd_ehlo_reply = mystrdup(STR(ps_temp));
+ if (*var_psc_tls_level) {
+ switch (tls_level_lookup(var_psc_tls_level)) {
+ default:
+ msg_fatal("Invalid TLS level \"%s\"", var_psc_tls_level);
+ /* NOTREACHED */
+ break;
+ case TLS_LEV_SECURE:
+ case TLS_LEV_VERIFY:
+ case TLS_LEV_FPRINT:
+ case TLS_LEV_ENCRYPT:
+ var_psc_enforce_tls = var_psc_use_tls = 1;
+ break;
+ case TLS_LEV_MAY:
+ var_psc_enforce_tls = 0;
+ var_psc_use_tls = 1;
+ break;
+ case TLS_LEV_NONE:
+ var_psc_enforce_tls = var_psc_use_tls = 0;
+ break;
+ }
+ }
+ psc_tls_enforce_tls = var_psc_enforce_tls;
+ psc_tls_use_tls = var_psc_use_tls || var_psc_enforce_tls;
+#ifdef TODO_SASL_AUTH
+ if (var_psc_tls_auth_only || psc_tls_enforce_tls)
+ psc_tls_auth_only = 1;
+#endif
+
+ /*
+ * Initialize the EHLO reply. Once for plaintext sessions, and once for
+ * TLS sessions.
+ */
+ psc_smtpd_format_ehlo_reply(psc_temp, psc_ehlo_discard_mask);
+ psc_smtpd_ehlo_reply_plain = mystrdup(STR(psc_temp));
+
+ psc_smtpd_format_ehlo_reply(psc_temp,
+ psc_ehlo_discard_mask | EHLO_MASK_STARTTLS);
+ psc_smtpd_ehlo_reply_tls = mystrdup(STR(psc_temp));
/*
* Initialize the 421 timeout reply.
*/
- vstring_sprintf(ps_temp, "421 4.4.2 %s Error: timeout exceeded\r\n",
+ vstring_sprintf(psc_temp, "421 4.4.2 %s Error: timeout exceeded\r\n",
var_myhostname);
- ps_smtpd_timeout_reply = mystrdup(STR(ps_temp));
+ psc_smtpd_timeout_reply = mystrdup(STR(psc_temp));
/*
* Initialize the generic 421 reply.
*/
- vstring_sprintf(ps_temp, "421 %s Service unavailable - try again later\r\n",
+ vstring_sprintf(psc_temp, "421 %s Service unavailable - try again later\r\n",
var_myhostname);
- ps_smtpd_421_reply = mystrdup(STR(ps_temp));
+ psc_smtpd_421_reply = mystrdup(STR(psc_temp));
+}
+
+/* psc_smtpd_pre_jail_init - per-process deep protocol test initialization */
+
+void psc_smtpd_pre_jail_init(void)
+{
+
+ /*
+ * Determine what server ESMTP features to suppress, typically to avoid
+ * inter-operability problems. We do the default filter here, and
+ * determine client-dependent filtering on the fly.
+ *
+ * XXX Bugger. This means we have to restart when the table changes!
+ */
+ psc_ehlo_discard_maps = maps_create(VAR_PSC_EHLO_DIS_MAPS,
+ var_psc_ehlo_dis_maps,
+ DICT_FLAG_LOCK);
+ psc_ehlo_discard_mask = ehlo_mask(var_psc_ehlo_dis_words);
}
--- /dev/null
+/*++
+/* NAME
+/* postscreen_starttls 3
+/* SUMMARY
+/* postscreen TLS proxy support
+/* SYNOPSIS
+/* #include <postscreen.h>
+/*
+/* int psc_starttls_open(state, resume_event)
+/* PSC_STATE *state;
+/* void (*resume_event)(int unused_event, char *context);
+/* DESCRIPTION
+/* This module inserts the tlsproxy(8) proxy between the
+/* postscreen(8) server and the remote SMTP client. The entire
+/* process happens in the background, including notification
+/* of completion to the remote SMTP client and to the calling
+/* application.
+/*
+/* Before calling psc_starttls_open() the caller must turn off
+/* all pending timer and I/O event requests on the SMTP client
+/* stream.
+/*
+/* psc_starttls_open() starts the first transaction in the
+/* tlsproxy(8) hand-off protocol, and sets up event handlers
+/* for the successive protocol stages.
+/*
+/* Upon completion, the event handlers call resume_event()
+/* which must reset the SMTP helo/sender/etc. state when the
+/* PSC_STATE_FLAG_USING_TLS is set, and set up timer and read
+/* event requests to receive the next SMTP command.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <connect.h>
+#include <stringops.h> /* concatenate() */
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mail_proto.h>
+
+/* Application-specific. */
+
+#include <postscreen.h>
+
+ /*
+ * For now, this code is built into the postscreen(8) daemon. In the future
+ * it may be abstracted into a reusable library module for use by other
+ * event-driven programs (perhaps smtp-source and smtp-sink).
+ */
+
+ /*
+ * Transient state for the portscreen(8)-to-tlsproxy(8) hand-off protocol.
+ */
+typedef struct {
+ VSTREAM *tlsproxy_stream; /* hand-off negotiation */
+ EVENT_NOTIFY_FN resume_event; /* call-back handler */
+ PSC_STATE *smtp_state; /* SMTP session state */
+} PSC_STARTTLS;
+
+#define TLSPROXY_SERVICE "tlsproxy"
+#define TLSPROXY_INIT_TIMEOUT 10
+
+/* psc_starttls_finish - complete negotiation with TLS proxy */
+
+static void psc_starttls_finish(int event, char *context)
+{
+ const char *myname = "psc_starttls_finish";
+ PSC_STARTTLS *starttls_state = (PSC_STARTTLS *) context;
+ PSC_STATE *smtp_state = starttls_state->smtp_state;
+ VSTREAM *tlsproxy_stream = starttls_state->tlsproxy_stream;
+ int status;
+
+ if (msg_verbose)
+ msg_info("%s: send client handle on proxy socket %d"
+ " for smtp socket %d from [%s]:%s flags=%s",
+ myname, vstream_fileno(tlsproxy_stream),
+ vstream_fileno(smtp_state->smtp_client_stream),
+ smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
+ psc_print_state_flags(smtp_state->flags, myname));
+
+ /*
+ * We leave read-event notification enabled on the postscreen to TLS
+ * proxy stream, to avoid two kqueue/epoll/etc. system calls: one here,
+ * and one when resuming the dummy SMTP engine.
+ */
+ if (event != EVENT_TIME)
+ event_cancel_timer(psc_starttls_finish, (char *) starttls_state);
+
+ /*
+ * Receive the "TLS is available" indication.
+ *
+ * This may seem out of order, but we must have a read transaction between
+ * sending the request attributes and sending the SMTP client file
+ * descriptor. We can't assume UNIX-domain socket semantics here.
+ */
+ if (event != EVENT_READ
+ || attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
+ ATTR_TYPE_END) != 1 || status == 0) {
+
+ /*
+ * The TLS proxy reports that the TLS engine is not available (due to
+ * configuration error, or other causes).
+ */
+ event_disable_readwrite(vstream_fileno(tlsproxy_stream));
+ vstream_fclose(tlsproxy_stream);
+ PSC_SEND_REPLY(smtp_state,
+ "454 4.7.0 TLS not available due to local problem\r\n");
+ }
+
+ /*
+ * Send the remote SMTP client file descriptor.
+ */
+ else if (LOCAL_SEND_FD(vstream_fileno(tlsproxy_stream),
+ vstream_fileno(smtp_state->smtp_client_stream)) < 0) {
+
+ /*
+ * Some error: drop the TLS proxy stream.
+ */
+ msg_warn("%s sending file handle to %s service",
+ event == EVENT_TIME ? "timeout" : "problem",
+ TLSPROXY_SERVICE);
+ event_disable_readwrite(vstream_fileno(tlsproxy_stream));
+ vstream_fclose(tlsproxy_stream);
+ PSC_SEND_REPLY(smtp_state,
+ "454 4.7.0 TLS not available due to local problem\r\n");
+ }
+
+ /*
+ * After we send the plaintext 220 greeting, the client-side TLS engine
+ * is supposed to talk first, then the server-side TLS engine. However,
+ * postscreen(8) will not participate in that conversation.
+ */
+ else {
+ PSC_SEND_REPLY(smtp_state, "220 2.0.0 Ready to start TLS\r\n");
+
+ /*
+ * Replace our SMTP client stream by the TLS proxy stream. Once the
+ * TLS handshake is done, the TLS proxy will deliver plaintext SMTP
+ * commands to postscreen(8).
+ */
+ vstream_fclose(smtp_state->smtp_client_stream);
+ smtp_state->smtp_client_stream = tlsproxy_stream;
+ smtp_state->flags |= PSC_STATE_FLAG_USING_TLS;
+ }
+
+ /*
+ * Resume the postscreen(8) dummy SMTP engine and clean up.
+ */
+ starttls_state->resume_event(event, (char *) smtp_state);
+ myfree((char *) starttls_state);
+}
+
+/* psc_starttls_open - open negotiations with TLS proxy */
+
+void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
+{
+ const char *myname = "psc_starttls_open";
+ PSC_STARTTLS *starttls_state;
+ VSTREAM *tlsproxy_stream;
+ char *remote_endpt;
+ int fd;
+
+ /*
+ * Connect to the tlsproxy(8) daemon. We report all errors
+ * asynchronously, to avoid having to maintain multiple delivery paths.
+ */
+ if ((fd = LOCAL_CONNECT("private/" TLSPROXY_SERVICE,
+ NON_BLOCKING, 1)) < 0) {
+ msg_warn("connect to %s service: %m", TLSPROXY_SERVICE);
+ PSC_SEND_REPLY(smtp_state,
+ "454 4.7.0 TLS not available due to local problem\r\n");
+ event_request_timer(resume_event, (char *) smtp_state, 0);
+ return;
+ }
+ if (msg_verbose)
+ msg_info("%s: send client name/address on proxy socket %d"
+ " for smtp socket %d from [%s]:%s flags=%s",
+ myname, fd, vstream_fileno(smtp_state->smtp_client_stream),
+ smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
+ psc_print_state_flags(smtp_state->flags, myname));
+
+ /*
+ * Initial handshake. Send the data attributes now, and send the client
+ * file descriptor in a later transaction. We report all errors
+ * asynchronously, to avoid having to maintain multiple delivery paths.
+ *
+ * XXX The formatted endpoint should be a state member. Then, we can
+ * simplify all the format strings throughout the program.
+ */
+ tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
+ remote_endpt = concatenate("[", smtp_state->smtp_client_addr, "]:",
+ smtp_state->smtp_client_port, (char *) 0);
+ attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_STR, MAIL_ATTR_REMOTE_ENDPT, remote_endpt,
+ ATTR_TYPE_STR, MAIL_ATTR_ROLE, MAIL_ATTR_ROLE_SERVER,
+ ATTR_TYPE_INT, MAIL_ATTR_TIMEOUT, psc_normal_cmd_time_limit,
+ ATTR_TYPE_END);
+ myfree(remote_endpt);
+ if (vstream_fflush(tlsproxy_stream) != 0) {
+ msg_warn("error sending request to %s service: %m", TLSPROXY_SERVICE);
+ vstream_fclose(tlsproxy_stream);
+ PSC_SEND_REPLY(smtp_state,
+ "454 4.7.0 TLS not available due to local problem\r\n");
+ event_request_timer(resume_event, (char *) smtp_state, 0);
+ return;
+ }
+
+ /*
+ * Set up a read event for the next phase of the TLS proxy handshake.
+ */
+ starttls_state = (PSC_STARTTLS *) mymalloc(sizeof(*starttls_state));
+ starttls_state->tlsproxy_stream = tlsproxy_stream;
+ starttls_state->resume_event = resume_event;
+ starttls_state->smtp_state = smtp_state;
+ PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
+ (char *) starttls_state, TLSPROXY_INIT_TIMEOUT);
+}
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* PS_STATE *ps_new_session_state(stream, addr, port)
+/* PSC_STATE *psc_new_session_state(stream, addr, port)
/* VSTREAM *stream;
/* const char *addr;
/* const char *port;
/*
-/* void ps_free_session_state(state)
-/* PS_STATE *state;
+/* void psc_free_session_state(state)
+/* PSC_STATE *state;
/*
-/* char *ps_print_state_flags(flags, context)
+/* char *psc_print_state_flags(flags, context)
/* int flags;
/* const char *context;
/*
-/* void PS_ADD_SERVER_STATE(state, server_fd)
-/* PS_STATE *state;
+/* void PSC_ADD_SERVER_STATE(state, server_fd)
+/* PSC_STATE *state;
/* int server_fd;
/*
-/* void PS_DEL_CLIENT_STATE(state)
-/* PS_STATE *state;
+/* void PSC_DEL_CLIENT_STATE(state)
+/* PSC_STATE *state;
/*
-/* void PS_DROP_SESSION_STATE(state, final_reply)
-/* PS_STATE *state;
+/* void PSC_DROP_SESSION_STATE(state, final_reply)
+/* PSC_STATE *state;
/* const char *final_reply;
/*
-/* void PS_ENFORCE_SESSION_STATE(state, rcpt_reply)
-/* PS_STATE *state;
+/* void PSC_ENFORCE_SESSION_STATE(state, rcpt_reply)
+/* PSC_STATE *state;
/* const char *rcpt_reply;
/*
-/* void PS_PASS_SESSION_STATE(state, testname, pass_flag)
-/* PS_STATE *state;
+/* void PSC_PASS_SESSION_STATE(state, testname, pass_flag)
+/* PSC_STATE *state;
/* const char *testname;
/* int pass_flag;
/*
-/* void PS_FAIL_SESSION_STATE(state, fail_flag)
-/* PS_STATE *state;
+/* void PSC_FAIL_SESSION_STATE(state, fail_flag)
+/* PSC_STATE *state;
/* int fail_flag;
/*
-/* void PS_UNFAIL_SESSION_STATE(state, fail_flag)
-/* PS_STATE *state;
+/* void PSC_UNFAIL_SESSION_STATE(state, fail_flag)
+/* PSC_STATE *state;
/* int fail_flag;
/* DESCRIPTION
/* This module maintains per-client session state, and two
/* global file descriptor counters:
-/* .IP ps_check_queue_length
+/* .IP psc_check_queue_length
/* The total number of remote SMTP client sockets.
-/* .IP ps_post_queue_length
+/* .IP psc_post_queue_length
/* The total number of server file descriptors that are currently
/* in use for client file descriptor passing. This number
/* equals the number of client file descriptors in transit.
/* .PP
-/* ps_new_session_state() creates a new session state object
+/* psc_new_session_state() creates a new session state object
/* for the specified client stream, and increments the
-/* ps_check_queue_length counter. The flags and per-test time
-/* stamps are initialized with PS_INIT_TESTS(). The addr and
+/* psc_check_queue_length counter. The flags and per-test time
+/* stamps are initialized with PSC_INIT_TESTS(). The addr and
/* port arguments are null-terminated strings with the remote
/* SMTP client endpoint. The _reply members are set to
/* polite "try again" SMTP replies. The protocol member is set
/* to "SMTP".
/*
-/* The ps_stress variable is set to non-zero when
-/* ps_check_queue_length passes over a high-water mark.
+/* The psc_stress variable is set to non-zero when
+/* psc_check_queue_length passes over a high-water mark.
/*
-/* ps_free_session_state() destroys the specified session state
+/* psc_free_session_state() destroys the specified session state
/* object, closes the applicable I/O channels, and decrements
-/* the applicable file descriptor counters: ps_check_queue_length
-/* and ps_post_queue_length.
+/* the applicable file descriptor counters: psc_check_queue_length
+/* and psc_post_queue_length.
/*
-/* The ps_stress variable is reset to zero when ps_check_queue_length
+/* The psc_stress variable is reset to zero when psc_check_queue_length
/* passes under a low-water mark.
/*
-/* ps_print_state_flags() converts per-session flags into
+/* psc_print_state_flags() converts per-session flags into
/* human-readable form. The context is for error reporting.
/* The result is overwritten upon each call.
/*
-/* PS_ADD_SERVER_STATE() updates the specified session state
+/* PSC_ADD_SERVER_STATE() updates the specified session state
/* object with the specified server file descriptor, and
-/* increments the global ps_post_queue_length file descriptor
+/* increments the global psc_post_queue_length file descriptor
/* counter.
/*
-/* PS_DEL_CLIENT_STATE() updates the specified session state
+/* PSC_DEL_CLIENT_STATE() updates the specified session state
/* object, closes the client stream, and decrements the global
-/* ps_check_queue_length file descriptor counter.
+/* psc_check_queue_length file descriptor counter.
/*
-/* PS_DROP_SESSION_STATE() updates the specified session state
+/* PSC_DROP_SESSION_STATE() updates the specified session state
/* object and closes the client stream after sending the
/* specified SMTP reply.
/*
-/* PS_ENFORCE_SESSION_STATE() updates the specified session
+/* PSC_ENFORCE_SESSION_STATE() updates the specified session
/* state object. It arranges that the built-in SMTP engine
/* logs sender/recipient information and rejects all RCPT TO
/* commands with the specified SMTP reply.
/*
-/* PS_PASS_SESSION_STATE() sets the specified "pass" flag.
+/* PSC_PASS_SESSION_STATE() sets the specified "pass" flag.
/* The testname is used for debug logging.
/*
-/* PS_FAIL_SESSION_STATE() sets the specified "fail" flag.
+/* PSC_FAIL_SESSION_STATE() sets the specified "fail" flag.
/*
-/* PS_UNFAIL_SESSION_STATE() unsets the specified "fail" flag.
+/* PSC_UNFAIL_SESSION_STATE() unsets the specified "fail" flag.
/* LICENSE
/* .ad
/* .fi
#include <postscreen.h>
-/* ps_new_session_state - fill in connection state for event processing */
+/* psc_new_session_state - fill in connection state for event processing */
-PS_STATE *ps_new_session_state(VSTREAM *stream,
- const char *addr,
- const char *port)
+PSC_STATE *psc_new_session_state(VSTREAM *stream,
+ const char *addr,
+ const char *port)
{
- PS_STATE *state;
+ PSC_STATE *state;
HTABLE_INFO *ht;
- state = (PS_STATE *) mymalloc(sizeof(*state));
- PS_INIT_TESTS(state);
+ state = (PSC_STATE *) mymalloc(sizeof(*state));
+ PSC_INIT_TESTS(state);
if ((state->smtp_client_stream = stream) != 0)
- ps_check_queue_length++;
+ psc_check_queue_length++;
state->smtp_server_fd = (-1);
state->smtp_client_addr = mystrdup(addr);
state->smtp_client_port = mystrdup(port);
state->sender = 0;
state->cmd_buffer = 0;
state->read_state = 0;
+ state->ehlo_discard_mask = 0; /* XXX Should be ~0 */
/*
* Update the stress level.
*/
- if (ps_stress == 0
- && ps_check_queue_length >= ps_check_queue_length_hiwat) {
- ps_stress = 1;
+ if (psc_stress == 0
+ && psc_check_queue_length >= psc_check_queue_length_hiwat) {
+ psc_stress = 1;
msg_info("entering STRESS mode with %d connections",
- ps_check_queue_length);
+ psc_check_queue_length);
}
/*
* Update the per-client session count.
*/
- if ((ht = htable_locate(ps_client_concurrency, addr)) == 0)
- ht = htable_enter(ps_client_concurrency, addr, (char *) 0);
+ if ((ht = htable_locate(psc_client_concurrency, addr)) == 0)
+ ht = htable_enter(psc_client_concurrency, addr, (char *) 0);
ht->value += 1;
state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value);
return (state);
}
-/* ps_free_session_state - destroy connection state including connections */
+/* psc_free_session_state - destroy connection state including connections */
-void ps_free_session_state(PS_STATE *state)
+void psc_free_session_state(PSC_STATE *state)
{
- const char *myname = "ps_free_session_state";
+ const char *myname = "psc_free_session_state";
HTABLE_INFO *ht;
/*
* Update the per-client session count.
*/
- if ((ht = htable_locate(ps_client_concurrency, state->smtp_client_addr)) == 0)
- msg_panic("%s: unknown client address: %s",
+ if ((ht = htable_locate(psc_client_concurrency,
+ state->smtp_client_addr)) == 0)
+ msg_panic("%s: unknown client address: %s",
myname, state->smtp_client_addr);
if (--(ht->value) == 0)
- htable_delete(ps_client_concurrency, state->smtp_client_addr, (void (*) (char *)) 0);
+ htable_delete(psc_client_concurrency, state->smtp_client_addr,
+ (void (*) (char *)) 0);
if (state->smtp_client_stream != 0) {
event_server_disconnect(state->smtp_client_stream);
- ps_check_queue_length--;
+ psc_check_queue_length--;
}
if (state->smtp_server_fd >= 0) {
close(state->smtp_server_fd);
- ps_post_queue_length--;
+ psc_post_queue_length--;
}
myfree(state->smtp_client_addr);
myfree(state->smtp_client_port);
vstring_free(state->cmd_buffer);
myfree((char *) state);
- if (ps_check_queue_length < 0 || ps_post_queue_length < 0)
+ if (psc_check_queue_length < 0 || psc_post_queue_length < 0)
msg_panic("bad queue length: check_queue=%d, post_queue=%d",
- ps_check_queue_length, ps_post_queue_length);
+ psc_check_queue_length, psc_post_queue_length);
/*
* Update the stress level.
*/
- if (ps_stress != 0
- && ps_check_queue_length <= ps_check_queue_length_lowat) {
- ps_stress = 0;
+ if (psc_stress != 0
+ && psc_check_queue_length <= psc_check_queue_length_lowat) {
+ psc_stress = 0;
msg_info("leaving STRESS mode with %d connections",
- ps_check_queue_length);
+ psc_check_queue_length);
}
}
-/* ps_print_state_flags - format state flags */
+/* psc_print_state_flags - format state flags */
-const char *ps_print_state_flags(int flags, const char *context)
+const char *psc_print_state_flags(int flags, const char *context)
{
static const NAME_MASK flags_mask[] = {
- "NOFORWARD", PS_STATE_FLAG_NOFORWARD,
- "NEW", PS_STATE_FLAG_NEW,
- "BLIST_FAIL", PS_STATE_FLAG_BLIST_FAIL,
- "HANGUP", PS_STATE_FLAG_HANGUP,
- "CACHE_EXPIRED", PS_STATE_FLAG_CACHE_EXPIRED,
+ "NOFORWARD", PSC_STATE_FLAG_NOFORWARD,
+ "USING_TLS", PSC_STATE_FLAG_USING_TLS,
+ "NEW", PSC_STATE_FLAG_NEW,
+ "BLIST_FAIL", PSC_STATE_FLAG_BLIST_FAIL,
+ "HANGUP", PSC_STATE_FLAG_HANGUP,
+ "CACHE_EXPIRED", PSC_STATE_FLAG_CACHE_EXPIRED,
- "PENAL_UPDATE", PS_STATE_FLAG_PENAL_UPDATE,
- "PENAL_FAIL", PS_STATE_FLAG_PENAL_FAIL,
+ "PENAL_UPDATE", PSC_STATE_FLAG_PENAL_UPDATE,
+ "PENAL_FAIL", PSC_STATE_FLAG_PENAL_FAIL,
- "PREGR_FAIL", PS_STATE_FLAG_PREGR_FAIL,
- "PREGR_PASS", PS_STATE_FLAG_PREGR_PASS,
- "PREGR_TODO", PS_STATE_FLAG_PREGR_TODO,
- "PREGR_DONE", PS_STATE_FLAG_PREGR_DONE,
+ "PREGR_FAIL", PSC_STATE_FLAG_PREGR_FAIL,
+ "PREGR_PASS", PSC_STATE_FLAG_PREGR_PASS,
+ "PREGR_TODO", PSC_STATE_FLAG_PREGR_TODO,
+ "PREGR_DONE", PSC_STATE_FLAG_PREGR_DONE,
- "DNSBL_FAIL", PS_STATE_FLAG_DNSBL_FAIL,
- "DNSBL_PASS", PS_STATE_FLAG_DNSBL_PASS,
- "DNSBL_TODO", PS_STATE_FLAG_DNSBL_TODO,
- "DNSBL_DONE", PS_STATE_FLAG_DNSBL_DONE,
+ "DNSBL_FAIL", PSC_STATE_FLAG_DNSBL_FAIL,
+ "DNSBL_PASS", PSC_STATE_FLAG_DNSBL_PASS,
+ "DNSBL_TODO", PSC_STATE_FLAG_DNSBL_TODO,
+ "DNSBL_DONE", PSC_STATE_FLAG_DNSBL_DONE,
- "PIPEL_FAIL", PS_STATE_FLAG_PIPEL_FAIL,
- "PIPEL_PASS", PS_STATE_FLAG_PIPEL_PASS,
- "PIPEL_TODO", PS_STATE_FLAG_PIPEL_TODO,
- "PIPEL_SKIP", PS_STATE_FLAG_PIPEL_SKIP,
+ "PIPEL_FAIL", PSC_STATE_FLAG_PIPEL_FAIL,
+ "PIPEL_PASS", PSC_STATE_FLAG_PIPEL_PASS,
+ "PIPEL_TODO", PSC_STATE_FLAG_PIPEL_TODO,
+ "PIPEL_SKIP", PSC_STATE_FLAG_PIPEL_SKIP,
- "NSMTP_FAIL", PS_STATE_FLAG_NSMTP_FAIL,
- "NSMTP_PASS", PS_STATE_FLAG_NSMTP_PASS,
- "NSMTP_TODO", PS_STATE_FLAG_NSMTP_TODO,
- "NSMTP_SKIP", PS_STATE_FLAG_NSMTP_SKIP,
+ "NSMTP_FAIL", PSC_STATE_FLAG_NSMTP_FAIL,
+ "NSMTP_PASS", PSC_STATE_FLAG_NSMTP_PASS,
+ "NSMTP_TODO", PSC_STATE_FLAG_NSMTP_TODO,
+ "NSMTP_SKIP", PSC_STATE_FLAG_NSMTP_SKIP,
- "BARLF_FAIL", PS_STATE_FLAG_BARLF_FAIL,
- "BARLF_PASS", PS_STATE_FLAG_BARLF_PASS,
- "BARLF_TODO", PS_STATE_FLAG_BARLF_TODO,
- "BARLF_SKIP", PS_STATE_FLAG_BARLF_SKIP,
+ "BARLF_FAIL", PSC_STATE_FLAG_BARLF_FAIL,
+ "BARLF_PASS", PSC_STATE_FLAG_BARLF_PASS,
+ "BARLF_TODO", PSC_STATE_FLAG_BARLF_TODO,
+ "BARLF_SKIP", PSC_STATE_FLAG_BARLF_SKIP,
0,
};
/* SYNOPSIS
/* #include <postscreen.h>
/*
-/* void PS_INIT_TESTS(state)
-/* PS_STATE *state;
+/* void PSC_INIT_TESTS(state)
+/* PSC_STATE *state;
/*
-/* void ps_new_tests(state)
-/* PS_STATE *state;
+/* void psc_new_tests(state)
+/* PSC_STATE *state;
/*
-/* void ps_parse_tests(state, stamp_text, time_value)
-/* PS_STATE *state;
+/* void psc_parse_tests(state, stamp_text, time_value)
+/* PSC_STATE *state;
/* const char *stamp_text;
/* time_t time_value;
/*
-/* char *ps_print_tests(buffer, state)
+/* char *psc_print_tests(buffer, state)
/* VSTRING *buffer;
-/* PS_STATE *state;
+/* PSC_STATE *state;
/*
-/* char *ps_print_grey_key(buffer, client, helo, sender, rcpt)
+/* char *psc_print_grey_key(buffer, client, helo, sender, rcpt)
/* VSTRING *buffer;
/* const char *client;
/* const char *helo;
/* as unsafe macros, meaning they evaluate one or more arguments
/* multiple times.
/*
-/* PS_INIT_TESTS() is an unsafe macro that sets the per-test
-/* expiration time stamps to PS_TIME_STAMP_INVALID, and that
+/* PSC_INIT_TESTS() is an unsafe macro that sets the per-test
+/* expiration time stamps to PSC_TIME_STAMP_INVALID, and that
/* zeroes all the flags bits. These values are not meant to
/* be stored into the postscreen(8) cache.
/*
-/* ps_new_tests() sets all test expiration time stamps to
-/* PS_TIME_STAMP_NEW, and overwrites all flags bits. Only
-/* enabled tests are flagged with PS_STATE_FLAG_TODO; the
-/* object is flagged with PS_STATE_FLAG_NEW.
+/* psc_new_tests() sets all test expiration time stamps to
+/* PSC_TIME_STAMP_NEW, and overwrites all flags bits. Only
+/* enabled tests are flagged with PSC_STATE_FLAG_TODO; the
+/* object is flagged with PSC_STATE_FLAG_NEW.
/*
-/* ps_parse_tests() parses a cache file record and overwrites
+/* psc_parse_tests() parses a cache file record and overwrites
/* all flags bits. Tests are considered "expired" when they
/* would be expired at the specified time value. Only enabled
/* tests are flagged as "expired"; the object is flagged as
/* "new" if some enabled tests have "new" time stamps.
/*
-/* ps_print_tests() creates a cache file record for the
+/* psc_print_tests() creates a cache file record for the
/* specified flags and per-test expiration time stamps.
/* This may modify the time stamps for disabled tests.
/*
-/* ps_print_grey_key() prints a greylist lookup key.
+/* psc_print_grey_key() prints a greylist lookup key.
/* LICENSE
/* .ad
/* .fi
/*
* Kludge to detect if some test is enabled.
*/
-#define PS_PREGR_TEST_ENABLE() (*var_ps_pregr_banner != 0)
-#define PS_DNSBL_TEST_ENABLE() (*var_ps_dnsbl_sites != 0)
+#define PSC_PREGR_TEST_ENABLE() (*var_psc_pregr_banner != 0)
+#define PSC_DNSBL_TEST_ENABLE() (*var_psc_dnsbl_sites != 0)
/*
* Format of a persistent cache entry (which is almost but not quite the
*
* Each cache entry has one time stamp for each test.
*
- * - A time stamp of PS_TIME_STAMP_INVALID must never appear in the cache. It
+ * - A time stamp of PSC_TIME_STAMP_INVALID must never appear in the cache. It
* is reserved for in-memory objects that are still being initialized.
*
- * - A time stamp of PS_TIME_STAMP_NEW indicates that the test never passed.
+ * - A time stamp of PSC_TIME_STAMP_NEW indicates that the test never passed.
* Postscreen will log the client with "pass new" when it passes the final
* test.
*
- * - A time stamp of PS_TIME_STAMP_DISABLED indicates that the test never
+ * - A time stamp of PSC_TIME_STAMP_DISABLED indicates that the test never
* passed, and that the test was disabled when the cache entry was written.
*
* - Otherwise, the test was passed, and the time stamp indicates when that
* expired.
*/
-/* ps_new_tests - initialize new test results from scratch */
+/* psc_new_tests - initialize new test results from scratch */
-void ps_new_tests(PS_STATE *state)
+void psc_new_tests(PSC_STATE *state)
{
/*
* We know this client is brand new.
*/
- state->flags = PS_STATE_FLAG_NEW;
+ state->flags = PSC_STATE_FLAG_NEW;
/*
- * Give all tests a PS_TIME_STAMP_NEW time stamp, so that we can later
+ * Give all tests a PSC_TIME_STAMP_NEW time stamp, so that we can later
* recognize cache entries that haven't passed all enabled tests. When we
* write a cache entry to the database, any new-but-disabled tests will
- * get a PS_TIME_STAMP_DISABLED time stamp.
+ * get a PSC_TIME_STAMP_DISABLED time stamp.
*/
- state->pregr_stamp = PS_TIME_STAMP_NEW;
- state->dnsbl_stamp = PS_TIME_STAMP_NEW;
- state->pipel_stamp = PS_TIME_STAMP_NEW;
- state->nsmtp_stamp = PS_TIME_STAMP_NEW;
- state->barlf_stamp = PS_TIME_STAMP_NEW;
- state->penal_stamp = PS_TIME_STAMP_NEW;
+ state->pregr_stamp = PSC_TIME_STAMP_NEW;
+ state->dnsbl_stamp = PSC_TIME_STAMP_NEW;
+ state->pipel_stamp = PSC_TIME_STAMP_NEW;
+ state->nsmtp_stamp = PSC_TIME_STAMP_NEW;
+ state->barlf_stamp = PSC_TIME_STAMP_NEW;
+ state->penal_stamp = PSC_TIME_STAMP_NEW;
/*
* Don't flag disabled tests as "todo", because there would be no way to
* make those bits go away.
*/
- if (PS_PREGR_TEST_ENABLE())
- state->flags |= PS_STATE_FLAG_PREGR_TODO;
- if (PS_DNSBL_TEST_ENABLE())
- state->flags |= PS_STATE_FLAG_DNSBL_TODO;
- if (var_ps_pipel_enable)
- state->flags |= PS_STATE_FLAG_PIPEL_TODO;
- if (var_ps_nsmtp_enable)
- state->flags |= PS_STATE_FLAG_NSMTP_TODO;
- if (var_ps_barlf_enable)
- state->flags |= PS_STATE_FLAG_BARLF_TODO;
+ if (PSC_PREGR_TEST_ENABLE())
+ state->flags |= PSC_STATE_FLAG_PREGR_TODO;
+ if (PSC_DNSBL_TEST_ENABLE())
+ state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
+ if (var_psc_pipel_enable)
+ state->flags |= PSC_STATE_FLAG_PIPEL_TODO;
+ if (var_psc_nsmtp_enable)
+ state->flags |= PSC_STATE_FLAG_NSMTP_TODO;
+ if (var_psc_barlf_enable)
+ state->flags |= PSC_STATE_FLAG_BARLF_TODO;
}
-/* ps_parse_tests - parse test results from cache */
+/* psc_parse_tests - parse test results from cache */
-void ps_parse_tests(PS_STATE *state,
- const char *stamp_str,
- time_t time_value)
+void psc_parse_tests(PSC_STATE *state,
+ const char *stamp_str,
+ time_t time_value)
{
unsigned long pregr_stamp;
unsigned long dnsbl_stamp;
&pregr_stamp, &dnsbl_stamp, &pipel_stamp, &nsmtp_stamp,
&barlf_stamp, &penal_stamp)) {
case 0:
- pregr_stamp = PS_TIME_STAMP_DISABLED;
+ pregr_stamp = PSC_TIME_STAMP_DISABLED;
case 1:
- dnsbl_stamp = PS_TIME_STAMP_DISABLED;
+ dnsbl_stamp = PSC_TIME_STAMP_DISABLED;
case 2:
- pipel_stamp = PS_TIME_STAMP_DISABLED;
+ pipel_stamp = PSC_TIME_STAMP_DISABLED;
case 3:
- nsmtp_stamp = PS_TIME_STAMP_DISABLED;
+ nsmtp_stamp = PSC_TIME_STAMP_DISABLED;
case 4:
- barlf_stamp = PS_TIME_STAMP_DISABLED;
+ barlf_stamp = PSC_TIME_STAMP_DISABLED;
case 5:
- penal_stamp = PS_TIME_STAMP_DISABLED;
+ penal_stamp = PSC_TIME_STAMP_DISABLED;
default:
break;
}
state->barlf_stamp = barlf_stamp;
state->penal_stamp = penal_stamp;
- if (pregr_stamp == PS_TIME_STAMP_NEW
- || dnsbl_stamp == PS_TIME_STAMP_NEW
- || pipel_stamp == PS_TIME_STAMP_NEW
- || nsmtp_stamp == PS_TIME_STAMP_NEW
- || barlf_stamp == PS_TIME_STAMP_NEW)
- state->flags |= PS_STATE_FLAG_NEW;
+ if (pregr_stamp == PSC_TIME_STAMP_NEW
+ || dnsbl_stamp == PSC_TIME_STAMP_NEW
+ || pipel_stamp == PSC_TIME_STAMP_NEW
+ || nsmtp_stamp == PSC_TIME_STAMP_NEW
+ || barlf_stamp == PSC_TIME_STAMP_NEW)
+ state->flags |= PSC_STATE_FLAG_NEW;
/*
* Don't flag a cache entry as expired just because some test was never
* Don't flag disabled tests as "todo", because there would be no way to
* make those bits go away.
*/
- if (PS_PREGR_TEST_ENABLE() && time_value > state->pregr_stamp) {
- state->flags |= PS_STATE_FLAG_PREGR_TODO;
- if (state->pregr_stamp > PS_TIME_STAMP_DISABLED)
- state->flags |= PS_STATE_FLAG_CACHE_EXPIRED;
+ if (PSC_PREGR_TEST_ENABLE() && time_value > state->pregr_stamp) {
+ state->flags |= PSC_STATE_FLAG_PREGR_TODO;
+ if (state->pregr_stamp > PSC_TIME_STAMP_DISABLED)
+ state->flags |= PSC_STATE_FLAG_CACHE_EXPIRED;
}
- if (PS_DNSBL_TEST_ENABLE() && time_value > state->dnsbl_stamp) {
- state->flags |= PS_STATE_FLAG_DNSBL_TODO;
- if (state->dnsbl_stamp > PS_TIME_STAMP_DISABLED)
- state->flags |= PS_STATE_FLAG_CACHE_EXPIRED;
+ if (PSC_DNSBL_TEST_ENABLE() && time_value > state->dnsbl_stamp) {
+ state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
+ if (state->dnsbl_stamp > PSC_TIME_STAMP_DISABLED)
+ state->flags |= PSC_STATE_FLAG_CACHE_EXPIRED;
}
- if (var_ps_pipel_enable && time_value > state->pipel_stamp) {
- state->flags |= PS_STATE_FLAG_PIPEL_TODO;
- if (state->pipel_stamp > PS_TIME_STAMP_DISABLED)
- state->flags |= PS_STATE_FLAG_CACHE_EXPIRED;
+ if (var_psc_pipel_enable && time_value > state->pipel_stamp) {
+ state->flags |= PSC_STATE_FLAG_PIPEL_TODO;
+ if (state->pipel_stamp > PSC_TIME_STAMP_DISABLED)
+ state->flags |= PSC_STATE_FLAG_CACHE_EXPIRED;
}
- if (var_ps_nsmtp_enable && time_value > state->nsmtp_stamp) {
- state->flags |= PS_STATE_FLAG_NSMTP_TODO;
- if (state->nsmtp_stamp > PS_TIME_STAMP_DISABLED)
- state->flags |= PS_STATE_FLAG_CACHE_EXPIRED;
+ if (var_psc_nsmtp_enable && time_value > state->nsmtp_stamp) {
+ state->flags |= PSC_STATE_FLAG_NSMTP_TODO;
+ if (state->nsmtp_stamp > PSC_TIME_STAMP_DISABLED)
+ state->flags |= PSC_STATE_FLAG_CACHE_EXPIRED;
}
- if (var_ps_barlf_enable && time_value > state->barlf_stamp) {
- state->flags |= PS_STATE_FLAG_BARLF_TODO;
- if (state->barlf_stamp > PS_TIME_STAMP_DISABLED)
- state->flags |= PS_STATE_FLAG_CACHE_EXPIRED;
+ if (var_psc_barlf_enable && time_value > state->barlf_stamp) {
+ state->flags |= PSC_STATE_FLAG_BARLF_TODO;
+ if (state->barlf_stamp > PSC_TIME_STAMP_DISABLED)
+ state->flags |= PSC_STATE_FLAG_CACHE_EXPIRED;
}
/*
* full postscreen_greet_wait too frequently.
*/
#if 0
- if (state->flags & PS_STATE_MASK_EARLY_TODO) {
- if (PS_PREGR_TEST_ENABLE())
- state->flags |= PS_STATE_FLAG_PREGR_TODO;
- if (PS_DNSBL_TEST_ENABLE())
- state->flags |= PS_STATE_FLAG_DNSBL_TODO;
+ if (state->flags & PSC_STATE_MASK_EARLY_TODO) {
+ if (PSC_PREGR_TEST_ENABLE())
+ state->flags |= PSC_STATE_FLAG_PREGR_TODO;
+ if (PSC_DNSBL_TEST_ENABLE())
+ state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
}
#endif
if ((penalty_left = state->penal_stamp - event_time()) > 0) {
msg_info("PENALTY %ld for %s",
(long) penalty_left, state->smtp_client_addr);
- PS_FAIL_SESSION_STATE(state, PS_STATE_FLAG_PENAL_FAIL);
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PENAL_FAIL);
#if 0
- switch (ps_penal_action) {
- case PS_ACT_DROP:
- PS_DROP_SESSION_STATE(state,
+ switch (psc_penal_action) {
+ case PSC_ACT_DROP:
+ PSC_DROP_SESSION_STATE(state,
"421 4.3.2 Service currently unavailable\r\n");
break;
- case PS_ACT_ENFORCE:
+ case PSC_ACT_ENFORCE:
#endif
- PS_ENFORCE_SESSION_STATE(state,
+ PSC_ENFORCE_SESSION_STATE(state,
"450 4.3.2 Service currently unavailable\r\n");
#if 0
break;
- case PS_ACT_IGNORE:
- PS_UNFAIL_SESSION_STATE(state, PS_STATE_FLAG_PENAL_FAIL);
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_PENAL_FAIL);
break;
default:
msg_panic("%s: unknown penalty action value %d",
- myname, ps_penal_action);
+ myname, psc_penal_action);
}
#endif
}
#endif /* NONPROD */
}
-/* ps_print_tests - print postscreen cache record */
+/* psc_print_tests - print postscreen cache record */
-char *ps_print_tests(VSTRING *buf, PS_STATE *state)
+char *psc_print_tests(VSTRING *buf, PSC_STATE *state)
{
- const char *myname = "ps_print_tests";
+ const char *myname = "psc_print_tests";
/*
* Sanity check.
*/
- if ((state->flags & PS_STATE_MASK_ANY_UPDATE) == 0)
+ if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) == 0)
msg_panic("%s: attempt to save a no-update record", myname);
/*
* time stamp only when the corresponding "pass" flag is raised.
*/
#ifdef NONPROD
- if (state->flags & PS_STATE_FLAG_PENAL_FAIL) {
+ if (state->flags & PSC_STATE_FLAG_PENAL_FAIL) {
state->pregr_stamp = state->dnsbl_stamp = state->pipel_stamp =
state->nsmtp_stamp = state->barlf_stamp =
- ((state->flags & PS_STATE_FLAG_NEW) ?
- PS_TIME_STAMP_NEW : PS_TIME_STAMP_DISABLED);
+ ((state->flags & PSC_STATE_FLAG_NEW) ?
+ PSC_TIME_STAMP_NEW : PSC_TIME_STAMP_DISABLED);
}
#endif
* with "pass new" when some disabled test becomes enabled at some later
* time.
*/
- if (PS_PREGR_TEST_ENABLE() == 0 && state->pregr_stamp == PS_TIME_STAMP_NEW)
- state->pregr_stamp = PS_TIME_STAMP_DISABLED;
- if (PS_DNSBL_TEST_ENABLE() == 0 && state->dnsbl_stamp == PS_TIME_STAMP_NEW)
- state->dnsbl_stamp = PS_TIME_STAMP_DISABLED;
- if (var_ps_pipel_enable == 0 && state->pipel_stamp == PS_TIME_STAMP_NEW)
- state->pipel_stamp = PS_TIME_STAMP_DISABLED;
- if (var_ps_nsmtp_enable == 0 && state->nsmtp_stamp == PS_TIME_STAMP_NEW)
- state->nsmtp_stamp = PS_TIME_STAMP_DISABLED;
- if (var_ps_barlf_enable == 0 && state->barlf_stamp == PS_TIME_STAMP_NEW)
- state->barlf_stamp = PS_TIME_STAMP_DISABLED;
+ if (PSC_PREGR_TEST_ENABLE() == 0 && state->pregr_stamp == PSC_TIME_STAMP_NEW)
+ state->pregr_stamp = PSC_TIME_STAMP_DISABLED;
+ if (PSC_DNSBL_TEST_ENABLE() == 0 && state->dnsbl_stamp == PSC_TIME_STAMP_NEW)
+ state->dnsbl_stamp = PSC_TIME_STAMP_DISABLED;
+ if (var_psc_pipel_enable == 0 && state->pipel_stamp == PSC_TIME_STAMP_NEW)
+ state->pipel_stamp = PSC_TIME_STAMP_DISABLED;
+ if (var_psc_nsmtp_enable == 0 && state->nsmtp_stamp == PSC_TIME_STAMP_NEW)
+ state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED;
+ if (var_psc_barlf_enable == 0 && state->barlf_stamp == PSC_TIME_STAMP_NEW)
+ state->barlf_stamp = PSC_TIME_STAMP_DISABLED;
vstring_sprintf(buf, "%lu;%lu;%lu;%lu;%lu;%lu",
(unsigned long) state->pregr_stamp,
return (STR(buf));
}
-/* ps_print_grey_key - print postscreen cache record */
+/* psc_print_grey_key - print postscreen cache record */
-char *ps_print_grey_key(VSTRING *buf, const char *client,
- const char *helo, const char *sender,
- const char *rcpt)
+char *psc_print_grey_key(VSTRING *buf, const char *client,
+ const char *helo, const char *sender,
+ const char *rcpt)
{
return (STR(vstring_sprintf(buf, "%s/%s/%s/%s",
client, helo, sender, rcpt)));
/* Try to detect a mail hijacking attack based on a TLS protocol
/* vulnerability (CVE-2009-3555), where an attacker prepends malicious
/* HELO, MAIL, RCPT, DATA commands to a Postfix SMTP client TLS session.
+/* .PP
+/* Available in Postfix version 2.8 and later:
+/* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
+/* List or bit-mask of OpenSSL bug work-arounds to disable.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
* Select DNS query flags.
*/
smtp_dns_res_opt = name_mask(VAR_SMTP_DNS_RES_OPT, dns_res_opt_masks,
- var_smtp_dns_res_opt);
+ var_smtp_dns_res_opt);
}
/* pre_init - pre-jail initialization */
XFORWARD_DOMAIN, SMTP_FEATURE_XFORWARD_DOMAIN,
0, 0,
};
- SOCKOPT_SIZE optlen;
- int sndbufsize;
const char *ehlo_words;
int discard_mask;
static const NAME_MASK pix_bug_table[] = {
}
if (*pix_bug_words) {
pix_bug_mask = name_mask_opt(pix_bug_source, pix_bug_table,
- pix_bug_words, NAME_MASK_ANY_CASE);
+ pix_bug_words,
+ NAME_MASK_ANY_CASE | NAME_MASK_IGNORE);
msg_info("%s: enabling PIX workarounds: %s for %s",
request->queue_id,
str_name_mask("pix workaround bitmask",
* XXX No need to do this before and after STARTTLS, but it's not a big deal
* if we do.
*
- * XXX This critically depends on VSTREAM buffers to never be smaller than
- * VSTREAM_BUFSIZE.
+ * XXX When TLS is turned on, the SMTP-level writes will be encapsulated as
+ * TLS messages. Thus, the TCP-level payload will be larger than the
+ * SMTP-level payload. This has implications for the PIPELINING engine.
+ *
+ * To avoid deadlock, the PIPELINING engine needs to request a TCP send
+ * buffer size that can hold the unacknowledged commands plus the TLS
+ * encapsulation overhead.
+ *
+ * The PIPELINING engine keeps the unacknowledged command size <= the
+ * default VSTREAM buffer size (to avoid small-write performance issues
+ * when the VSTREAM buffer size is at its default size). With a default
+ * VSTREAM buffer size of 4096 there is no reason to increase the
+ * unacknowledged command size as the TCP MSS increases. It's safer to
+ * spread the remote SMTP server's recipient processing load over time,
+ * than dumping a very large recipient list all at once.
+ *
+ * For TLS encapsulation overhead we make a conservative guess: take the
+ * current protocol overhead of ~40 bytes, double the number for future
+ * proofing (~80 bytes), then round up the result to the nearest power of
+ * 2 (128 bytes). Plus, be prepared for worst-case compression that
+ * expands data by 1 kbyte, so that the worst-case SMTP payload per TLS
+ * message becomes 15 kbytes.
*/
+#define PIPELINING_BUFSIZE VSTREAM_BUFSIZE
+#ifdef USE_TLS
+#define TLS_WORST_PAYLOAD 16384
+#define TLS_WORST_COMP_OVERHD 1024
+#define TLS_WORST_PROTO_OVERHD 128
+#define TLS_WORST_SMTP_PAYLOAD (TLS_WORST_PAYLOAD - TLS_WORST_COMP_OVERHD)
+#define TLS_WORST_TOTAL_OVERHD (TLS_WORST_COMP_OVERHD + TLS_WORST_PROTO_OVERHD)
+#endif
+
if (session->features & SMTP_FEATURE_PIPELINING) {
- optlen = sizeof(sndbufsize);
+ SOCKOPT_SIZE optlen;
+ int tcp_bufsize;
+ int enc_overhead = 0;
+
+ optlen = sizeof(tcp_bufsize);
if (getsockopt(vstream_fileno(session->stream), SOL_SOCKET,
- SO_SNDBUF, (char *) &sndbufsize, &optlen) < 0)
+ SO_SNDBUF, (char *) &tcp_bufsize, &optlen) < 0)
msg_fatal("%s: getsockopt: %m", myname);
- if (sndbufsize > VSTREAM_BUFSIZE)
- sndbufsize = VSTREAM_BUFSIZE;
- if (sndbufsize < VSTREAM_BUFSIZE) {
- sndbufsize = VSTREAM_BUFSIZE;
+#ifdef USE_TLS
+ if (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS)
+ enc_overhead +=
+ (1 + (PIPELINING_BUFSIZE - 1)
+ / TLS_WORST_SMTP_PAYLOAD) * TLS_WORST_TOTAL_OVERHD;
+#endif
+ if (tcp_bufsize < PIPELINING_BUFSIZE + enc_overhead) {
+ tcp_bufsize = PIPELINING_BUFSIZE + enc_overhead;
if (setsockopt(vstream_fileno(session->stream), SOL_SOCKET,
- SO_SNDBUF, (char *) &sndbufsize, optlen) < 0)
+ SO_SNDBUF, (char *) &tcp_bufsize, optlen) < 0)
msg_fatal("%s: setsockopt: %m", myname);
}
if (msg_verbose)
- msg_info("Using %s PIPELINING, TCP send buffer size is %d",
- (state->misc_flags &
- SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP",
- sndbufsize);
+ msg_info("Using %s PIPELINING, TCP send buffer size is %d, "
+ "PIPELINING buffer size is %d", (state->misc_flags &
+ SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP",
+ tcp_bufsize, PIPELINING_BUFSIZE);
}
#ifdef USE_TLS
* Flush unsent output if command pipelining is off or if no I/O
* happened for a while. This limits the accumulation of client-side
* delays in pipelined sessions.
+ *
+ * The PIPELINING engine will flush the VSTREAM buffer if the sender
+ * could otherwise produce more output than fits the PIPELINING
+ * buffer. This generally works because we know exactly how much
+ * output we produced since the last time that the sender and
+ * receiver synchronized the SMTP state. However this logic is not
+ * applicable after the sender enters the DATA phase, where it does
+ * not synchronize with the receiver until the <CR><LF>.<CR><LF>.
+ * Thus, the PIPELINING engine no longer knows how much data is
+ * pending in the TCP send buffer. For this reason, if PIPELINING is
+ * enabled, we always pipeline QUIT after <CR><LF>.<CR><LF>. This is
+ * safe because once the receiver reads <CR><LF>.<CR><LF>, its TCP
+ * stack either has already received the QUIT<CR><LF>, or else it
+ * acknowledges all bytes up to and including <CR><LF>.<CR><LF>,
+ * making room in the sender's TCP stack for QUIT<CR><LF>.
*/
+#define CHECK_PIPELINING_BUFSIZE \
+ (recv_state != SMTP_STATE_DOT || send_state != SMTP_STATE_QUIT)
+
if (SENDER_IN_WAIT_STATE
|| (SENDER_IS_AHEAD
&& ((session->features & SMTP_FEATURE_PIPELINING) == 0
- || (VSTRING_LEN(next_command) + 2
+ || (CHECK_PIPELINING_BUFSIZE
+ && (VSTRING_LEN(next_command) + 2
+ vstream_bufstat(session->stream, VSTREAM_BST_OUT_PEND)
- > VSTREAM_BUFSIZE)
+ > PIPELINING_BUFSIZE))
|| time((time_t *) 0)
- vstream_ftime(session->stream) > 10))) {
while (SENDER_IS_AHEAD) {
/* .IP "\fBtls_eecdh_ultra_curve (secp384r1)\fR"
/* The elliptic curve used by the SMTP server for maximally strong
/* ephemeral ECDH key exchange.
+/* .PP
+/* Available in Postfix version 2.8 and later:
+/* .IP "\fBtls_preempt_cipherlist (no)\fR"
+/* With SSLv3 and later, use the server's cipher preference order
+/* instead of the client's cipher preference order.
+/* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
+/* List or bit-mask of OpenSSL bug work-arounds to disable.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
/*
* When TLS is turned on, we may offer AUTH methods that would not be
* offered within a plain-text session.
+ *
+ * XXX Always refresh SASL the mechanism list after STARTTLS. Dovecot
+ * responses may depend on whether the SMTP connection is encrypted.
*/
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable) {
/* Non-wrappermode, presumably. */
- if (smtpd_sasl_is_active(state)
- && strcmp(var_smtpd_sasl_opts, var_smtpd_sasl_tls_opts) != 0) {
+ if (smtpd_sasl_is_active(state)) {
smtpd_sasl_auth_reset(state);
smtpd_sasl_deactivate(state);
}
int log_level; /* TLS library logging level */
int session_reused; /* this session was reused */
int am_server; /* Are we an SSL server or client? */
+ /* Built-in vs external SSL_accept/read/write/shutdown support. */
+ char *fpt_dgst; /* Certificate fingerprint digest */
+ VSTREAM *stream; /* Blocking-mode SMTP session */
} TLS_SESS_STATE;
/*
extern TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *);
extern TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props);
+extern TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *);
#define tls_server_stop(ctx, stream, timeout, failure, TLScontext) \
tls_session_stop(ctx, (stream), (timeout), (failure), (TLScontext))
* Connect the SSL connection with the network socket.
*/
if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) {
- msg_info("SSL_set_fd error to %s: %d", props->namaddr, sts);
+ msg_info("SSL_set_fd error to %s", props->namaddr);
tls_print_errors();
uncache_session(app_ctx->ssl_ctx, TLScontext);
tls_free_context(TLScontext);
/* char *var_tls_eecdh_ultra;
/* int var_tls_daemon_rand_bytes;
/* bool var_tls_append_def_CA;
+/* bool var_tls_preempt_clist;
/*
/* TLS_APPL_STATE *tls_alloc_app_context(ssl_ctx)
/* SSL_CTX *ssl_ctx;
#include <vstring.h>
#include <stringops.h>
#include <argv.h>
+#include <name_mask.h>
+#include <name_code.h>
/*
* Global library.
char *var_tls_eecdh_strong;
char *var_tls_eecdh_ultra;
bool var_tls_append_def_CA;
+char *var_tls_bug_tweaks;
+
+#ifdef VAR_TLS_PREEMPT_CLIST
+bool var_tls_preempt_clist;
+
+#endif
/*
* Index to attach TLScontext pointers to SSL objects, so that they can be
0, TLS_PROTOCOL_INVALID,
};
+ /*
+ * SSL_OP_MUMBLE bug work-around name <=> mask conversion. We expect the C
+ * preprocessor to be able to handle "long" #if operands
+ */
+#define NAMEBUG(x) #x, SSL_OP_##x
+static const LONG_NAME_MASK ssl_bug_tweaks[] = {
+
+#if defined(SSL_OP_MICROSOFT_SESS_ID_BUG) && \
+ ((SSL_OP_MICROSOFT_SESS_ID_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(MICROSOFT_SESS_ID_BUG), /* 0x00000001L */
+#endif
+
+#if defined(SSL_OP_NETSCAPE_CHALLENGE_BUG) && \
+ ((SSL_OP_NETSCAPE_CHALLENGE_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(NETSCAPE_CHALLENGE_BUG), /* 0x00000002L */
+#endif
+
+#if defined(SSL_OP_LEGACY_SERVER_CONNECT) && \
+ ((SSL_OP_LEGACY_SERVER_CONNECT & SSL_OP_ALL) != 0L)
+ NAMEBUG(LEGACY_SERVER_CONNECT), /* 0x00000004L */
+#endif
+
+#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && \
+ ((SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(NETSCAPE_REUSE_CIPHER_CHANGE_BUG), /* 0x00000008L */
+ "CVE-2010-4180", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
+#endif
+
+#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG) && \
+ ((SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(SSLREF2_REUSE_CERT_TYPE_BUG), /* 0x00000010L */
+#endif
+
+#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) && \
+ ((SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER & SSL_OP_ALL) != 0L)
+ NAMEBUG(MICROSOFT_BIG_SSLV3_BUFFER),/* 0x00000020L */
+#endif
+
+#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING) && \
+ ((SSL_OP_MSIE_SSLV2_RSA_PADDING & SSL_OP_ALL) != 0L)
+ NAMEBUG(MSIE_SSLV2_RSA_PADDING), /* 0x00000040L */
+ "CVE-2005-2969", SSL_OP_MSIE_SSLV2_RSA_PADDING,
+#endif
+
+#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG) && \
+ ((SSL_OP_SSLEAY_080_CLIENT_DH_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(SSLEAY_080_CLIENT_DH_BUG), /* 0x00000080L */
+#endif
+
+#if defined(SSL_OP_TLS_D5_BUG) && \
+ ((SSL_OP_TLS_D5_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(TLS_D5_BUG), /* 0x00000100L */
+#endif
+
+#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG) && \
+ ((SSL_OP_TLS_BLOCK_PADDING_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(TLS_BLOCK_PADDING_BUG), /* 0x00000200L */
+#endif
+
+#if defined(SSL_OP_TLS_ROLLBACK_BUG) && \
+ ((SSL_OP_TLS_ROLLBACK_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(TLS_ROLLBACK_BUG), /* 0x00000400L */
+#endif
+
+#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) && \
+ ((SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS & SSL_OP_ALL) != 0L)
+ NAMEBUG(DONT_INSERT_EMPTY_FRAGMENTS), /* 0x00000800L */
+#endif
+
+#if defined(SSL_OP_CRYPTOPRO_TLSEXT_BUG) && \
+ ((SSL_OP_CRYPTOPRO_TLSEXT_BUG & SSL_OP_ALL) != 0L)
+ NAMEBUG(CRYPTOPRO_TLSEXT_BUG), /* 0x80000000L */
+#endif
+ 0, 0,
+};
+
/*
* Ciphersuite name <=> code conversion.
*/
VAR_TLS_NULL_CLIST, DEF_TLS_NULL_CLIST, &var_tls_null_clist, 1, 0,
VAR_TLS_EECDH_STRONG, DEF_TLS_EECDH_STRONG, &var_tls_eecdh_strong, 1, 0,
VAR_TLS_EECDH_ULTRA, DEF_TLS_EECDH_ULTRA, &var_tls_eecdh_ultra, 1, 0,
+ VAR_TLS_BUG_TWEAKS, DEF_TLS_BUG_TWEAKS, &var_tls_bug_tweaks, 0, 0,
0,
};
static const CONFIG_INT_TABLE int_table[] = {
};
static const CONFIG_BOOL_TABLE bool_table[] = {
VAR_TLS_APPEND_DEF_CA, DEF_TLS_APPEND_DEF_CA, &var_tls_append_def_CA,
+#if OPENSSL_VERSION_NUMBER >= 0x0090700fL /* OpenSSL 0.9.7 and later */
+ VAR_TLS_PREEMPT_CLIST, DEF_TLS_PREEMPT_CLIST, &var_tls_preempt_clist,
+#endif
0,
};
static int init_done;
TLScontext->cipher_name = 0;
TLScontext->log_level = log_level;
TLScontext->namaddr = lowercase(mystrdup(namaddr));
+ TLScontext->fpt_dgst = 0;
return (TLScontext);
}
myfree(TLScontext->issuer_CN);
if (TLScontext->peer_fingerprint)
myfree(TLScontext->peer_fingerprint);
+ if (TLScontext->fpt_dgst)
+ myfree(TLScontext->fpt_dgst);
myfree((char *) TLScontext);
}
long tls_bug_bits(void)
{
long bits = SSL_OP_ALL; /* Work around all known bugs */
+ long mask;
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
long lib_version = SSLeay();
bits &= ~SSL_OP_TLS_BLOCK_PADDING_BUG;
}
#endif
+
+ /*
+ * Silently ignore any strings that don't appear in the tweaks table, or
+ * hex bits that are not in SSL_OP_ALL.
+ */
+ if (*var_tls_bug_tweaks) {
+ bits &= ~long_name_mask_opt(VAR_TLS_BUG_TWEAKS, ssl_bug_tweaks,
+ var_tls_bug_tweaks, NAME_MASK_ANY_CASE |
+ NAME_MASK_NUMBER | NAME_MASK_WARN);
+ }
return (bits);
}
/* TLS_SESS_STATE *tls_server_start(props)
/* const TLS_SERVER_START_PROPS *props;
/*
+/* TLS_SESS_STATE *tls_server_post_accept(TLScontext)
+/* TLS_SESS_STATE *TLScontext;
+/*
/* void tls_server_stop(app_ctx, stream, failure, TLScontext)
/* TLS_APPL_STATE *app_ctx;
/* VSTREAM *stream;
/* This module is the interface between Postfix TLS servers,
/* the OpenSSL library, and the TLS entropy and cache manager.
/*
+/* See "EVENT_DRIVEN APPLICATIONS" below for using this code
+/* in event-driven programs.
+/*
/* tls_server_init() is called once when the SMTP server
/* initializes.
/* Certificate details are also decided during this phase,
/*
/* tls_server_start() activates the TLS feature for the VSTREAM
/* passed as argument. We assume that network buffers are flushed
-/* and the TLS handshake can begin immediately.
+/* and the TLS handshake can begin immediately.
/*
/* tls_server_stop() sends the "close notify" alert via
/* SSL_shutdown() to the peer and resets all connection specific
/* certificate is available.
/* .PP
/* If no peer certificate is presented the peer_status is set to 0.
+/* EVENT_DRIVEN APPLICATIONS
+/* .ad
+/* .fi
+/* Event-driven programs manage multiple I/O channels. Such
+/* programs cannot use the synchronous VSTREAM-over-TLS
+/* implementation that the current TLS library provides,
+/* including tls_server_stop() and the underlying tls_stream(3)
+/* and tls_bio_ops(3) routines.
+/*
+/* With the current TLS library implementation, this means
+/* that the application is responsible for calling and retrying
+/* SSL_accept(), SSL_read(), SSL_write() and SSL_shutdown().
+/*
+/* To maintain control over TLS I/O, an event-driven server
+/* invokes tls_server_start() with a null VSTREAM argument.
+/* Then, tls_server_start() performs all the necessary
+/* preparations before the TLS handshake and returns a partially
+/* populated TLS context. The event-driven application is then
+/* responsible for invoking SSL_accept(), and if successful,
+/* for invoking tls_server_post_accept() to finish the work
+/* that was started by tls_server_start(). In case of unrecoverable
+/* failure, tls_server_post_accept() destroys the TLS context
+/* and returns a null pointer value.
/* LICENSE
/* .ad
/* .fi
| ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));
+#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
+
+ /*
+ * Some sites may want to give the client less rope. On the other hand,
+ * this could trigger inter-operability issues, the client should not
+ * offer ciphers it implements poorly, but this hasn't stopped some
+ * vendors from getting it wrong.
+ *
+ * XXX: Given OpenSSL's security history, nobody should still be using
+ * 0.9.7, let alone 0.9.6 or earlier. Warning added to TLS_README.html.
+ */
+ if (var_tls_preempt_clist)
+ SSL_CTX_set_options(server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
+#endif
+
/*
* Set the call-back routine to debug handshake progress.
*/
{
int sts;
TLS_SESS_STATE *TLScontext;
- const SSL_CIPHER *cipher;
- X509 *peer;
- char buf[CCERT_BUFSIZ];
const char *cipher_list;
TLS_APPL_STATE *app_ctx = props->ctx;
TLScontext->serverid = mystrdup(props->serverid);
TLScontext->am_server = 1;
+ TLScontext->fpt_dgst = mystrdup(props->fpt_dgst);
+ TLScontext->stream = props->stream;
+
ERR_clear_error();
if ((TLScontext->con = (SSL *) SSL_new(app_ctx->ssl_ctx)) == 0) {
msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
*/
SSL_set_accept_state(TLScontext->con);
+ /*
+ * If the debug level selected is high enough, all of the data is dumped:
+ * 3 will dump the SSL negotiation, 4 will dump everything.
+ *
+ * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
+ * Well there is a BIO below the SSL routines that is automatically
+ * created for us, so we can use it for debugging purposes.
+ */
+ if (props->log_level >= 3)
+ BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
+
+ /*
+ * If we don't trigger the handshake in the library, leave control over
+ * SSL_accept/read/write/etc with the application.
+ */
+ if (props->stream == 0)
+ return (TLScontext);
+
/*
* Connect the SSL connection with the network socket.
*/
if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) {
- msg_info("SSL_set_fd error to %s: %d", props->namaddr, sts);
+ msg_info("SSL_set_fd error to %s", props->namaddr);
tls_print_errors();
uncache_session(app_ctx->ssl_ctx, TLScontext);
tls_free_context(TLScontext);
*/
non_blocking(vstream_fileno(props->stream), NON_BLOCKING);
- /*
- * If the debug level selected is high enough, all of the data is dumped:
- * 3 will dump the SSL negotiation, 4 will dump everything.
- *
- * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
- * Well there is a BIO below the SSL routines that is automatically
- * created for us, so we can use it for debugging purposes.
- */
- if (props->log_level >= 3)
- BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
-
/*
* Start TLS negotiations. This process is a black box that invokes our
* call-backs for session caching and certificate verification.
tls_free_context(TLScontext);
return (0);
}
+ return (tls_server_post_accept(TLScontext));
+}
+
+/* tls_server_post_accept - post-handshake processing */
+
+TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
+{
+ const SSL_CIPHER *cipher;
+ X509 *peer;
+ char buf[CCERT_BUFSIZ];
+
/* Only loglevel==4 dumps everything */
- if (props->log_level < 4)
+ if (TLScontext->log_level < 4)
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
/*
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
- if (props->log_level >= 2) {
+ if (TLScontext->log_level >= 2) {
X509_NAME_oneline(X509_get_subject_name(peer),
buf, sizeof(buf));
msg_info("subject=%s", buf);
}
TLScontext->peer_CN = tls_peer_CN(peer, TLScontext);
TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext);
- TLScontext->peer_fingerprint = tls_fingerprint(peer, props->fpt_dgst);
+ TLScontext->peer_fingerprint =
+ tls_fingerprint(peer, TLScontext->fpt_dgst);
- if (props->log_level >= 1) {
+ if (TLScontext->log_level >= 1) {
msg_info("%s: %s: subject_CN=%s, issuer=%s, fingerprint=%s",
- props->namaddr,
+ TLScontext->namaddr,
TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
TLScontext->peer_CN, TLScontext->issuer_CN,
TLScontext->peer_fingerprint);
&(TLScontext->cipher_algbits));
/*
- * The TLS engine is active. Switch to the tls_timed_read/write()
- * functions and make the TLScontext available to those functions.
+ * If the library triggered the SSL handshake, switch to the
+ * tls_timed_read/write() functions and make the TLScontext available to
+ * those functions. Otherwise, leave control over SSL_read/write/etc.
+ * with the application.
*/
- tls_stream_start(props->stream, TLScontext);
+ if (TLScontext->stream != 0)
+ tls_stream_start(TLScontext->stream, TLScontext);
/*
* All the key facts in a single log entry.
*/
- if (props->log_level >= 1)
+ if (TLScontext->log_level >= 1)
msg_info("%s TLS connection established from %s: %s with cipher %s "
"(%d/%d bits)", !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous"
: TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
- props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
+ TLScontext->namaddr, TLScontext->protocol, TLScontext->cipher_name,
TLScontext->cipher_usebits, TLScontext->cipher_algbits);
tls_int_seed();
--- /dev/null
+../../.indent.pro
\ No newline at end of file
--- /dev/null
+SHELL = /bin/sh
+SRCS = tlsproxy.c tlsproxy_state.c
+OBJS = tlsproxy.o tlsproxy_state.o
+HDRS =
+TESTSRC =
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = tlsproxy
+INC_DIR = ../../include
+LIBS = ../../lib/libtls.a ../../lib/libmaster.a ../../lib/libglobal.a \
+ ../../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+$(OBJS): ../../conf/makedefs.out
+
+Makefile: Makefile.in
+ cat ../../conf/makedefs.out $? >$@
+
+test: $(TESTPROG)
+
+tests: test
+
+root_tests:
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+ -e 's/o: \.\//o: /' -e p -e '}' ; \
+ done | sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+tlsproxy.o: ../../include/argv.h
+tlsproxy.o: ../../include/attr.h
+tlsproxy.o: ../../include/events.h
+tlsproxy.o: ../../include/iostuff.h
+tlsproxy.o: ../../include/mail_conf.h
+tlsproxy.o: ../../include/mail_params.h
+tlsproxy.o: ../../include/mail_proto.h
+tlsproxy.o: ../../include/mail_server.h
+tlsproxy.o: ../../include/mail_version.h
+tlsproxy.o: ../../include/msg.h
+tlsproxy.o: ../../include/mymalloc.h
+tlsproxy.o: ../../include/name_code.h
+tlsproxy.o: ../../include/name_mask.h
+tlsproxy.o: ../../include/nbbio.h
+tlsproxy.o: ../../include/sys_defs.h
+tlsproxy.o: ../../include/tls.h
+tlsproxy.o: ../../include/vbuf.h
+tlsproxy.o: ../../include/vstream.h
+tlsproxy.o: ../../include/vstring.h
+tlsproxy.o: tlsproxy.c
+tlsproxy.o: tlsproxy.h
+tlsproxy_state.o: ../../include/argv.h
+tlsproxy_state.o: ../../include/events.h
+tlsproxy_state.o: ../../include/mail_server.h
+tlsproxy_state.o: ../../include/msg.h
+tlsproxy_state.o: ../../include/mymalloc.h
+tlsproxy_state.o: ../../include/name_code.h
+tlsproxy_state.o: ../../include/name_mask.h
+tlsproxy_state.o: ../../include/nbbio.h
+tlsproxy_state.o: ../../include/sys_defs.h
+tlsproxy_state.o: ../../include/tls.h
+tlsproxy_state.o: ../../include/vbuf.h
+tlsproxy_state.o: ../../include/vstream.h
+tlsproxy_state.o: ../../include/vstring.h
+tlsproxy_state.o: tlsproxy.h
+tlsproxy_state.o: tlsproxy_state.c
--- /dev/null
+/*++
+/* NAME
+/* tlsproxy 8
+/* SUMMARY
+/* Postfix TLS proxy
+/* SYNOPSIS
+/* \fBtlsproxy\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* The \fBtlsproxy\fR(8) server implements a server-side TLS
+/* proxy. Its primary use is to talk plaintext SMTP with
+/* \fBpostscreen\fR(8), and to talk SMTP-over-TLS with remote
+/* SMTP clients whose whitelist status has expired, but it
+/* should also work for non-SMTP protocols.
+/*
+/* Although one \fBtlsproxy\fR(8) process can serve multiple
+/* sessions at the same time, it is a good idea to allow the
+/* number of processes to increase with load, so that the
+/* service remains available.
+/* PROTOCOL EXAMPLE
+/* .ad
+/* .fi
+/* The example below involves \fBpostscreen\fR(8). However,
+/* the \fBtlsproxy\fR(8) server is agnostic of the application
+/* protocol, and the example is easily adapted to other
+/* applications.
+/*
+/* The \fBpostscreen\fR(8) server sends the remote SMTP client
+/* endpoint string, the requested role (server), and the
+/* requested timeout to \fBtlsproxy\fR(8). \fBpostscreen\fR(8)
+/* then receives a "TLS available" indication from \fBtlsproxy\fR(8).
+/* If the TLS service is available, \fBpostscreen\fR(8) sends
+/* the remote SMTP client file descriptor to \fBtlsproxy\fR(8),
+/* and sends the plaintext 220 greeting to the remote SMTP
+/* client. This triggers TLS negotiations between the remote
+/* SMTP client and \fBtlsproxy\fR(8). Upon completion of the
+/* TLS-level handshake, \fBtlsproxy\fR(8) translates between
+/* plaintext from/to \fBpostscreen\fR(8) and ciphertext to/from
+/* the remote SMTP client.
+/* SECURITY
+/* .ad
+/* .fi
+/* The \fBtlsproxy\fR(8) server is moderately security-sensitive.
+/* It talks to untrusted clients on the network. The process
+/* can be run chrooted at fixed low privilege.
+/* DIAGNOSTICS
+/* Problems and transactions are logged to \fBsyslogd\fR(8).
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* Changes to \fBmain.cf\fR are not picked up automatically,
+/* as \fBtlsproxy\fR(8) processes may run for a long time
+/* depending on mail server load. Use the command "\fBpostfix
+/* reload\fR" to speed up a change.
+/*
+/* The text below provides only a parameter summary. See
+/* \fBpostconf\fR(5) for more details including examples.
+/* STARTTLS SUPPORT CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBtlsproxy_tls_CAfile ($smtpd_tls_CAfile)\fR"
+/* A file containing (PEM format) CA certificates of root CAs
+/* trusted to sign either remote SMTP client certificates or intermediate
+/* CA certificates.
+/* .IP "\fBtlsproxy_tls_CApath ($smtpd_tls_CApath)\fR"
+/* A directory containing (PEM format) CA certificates of root CAs
+/* trusted to sign either remote SMTP client certificates or intermediate
+/* CA certificates.
+/* .IP "\fBtlsproxy_tls_always_issue_session_ids ($smtpd_tls_always_issue_session_ids)\fR"
+/* Force the Postfix \fBtlsproxy\fR(8) server to issue a TLS session id,
+/* even when TLS session caching is turned off.
+/* .IP "\fBtlsproxy_tls_ask_ccert ($smtpd_tls_ask_ccert)\fR"
+/* Ask a remote SMTP client for a client certificate.
+/* .IP "\fBtlsproxy_tls_ccert_verifydepth ($smtpd_tls_ccert_verifydepth)\fR"
+/* The verification depth for remote SMTP client certificates.
+/* .IP "\fBtlsproxy_tls_cert_file ($smtpd_tls_cert_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server RSA certificate in PEM
+/* format.
+/* .IP "\fBtlsproxy_tls_ciphers ($smtpd_tls_ciphers)\fR"
+/* The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+/* will use with opportunistic TLS encryption.
+/* .IP "\fBtlsproxy_tls_dcert_file ($smtpd_tls_dcert_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server DSA certificate in PEM
+/* format.
+/* .IP "\fBtlsproxy_tls_dh1024_param_file ($smtpd_tls_dh1024_param_file)\fR"
+/* File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+/* should use with EDH ciphers.
+/* .IP "\fBtlsproxy_tls_dh512_param_file ($smtpd_tls_dh512_param_file)\fR"
+/* File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
+/* should use with EDH ciphers.
+/* .IP "\fBtlsproxy_tls_dkey_file ($smtpd_tls_dkey_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM
+/* format.
+/* .IP "\fBtlsproxy_tls_eccert_file ($smtpd_tls_eccert_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in
+/* PEM format.
+/* .IP "\fBtlsproxy_tls_eckey_file ($smtpd_tls_eckey_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in
+/* PEM format.
+/* .IP "\fBtlsproxy_tls_eecdh_grade ($smtpd_tls_eecdh_grade)\fR"
+/* The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral
+/* elliptic-curve Diffie-Hellman (EECDH) key exchange.
+/* .IP "\fBtlsproxy_tls_exclude_ciphers ($smtpd_tls_exclude_ciphers)\fR"
+/* List of ciphers or cipher types to exclude from the \fBtlsproxy\fR(8)
+/* server cipher list at all TLS security levels.
+/* .IP "\fBtlsproxy_tls_fingerprint_digest ($smtpd_tls_fingerprint_digest)\fR"
+/* The message digest algorithm used to construct client-certificate
+/* fingerprints.
+/* .IP "\fBtlsproxy_tls_key_file ($smtpd_tls_key_file)\fR"
+/* File with the Postfix \fBtlsproxy\fR(8) server RSA private key in PEM
+/* format.
+/* .IP "\fBtlsproxy_tls_loglevel ($smtpd_tls_loglevel)\fR"
+/* Enable additional Postfix \fBtlsproxy\fR(8) server logging of TLS
+/* activity.
+/* .IP "\fBtlsproxy_tls_mandatory_ciphers ($smtpd_tls_mandatory_ciphers)\fR"
+/* The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server
+/* will use with mandatory TLS encryption.
+/* .IP "\fBtlsproxy_tls_mandatory_exclude_ciphers ($smtpd_tls_mandatory_exclude_ciphers)\fR"
+/* Additional list of ciphers or cipher types to exclude from the
+/* \fBtlsproxy\fR(8) server cipher list at mandatory TLS security levels.
+/* .IP "\fBtlsproxy_tls_mandatory_protocols ($smtpd_tls_mandatory_protocols)\fR"
+/* The SSL/TLS protocols accepted by the Postfix \fBtlsproxy\fR(8) server
+/* with mandatory TLS encryption.
+/* .IP "\fBtlsproxy_tls_protocols ($smtpd_tls_protocols)\fR"
+/* List of TLS protocols that the Postfix \fBtlsproxy\fR(8) server will
+/* exclude or include with opportunistic TLS encryption.
+/* .IP "\fBtlsproxy_tls_req_ccert ($smtpd_tls_req_ccert)\fR"
+/* With mandatory TLS encryption, require a trusted remote SMTP
+/* client certificate in order to allow TLS connections to proceed.
+/* .IP "\fBtlsproxy_tls_security_level ($smtpd_tls_security_level)\fR"
+/* The SMTP TLS security level for the Postfix \fBtlsproxy\fR(8) server;
+/* when a non-empty value is specified, this overrides the obsolete
+/* parameters smtpd_use_tls and smtpd_enforce_tls.
+/* .IP "\fBtlsproxy_tls_session_cache_timeout ($smtpd_tls_session_cache_timeout)\fR"
+/* The expiration time of Postfix \fBtlsproxy\fR(8) server TLS session
+/* cache information.
+/* OBSOLETE STARTTLS SUPPORT CONTROLS
+/* .ad
+/* .fi
+/* These parameters are supported for compatibility with
+/* \fBsmtpd\fR(8) legacy parameters.
+/* .IP "\fBtlsproxy_use_tls ($smtpd_use_tls)\fR"
+/* Opportunistic TLS: announce STARTTLS support to SMTP clients,
+/* but do not require that clients use TLS encryption.
+/* .IP "\fBtlsproxy_enforce_tls ($smtpd_enforce_tls)\fR"
+/* Mandatory TLS: announce STARTTLS support to SMTP clients, and
+/* require that clients use TLS encryption.
+/* RESOURCE CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBtlsproxy_watchdog_timeout (10s)\fR"
+/* How much time a \fBtlsproxy\fR(8) process may take to process local
+/* or remote I/O before it is terminated by a built-in watchdog timer.
+/* MISCELLANEOUS CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+/* The default location of the Postfix main.cf and master.cf
+/* configuration files.
+/* .IP "\fBprocess_id (read-only)\fR"
+/* The process ID of a Postfix command or daemon process.
+/* .IP "\fBprocess_name (read-only)\fR"
+/* The process name of a Postfix command or daemon process.
+/* .IP "\fBsyslog_facility (mail)\fR"
+/* The syslog facility of Postfix logging.
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+/* The mail system name that is prepended to the process name in syslog
+/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/* SEE ALSO
+/* postscreen(8), Postfix zombie blocker
+/* smtpd(8), Postfix SMTP server
+/* postconf(5), configuration parameters
+/* syslogd(5), system logging
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* HISTORY
+/* .ad
+/* .fi
+/* This service was introduced with Postfix version 2.8.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <vstream.h>
+#include <iostuff.h>
+#include <nbbio.h>
+#include <mymalloc.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_proto.h>
+#include <mail_params.h>
+#include <mail_conf.h>
+#include <mail_version.h>
+
+ /*
+ * Master library.
+ */
+#include <mail_server.h>
+
+ /*
+ * TLS library.
+ */
+#ifdef USE_TLS
+#define TLS_INTERNAL /* XXX */
+#include <tls.h>
+
+ /*
+ * Application-specific.
+ */
+#include <tlsproxy.h>
+
+ /*
+ * Tunable parameters. We define our clones of the smtpd(8) parameters to
+ * avoid any confusion about which parameters are used by this program.
+ */
+int var_smtpd_tls_ccert_vd;
+int var_smtpd_tls_loglevel;
+int var_smtpd_tls_scache_timeout;
+bool var_smtpd_use_tls;
+bool var_smtpd_enforce_tls;
+bool var_smtpd_tls_ask_ccert;
+bool var_smtpd_tls_req_ccert;
+bool var_smtpd_tls_set_sessid;
+char *var_smtpd_relay_ccerts;
+char *var_smtpd_tls_cert_file;
+char *var_smtpd_tls_key_file;
+char *var_smtpd_tls_dcert_file;
+char *var_smtpd_tls_dkey_file;
+char *var_smtpd_tls_eccert_file;
+char *var_smtpd_tls_eckey_file;
+char *var_smtpd_tls_CAfile;
+char *var_smtpd_tls_CApath;
+char *var_smtpd_tls_ciph;
+char *var_smtpd_tls_mand_ciph;
+char *var_smtpd_tls_excl_ciph;
+char *var_smtpd_tls_mand_excl;
+char *var_smtpd_tls_proto;
+char *var_smtpd_tls_mand_proto;
+char *var_smtpd_tls_dh512_param_file;
+char *var_smtpd_tls_dh1024_param_file;
+char *var_smtpd_tls_eecdh;
+char *var_smtpd_tls_fpt_dgst;
+char *var_smtpd_tls_level;
+
+int var_tlsp_tls_ccert_vd;
+int var_tlsp_tls_loglevel;
+int var_tlsp_tls_scache_timeout;
+bool var_tlsp_use_tls;
+bool var_tlsp_enforce_tls;
+bool var_tlsp_tls_ask_ccert;
+bool var_tlsp_tls_req_ccert;
+bool var_tlsp_tls_set_sessid;
+char *var_tlsp_tls_cert_file;
+char *var_tlsp_tls_key_file;
+char *var_tlsp_tls_dcert_file;
+char *var_tlsp_tls_dkey_file;
+char *var_tlsp_tls_eccert_file;
+char *var_tlsp_tls_eckey_file;
+char *var_tlsp_tls_CAfile;
+char *var_tlsp_tls_CApath;
+char *var_tlsp_tls_ciph;
+char *var_tlsp_tls_mand_ciph;
+char *var_tlsp_tls_excl_ciph;
+char *var_tlsp_tls_mand_excl;
+char *var_tlsp_tls_proto;
+char *var_tlsp_tls_mand_proto;
+char *var_tlsp_tls_dh512_param_file;
+char *var_tlsp_tls_dh1024_param_file;
+char *var_tlsp_tls_eecdh;
+char *var_tlsp_tls_fpt_dgst;
+char *var_tlsp_tls_level;
+
+int var_tlsp_watchdog;
+
+ /*
+ * TLS per-process status.
+ */
+static TLS_APPL_STATE *tlsp_server_ctx;
+static int ask_client_cert;
+static int enforce_tls;
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+
+ /*
+ * This code looks simpler than expected. That is the result of a great deal
+ * of effort, mainly in design and analysis.
+ *
+ * By design, postscreen(8) is an event-driven server that must scale up to a
+ * large number of clients. This means that postscreen(8) must avoid doing
+ * CPU-intensive operations such as those in OpenSSL.
+ *
+ * tlsproxy(8) runs the OpenSSL code on behalf of postscreen(8), translating
+ * plaintext SMTP messages from postscreen(8) into SMTP-over-TLS messages to
+ * the remote SMTP client, and vice versa. As long as postscreen(8) does not
+ * receive email messages, the cost of doing TLS operations will be modest.
+ *
+ * Like postscreen(8), one tlsproxy(8) process services multiple remote SMTP
+ * clients. Unlike postscreen(8), there can be more than one tlsproxy(8)
+ * process, although their number is meant to be much smaller than the
+ * number of remote SMTP clients that talk TLS.
+ *
+ * As with postscreen(8), all I/O must be event-driven: encrypted traffic
+ * between tlsproxy(8) and remote SMTP clients, and plaintext traffic
+ * between tlsproxy(8) and postscreen(8). Event-driven plaintext I/O is
+ * straightforward enough that it could be abstracted away with the nbbio(3)
+ * module.
+ *
+ * The event-driven TLS I/O implementation is founded on on-line OpenSSL
+ * documentation, supplemented by statements from OpenSSL developers on
+ * public mailing lists. After some field experience with this code, we may
+ * be able to factor it out as a library module, like nbbio(3), that can
+ * become part of the TLS library.
+ */
+
+static void tlsp_ciphertext_event(int, char *);
+
+#define TLSP_INIT_TIMEOUT 100
+
+/* tlsp_drain - delayed exit after "postfix reload" */
+
+static void tlsp_drain(char *unused_service, char **unused_argv)
+{
+ int count;
+
+ /*
+ * After "postfix reload", complete work-in-progress in the background,
+ * instead of dropping already-accepted connections on the floor.
+ *
+ * All error retry counts shall be limited. Instead of blocking here, we
+ * could retry failed fork() operations in the event call-back routines,
+ * but we don't need perfection. The host system is severely overloaded
+ * and service levels are already way down.
+ */
+ for (count = 0; /* see below */ ; count++) {
+ if (count >= 5) {
+ msg_fatal("fork: %m");
+ } else if (event_server_drain() != 0) {
+ msg_warn("fork: %m");
+ sleep(1);
+ continue;
+ } else {
+ return;
+ }
+ }
+}
+
+/* tlsp_eval_tls_error - translate TLS "error" result into action */
+
+static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
+{
+ int ciphertext_fd = state->ciphertext_fd;
+
+ /*
+ * The ciphertext file descriptor is in non-blocking mode, meaning that
+ * each SSL_accept/connect/read/write/shutdown request may return an
+ * "error" indication that it needs to read or write more ciphertext. The
+ * purpose of this routine is to translate those "error" indications into
+ * the appropriate read/write/timeout event requests.
+ */
+ switch (err) {
+
+ /*
+ * No error from SSL_read and SSL_write means that the plaintext
+ * output buffer is full and that the plaintext input buffer is
+ * empty. Stop read/write events on the ciphertext stream. Keep the
+ * timer alive as a safety mechanism for the case that the plaintext
+ * pseudothreads get stuck.
+ */
+ case SSL_ERROR_NONE:
+ if (state->ssl_last_err != SSL_ERROR_NONE) {
+ event_disable_readwrite(ciphertext_fd);
+ event_request_timer(tlsp_ciphertext_event, (char *) state,
+ state->timeout);
+ state->ssl_last_err = SSL_ERROR_NONE;
+ }
+ return (0);
+
+ /*
+ * The TLS engine wants to write to the network. Turn on
+ * write/timeout events on the ciphertext stream.
+ */
+ case SSL_ERROR_WANT_WRITE:
+ if (state->ssl_last_err == SSL_ERROR_WANT_READ)
+ event_disable_readwrite(ciphertext_fd);
+ if (state->ssl_last_err != SSL_ERROR_WANT_WRITE) {
+ event_enable_write(ciphertext_fd, tlsp_ciphertext_event,
+ (char *) state);
+ state->ssl_last_err = SSL_ERROR_WANT_WRITE;
+ }
+ event_request_timer(tlsp_ciphertext_event, (char *) state,
+ state->timeout);
+ return (0);
+
+ /*
+ * The TLS engine wants to read from the network. Turn on
+ * read/timeout events on the ciphertext stream.
+ */
+ case SSL_ERROR_WANT_READ:
+ if (state->ssl_last_err == SSL_ERROR_WANT_WRITE)
+ event_disable_readwrite(ciphertext_fd);
+ if (state->ssl_last_err != SSL_ERROR_WANT_READ) {
+ event_enable_read(ciphertext_fd, tlsp_ciphertext_event,
+ (char *) state);
+ state->ssl_last_err = SSL_ERROR_WANT_READ;
+ }
+ event_request_timer(tlsp_ciphertext_event, (char *) state,
+ state->timeout);
+ return (0);
+
+ /*
+ * Some error. Self-destruct. This automagically cleans up all
+ * pending read/write and timeout event requests, making state a
+ * dangling pointer.
+ */
+ case SSL_ERROR_SSL:
+ tls_print_errors();
+ /* FALLTHROUGH */
+ default:
+ tlsp_state_free(state);
+ return (-1);
+ }
+}
+
+/* tlsp_strategy - decide what to read or write next. */
+
+static void tlsp_strategy(TLSP_STATE *state)
+{
+ TLS_SESS_STATE *tls_context = state->tls_context;
+ NBBIO *plaintext_buf;
+ int ssl_stat;
+ int ssl_read_err;
+ int ssl_write_err;
+ int handshake_err;
+
+ /*
+ * Be sure to complete the TLS handshake before enabling plain-text I/O.
+ * In case of an unrecoverable error, this automagically cleans up all
+ * pending read/write and timeout event requests.
+ */
+ if (state->flags & TLSP_FLAG_DO_HANDSHAKE) {
+ ssl_stat = SSL_accept(tls_context->con);
+ if (ssl_stat != 1) {
+ handshake_err = SSL_get_error(tls_context->con, ssl_stat);
+ tlsp_eval_tls_error(state, handshake_err);
+ /* At this point, state could be a dangling pointer. */
+ return;
+ }
+ if ((state->tls_context = tls_server_post_accept(tls_context)) == 0) {
+ tlsp_state_free(state);
+ return;
+ }
+ state->flags &= ~TLSP_FLAG_DO_HANDSHAKE;
+ }
+
+ /*
+ * Shutdown and self-destruct after NBBIO error. This automagically
+ * cleans up all pending read/write and timeout event requests. Before
+ * shutting down TLS, we stop all plain-text I/O events but keep the
+ * NBBIO error flags.
+ */
+ plaintext_buf = state->plaintext_buf;
+ if (NBBIO_ERROR_FLAGS(plaintext_buf)) {
+ if (NBBIO_ACTIVE_FLAGS(plaintext_buf))
+ nbbio_disable_readwrite(state->plaintext_buf);
+ ssl_stat = SSL_shutdown(tls_context->con);
+ /* XXX Wait for return value 1 if sessions are to be reused? */
+ if (ssl_stat < 0) {
+ handshake_err = SSL_get_error(tls_context->con, ssl_stat);
+ tlsp_eval_tls_error(state, handshake_err);
+ /* At this point, state could be a dangling pointer. */
+ return;
+ }
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * Try to move data from the plaintext input buffer to the TLS engine.
+ *
+ * XXX We're supposed to repeat the exact same SSL_write() call arguments
+ * after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE result. Rumor has
+ * it that this is because each SSL_write() call reads from the buffer
+ * incrementally, and returns > 0 only after the final byte is processed.
+ * Rumor also has it that setting SSL_MODE_ENABLE_PARTIAL_WRITE and
+ * SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER voids this requirement, and that
+ * repeating the request with an increased request size is OK.
+ * Unfortunately all this is not or poorly documented, and one has to
+ * rely on statements from OpenSSL developers in public mailing archives.
+ */
+ ssl_write_err = SSL_ERROR_NONE;
+ while (NBBIO_READ_PEND(plaintext_buf) > 0) {
+ ssl_stat = SSL_write(tls_context->con, NBBIO_READ_BUF(plaintext_buf),
+ NBBIO_READ_PEND(plaintext_buf));
+ ssl_write_err = SSL_get_error(tls_context->con, ssl_stat);
+ if (ssl_write_err != SSL_ERROR_NONE)
+ break;
+ /* Allow the plaintext pseudothread to read more data. */
+ NBBIO_READ_PEND(plaintext_buf) -= ssl_stat;
+ if (NBBIO_READ_PEND(plaintext_buf) > 0)
+ memmove(NBBIO_READ_BUF(plaintext_buf),
+ NBBIO_READ_BUF(plaintext_buf) + ssl_stat,
+ NBBIO_READ_PEND(plaintext_buf));
+ }
+
+ /*
+ * Try to move data from the TLS engine to the plaintext output buffer.
+ * Note: data may arrive as a side effect of calling SSL_write(),
+ * therefore we call SSL_read() after calling SSL_write().
+ *
+ * XXX We're supposed to repeat the exact same SSL_read() call arguments
+ * after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE result. This
+ * supposedly means that our plaintext writer must not memmove() the
+ * plaintext output buffer until after the SSL_read() call succeeds. For
+ * now I'll ignore this, because 1) SSL_read() is documented to return
+ * the bytes available, instead of returning > 0 only after the entire
+ * buffer is processed like SSL_write() does; and 2) there is no "read"
+ * equivalent of the SSL_R_BAD_WRITE_RETRY, SSL_MODE_ENABLE_PARTIAL_WRITE
+ * or SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER features.
+ */
+ ssl_read_err = SSL_ERROR_NONE;
+ while (NBBIO_WRITE_PEND(state->plaintext_buf) < NBBIO_BUFSIZE(plaintext_buf)) {
+ ssl_stat = SSL_read(tls_context->con,
+ NBBIO_WRITE_BUF(plaintext_buf)
+ + NBBIO_WRITE_PEND(state->plaintext_buf),
+ NBBIO_BUFSIZE(plaintext_buf)
+ - NBBIO_WRITE_PEND(state->plaintext_buf));
+ ssl_read_err = SSL_get_error(tls_context->con, ssl_stat);
+ if (ssl_read_err != SSL_ERROR_NONE)
+ break;
+ NBBIO_WRITE_PEND(plaintext_buf) += ssl_stat;
+ }
+
+ /*
+ * Try to enable/disable ciphertext read/write events. If SSL_write() was
+ * satisfied, see if SSL_read() wants to do some work. In case of an
+ * unrecoverable error, this automagically destroys the session state
+ * after cleaning up all pending read/write and timeout event requests.
+ */
+ if (tlsp_eval_tls_error(state, ssl_write_err != SSL_ERROR_NONE ?
+ ssl_write_err : ssl_read_err) < 0)
+ return;
+
+ /*
+ * Try to enable/disable plaintext read/write events. Basically, if we
+ * have nothing to write to the postscreen(8) server, see if there is
+ * something to read. If the write buffer is empty and the read buffer is
+ * full, suspend plaintext I/O until conditions change (but keep the
+ * timer active, as a safety mechanism in case ciphertext I/O gets
+ * stuck).
+ *
+ * XXX In theory, if the client keeps writing fast enough then we would
+ * never read from postscreen(8), and cause postscreen(8) to block. In
+ * practice, postscreen(8) limits the number of client commands, and thus
+ * postscreen(8)'s output will fit in a kernel buffer. This may not be
+ * true in other scenarios where the tlsproxy(8) server could be used.
+ */
+ if (NBBIO_WRITE_PEND(plaintext_buf) > 0) {
+ if (NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_READ)
+ nbbio_disable_readwrite(plaintext_buf);
+ if ((NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_WRITE) == 0)
+ nbbio_enable_write(plaintext_buf, state->timeout);
+ } else if (NBBIO_READ_PEND(plaintext_buf) < NBBIO_BUFSIZE(plaintext_buf)) {
+ if (NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_WRITE)
+ nbbio_disable_readwrite(plaintext_buf);
+ if ((NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_READ) == 0)
+ nbbio_enable_read(plaintext_buf, state->timeout);
+ } else {
+ if (NBBIO_ACTIVE_FLAGS(plaintext_buf))
+ nbbio_slumber(plaintext_buf, state->timeout);
+ }
+}
+
+/* tlsp_plaintext_event - plaintext was read/written */
+
+static void tlsp_plaintext_event(int event, char *context)
+{
+ TLSP_STATE *state = (TLSP_STATE *) context;
+
+ /*
+ * Safety alert: the plaintext pseudothreads have "slumbered" for too
+ * long (see code above). This means that the ciphertext pseudothreads
+ * are stuck.
+ */
+ if ((NBBIO_ERROR_FLAGS(state->plaintext_buf) & NBBIO_FLAG_TIMEOUT) != 0
+ && NBBIO_ACTIVE_FLAGS(state->plaintext_buf) == 0)
+ msg_warn("deadlock on ciphertext stream for %s", state->remote_endpt);
+
+ /*
+ * This is easy, because the NBBIO layer has already done the event
+ * decoding and plaintext I/O for us. All we need to do is decide if we
+ * want to read or write more plaintext.
+ */
+ tlsp_strategy(state);
+}
+
+/* tlsp_ciphertext_event - ciphertext is ready to read/write */
+
+static void tlsp_ciphertext_event(int event, char *context)
+{
+ TLSP_STATE *state = (TLSP_STATE *) context;
+
+ /*
+ * Without a TLS quivalent of the NBBIO layer, we must decode the events
+ * ourselves and do the ciphertext I/O. Then, we can decide if we want to
+ * read or write more ciphertext.
+ */
+ if (event == EVENT_READ || event == EVENT_WRITE) {
+ tlsp_strategy(state);
+ } else {
+ msg_warn("read/write %s for %s",
+ event == EVENT_TIME ? "timeout" : "error",
+ state->remote_endpt);
+ tlsp_state_free(state);
+ }
+}
+
+/* tlsp_start_tls - turn on TLS or force disconnect */
+
+static void tlsp_start_tls(TLSP_STATE *state)
+{
+ TLS_SERVER_START_PROPS props;
+ static char *cipher_grade;
+ static VSTRING *cipher_exclusions;
+
+ /*
+ * The code in this routine is pasted literally from smtpd(8). I am not
+ * going to sanitize this because doing so surely will break things in
+ * unexpected ways.
+ */
+ state->tls_use_tls = var_tlsp_use_tls | var_tlsp_enforce_tls;
+ state->tls_enforce_tls = var_tlsp_enforce_tls;
+
+ /*
+ * Perform the before-handshake portion of the per-session initalization.
+ * Pass a null VSTREAM to indicate that this program, will do the
+ * ciphertext I/O, not libtls.
+ *
+ * The cipher grade and exclusions don't change between sessions. Compute
+ * just once and cache.
+ */
+#define ADD_EXCLUDE(vstr, str) \
+ do { \
+ if (*(str)) \
+ vstring_sprintf_append((vstr), "%s%s", \
+ VSTRING_LEN(vstr) ? " " : "", (str)); \
+ } while (0)
+
+ if (cipher_grade == 0) {
+ cipher_grade =
+ enforce_tls ? var_tlsp_tls_mand_ciph : var_tlsp_tls_ciph;
+ cipher_exclusions = vstring_alloc(10);
+ ADD_EXCLUDE(cipher_exclusions, var_tlsp_tls_excl_ciph);
+ if (enforce_tls)
+ ADD_EXCLUDE(cipher_exclusions, var_tlsp_tls_mand_excl);
+ if (ask_client_cert)
+ ADD_EXCLUDE(cipher_exclusions, "aNULL");
+ }
+ state->tls_context =
+ TLS_SERVER_START(&props,
+ ctx = tlsp_server_ctx,
+ stream = (VSTREAM *) 0,/* unused */
+ log_level = var_tlsp_tls_loglevel,
+ timeout = 0, /* unused */
+ requirecert = (var_tlsp_tls_req_ccert
+ && state->tls_enforce_tls),
+ serverid = state->service,
+ namaddr = state->remote_endpt,
+ cipher_grade = cipher_grade,
+ cipher_exclusions = STR(cipher_exclusions),
+ fpt_dgst = var_tlsp_tls_fpt_dgst);
+
+ if (state->tls_context == 0) {
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * This program will do the ciphertext I/O, not libtls. In the future,
+ * the above event-driven engine may be factored out as a libtls library
+ * module.
+ */
+ if (SSL_set_fd(state->tls_context->con, state->ciphertext_fd) != 1) {
+ msg_info("SSL_set_fd error to %s", state->remote_endpt);
+ tls_print_errors();
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * XXX Do we care about TLS session rate limits? Good postscreen(8)
+ * clients will occasionally require the tlsproxy to renew their
+ * whitelist status, but bad clients hammering the server can suck up
+ * lots of CPU cycles. Per-client concurrency limits in postscreen(8)
+ * will divert only naive security "researchers".
+ *
+ * XXX Do we care about certificate verification results? Not as long as
+ * postscreen(8) doesn't actually receive email.
+ */
+}
+
+/* tlsp_get_fd_event - receive final postscreen(8) hand-off information */
+
+static void tlsp_get_fd_event(int event, char *context)
+{
+ const char *myname = "tlsp_get_fd_event";
+ TLSP_STATE *state = (TLSP_STATE *) context;
+ int plaintext_fd = vstream_fileno(state->plaintext_stream);
+
+ /*
+ * At this point we still manually manage plaintext read/write/timeout
+ * events. Disable I/O and timer events. Don't assume that the first
+ * plaintext request will be a read.
+ */
+ event_disable_readwrite(plaintext_fd);
+ if (event != EVENT_TIME)
+ event_cancel_timer(tlsp_get_fd_event, (char *) state);
+
+ /*
+ * Initialize plaintext-related session state. Once we have this behind
+ * us, the TLSP_STATE destructor will automagically clean up requests for
+ * read/write/timeout events, which makes error recovery easier.
+ *
+ * Register the plaintext event handler for timer cleanup in the TLSP_STATE
+ * destructor. Insert the NBBIO event-driven I/O layer between the
+ * postscreen(8) server and the TLS engine.
+ */
+ if (event != EVENT_READ
+ || (state->ciphertext_fd = LOCAL_RECV_FD(plaintext_fd)) < 0) {
+ msg_warn("%s: receive SMTP client file descriptor: %m", myname);
+ tlsp_state_free(state);
+ return;
+ }
+ non_blocking(state->ciphertext_fd, NON_BLOCKING);
+ state->ciphertext_timer = tlsp_ciphertext_event;
+ state->plaintext_buf = nbbio_create(plaintext_fd,
+ VSTREAM_BUFSIZE, "postscreen",
+ tlsp_plaintext_event,
+ (char *) state);
+
+ /*
+ * Perform the TLS layer before-handshake initialization. We perform the
+ * remainder after the TLS handshake completes.
+ */
+ tlsp_start_tls(state);
+
+ /*
+ * Trigger the initial proxy server I/Os.
+ */
+ tlsp_strategy(state);
+}
+
+/* tlsp_get_request_event - receive initial postscreen(8) hand-off info */
+
+static void tlsp_get_request_event(int event, char *context)
+{
+ const char *myname = "tlsp_get_request_event";
+ TLSP_STATE *state = (TLSP_STATE *) context;
+ VSTREAM *plaintext_stream = state->plaintext_stream;
+ int plaintext_fd = vstream_fileno(plaintext_stream);
+ static VSTRING *remote_endpt;
+ static VSTRING *role;
+ int timeout;
+ int ready;
+
+ /*
+ * One-time initialization.
+ */
+ if (remote_endpt == 0) {
+ remote_endpt = vstring_alloc(10);
+ role = vstring_alloc(10);
+ }
+
+ /*
+ * At this point we still manually manage plaintext read/write/timeout
+ * events. Turn off timer events. Below we disable read events on error,
+ * and redefine read events on success.
+ */
+ if (event != EVENT_TIME)
+ event_cancel_timer(tlsp_get_request_event, (char *) state);
+
+ /*
+ * We must send some data, after receiving the request attributes and
+ * before receiving the remote file descriptor. We can't assume
+ * UNIX-domain socket semantics here.
+ */
+ if (event != EVENT_READ
+ || attr_scan(plaintext_stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_STR, MAIL_ATTR_REMOTE_ENDPT, remote_endpt,
+ ATTR_TYPE_STR, MAIL_ATTR_ROLE, role,
+ ATTR_TYPE_INT, MAIL_ATTR_TIMEOUT, &timeout,
+ ATTR_TYPE_END) != 3) {
+ msg_warn("%s: receive request attributes: %m", myname);
+ event_disable_readwrite(plaintext_fd);
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * If the requested TLS engine is unavailable, hang up after making sure
+ * that the plaintext peer has received our "sorry" indication.
+ */
+ ready = (strcmp(STR(role), MAIL_ATTR_ROLE_SERVER) == 0
+ && tlsp_server_ctx != 0);
+ if (attr_print(plaintext_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_INT, MAIL_ATTR_STATUS, ready,
+ ATTR_TYPE_END) != 0
+ || vstream_fflush(plaintext_stream) != 0
+ || ready == 0) {
+ read_wait(plaintext_fd, TLSP_INIT_TIMEOUT); /* XXX */
+ event_disable_readwrite(plaintext_fd);
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * XXX We use the same fixed timeout throughout the entire session for
+ * both plaintext and ciphertext communication. This timeout is just a
+ * safety feature; the real timeout will be enforced by our plaintext
+ * peer.
+ */
+ else {
+ state->remote_endpt = mystrdup(STR(remote_endpt));
+ msg_info("CONNECT %s", state->remote_endpt);
+ state->timeout = timeout + 10; /* XXX */
+ event_enable_read(plaintext_fd, tlsp_get_fd_event, (char *) state);
+ event_request_timer(tlsp_get_fd_event, (char *) state,
+ TLSP_INIT_TIMEOUT);
+ return;
+ }
+}
+
+/* tlsp_service - handle new client connection */
+
+static void tlsp_service(VSTREAM *plaintext_stream,
+ char *service,
+ char **argv)
+{
+ TLSP_STATE *state;
+ int plaintext_fd = vstream_fileno(plaintext_stream);
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * This program handles multiple connections, so it must not block. We
+ * use event-driven code for all operations that introduce latency.
+ */
+ non_blocking(plaintext_fd, NON_BLOCKING);
+ vstream_control(plaintext_stream,
+ VSTREAM_CTL_PATH, "plaintext",
+ VSTREAM_CTL_END);
+
+ /*
+ * Receive postscreen's remote SMTP client address/port and socket.
+ */
+ state = tlsp_state_create(service, plaintext_stream);
+ event_enable_read(plaintext_fd, tlsp_get_request_event, (char *) state);
+ event_request_timer(tlsp_get_request_event, (char *) state,
+ TLSP_INIT_TIMEOUT);
+}
+
+/* pre_jail_init - pre-jail initialization */
+
+static void pre_jail_init(char *unused_name, char **unused_argv)
+{
+ TLS_SERVER_INIT_PROPS props;
+ const char *cert_file;
+ int have_server_cert;
+ int no_server_cert_ok;
+ int require_server_cert;
+
+ /*
+ * The code in this routine is pasted literally from smtpd(8). I am not
+ * going to sanitize this because doing so surely will break things in
+ * unexpected ways.
+ *
+ * Load TLS keys before dropping privileges.
+ *
+ * Can't use anonymous ciphers if we want client certificates. Must use
+ * anonymous ciphers if we have no certificates.
+ */
+ ask_client_cert = require_server_cert =
+ (var_tlsp_tls_ask_ccert
+ || (enforce_tls && var_tlsp_tls_req_ccert));
+ if (strcasecmp(var_tlsp_tls_cert_file, "none") == 0) {
+ no_server_cert_ok = 1;
+ cert_file = "";
+ } else {
+ no_server_cert_ok = 0;
+ cert_file = var_tlsp_tls_cert_file;
+ }
+ have_server_cert =
+ (*cert_file || *var_tlsp_tls_dcert_file || *var_tlsp_tls_eccert_file);
+
+ /* Some TLS configuration errors are not show stoppers. */
+ if (!have_server_cert && require_server_cert)
+ msg_warn("Need a server cert to request client certs");
+ if (!enforce_tls && var_tlsp_tls_req_ccert)
+ msg_warn("Can't require client certs unless TLS is required");
+ /* After a show-stopper error, log a warning. */
+ if (have_server_cert || (no_server_cert_ok && !require_server_cert))
+
+ /*
+ * Large parameter lists are error-prone, so we emulate a language
+ * feature that C does not have natively: named parameter lists.
+ */
+ tlsp_server_ctx =
+ TLS_SERVER_INIT(&props,
+ log_level = var_tlsp_tls_loglevel,
+ verifydepth = var_tlsp_tls_ccert_vd,
+ cache_type = TLS_MGR_SCACHE_SMTPD,
+ scache_timeout = var_tlsp_tls_scache_timeout,
+ set_sessid = var_tlsp_tls_set_sessid,
+ cert_file = cert_file,
+ key_file = var_tlsp_tls_key_file,
+ dcert_file = var_tlsp_tls_dcert_file,
+ dkey_file = var_tlsp_tls_dkey_file,
+ eccert_file = var_tlsp_tls_eccert_file,
+ eckey_file = var_tlsp_tls_eckey_file,
+ CAfile = var_tlsp_tls_CAfile,
+ CApath = var_tlsp_tls_CApath,
+ dh1024_param_file
+ = var_tlsp_tls_dh1024_param_file,
+ dh512_param_file
+ = var_tlsp_tls_dh512_param_file,
+ eecdh_grade = var_tlsp_tls_eecdh,
+ protocols = enforce_tls ?
+ var_tlsp_tls_mand_proto :
+ var_tlsp_tls_proto,
+ ask_ccert = ask_client_cert,
+ fpt_dgst = var_tlsp_tls_fpt_dgst);
+ else
+ msg_warn("No server certs available. TLS can't be enabled");
+
+ /*
+ * To maintain sanity, allow partial SSL_write() operations, and allow
+ * SSL_write() buffer pointers to change after a WANT_READ or WANT_WRITE
+ * result. This is based on OpenSSL developers talking on a mailing list,
+ * but is not supported by documentation. If this code stops working then
+ * no-one can be held responsible.
+ */
+ if (tlsp_server_ctx)
+ SSL_CTX_set_mode(tlsp_server_ctx->ssl_ctx,
+ SSL_MODE_ENABLE_PARTIAL_WRITE
+ | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+}
+
+/* post_jail_init - post-jail initialization */
+
+static void post_jail_init(char *unused_name, char **unused_argv)
+{
+ /* void */ ;
+}
+
+MAIL_VERSION_STAMP_DECLARE;
+
+/* main - the main program */
+
+int main(int argc, char **argv)
+{
+ static const CONFIG_INT_TABLE int_table[] = {
+ VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
+ VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
+ 0,
+ };
+ static const CONFIG_NINT_TABLE nint_table[] = {
+ VAR_TLSP_TLS_CCERT_VD, DEF_TLSP_TLS_CCERT_VD, &var_tlsp_tls_ccert_vd, 0, 0,
+ VAR_TLSP_TLS_LOGLEVEL, DEF_TLSP_TLS_LOGLEVEL, &var_tlsp_tls_loglevel, 0, 0,
+ 0,
+ };
+ static const CONFIG_TIME_TABLE time_table[] = {
+ VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
+ VAR_TLSP_WATCHDOG, DEF_TLSP_WATCHDOG, &var_tlsp_watchdog, 10, 0,
+ VAR_TLSP_TLS_SCACHTIME, DEF_TLSP_TLS_SCACHTIME, &var_tlsp_tls_scache_timeout, 0, 0,
+ 0,
+ };
+ static const CONFIG_BOOL_TABLE bool_table[] = {
+ VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
+ VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
+ VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
+ VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
+ VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid,
+ 0,
+ };
+ static const CONFIG_NBOOL_TABLE nbool_table[] = {
+ VAR_TLSP_USE_TLS, DEF_TLSP_USE_TLS, &var_tlsp_use_tls,
+ VAR_TLSP_ENFORCE_TLS, DEF_TLSP_ENFORCE_TLS, &var_tlsp_enforce_tls,
+ VAR_TLSP_TLS_ACERT, DEF_TLSP_TLS_ACERT, &var_tlsp_tls_ask_ccert,
+ VAR_TLSP_TLS_RCERT, DEF_TLSP_TLS_RCERT, &var_tlsp_tls_req_ccert,
+ VAR_TLSP_TLS_SET_SESSID, DEF_TLSP_TLS_SET_SESSID, &var_tlsp_tls_set_sessid,
+ 0,
+ };
+ static const CONFIG_STR_TABLE str_table[] = {
+ VAR_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CERT_FILE, &var_smtpd_tls_cert_file, 0, 0,
+ VAR_SMTPD_TLS_KEY_FILE, DEF_SMTPD_TLS_KEY_FILE, &var_smtpd_tls_key_file, 0, 0,
+ VAR_SMTPD_TLS_DCERT_FILE, DEF_SMTPD_TLS_DCERT_FILE, &var_smtpd_tls_dcert_file, 0, 0,
+ VAR_SMTPD_TLS_DKEY_FILE, DEF_SMTPD_TLS_DKEY_FILE, &var_smtpd_tls_dkey_file, 0, 0,
+ VAR_SMTPD_TLS_ECCERT_FILE, DEF_SMTPD_TLS_ECCERT_FILE, &var_smtpd_tls_eccert_file, 0, 0,
+ VAR_SMTPD_TLS_ECKEY_FILE, DEF_SMTPD_TLS_ECKEY_FILE, &var_smtpd_tls_eckey_file, 0, 0,
+ VAR_SMTPD_TLS_CA_FILE, DEF_SMTPD_TLS_CA_FILE, &var_smtpd_tls_CAfile, 0, 0,
+ VAR_SMTPD_TLS_CA_PATH, DEF_SMTPD_TLS_CA_PATH, &var_smtpd_tls_CApath, 0, 0,
+ VAR_SMTPD_TLS_CIPH, DEF_SMTPD_TLS_CIPH, &var_smtpd_tls_ciph, 1, 0,
+ VAR_SMTPD_TLS_MAND_CIPH, DEF_SMTPD_TLS_MAND_CIPH, &var_smtpd_tls_mand_ciph, 1, 0,
+ VAR_SMTPD_TLS_EXCL_CIPH, DEF_SMTPD_TLS_EXCL_CIPH, &var_smtpd_tls_excl_ciph, 0, 0,
+ VAR_SMTPD_TLS_MAND_EXCL, DEF_SMTPD_TLS_MAND_EXCL, &var_smtpd_tls_mand_excl, 0, 0,
+ VAR_SMTPD_TLS_PROTO, DEF_SMTPD_TLS_PROTO, &var_smtpd_tls_proto, 0, 0,
+ VAR_SMTPD_TLS_MAND_PROTO, DEF_SMTPD_TLS_MAND_PROTO, &var_smtpd_tls_mand_proto, 0, 0,
+ VAR_SMTPD_TLS_512_FILE, DEF_SMTPD_TLS_512_FILE, &var_smtpd_tls_dh512_param_file, 0, 0,
+ VAR_SMTPD_TLS_1024_FILE, DEF_SMTPD_TLS_1024_FILE, &var_smtpd_tls_dh1024_param_file, 0, 0,
+ VAR_SMTPD_TLS_EECDH, DEF_SMTPD_TLS_EECDH, &var_smtpd_tls_eecdh, 1, 0,
+ VAR_SMTPD_TLS_FPT_DGST, DEF_SMTPD_TLS_FPT_DGST, &var_smtpd_tls_fpt_dgst, 1, 0,
+ VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0,
+ VAR_TLSP_TLS_CERT_FILE, DEF_TLSP_TLS_CERT_FILE, &var_tlsp_tls_cert_file, 0, 0,
+ VAR_TLSP_TLS_KEY_FILE, DEF_TLSP_TLS_KEY_FILE, &var_tlsp_tls_key_file, 0, 0,
+ VAR_TLSP_TLS_DCERT_FILE, DEF_TLSP_TLS_DCERT_FILE, &var_tlsp_tls_dcert_file, 0, 0,
+ VAR_TLSP_TLS_DKEY_FILE, DEF_TLSP_TLS_DKEY_FILE, &var_tlsp_tls_dkey_file, 0, 0,
+ VAR_TLSP_TLS_ECCERT_FILE, DEF_TLSP_TLS_ECCERT_FILE, &var_tlsp_tls_eccert_file, 0, 0,
+ VAR_TLSP_TLS_ECKEY_FILE, DEF_TLSP_TLS_ECKEY_FILE, &var_tlsp_tls_eckey_file, 0, 0,
+ VAR_TLSP_TLS_CA_FILE, DEF_TLSP_TLS_CA_FILE, &var_tlsp_tls_CAfile, 0, 0,
+ VAR_TLSP_TLS_CA_PATH, DEF_TLSP_TLS_CA_PATH, &var_tlsp_tls_CApath, 0, 0,
+ VAR_TLSP_TLS_CIPH, DEF_TLSP_TLS_CIPH, &var_tlsp_tls_ciph, 1, 0,
+ VAR_TLSP_TLS_MAND_CIPH, DEF_TLSP_TLS_MAND_CIPH, &var_tlsp_tls_mand_ciph, 1, 0,
+ VAR_TLSP_TLS_EXCL_CIPH, DEF_TLSP_TLS_EXCL_CIPH, &var_tlsp_tls_excl_ciph, 0, 0,
+ VAR_TLSP_TLS_MAND_EXCL, DEF_TLSP_TLS_MAND_EXCL, &var_tlsp_tls_mand_excl, 0, 0,
+ VAR_TLSP_TLS_PROTO, DEF_TLSP_TLS_PROTO, &var_tlsp_tls_proto, 0, 0,
+ VAR_TLSP_TLS_MAND_PROTO, DEF_TLSP_TLS_MAND_PROTO, &var_tlsp_tls_mand_proto, 0, 0,
+ VAR_TLSP_TLS_512_FILE, DEF_TLSP_TLS_512_FILE, &var_tlsp_tls_dh512_param_file, 0, 0,
+ VAR_TLSP_TLS_1024_FILE, DEF_TLSP_TLS_1024_FILE, &var_tlsp_tls_dh1024_param_file, 0, 0,
+ VAR_TLSP_TLS_EECDH, DEF_TLSP_TLS_EECDH, &var_tlsp_tls_eecdh, 1, 0,
+ VAR_TLSP_TLS_FPT_DGST, DEF_TLSP_TLS_FPT_DGST, &var_tlsp_tls_fpt_dgst, 1, 0,
+ VAR_TLSP_TLS_LEVEL, DEF_TLSP_TLS_LEVEL, &var_tlsp_tls_level, 0, 0,
+ 0,
+ };
+
+ /*
+ * Fingerprint executables and core dumps.
+ */
+ MAIL_VERSION_STAMP_ALLOCATE;
+
+ /*
+ * Pass control to the single-threaded service skeleton.
+ */
+ event_server_main(argc, argv, tlsp_service,
+ MAIL_SERVER_INT_TABLE, int_table,
+ MAIL_SERVER_NINT_TABLE, nint_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_BOOL_TABLE, bool_table,
+ MAIL_SERVER_NBOOL_TABLE, nbool_table,
+ MAIL_SERVER_TIME_TABLE, time_table,
+ MAIL_SERVER_PRE_INIT, pre_jail_init,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ MAIL_SERVER_SLOW_EXIT, tlsp_drain,
+ MAIL_SERVER_WATCHDOG, &var_tlsp_watchdog,
+ 0);
+}
+
+#else
+
+/* tlsp_service - respond to external trigger(s), non-TLS version */
+
+static void tlsp_service(VSTREAM *stream, char *unused_service,
+ char **unused_argv)
+{
+ msg_info("TLS support is not compiled in -- exiting");
+ event_server_disconnect(stream);
+}
+
+/* main - the main program */
+
+int main(int argc, char **argv)
+{
+
+ /*
+ * We can't simply use msg_fatal() here, because the logging hasn't been
+ * initialized. The text would disappear because stderr is redirected to
+ * /dev/null.
+ *
+ * We invoke event_server_main() to complete program initialization
+ * (including logging) and then invoke the tlsp_service() routine to log
+ * the message that says why this program will not run.
+ */
+ multi_server_main(argc, argv, tlsp_service,
+ 0);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tlsproxy 3h
+/* SUMMARY
+/* tlsproxy internal interfaces
+/* SYNOPSIS
+/* #include <tlsproxy.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstream.h>
+#include <nbbio.h>
+
+ /*
+ * TLS library.
+ */
+#include <tls.h>
+
+ /*
+ * Internal interface.
+ */
+typedef struct {
+ int flags; /* see below */
+ char *service; /* argv[0] */
+ VSTREAM *plaintext_stream; /* local peer: postscreen(8), etc. */
+ NBBIO *plaintext_buf; /* plaintext buffer */
+ int ciphertext_fd; /* remote peer */
+ EVENT_NOTIFY_FN ciphertext_timer; /* kludge */
+ int timeout; /* read/write time limit */
+ char *remote_endpt; /* printable remote endpoint */
+ TLS_SESS_STATE *tls_context; /* llibtls state */
+ int ssl_last_err; /* TLS I/O state */
+ int tls_use_tls; /* legacy libtls API */
+ int tls_enforce_tls; /* legacy libtls API */
+} TLSP_STATE;
+
+#define TLSP_FLAG_DO_HANDSHAKE (1<<0)
+
+extern TLSP_STATE *tlsp_state_create(const char *, VSTREAM *);
+extern void tlsp_state_free(TLSP_STATE *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
--- /dev/null
+/*++
+/* NAME
+/* tlsp_state 3
+/* SUMMARY
+/* Postfix SMTP server
+/* SYNOPSIS
+/* #include <tlsproxy.h>
+/*
+/* TLSP_STATE *tlsp_state_create(service, plaintext_stream)
+/* const char *service;
+/* VSTREAM *plaintext_stream;
+/*
+/* void tlsp_state_free(state)
+/* TLSP_STATE *state;
+/* DESCRIPTION
+/* This module provides TLSP_STATE constructor and destructor
+/* routines.
+/*
+/* tlsp_state_create() initializes session context.
+/*
+/* tlsp_state_free() destroys session context.
+/*
+/* Arguments:
+/* .IP service
+/* The service name for the TLS library. This argument is copied.
+/* The destructor will automatically destroy the string.
+/* .IP plaintext_stream
+/* The VSTREAM between postscreen(8) and tlsproxy(8).
+/* The destructor will automatically close the stream.
+/* .PP
+/* Other structure members are set by the application. The
+/* text below describes how the TLSP_STATE destructor
+/* disposes of them.
+/* .IP plaintext_buf
+/* NBBIO for plaintext I/O.
+/* The destructor will automatically turn off read/write/timeout
+/* events and destroy the NBBIO.
+/* .IP ciphertext_fd
+/* The file handle for the remote SMTP client socket.
+/* The destructor will automatically turn off read/write events
+/* and close the file handle.
+/* .IP ciphertext_timer
+/* The destructor will automatically turn off this time event.
+/* .IP timeout
+/* Time limit for plaintext and ciphertext I/O.
+/* .IP remote_endpt
+/* Printable remote endpoint name.
+/* The destructor will automatically destroy the string.
+/* DIAGNOSTICS
+/* All errors are fatal.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <mymalloc.h>
+#include <nbbio.h>
+
+ /*
+ * Master library.
+ */
+#include <mail_server.h>
+
+ /*
+ * TLS library.
+ */
+#ifdef USE_TLS
+#define TLS_INTERNAL /* XXX */
+#include <tls.h>
+
+ /*
+ * Application-specific.
+ */
+#include <tlsproxy.h>
+
+/* tlsp_state_create - create TLS proxy state object */
+
+TLSP_STATE *tlsp_state_create(const char *service,
+ VSTREAM *plaintext_stream)
+{
+ TLSP_STATE *state = (TLSP_STATE *) mymalloc(sizeof(*state));
+
+ state->flags = TLSP_FLAG_DO_HANDSHAKE;
+ state->service = mystrdup(service);
+ state->plaintext_stream = plaintext_stream;
+ state->plaintext_buf = 0;
+ state->ciphertext_fd = -1;
+ state->ciphertext_timer = 0;
+ state->timeout = -1;
+ state->remote_endpt = 0;
+ state->tls_context = 0;
+
+ return (state);
+}
+
+/* tlsp_state_free - destroy state objects, connection and events */
+
+void tlsp_state_free(TLSP_STATE *state)
+{
+ myfree(state->service);
+ if (state->plaintext_buf) /* turns off plaintext events */
+ nbbio_free(state->plaintext_buf);
+ event_server_disconnect(state->plaintext_stream);
+ if (state->ciphertext_fd >= 0) {
+ event_disable_readwrite(state->ciphertext_fd);
+ (void) close(state->ciphertext_fd);
+ }
+ if (state->ciphertext_timer)
+ event_cancel_timer(state->ciphertext_timer, (char *) state);
+ if (state->remote_endpt) {
+ msg_info("DISCONNECT %s", state->remote_endpt);
+ myfree(state->remote_endpt);
+ }
+ if (state->tls_context)
+ tls_free_context(state->tls_context);
+ myfree((char *) state);
+}
+
+#endif
allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \
upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \
unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
- ip_match.c
+ ip_match.c nbbio.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \
upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \
unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
- ip_match.o
+ ip_match.o nbbio.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
edit_file.h dict_cache.h dict_thash.h \
- ip_match.h
+ ip_match.h nbbio.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
- stream_test.c dup2_pass_on_exec.c test_send_fd test_recv_fd
+ stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
FILES = Makefile $(SRCS) $(HDRS)
attr_scan0 host_port attr_scan_plain attr_print_plain htable \
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
- test_send_fd test_recv_fd valid_utf_8 ip_match
+ valid_utf_8 ip_match
LIB_DIR = ../../lib
INC_DIR = ../../include
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
- myaddrinfo_test format_tv_test ip_match_test
+ myaddrinfo_test format_tv_test ip_match_test name_mask_tests
root_tests:
diff ip_match.ref ip_match.tmp
rm -f ip_match.tmp
+name_mask_tests: name_mask_test0 name_mask_test1 name_mask_test2 \
+ name_mask_test3 name_mask_test4 name_mask_test5 name_mask_test6 \
+ name_mask_test7 name_mask_test8 name_mask_test9
+
+name_mask_test0: name_mask name_mask.in name_mask.ref0
+ ./name_mask IGNORE IGNORE < name_mask.in > name_mask.tmp 2>&0
+ diff name_mask.ref0 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test1: name_mask name_mask.in name_mask.ref1
+ ./name_mask NUMBER,WARN NUMBER < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref1 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test2: name_mask name_mask.in name_mask.ref2
+ ./name_mask NUMBER,RETURN NUMBER < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref2 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test3: name_mask name_mask.in name_mask.ref3
+ ./name_mask WARN NUMBER < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref3 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test4: name_mask name_mask.in name_mask.ref4
+ ./name_mask RETURN NUMBER < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref4 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test5: name_mask name_mask.in name_mask.ref5
+ ./name_mask NUMBER,WARN RETURN < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref5 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test6: name_mask name_mask.in name_mask.ref6
+ ./name_mask NUMBER,WARN WARN < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref6 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test7: name_mask name_mask.in name_mask.ref7
+ ./name_mask NUMBER,WARN IGNORE < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref7 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test8: name_mask name_mask.in name_mask.ref8
+ ./name_mask NUMBER,WARN NUMBER,COMMA < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref8 name_mask.tmp
+ rm -f name_mask.tmp
+
+name_mask_test9: name_mask name_mask.in name_mask.ref9
+ ./name_mask NUMBER,WARN NUMBER,PIPE < name_mask.in > name_mask.tmp 2>&1
+ diff name_mask.ref9 name_mask.tmp
+ rm -f name_mask.tmp
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
name_mask.o: sys_defs.h
name_mask.o: vbuf.h
name_mask.o: vstring.h
+nbbio.o: events.h
+nbbio.o: msg.h
+nbbio.o: mymalloc.h
+nbbio.o: nbbio.c
+nbbio.o: nbbio.h
+nbbio.o: sys_defs.h
netstring.o: msg.h
netstring.o: netstring.c
netstring.o: netstring.h
/*
* External interface.
*/
-typedef void (*EVENT_NOTIFY_RDWR_FN) (int, char *);
-typedef void (*EVENT_NOTIFY_TIME_FN) (int, char *);
+typedef void (*EVENT_NOTIFY_FN) (int, char *);
+
+#define EVENT_NOTIFY_TIME_FN EVENT_NOTIFY_FN /* legacy */
+#define EVENT_NOTIFY_RDWR_FN EVENT_NOTIFY_FN /* legacy */
extern time_t event_time(void);
extern void event_enable_read(int, EVENT_NOTIFY_RDWR_FN, char *);
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
/* Utility library. */
/* const NAME_MASK *table;
/* const char *names;
/*
+/* long long_name_mask(context, table, names)
+/* const char *context;
+/* const LONG_NAME_MASK *table;
+/* const char *names;
+/*
/* const char *str_name_mask(context, table, mask)
/* const char *context;
/* const NAME_MASK *table;
/* int mask;
/*
+/* const char *str_long_name_mask(context, table, mask)
+/* const char *context;
+/* const LONG_NAME_MASK *table;
+/* long mask;
+/*
/* int name_mask_opt(context, table, names, flags)
/* const char *context;
/* const NAME_MASK *table;
/* const char *names;
/* int flags;
/*
+/* long long_name_mask_opt(context, table, names, flags)
+/* const char *context;
+/* const LONG_NAME_MASK *table;
+/* const char *names;
+/* int flags;
+/*
/* int name_mask_delim_opt(context, table, names, delim, flags)
/* const char *context;
/* const NAME_MASK *table;
/* const char *delim;
/* int flags;
/*
+/* long long_name_mask_delim_opt(context, table, names, delim, flags)
+/* const char *context;
+/* const LONG_NAME_MASK *table;
+/* const char *names;
+/* const char *delim;
+/* int flags;
+/*
/* const char *str_name_mask_opt(buf, context, table, mask, flags)
/* VSTRING *buf;
/* const char *context;
/* const NAME_MASK *table;
/* int mask;
/* int flags;
+/*
+/* const char *str_long_name_mask_opt(buf, context, table, mask, flags)
+/* VSTRING *buf;
+/* const char *context;
+/* const LONG_NAME_MASK *table;
+/* long mask;
+/* int flags;
/* DESCRIPTION
/* name_mask() takes a null-terminated \fItable\fR with (name, mask)
/* values and computes the bit-wise OR of the masks that correspond
/* to the names listed in the \fInames\fR argument, separated by
-/* comma and/or whitespace characters.
+/* comma and/or whitespace characters. The "long_" version returns
+/* a "long int" bitmask, rather than an "int" bitmask.
/*
-/* str_name_mask() translates a mask into its equivalent names.
+/* str_name_mask() translates a mask into its equlvalent names.
/* The result is written to a static buffer that is overwritten
-/* upon each call.
+/* upon each call. The "long_" version converts a "long int"
+/* bitmask, rather than an "int" bitmask.
/*
/* name_mask_opt() and str_name_mask_opt() are extended versions
/* with additional fine control. name_mask_delim_opt() supports
/* A list of names that is to be converted into a bit mask.
/* .IP mask
/* A bit mask.
-/* .IP flags
-/* Bit-wise OR of zero or more of the following:
/* .IP delim
/* Delimiter characters to use instead of whitespace and commas.
+/* .IP flags
+/* Bit-wise OR of one or more of the following. Where features
+/* would have conflicting results (e.g., FATAL versus IGNORE),
+/* the feature that takes precedence is described first.
+/*
+/* When converting from string to mask, at least one of the
+/* following must be specified: NAME_MASK_FATAL, NAME_MASK_RETURN,
+/* NAME_MASK_WARN or NAME_MASK_IGNORE.
+/*
+/* When converting from mask to string, at least one of the
+/* following must be specified: NAME_MASK_NUMBER, NAME_MASK_FATAL,
+/* NAME_MASK_RETURN, NAME_MASK_WARN or NAME_MASK_IGNORE.
/* .RS
+/* .IP NAME_MASK_NUMBER
+/* When converting from string to mask, accept hexadecimal
+/* inputs starting with "0x" followed by hexadecimal digits.
+/* Each hexadecimal input may specify multiple bits. This
+/* feature is ignored for hexadecimal inputs that cannot be
+/* converted (malformed, out of range, etc.).
+/*
+/* When converting from mask to string, represent bits not
+/* defined in \fItable\fR as "0x" followed by hexadecimal
+/* digits. This conversion always succeeds.
/* .IP NAME_MASK_FATAL
-/* Require that all names listed in \fIname\fR exist in \fItable\fR,
-/* and that all bits listed in \fImask\fR exist in \fItable\fR.
-/* Terminate with a fatal run-time error if this condition is not met.
-/* This feature is enabled by default when calling name_mask()
-/* or str_name_mask().
+/* Require that all names listed in \fIname\fR exist in
+/* \fItable\fR or that they can be parsed as a hexadecimal
+/* string, and require that all bits listed in \fImask\fR exist
+/* in \fItable\fR or that they can be converted to hexadecimal
+/* string. Terminate with a fatal run-time error if this
+/* condition is not met. This feature is enabled by default
+/* when calling name_mask() or str_name_mask().
/* .IP NAME_MASK_RETURN
-/* Require that all names listed in \fIname\fR exist in \fItable\fR,
-/* and that all bits listed in \fImask\fR exist in \fItable\fR.
-/* Log a warning, and return 0 (name_mask()) or a null pointer
-/* (str_name_mask()) if this condition is not met.
-/* .IP NAME_MASK_NUMBER
-/* Require that all bits listed in \fImask\fR exist in \fItable\fR.
-/* For unrecognized bits, print the numerical hexadecimal form.
+/* Require that all names listed in \fIname\fR exist in
+/* \fItable\fR or that they can be parsed as a hexadecimal
+/* string, and require that all bits listed in \fImask\fR exist
+/* in \fItable\fR or that they can be converted to hexadecimal
+/* string. Log a warning, and return 0 (name_mask()) or a
+/* null pointer (str_name_mask()) if this condition is not
+/* met. This feature is not enabled by default when calling
+/* name_mask() or str_name_mask().
+/* .IP NAME_MASK_WARN
+/* Require that all names listed in \fIname\fR exist in
+/* \fItable\fR or that they can be parsed as a hexadecimal
+/* string, and require that all bits listed in \fImask\fR exist
+/* in \fItable\fR or that they can be converted to hexadecimal
+/* string. Log a warning if this condition is not met, continue
+/* processing, and return all valid bits or names. This feature
+/* is not enabled by default when calling name_mask() or
+/* str_name_mask().
+/* .IP NAME_MASK_IGNORE
+/* Silently ignore names listed in \fIname\fR that don't exist
+/* in \fItable\fR and that can't be parsed as a hexadecimal
+/* string, and silently ignore bits listed in \fImask\fR that
+/* don't exist in \fItable\fR and that can't be converted to
+/* hexadecimal string.
/* .IP NAME_MASK_ANY_CASE
/* Enable case-insensitive matching.
/* This feature is not enabled by default when calling name_mask();
#include <sys_defs.h>
#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#include <name_mask.h>
#include <vstring.h>
+static int hex_to_ulong(char *, unsigned long, unsigned long *);
+
#define STR(x) vstring_str(x)
/* name_mask_delim_opt - compute mask corresponding to list of names */
const NAME_MASK *np;
char *name;
int (*lookup) (const char *, const char *);
+ unsigned long ulval;
+
+ if ((flags & NAME_MASK_REQUIRED) == 0)
+ msg_panic("%s: missing NAME_MASK_FATAL/RETURN/WARN/IGNORE flag",
+ myname);
if (flags & NAME_MASK_ANY_CASE)
lookup = strcasecmp;
while ((name = mystrtok(&bp, delim)) != 0) {
for (np = table; /* void */ ; np++) {
if (np->name == 0) {
- if (flags & NAME_MASK_FATAL)
+ if ((flags & NAME_MASK_NUMBER)
+ && hex_to_ulong(name, ~0U, &ulval)) {
+ result |= (unsigned int) ulval;
+ } else if (flags & NAME_MASK_FATAL) {
msg_fatal("unknown %s value \"%s\" in \"%s\"",
context, name, names);
- if (flags & NAME_MASK_RETURN) {
+ } else if (flags & NAME_MASK_RETURN) {
msg_warn("unknown %s value \"%s\" in \"%s\"",
context, name, names);
return (0);
+ } else if (flags & NAME_MASK_WARN) {
+ msg_warn("unknown %s value \"%s\" in \"%s\"",
+ context, name, names);
}
break;
}
int delim = (flags & NAME_MASK_COMMA ? ',' :
(flags & NAME_MASK_PIPE ? '|' : ' '));
+ if ((flags & STR_NAME_MASK_REQUIRED) == 0)
+ msg_panic("%s: missing NAME_MASK_NUMBER/FATAL/RETURN/WARN/IGNORE flag",
+ myname);
+
if (buf == 0) {
if (my_buf == 0)
my_buf = vstring_alloc(1);
for (np = table; mask != 0; np++) {
if (np->name == 0) {
- if (flags & NAME_MASK_FATAL) {
+ if (flags & NAME_MASK_NUMBER) {
+ vstring_sprintf_append(buf, "0x%x%c", mask, delim);
+ } else if (flags & NAME_MASK_FATAL) {
msg_fatal("%s: unknown %s bit in mask: 0x%x",
myname, context, mask);
} else if (flags & NAME_MASK_RETURN) {
msg_warn("%s: unknown %s bit in mask: 0x%x",
myname, context, mask);
return (0);
- } else if (flags & NAME_MASK_NUMBER) {
- vstring_sprintf_append(buf, "0x%x%c", mask, delim);
+ } else if (flags & NAME_MASK_WARN) {
+ msg_warn("%s: unknown %s bit in mask: 0x%x",
+ myname, context, mask);
}
break;
}
return (STR(buf));
}
+/* long_name_mask_delim_opt - compute mask corresponding to list of names */
+
+long long_name_mask_delim_opt(const char *context,
+ const LONG_NAME_MASK * table,
+ const char *names, const char *delim,
+ int flags)
+{
+ const char *myname = "name_mask";
+ char *saved_names = mystrdup(names);
+ char *bp = saved_names;
+ long result = 0;
+ const LONG_NAME_MASK *np;
+ char *name;
+ int (*lookup) (const char *, const char *);
+ unsigned long ulval;
+
+ if ((flags & NAME_MASK_REQUIRED) == 0)
+ msg_panic("%s: missing NAME_MASK_FATAL/RETURN/WARN/IGNORE flag",
+ myname);
+
+ if (flags & NAME_MASK_ANY_CASE)
+ lookup = strcasecmp;
+ else
+ lookup = strcmp;
+
+ /*
+ * Break up the names string, and look up each component in the table. If
+ * the name is found, merge its mask with the result.
+ */
+ while ((name = mystrtok(&bp, delim)) != 0) {
+ for (np = table; /* void */ ; np++) {
+ if (np->name == 0) {
+ if ((flags & NAME_MASK_NUMBER)
+ && hex_to_ulong(name, ~0UL, &ulval)) {
+ result |= ulval;
+ } else if (flags & NAME_MASK_FATAL) {
+ msg_fatal("unknown %s value \"%s\" in \"%s\"",
+ context, name, names);
+ } else if (flags & NAME_MASK_RETURN) {
+ msg_warn("unknown %s value \"%s\" in \"%s\"",
+ context, name, names);
+ return (0);
+ } else if (flags & NAME_MASK_WARN) {
+ msg_warn("unknown %s value \"%s\" in \"%s\"",
+ context, name, names);
+ }
+ break;
+ }
+ if (lookup(name, np->name) == 0) {
+ if (msg_verbose)
+ msg_info("%s: %s", myname, name);
+ result |= np->mask;
+ break;
+ }
+ }
+ }
+
+ myfree(saved_names);
+ return (result);
+}
+
+/* str_long_name_mask_opt - mask to string */
+
+const char *str_long_name_mask_opt(VSTRING *buf, const char *context,
+ const LONG_NAME_MASK * table,
+ long mask, int flags)
+{
+ const char *myname = "name_mask";
+ int len;
+ static VSTRING *my_buf = 0;
+ int delim = (flags & NAME_MASK_COMMA ? ',' :
+ (flags & NAME_MASK_PIPE ? '|' : ' '));
+ const LONG_NAME_MASK *np;
+
+ if ((flags & STR_NAME_MASK_REQUIRED) == 0)
+ msg_panic("%s: missing NAME_MASK_NUMBER/FATAL/RETURN/WARN/IGNORE flag",
+ myname);
+
+ if (buf == 0) {
+ if (my_buf == 0)
+ my_buf = vstring_alloc(1);
+ buf = my_buf;
+ }
+ VSTRING_RESET(buf);
+
+ for (np = table; mask != 0; np++) {
+ if (np->name == 0) {
+ if (flags & NAME_MASK_NUMBER) {
+ vstring_sprintf_append(buf, "0x%lx%c", mask, delim);
+ } else if (flags & NAME_MASK_FATAL) {
+ msg_fatal("%s: unknown %s bit in mask: 0x%lx",
+ myname, context, mask);
+ } else if (flags & NAME_MASK_RETURN) {
+ msg_warn("%s: unknown %s bit in mask: 0x%lx",
+ myname, context, mask);
+ return (0);
+ } else if (flags & NAME_MASK_WARN) {
+ msg_warn("%s: unknown %s bit in mask: 0x%lx",
+ myname, context, mask);
+ }
+ break;
+ }
+ if (mask & np->mask) {
+ mask &= ~np->mask;
+ vstring_sprintf_append(buf, "%s%c", np->name, delim);
+ }
+ }
+ if ((len = VSTRING_LEN(buf)) > 0)
+ vstring_truncate(buf, len - 1);
+ VSTRING_TERMINATE(buf);
+
+ return (STR(buf));
+}
+
+/* hex_to_ulong - 0x... to unsigned long or smaller */
+
+static int hex_to_ulong(char *value, unsigned long mask, unsigned long *ulp)
+{
+ unsigned long result;
+ char *cp;
+
+ if (strncasecmp(value, "0x", 2) != 0)
+ return (0);
+
+ /*
+ * Check for valid hex number. Since the value starts with 0x, strtoul()
+ * will not allow a negative sign before the first nibble. So we don't
+ * need to worry about explicit +/- signs.
+ */
+ errno = 0;
+ result = strtoul(value, &cp, 16);
+ if (*cp != '\0' || errno == ERANGE)
+ return (0);
+
+ if (ulp)
+ *ulp = (result & mask);
+ return (*ulp == result);
+}
+
#ifdef TEST
/*
*/
#include <stdlib.h>
#include <vstream.h>
+#include <vstring_vstream.h>
int main(int argc, char **argv)
{
- static const NAME_MASK table[] = {
+ static const NAME_MASK demo_table[] = {
"zero", 1 << 0,
"one", 1 << 1,
"two", 1 << 2,
"three", 1 << 3,
0, 0,
};
- int mask;
- VSTRING *buf = vstring_alloc(1);
+ static const NAME_MASK feature_table[] = {
+ "DEFAULT", NAME_MASK_DEFAULT,
+ "FATAL", NAME_MASK_FATAL,
+ "ANY_CASE", NAME_MASK_ANY_CASE,
+ "RETURN", NAME_MASK_RETURN,
+ "COMMA", NAME_MASK_COMMA,
+ "PIPE", NAME_MASK_PIPE,
+ "NUMBER", NAME_MASK_NUMBER,
+ "WARN", NAME_MASK_WARN,
+ "IGNORE", NAME_MASK_IGNORE,
+ 0,
+ };
+ int in_feature_mask;
+ int out_feature_mask;
+ int demo_mask;
+ const char *demo_str;
+ VSTRING *out_buf = vstring_alloc(1);
+ VSTRING *in_buf = vstring_alloc(1);
- while (--argc && *++argv) {
- mask = name_mask("test", table, *argv);
+ if (argc != 3)
+ msg_fatal("usage: %s in-feature-mask out-feature-mask", argv[0]);
+ in_feature_mask = name_mask(argv[1], feature_table, argv[1]);
+ out_feature_mask = name_mask(argv[2], feature_table, argv[2]);
+ while (vstring_get_nonl(in_buf, VSTREAM_IN) != VSTREAM_EOF) {
+ demo_mask = name_mask_opt("name", demo_table,
+ STR(in_buf), in_feature_mask);
+ demo_str = str_name_mask_opt(out_buf, "mask", demo_table,
+ demo_mask, out_feature_mask);
vstream_printf("%s -> 0x%x -> %s\n",
- *argv, mask, str_name_mask("mask_test", table, mask));
+ STR(in_buf), demo_mask,
+ demo_str ? demo_str : "(null)");
vstream_fflush(VSTREAM_OUT);
}
- vstring_free(buf);
+ vstring_free(in_buf);
+ vstring_free(out_buf);
exit(0);
}
#define NAME_MASK_COMMA (1<<3)
#define NAME_MASK_PIPE (1<<4)
#define NAME_MASK_NUMBER (1<<5)
+#define NAME_MASK_WARN (1<<6)
+#define NAME_MASK_IGNORE (1<<7)
+
+#define NAME_MASK_REQUIRED \
+ (NAME_MASK_FATAL | NAME_MASK_RETURN | NAME_MASK_WARN | NAME_MASK_IGNORE)
+#define STR_NAME_MASK_REQUIRED (NAME_MASK_REQUIRED | NAME_MASK_NUMBER)
#define NAME_MASK_MATCH_REQ NAME_MASK_FATAL
extern int name_mask_delim_opt(const char *, const NAME_MASK *, const char *, const char *, int);
extern const char *str_name_mask_opt(VSTRING *, const char *, const NAME_MASK *, int, int);
+ /*
+ * "long" API
+ */
+typedef struct {
+ const char *name;
+ long mask;
+} LONG_NAME_MASK;
+
+#define long_name_mask_opt(tag, table, str, flags) \
+ long_name_mask_delim_opt((tag), (table), (str), NAME_MASK_DEFAULT_DELIM, (flags))
+#define long_name_mask(tag, table, str) \
+ long_name_mask_opt((tag), (table), (str), NAME_MASK_DEFAULT)
+#define str_long_name_mask(tag, table, mask) \
+ str_long_name_mask_opt(((VSTRING *) 0), (tag), (table), (mask), NAME_MASK_DEFAULT)
+
+extern long long_name_mask_delim_opt(const char *, const LONG_NAME_MASK *, const char *, const char *, int);
+extern const char *str_long_name_mask_opt(VSTRING *, const char *, const LONG_NAME_MASK *, long, int);
+
/* LICENSE
/* .ad
/* .fi
--- /dev/null
+zero
+one
+two
+three
+four
+zero one two three four
+0xff
+0xffffffff
+0xffffffffffffffff
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+four -> 0x0 ->
+zero one two three four -> 0xf -> zero one two three
+0xff -> 0x0 ->
+0xffffffff -> 0x0 ->
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero one two three
+0xff -> 0xff -> zero one two three 0xf0
+0xffffffff -> 0xffffffff -> zero one two three 0xfffffff0
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0x0 ->
+0xff -> 0xff -> zero one two three 0xf0
+0xffffffff -> 0xffffffff -> zero one two three 0xfffffff0
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero one two three
+unknown: warning: unknown name value "0xff" in "0xff"
+0xff -> 0x0 ->
+unknown: warning: unknown name value "0xffffffff" in "0xffffffff"
+0xffffffff -> 0x0 ->
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0x0 ->
+unknown: warning: unknown name value "0xff" in "0xff"
+0xff -> 0x0 ->
+unknown: warning: unknown name value "0xffffffff" in "0xffffffff"
+0xffffffff -> 0x0 ->
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero one two three
+unknown: warning: name_mask: unknown mask bit in mask: 0xf0
+0xff -> 0xff -> (null)
+unknown: warning: name_mask: unknown mask bit in mask: 0xfffffff0
+0xffffffff -> 0xffffffff -> (null)
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero one two three
+unknown: warning: name_mask: unknown mask bit in mask: 0xf0
+0xff -> 0xff -> zero one two three
+unknown: warning: name_mask: unknown mask bit in mask: 0xfffffff0
+0xffffffff -> 0xffffffff -> zero one two three
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero one two three
+0xff -> 0xff -> zero one two three
+0xffffffff -> 0xffffffff -> zero one two three
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero,one,two,three
+0xff -> 0xff -> zero,one,two,three,0xf0
+0xffffffff -> 0xffffffff -> zero,one,two,three,0xfffffff0
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+zero -> 0x1 -> zero
+one -> 0x2 -> one
+two -> 0x4 -> two
+three -> 0x8 -> three
+unknown: warning: unknown name value "four" in "four"
+four -> 0x0 ->
+unknown: warning: unknown name value "four" in "zero one two three four"
+zero one two three four -> 0xf -> zero|one|two|three
+0xff -> 0xff -> zero|one|two|three|0xf0
+0xffffffff -> 0xffffffff -> zero|one|two|three|0xfffffff0
+unknown: warning: unknown name value "0xffffffffffffffff" in "0xffffffffffffffff"
+0xffffffffffffffff -> 0x0 ->
--- /dev/null
+/*++
+/* NAME
+/* nbbio 3
+/* SUMMARY
+/* non-blocking buffered I/O
+/* SYNOPSIS
+/* #include <nbbio.h>
+/*
+/* NBBIO *nbbio_create(fd, bufsize, label, action, context)
+/* int fd;
+/* ssize_t bufsize;
+/* const char *label;
+/* void (*action)(int event, char *context);
+/* char *context;
+/*
+/* void nbbio_free(np)
+/* NBBIO *np;
+/*
+/* void nbbio_enable_read(np, timeout)
+/* NBBIO *np;
+/* int timeout;
+/*
+/* void nbbio_enable_write(np, timeout)
+/* NBBIO *np;
+/* int timeout;
+/*
+/* void nbbio_disable_readwrite(np)
+/* NBBIO *np;
+/*
+/* void nbbio_slumber(np, timeout)
+/* NBBIO *np;
+/* int timeout;
+/*
+/* int NBBIO_ACTIVE_FLAGS(np)
+/* NBBIO *np;
+/*
+/* int NBBIO_ERROR_FLAGS(np)
+/* NBBIO *np;
+/*
+/* const ssize_t NBBIO_BUFSIZE(np)
+/* NBBIO *np;
+/*
+/* ssize_t NBBIO_READ_PEND(np)
+/* NBBIO *np;
+/*
+/* char *NBBIO_READ_BUF(np)
+/* NBBIO *np;
+/*
+/* const ssize_t NBBIO_WRITE_PEND(np)
+/* NBBIO *np;
+/*
+/* char *NBBIO_WRITE_BUF(np)
+/* NBBIO *np;
+/* DESCRIPTION
+/* This module implements low-level support for event-driven
+/* I/O on a full-duplex stream. Read/write events are handled
+/* by pseudothreads that run under control by the events(5)
+/* module. After each I/O operation, the application is
+/* notified via a call-back routine.
+/*
+/* It is up to the call-back routine to turn on/off read/write
+/* events as appropriate. It is an error to leave read events
+/* enabled for a buffer that is full, or to leave write events
+/* enabled for a buffer that is empty.
+/*
+/* nbbio_create() creates a pair of buffers of the named size
+/* for the named stream. The label specifies the purpose of
+/* the stream, and is used for diagnostic messages. The
+/* nbbio(3) event handler invokes the application call-back
+/* routine with the current event type (EVENT_READ etc.) and
+/* with the application-specified context.
+/*
+/* nbbio_free() terminates any pseudothreads associated with
+/* the named buffer pair, closes the stream, and destroys the
+/* buffer pair.
+/*
+/* nbbio_enable_read() enables a read pseudothread for the
+/* named buffer pair. It is an error to enable a read
+/* pseudothread while the read buffer is full, or while a read
+/* or write pseudothread is still enabled.
+/*
+/* nbbio_enable_write() enables a write pseudothread for the
+/* named buffer pair. It is an error to enable a write
+/* pseudothread while the write buffer is empty, or while a
+/* read or write pseudothread is still enabled.
+/*
+/* nbbio_disable_readwrite() disables any read/write pseudothreads
+/* for the named buffer pair, including timeouts. To ensure
+/* buffer liveness, use nbbio_slumber() instead of
+/* nbbio_disable_readwrite(). It is no error to call this
+/* function while no read/write pseudothread is enabled.
+/*
+/* nbbio_slumber() disables any read/write pseudothreads for
+/* the named buffer pair, but keeps the timer active to ensure
+/* buffer liveness. It is no error to call this function while
+/* no read/write pseudothread is enabled.
+/*
+/* NBBIO_ERROR_FLAGS() returns the error flags for the named buffer
+/* pair: zero or more of NBBIO_FLAG_EOF (read EOF), NBBIO_FLAG_ERROR
+/* (read/write error) or NBBIO_FLAG_TIMEOUT (time limit
+/* exceeded).
+/*
+/* NBBIO_ACTIVE_FLAGS() returns the pseudothread flags for the
+/* named buffer pair: NBBIO_FLAG_READ (read pseudothread is
+/* active), NBBIO_FLAG_WRITE (write pseudothread is active),
+/* or zero (no pseudothread is active).
+/*
+/* NBBIO_WRITE_PEND() and NBBIO_WRITE_BUF() evaluate to the
+/* number of to-be-written bytes and the write buffer for the
+/* named buffer pair. NBBIO_WRITE_PEND() must be updated by
+/* the application code that fills the write buffer; no more
+/* than NBBIO_BUFSIZE() bytes may be filled.
+/*
+/* NBBIO_READ_PEND() and NBBIO_READ_BUF() evaluate to the
+/* number of unread bytes and the read buffer for the named
+/* buffer pair. NBBIO_READ_PEND() and NBBIO_READ_BUF() must
+/* be updated by the application code that drains the read
+/* buffer.
+/* SEE ALSO
+/* events(3) event manager
+/* DIAGNOSTICS
+/* Panic: interface violation.
+/*
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h> /* memmove() */
+
+ /*
+ * Utility library.
+ */
+#include <mymalloc.h>
+#include <msg.h>
+#include <events.h>
+#include <nbbio.h>
+
+/* nbbio_event - non-blocking event handler */
+
+static void nbbio_event(int event, char *context)
+{
+ const char *myname = "nbbio_event";
+ NBBIO *np = (NBBIO *) context;
+ ssize_t count;
+
+ switch (event) {
+
+ /*
+ * Read data into the read buffer. Leave it up to the application to
+ * drain the buffer until it is empty.
+ */
+ case EVENT_READ:
+ if (np->read_pend == np->bufsize)
+ msg_panic("%s: socket fd=%d: read buffer is full",
+ myname, np->fd);
+ if (np->read_pend < 0 || np->read_pend > np->bufsize)
+ msg_panic("%s: socket fd=%d: bad pending read count %ld",
+ myname, np->fd, (long) np->read_pend);
+ count = read(np->fd, np->read_buf + np->read_pend,
+ np->bufsize - np->read_pend);
+ if (count > 0) {
+ np->read_pend += count;
+ if (msg_verbose)
+ msg_info("%s: read %ld on %s fd=%d",
+ myname, (long) count, np->label, np->fd);
+ } else if (count == 0) {
+ np->flags |= NBBIO_FLAG_EOF;
+ if (msg_verbose)
+ msg_info("%s: read EOF on %s fd=%d",
+ myname, np->label, np->fd);
+ } else {
+ if (errno == EAGAIN)
+ msg_warn("%s: read() returns EAGAIN on readable descriptor",
+ myname);
+ np->flags |= NBBIO_FLAG_ERROR;
+ if (msg_verbose)
+ msg_info("%s: read %s fd=%d: %m", myname, np->label, np->fd);
+ }
+ break;
+
+ /*
+ * Drain data from the output buffer. Notify the application
+ * whenever some bytes are written.
+ *
+ * XXX Enforce a total time limit to ensure liveness when a hostile
+ * receiver sets a very small TCP window size.
+ */
+ case EVENT_WRITE:
+ if (np->write_pend == 0)
+ msg_panic("%s: socket fd=%d: empty write buffer", myname, np->fd);
+ if (np->write_pend < 0 || np->write_pend > np->bufsize)
+ msg_panic("%s: socket fd=%d: bad pending write count %ld",
+ myname, np->fd, (long) np->write_pend);
+ count = write(np->fd, np->write_buf, np->write_pend);
+ if (count > 0) {
+ np->write_pend -= count;
+ if (np->write_pend > 0)
+ memmove(np->write_buf, np->write_buf + count, np->write_pend);
+ } else {
+ if (errno == EAGAIN)
+ msg_warn("%s: write() returns EAGAIN on writable descriptor",
+ myname);
+ np->flags |= NBBIO_FLAG_ERROR;
+ if (msg_verbose)
+ msg_info("%s: write %s fd=%d: %m", myname, np->label, np->fd);
+ }
+ break;
+
+ /*
+ * Something bad happened.
+ */
+ case EVENT_XCPT:
+ np->flags |= NBBIO_FLAG_ERROR;
+ if (msg_verbose)
+ msg_info("%s: error on %s fd=%d: %m", myname, np->label, np->fd);
+ break;
+
+ /*
+ * Something good didn't happen.
+ */
+ case EVENT_TIME:
+ np->flags |= NBBIO_FLAG_TIMEOUT;
+ if (msg_verbose)
+ msg_info("%s: %s timeout on %s fd=%d",
+ myname, NBBIO_OP_NAME(np), np->label, np->fd);
+ break;
+
+ default:
+ msg_panic("%s: unknown event %d", myname, event);
+ }
+
+ /*
+ * Application notification. The application will check for any error
+ * flags, copy application data from or to our buffer pair, and decide
+ * what I/O happens next.
+ */
+ np->action(event, np->context);
+}
+
+/* nbbio_enable_read - enable reading from socket into buffer */
+
+void nbbio_enable_read(NBBIO *np, int timeout)
+{
+ const char *myname = "nbbio_enable_read";
+
+ /*
+ * Sanity checks.
+ */
+ if (np->flags & NBBIO_MASK_ACTIVE)
+ msg_panic("%s: socket fd=%d is enabled for %s",
+ myname, np->fd, NBBIO_OP_NAME(np));
+ if (timeout <= 0)
+ msg_panic("%s: socket fd=%d: bad timeout %d",
+ myname, np->fd, timeout);
+ if (np->read_pend >= np->bufsize)
+ msg_panic("%s: socket fd=%d: read buffer is full",
+ myname, np->fd);
+
+ /*
+ * Enable events.
+ */
+ event_enable_read(np->fd, nbbio_event, (char *) np);
+ event_request_timer(nbbio_event, (char *) np, timeout);
+ np->flags |= NBBIO_FLAG_READ;
+}
+
+/* nbbio_enable_write - enable writing from buffer to socket */
+
+void nbbio_enable_write(NBBIO *np, int timeout)
+{
+ const char *myname = "nbbio_enable_write";
+
+ /*
+ * Sanity checks.
+ */
+ if (np->flags & NBBIO_MASK_ACTIVE)
+ msg_panic("%s: socket fd=%d is enabled for %s",
+ myname, np->fd, NBBIO_OP_NAME(np));
+ if (timeout <= 0)
+ msg_panic("%s: socket fd=%d bad timeout %d",
+ myname, np->fd, timeout);
+ if (np->write_pend <= 0)
+ msg_panic("%s: socket fd=%d: empty write buffer",
+ myname, np->fd);
+
+ /*
+ * Enable events.
+ */
+ event_enable_write(np->fd, nbbio_event, (char *) np);
+ event_request_timer(nbbio_event, (char *) np, timeout);
+ np->flags |= NBBIO_FLAG_WRITE;
+}
+
+/* nbbio_disable_readwrite - disable read/write/timer events */
+
+void nbbio_disable_readwrite(NBBIO *np)
+{
+ np->flags &= ~NBBIO_MASK_ACTIVE;
+ event_disable_readwrite(np->fd);
+ event_cancel_timer(nbbio_event, (char *) np);
+}
+
+/* nbbio_slumber - disable read/write events, keep timer */
+
+void nbbio_slumber(NBBIO *np, int timeout)
+{
+ np->flags &= ~NBBIO_MASK_ACTIVE;
+ event_disable_readwrite(np->fd);
+ event_request_timer(nbbio_event, (char *) np, timeout);
+}
+
+/* nbbio_create - create socket buffer */
+
+NBBIO *nbbio_create(int fd, ssize_t bufsize, const char *label,
+ NBBIO_ACTION action, char *context)
+{
+ NBBIO *np;
+
+ /*
+ * Sanity checks.
+ */
+ if (fd < 0)
+ msg_panic("nbbio_create: bad file descriptor: %d", fd);
+ if (bufsize <= 0)
+ msg_panic("nbbio_create: bad buffer size: %ld", (long) bufsize);
+
+ /*
+ * Create a new buffer pair.
+ */
+ np = (NBBIO *) mymalloc(sizeof(*np));
+ np->fd = fd;
+ np->bufsize = bufsize;
+ np->label = mystrdup(label);
+ np->action = action;
+ np->context = context;
+ np->flags = 0;
+
+ np->read_buf = mymalloc(bufsize);
+ np->read_pend = 0;
+
+ np->write_buf = mymalloc(bufsize);
+ np->write_pend = 0;
+
+ return (np);
+}
+
+/* nbbio_free - destroy socket buffer */
+
+void nbbio_free(NBBIO *np)
+{
+ nbbio_disable_readwrite(np);
+ (void) close(np->fd);
+ myfree(np->label);
+ myfree(np->read_buf);
+ myfree(np->write_buf);
+ myfree((char *) np);
+}
--- /dev/null
+#ifndef _NBBIO_H_INCLUDED_
+#define _NBBIO_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbbio 3h
+/* SUMMARY
+/* non-blocking buffered I/O
+/* SYNOPSIS
+/* #include "nbbio.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <events.h> /* Needed for EVENT_READ etc. */
+
+ /*
+ * External interface. All structure members are private.
+ */
+typedef void (*NBBIO_ACTION) (int, char *);
+
+typedef struct {
+ int fd; /* socket file descriptor */
+ ssize_t bufsize; /* read/write buffer size */
+ char *label; /* diagnostics */
+ NBBIO_ACTION action; /* call-back routine */
+ char *context; /* call-back context */
+ int flags; /* buffer-pair status */
+
+ char *read_buf; /* start of buffer */
+ ssize_t read_pend; /* nr of unread bytes */
+
+ char *write_buf; /* start of buffer */
+ ssize_t write_pend; /* nr of unwritten bytes */
+} NBBIO;
+
+#define NBBIO_FLAG_READ (1<<0)
+#define NBBIO_FLAG_WRITE (1<<1)
+#define NBBIO_FLAG_EOF (1<<2)
+#define NBBIO_FLAG_ERROR (1<<3)
+#define NBBIO_FLAG_TIMEOUT (1<<4)
+
+#define NBBIO_OP_NAME(np) \
+ (((np)->flags & NBBIO_FLAG_READ) ? "read" : \
+ ((np)->flags & NBBIO_FLAG_WRITE) ? "write" : \
+ "unknown")
+
+#define NBBIO_MASK_ACTIVE \
+ (NBBIO_FLAG_READ | NBBIO_FLAG_WRITE)
+
+#define NBBIO_MASK_ERROR \
+ (NBBIO_FLAG_EOF | NBBIO_FLAG_ERROR | NBBIO_FLAG_TIMEOUT)
+
+#define NBBIO_BUFSIZE(np) (((np)->bufsize) + 0) /* Read-only */
+
+#define NBBIO_READ_PEND(np) ((np)->read_pend)
+#define NBBIO_READ_BUF(np) ((np)->read_buf + 0) /* Read-only */
+
+#define NBBIO_WRITE_PEND(np) ((np)->write_pend)
+#define NBBIO_WRITE_BUF(np) ((np)->write_buf + 0) /* Read-only */
+
+#define NBBIO_ACTIVE_FLAGS(np) ((np)->flags & NBBIO_MASK_ACTIVE)
+#define NBBIO_ERROR_FLAGS(np) ((np)->flags & NBBIO_MASK_ERROR)
+
+extern NBBIO *nbbio_create(int, ssize_t, const char *, NBBIO_ACTION, char *);
+extern void nbbio_free(NBBIO *);
+extern void nbbio_enable_read(NBBIO *, int);
+extern void nbbio_enable_write(NBBIO *, int);
+extern void nbbio_disable_readwrite(NBBIO *);
+extern void nbbio_slumber(NBBIO *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
/* int vstream_fileno(stream)
/* VSTREAM *stream;
/*
+/* const ssize_t vstream_req_bufsize(stream)
+/* VSTREAM *stream;
+/*
/* void *vstream_context(stream)
/* VSTREAM *stream;
/*
/* ignored. Requests to change a fixed-size buffer (stdin,
/* stdout, stderr) are not allowed.
/*
+/* NOTE: the VSTREAM_CTL_BUFSIZE request specifies intent, not
+/* reality. Actual buffer sizes are not updated immediately.
+/* Instead, an existing write buffer will be resized when it
+/* is full, and an existing read buffer will be resized when
+/* the buffer is filled.
+/*
/* NOTE: the VSTREAM_CTL_BUFSIZE argument type is ssize_t, not
/* int. Use an explicit cast to avoid problems on LP64
/* environments and other environments where ssize_t is larger
/* a buffered stream. With streams that have separate read/write
/* file descriptors, the result is the current descriptor.
/*
+/* vstream_req_bufsize() returns the requested buffer size for
+/* the named stream (default: VSTREAM_BUFSIZE). The result
+/* value reflects intent, not reality: actual buffer sizes are
+/* not updated immediately when the requested buffer size is
+/* specified with vstream_control(). Instead, an existing
+/* write buffer will be resized when it is full, and an existing
+/* read buffer will be resized when the buffer is filled.
+/*
/* vstream_context() returns the application context that is passed on to
/* the application-specified read/write routines.
/*
* Initialization of the three pre-defined streams. Pre-allocate a static
* I/O buffer for the standard error stream, so that the error handler can
* produce a diagnostic even when memory allocation fails.
- *
- * XXX We don't (yet) statically initialize the req_bufsize field: it is the
- * last VSTREAM member so we don't break Postfix 2.4 binary compatibility,
- * and Wietse doesn't know how to specify an initializer for the jmp_buf
- * VSTREAM member (which can be a struct or an array) without collateral
- * damage to the source code. We can fix the initialization later in the
- * Postfix 2.5 development cycle.
*/
static unsigned char vstream_fstd_buf[VSTREAM_BUFSIZE];
0, /* flags */
0, 0, 0, 0, /* buffer */
vstream_buf_get_ready, vstream_buf_put_ready, vstream_buf_space,
- }, STDIN_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,},
+ }, STDIN_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,
+ VSTREAM_BUFSIZE,},
{{
0, /* flags */
0, 0, 0, 0, /* buffer */
vstream_buf_get_ready, vstream_buf_put_ready, vstream_buf_space,
- }, STDOUT_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,},
+ }, STDOUT_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,
+ VSTREAM_BUFSIZE,},
{{
VBUF_FLAG_FIXED | VSTREAM_FLAG_WRITE,
vstream_fstd_buf, VSTREAM_BUFSIZE, VSTREAM_BUFSIZE, vstream_fstd_buf,
vstream_buf_get_ready, vstream_buf_put_ready, vstream_buf_space,
- }, STDERR_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,},
+ }, STDERR_FILENO, (VSTREAM_FN) timed_read, (VSTREAM_FN) timed_write,
+ VSTREAM_BUFSIZE,},
};
#define VSTREAM_STATIC(v) ((v) >= VSTREAM_IN && (v) <= VSTREAM_ERR)
* allocation gives the application a chance to override the default
* buffering policy.
*/
- if (stream->req_bufsize == 0)
- stream->req_bufsize = VSTREAM_BUFSIZE;
if (bp->len < stream->req_bufsize)
vstream_buf_alloc(bp, stream->req_bufsize);
* new buffer; obviously there is no data to be flushed yet. Otherwise,
* flush the buffer.
*/
- if (stream->req_bufsize == 0)
- stream->req_bufsize = VSTREAM_BUFSIZE; /* Postfix 2.4 binary compat. */
if (bp->len < stream->req_bufsize) {
vstream_buf_alloc(bp, stream->req_bufsize);
} else if (bp->cnt <= 0) {
#define VSTREAM_ROUNDUP(count, base) VSTREAM_TRUNCATE(count + base - 1, base)
if (want > bp->cnt) {
- if (stream->req_bufsize == 0)
- stream->req_bufsize = VSTREAM_BUFSIZE; /* 2.4 binary compat. */
if ((used = bp->len - bp->cnt) > stream->req_bufsize)
if (vstream_fflush_some(stream, VSTREAM_TRUNCATE(used, stream->req_bufsize)))
return (VSTREAM_EOF);
if (req_bufsize < 0)
msg_panic("VSTREAM_CTL_BUFSIZE with negative size: %ld",
(long) req_bufsize);
- if (stream->req_bufsize == 0)
- stream->req_bufsize = VSTREAM_BUFSIZE; /* 2.4 binary compat. */
if (stream != VSTREAM_ERR
&& req_bufsize > stream->req_bufsize)
stream->req_bufsize = req_bufsize;
int fd; /* file handle, no 256 limit */
VSTREAM_FN read_fn; /* buffer fill action */
VSTREAM_FN write_fn; /* buffer fill action */
+ ssize_t req_bufsize; /* requested read/write buffer size */
void *context; /* application context */
off_t offset; /* cached seek info */
char *path; /* give it at least try */
int timeout; /* read/write timout */
VSTREAM_JMP_BUF *jbuf; /* exception handling */
struct timeval iotime; /* time of last fill/flush */
- /* At bottom for Postfix 2.4 binary compatibility. */
- ssize_t req_bufsize; /* write buffer size */
} VSTREAM;
extern VSTREAM vstream_fstd[]; /* pre-defined streams */
#define VSTREAM_GETCHAR() VSTREAM_GETC(VSTREAM_IN)
#define vstream_fileno(vp) ((vp)->fd)
+#define vstream_req_bufsize(vp) ((const ssize_t) ((vp)->req_bufsize))
#define vstream_context(vp) ((vp)->context)
#define vstream_ferror(vp) vbuf_error(&(vp)->buf)
#define vstream_feof(vp) vbuf_eof(&(vp)->buf)
sec_props =
name_mask_delim_opt(myname,
xsasl_dovecot_serv_sec_props,
- line, "\t", NAME_MASK_ANY_CASE);
+ line, "\t",
+ NAME_MASK_ANY_CASE | NAME_MASK_IGNORE);
if ((sec_props & SEC_PROPS_PRIVATE) != 0)
continue;
} else