stress-dependent. Files: global/mail_params.h,
proto/postconf.proto.
+ Compatibility: postscreen_discard_ehlo_keyword(s|maps)
+ support for compatibility with smtpd_discard_ehlo_keyword(s|maps).
+ Files: postscreen/postscreen_smtpd.c.
+
20110102
Feature: STARTTLS support for the postscreen(8) daemon.
20110104
Feature: add contact information to each SMTP server reject
- message. For example, "smtpd_reject_contact_information =
+ message. For example, "smtpd_reject_footer =
call 800-555-0101 for assistance", with macro expansion and
with multi-line support. Files: global/mail_params.h,
mantools/postlink, proto/postconf.proto, smtpd/smtpd.c,
Seen from outside, Postfix works just as if it has TLS
support built into in smtpd(8). Files: smtpd/smtpd.c,
tls/tls_proxy*.[hc], tlsproxy/tlsproxy.c, util/vstream.[hc].
+
+ Bugfix (introduced with the Postfix TLS patch): discard
+ plaintext following the STARTTLS command or response. This
+ matters only for the minority of SMTP clients that actually
+ verify server certificates. Files: smtpd/smtpd.c,
+ smtp/smtp_proto.c.
+
+20110106:
+
+ Non-production: cleaned up the tlsproxy support in the
+ Postfix SMTP server for stress testing of the tlsproxy
+ daemon (still #ifdef TLSPROXY). File: smtpd/smtpd.c.
+
+20110107
+
+ Cleanup: smtpd_reject_contact_information is renamed to
+ smtpd_reject_footer, because it can be used for non-contact
+ information.
+
+ Compatibility: postscreen_reject_footer support for
+ compatibility with smtpd_reject_footer. Files:
+ global/smtp_reply_footer.[hc], global/mail_conf.[hc],
+ postscreen/postscreen_expand.c, postscreen/postscreen_send.c,
+ postscreen/postscreen.c, smtpd/smtpd_chat.c.
+
+ Compatibility: postscreen_command_filter support for
+ compatibility with smtpd_command_filter. Files:
+ postscreen/postscreen_dict.c, postscreen/postscreen_smtpd.c
+
+ Cleanup: postscreen(8) now displays control characters in
+ PREGREET responses as C-style \letter escapes, instead of
+ "?". File: postscreen/postscreen_early.c.
Translation: the client at [address]:port sent count bytes before its turn to
speak. This happened time seconds after the postscreen_greet_wait timer was
started. The text is what the client sent (truncated to 100 bytes, and with
-non-printable characters replaced with "?").
+non-printable characters replaced with C-style escapes such as \r for carriage-
+return and \n for newline).
The postscreen_greet_action parameter specifies the action that is taken next.
See "When tests fail before the 220 SMTP server greeting" below.
errors, or unsupported commands.
Example:
- smtpd_reject_contact_information = For assistance, call 800-555-0101.
+ smtpd_reject_footer = For assistance, call 800-555-0101.
Server response:
550-5.5.1 <user@example> Recipient address rejected: User unknown
This feature supports macro expansion ($client_address, $localtime,
etc.), as documented in the postconf(5) manpage.
+This feature is also supported as postscreen_reject_footer
+using the same setting as smtpd_reject_footer by
+default.
+
Incompatibility with snapshot 20110102
======================================
Re-run "make depend" with all plugins enabled.
+ Make very clear in postscreen manpage and readme that this
+ program is not to be used against your own mail clients.
+
+ Test postscreen on Solaris.
+
+ match_list support that does not recompile CIDR patterns
+ on every call.
+
+ tlsproxy(8) should receive TLS preferences from postscreen(8)
+ and smtpd(8), instead of reading them from main.cf. This
+ means that many tlsproxy_ parameters become postscreen_
+ parameters. This also means that tls_server_init() must not
+ "validate" preferences that are supplied later at
+ tls_server_start() time, which was dubious design anyway.
+
anvil rate limit for sasl_username.
Encapsulate nbbio buffer access and update by tlsproxy.
This would apply to postmaster notices and bounce messages
(DKIM), and address verification (BATV).
- Replace sscanf() numerical conversions by strto[dl]()
- for better error reporting.
-
As postscreen implements more ESMTP keywords, need to copy
inter-operability features from smtpd to filter keywords
and command syntax.
the same cleanup_service value for receiving remote mail
and for submitting postmaster problem reports. Do we need
separate mumble_cleanup_service_name parameters for "inject",
- "notify" and "forward" (with backwards compatinble defaults)?
+ "notify" and "forward" (with backwards compatible defaults)?
IF/ENDIF support for CIDR tables.
bytes before its turn to speak. This happened <i>time</i> seconds
after the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer was started. The <i>text</i>
is what the client sent (truncated to 100 bytes, and with non-printable
-characters replaced with "?"). </p>
+characters replaced with C-style escapes such as \r for carriage-return
+and \n for newline). </p>
<p> The <a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> parameter specifies the action that
is taken next. See "<a href="#fail_before_220">When tests fail
<p> This feature is available in Postfix 2.8. </p>
+</DD>
+
+<DT><b><a name="postscreen_command_filter">postscreen_command_filter</a>
+(default: $<a href="postconf.5.html#smtpd_command_filter">smtpd_command_filter</a>)</b></DT><DD>
+
+<p> A mechanism to transform commands from remote SMTP clients.
+See <a href="postconf.5.html#smtpd_command_filter">smtpd_command_filter</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
</DD>
<DT><b><a name="postscreen_command_time_limit">postscreen_command_time_limit</a>
Preferably, use <a href="postconf.5.html#postscreen_tls_security_level">postscreen_tls_security_level</a> instead. </p>
+</DD>
+
+<DT><b><a name="postscreen_expansion_filter">postscreen_expansion_filter</a>
+(default: see "postconf -d" output)</b></DT><DD>
+
+<p> List of characters that are permitted in <a href="postconf.5.html#postscreen_reject_footer">postscreen_reject_footer</a>
+attribute expansions. See <a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> for further
+details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </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_reject_footer">postscreen_reject_footer</a>
+(default: $<a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a>)</b></DT><DD>
+
+<p> Optional information that is appended after a 4XX or 5XX server
+response. See <a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a> for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+
</DD>
<DT><b><a name="postscreen_tls_security_level">postscreen_tls_security_level</a>
</DD>
-<DT><b><a name="smtpd_reject_contact_information">smtpd_reject_contact_information</a>
+<DT><b><a name="smtpd_reject_footer">smtpd_reject_footer</a>
(default: empty)</b></DT><DD>
-<p> Optional contact information that is appended after each SMTP
-server 4XX or 5XX response. </p>
+<p> Optional information that is appended after each SMTP server
+4XX or 5XX response. </p>
<p> Example: </p>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#smtpd_reject_contact_information">smtpd_reject_contact_information</a> = For assistance, call 800-555-0101.
+ <a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a> = For assistance, call 800-555-0101.
Please provide the following information in your problem report:
- time ($localtime) and client address ($client_address).
+ time ($localtime), client ($client_address) and server
+ ($server_name).
</pre>
<p> Server response: </p>
<pre>
-550-5.5.1 <user@example> Recipient address rejected: User unknown
-550 5.5.1 For assistance, call 800-555-0101. Please provide the
-following information in your problem report: time (Jan 4 15:42:00)
-and client address (192.168.1.248).
+ 550-5.5.1 <user@example> Recipient address rejected: User unknown
+ 550 5.5.1 For assistance, call 800-555-0101. Please provide the
+ following information in your problem report: time (Jan 4 15:42:00),
+ client (192.168.1.248) and server (mail1.example.com).
</pre>
-<p> Note: this text is meant to make it easier to find the Postfix
-logfile records for a failed SMTP session. The text itself is not
-logged to the Postfix server's maillog file. </p>
+<p> Note: the above text is meant to make it easier to find the
+Postfix logfile records for a failed SMTP session. The text itself
+is not logged to the Postfix SMTP server's maillog file. </p>
<p> Be sure to keep the text as short as possible. Long text may
-be truncated before it is logged in the senders maillog file, or
-before it is returned to the sender in a delivery status notification.
-</p>
+be truncated before it is logged in the Postfix SMTP server's maillog
+file, or before it is returned to the sender in a delivery status
+notification. </p>
<p> This feature supports a limited number of $name attributes in
-the contact text. These are replaced by their current value for the
+the footer text. These are replaced by their current value for the
SMTP session: </p>
<dl>
-<dt> client_address </dt> <dd> Client IP address </dd>
-
-<dt> client_port </dt> <dd> Client TCP port </dd>
+<dt> <b>client_address</b> </dt> <dd> The Client IP address that
+is logged in the maillog file. </dd>
-<dt> localtime </dt> <dd> Server local time (Mmm dd hh:mm:ss) </dd>
+<dt> <b>client_port</b> </dt> <dd> The client TCP port that is
+logged in the maillog file. </dd>
-<dt> recipient </dt> <dd> The address in the RCPT TO command </dd>
+<dt> <b>localtime</b> </dt> <dd> The server local time (Mmm dd
+hh:mm:ss) that is logged in the maillog file. </dd>
-<dt> sender </dt> <dd> The address in the MAIL FROM command </dd>
+<dt> <b>server_name</b> </dt> <dd> The server's <a href="postconf.5.html#myhostname">myhostname</a> value.
+This attribute is made available for sites with multiple MTAs
+(perhaps behind a load-balancer), where the server name can help
+the server support team to quickly find the right log files. </dd>
</dl>
-<p> For safety reasons, text that does not match $<a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a>
-is censored. </p>
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> NOT SUPPORTED are other attributes such as sender, recipient,
+or <a href="postconf.5.html">main.cf</a> parameters. </p>
-<p> This feature supports \n as a request for a line break in the
-contact text. Postfix automatically inserts after each line break
-the three-digit SMTP reply code (and optional enhanced status code)
-from the original Postfix reject message. </p>
+<li> <p> For safety reasons, text that does not match
+$<a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> is censored. </p>
+
+</ul>
+
+<p> This feature supports the two-character sequence \n as a request
+for a line break in the footer text. Postfix automatically inserts
+after each line break the three-digit SMTP reply code (and optional
+enhanced status code) from the original Postfix reject message.
+</p>
<p> This feature is available in Postfix 2.8 and later. </p>
ter value is the empty string.
<b>COMPATIBILITY CONTROLS</b>
+ <b><a href="postconf.5.html#postscreen_command_filter">postscreen_command_filter</a> ($<a href="postconf.5.html#smtpd_command_filter">smtpd_command_filter</a>)</b>
+ A mechanism to transform commands from remote SMTP
+ clients.
+
<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
+ 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
+ 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
+ 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
+ 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
+ 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-
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
tion.
+<b>TROUBLE SHOOTING CONTROLS</b>
+ <b><a href="postconf.5.html#postscreen_expansion_filter">postscreen_expansion_filter</a> (see 'postconf -d' output)</b>
+ List of characters that are permitted in
+ <a href="postconf.5.html#postscreen_reject_footer">postscreen_reject_footer</a> attribute expansions.
+
+ <b><a href="postconf.5.html#postscreen_reject_footer">postscreen_reject_footer</a> ($<a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a>)</b>
+ Optional information that is appended after a 4XX
+ or 5XX server response.
+
<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>
- The time limit for sending or receiving information
- 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 list of error classes that are reported to the
postmaster.
- <b><a href="postconf.5.html#smtpd_reject_contact_information">smtpd_reject_contact_information</a> (empty)</b>
- Optional contact information that is appended after
- each SMTP server 4XX or 5XX response.
+ <b><a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a> (empty)</b>
+ Optional information that is appended after each
+ SMTP server 4XX or 5XX response.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
Safety net to keep mail queued that would otherwise
and error commands.
.PP
This feature is available in Postfix 2.8.
+.SH postscreen_command_filter (default: $smtpd_command_filter)
+A mechanism to transform commands from remote SMTP clients.
+See smtpd_command_filter for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
.SH postscreen_command_time_limit (default: ${stress?10}${stress:300}s)
The command "read" time limit for \fBpostscreen\fR(8)'s built-in SMTP
protocol engine. This bounds the time to receive an entire command.
.PP
This feature is available in Postfix 2.8 and later.
Preferably, use postscreen_tls_security_level instead.
+.SH postscreen_expansion_filter (default: see "postconf -d" output)
+List of characters that are permitted in postscreen_reject_footer
+attribute expansions. See smtpd_expansion_filter for further
+details.
+.PP
+This feature is available in Postfix 2.8 and later.
.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_reject_footer (default: $smtpd_reject_footer)
+Optional information that is appended after a 4XX or 5XX server
+response. See smtpd_reject_footer for further details.
+.PP
+This feature is available in Postfix 2.8 and later.
.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
.fi
.ad
.ft R
-.SH smtpd_reject_contact_information (default: empty)
-Optional contact information that is appended after each SMTP
-server 4XX or 5XX response.
+.SH smtpd_reject_footer (default: empty)
+Optional information that is appended after each SMTP server
+4XX or 5XX response.
.PP
Example:
.PP
.na
.ft C
/etc/postfix/main.cf:
- smtpd_reject_contact_information = For assistance, call 800-555-0101.
+ smtpd_reject_footer = For assistance, call 800-555-0101.
Please provide the following information in your problem report:
- time ($localtime) and client address ($client_address).
+ time ($localtime), client ($client_address) and server
+ ($server_name).
.fi
.ad
.ft R
.nf
.na
.ft C
-550-5.5.1 <user@example> Recipient address rejected: User unknown
-550 5.5.1 For assistance, call 800-555-0101. Please provide the
-following information in your problem report: time (Jan 4 15:42:00)
-and client address (192.168.1.248).
+ 550-5.5.1 <user@example> Recipient address rejected: User unknown
+ 550 5.5.1 For assistance, call 800-555-0101. Please provide the
+ following information in your problem report: time (Jan 4 15:42:00),
+ client (192.168.1.248) and server (mail1.example.com).
.fi
.ad
.ft R
.PP
-Note: this text is meant to make it easier to find the Postfix
-logfile records for a failed SMTP session. The text itself is not
-logged to the Postfix server's maillog file.
+Note: the above text is meant to make it easier to find the
+Postfix logfile records for a failed SMTP session. The text itself
+is not logged to the Postfix SMTP server's maillog file.
.PP
Be sure to keep the text as short as possible. Long text may
-be truncated before it is logged in the senders maillog file, or
-before it is returned to the sender in a delivery status notification.
+be truncated before it is logged in the Postfix SMTP server's maillog
+file, or before it is returned to the sender in a delivery status
+notification.
.PP
This feature supports a limited number of $name attributes in
-the contact text. These are replaced by their current value for the
+the footer text. These are replaced by their current value for the
SMTP session:
-.IP "client_address"
-Client IP address
-.IP "client_port"
-Client TCP port
-.IP "localtime"
-Server local time (Mmm dd hh:mm:ss)
-.IP "recipient"
-The address in the RCPT TO command
-.IP "sender"
-The address in the MAIL FROM command
-.PP
-For safety reasons, text that does not match $smtpd_expansion_filter
-is censored.
-.PP
-This feature supports \en as a request for a line break in the
-contact text. Postfix automatically inserts after each line break
-the three-digit SMTP reply code (and optional enhanced status code)
-from the original Postfix reject message.
+.IP "\fBclient_address\fR"
+The Client IP address that
+is logged in the maillog file.
+.IP "\fBclient_port\fR"
+The client TCP port that is
+logged in the maillog file.
+.IP "\fBlocaltime\fR"
+The server local time (Mmm dd
+hh:mm:ss) that is logged in the maillog file.
+.IP "\fBserver_name\fR"
+The server's myhostname value.
+This attribute is made available for sites with multiple MTAs
+(perhaps behind a load-balancer), where the server name can help
+the server support team to quickly find the right log files.
+.PP
+Notes:
+.IP \(bu
+NOT SUPPORTED are other attributes such as sender, recipient,
+or main.cf parameters.
+.IP \(bu
+For safety reasons, text that does not match
+$smtpd_expansion_filter is censored.
+.PP
+This feature supports the two-character sequence \en as a request
+for a line break in the footer text. Postfix automatically inserts
+after each line break the three-digit SMTP reply code (and optional
+enhanced status code) from the original Postfix reject message.
.PP
This feature is available in Postfix 2.8 and later.
.SH smtpd_reject_unlisted_recipient (default: yes)
.nf
.ad
.fi
+.IP "\fBpostscreen_command_filter ($smtpd_command_filter)\fR"
+A mechanism to transform commands from remote SMTP clients.
.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,
.IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
Mandatory TLS: announce STARTTLS support to SMTP clients, and
require that clients use TLS encryption.
+.SH "TROUBLE SHOOTING CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBpostscreen_expansion_filter (see 'postconf -d' output)\fR"
+List of characters that are permitted in postscreen_reject_footer
+attribute expansions.
+.IP "\fBpostscreen_reject_footer ($smtpd_reject_footer)\fR"
+Optional information that is appended after a 4XX or 5XX server
+response.
.SH "MISCELLANEOUS CONTROLS"
.na
.nf
sub-second delay values.
.IP "\fBcommand_directory (see 'postconf -d' output)\fR"
The location of all postfix administrative commands.
-.IP "\fBipc_timeout (3600s)\fR"
-The time limit for sending or receiving information over an internal
-communication channel.
.IP "\fBmax_idle (100s)\fR"
The maximum amount of time that an idle Postfix daemon process waits
for an incoming connection before terminating voluntarily.
and body_checks.
.IP "\fBnotify_classes (resource, software)\fR"
The list of error classes that are reported to the postmaster.
-.IP "\fBsmtpd_reject_contact_information (empty)\fR"
-Optional contact information that is appended after each SMTP
-server 4XX or 5XX response.
+.IP "\fBsmtpd_reject_footer (empty)\fR"
+Optional information that is appended after each SMTP server
+4XX or 5XX response.
.IP "\fBsoft_bounce (no)\fR"
Safety net to keep mail queued that would otherwise be returned to
the sender.
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;\bsmtpd_reject_contact_information\b;<a href="postconf.5.html#smtpd_reject_contact_information">$&</a>;g;
+ s;\bsmtpd_reject_footer\b;<a href="postconf.5.html#smtpd_reject_footer">$&</a>;g;
s;\btls_daemon_random_bytes\b;<a href="postconf.5.html#tls_daemon_random_bytes">$&</a>;g;
s;\btls_daemon_random_source\b;<a href="postconf.5.html#tls_daemon_random_source">$&</a>;g;
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_bytes\b;<a href="postconf.5.html#tls_random_bytes">$&</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;\bpostscreen_expansion_filter\b;<a href="postconf.5.html#postscreen_expansion_filter">$&</a>;g;
+ s;\bpostscreen_reject_footer\b;<a href="postconf.5.html#postscreen_reject_footer">$&</a>;g;
+ s;\bpostscreen_command_filter\b;<a href="postconf.5.html#postscreen_command_filter">$&</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;
bytes before its turn to speak. This happened <i>time</i> seconds
after the postscreen_greet_wait timer was started. The <i>text</i>
is what the client sent (truncated to 100 bytes, and with non-printable
-characters replaced with "?"). </p>
+characters replaced with C-style escapes such as \r for carriage-return
+and \n for newline). </p>
<p> The postscreen_greet_action parameter specifies the action that
is taken next. See "<a href="#fail_before_220">When tests fail
<p> This feature is available in Postfix 2.8 and later. </p>
-%PARAM smtpd_reject_contact_information
+%PARAM smtpd_reject_footer
-<p> Optional contact information that is appended after each SMTP
-server 4XX or 5XX response. </p>
+<p> Optional information that is appended after each SMTP server
+4XX or 5XX response. </p>
<p> Example: </p>
<pre>
/etc/postfix/main.cf:
- smtpd_reject_contact_information = For assistance, call 800-555-0101.
+ smtpd_reject_footer = For assistance, call 800-555-0101.
Please provide the following information in your problem report:
- time ($localtime) and client address ($client_address).
+ time ($localtime), client ($client_address) and server
+ ($server_name).
</pre>
<p> Server response: </p>
<pre>
-550-5.5.1 <user@example> Recipient address rejected: User unknown
-550 5.5.1 For assistance, call 800-555-0101. Please provide the
-following information in your problem report: time (Jan 4 15:42:00)
-and client address (192.168.1.248).
+ 550-5.5.1 <user@example> Recipient address rejected: User unknown
+ 550 5.5.1 For assistance, call 800-555-0101. Please provide the
+ following information in your problem report: time (Jan 4 15:42:00),
+ client (192.168.1.248) and server (mail1.example.com).
</pre>
-<p> Note: this text is meant to make it easier to find the Postfix
-logfile records for a failed SMTP session. The text itself is not
-logged to the Postfix server's maillog file. </p>
+<p> Note: the above text is meant to make it easier to find the
+Postfix logfile records for a failed SMTP session. The text itself
+is not logged to the Postfix SMTP server's maillog file. </p>
<p> Be sure to keep the text as short as possible. Long text may
-be truncated before it is logged in the senders maillog file, or
-before it is returned to the sender in a delivery status notification.
-</p>
+be truncated before it is logged in the Postfix SMTP server's maillog
+file, or before it is returned to the sender in a delivery status
+notification. </p>
<p> This feature supports a limited number of $name attributes in
-the contact text. These are replaced by their current value for the
+the footer text. These are replaced by their current value for the
SMTP session: </p>
<dl>
-<dt> client_address </dt> <dd> Client IP address </dd>
-
-<dt> client_port </dt> <dd> Client TCP port </dd>
+<dt> <b>client_address</b> </dt> <dd> The Client IP address that
+is logged in the maillog file. </dd>
-<dt> localtime </dt> <dd> Server local time (Mmm dd hh:mm:ss) </dd>
+<dt> <b>client_port</b> </dt> <dd> The client TCP port that is
+logged in the maillog file. </dd>
-<dt> recipient </dt> <dd> The address in the RCPT TO command </dd>
+<dt> <b>localtime</b> </dt> <dd> The server local time (Mmm dd
+hh:mm:ss) that is logged in the maillog file. </dd>
-<dt> sender </dt> <dd> The address in the MAIL FROM command </dd>
+<dt> <b>server_name</b> </dt> <dd> The server's myhostname value.
+This attribute is made available for sites with multiple MTAs
+(perhaps behind a load-balancer), where the server name can help
+the server support team to quickly find the right log files. </dd>
</dl>
-<p> For safety reasons, text that does not match $smtpd_expansion_filter
-is censored. </p>
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> NOT SUPPORTED are other attributes such as sender, recipient,
+or main.cf parameters. </p>
+
+<li> <p> For safety reasons, text that does not match
+$smtpd_expansion_filter is censored. </p>
+
+</ul>
+
+<p> This feature supports the two-character sequence \n as a request
+for a line break in the footer text. Postfix automatically inserts
+after each line break the three-digit SMTP reply code (and optional
+enhanced status code) from the original Postfix reject message.
+</p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM postscreen_expansion_filter see "postconf -d" output
+
+<p> List of characters that are permitted in postscreen_reject_footer
+attribute expansions. See smtpd_expansion_filter for further
+details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
-<p> This feature supports \n as a request for a line break in the
-contact text. Postfix automatically inserts after each line break
-the three-digit SMTP reply code (and optional enhanced status code)
-from the original Postfix reject message. </p>
+%PARAM postscreen_reject_footer $smtpd_reject_footer
+
+<p> Optional information that is appended after a 4XX or 5XX server
+response. See smtpd_reject_footer for further details. </p>
+
+<p> This feature is available in Postfix 2.8 and later. </p>
+
+%PARAM postscreen_command_filter $smtpd_command_filter
+
+<p> A mechanism to transform commands from remote SMTP clients.
+See smtpd_command_filter for further details. </p>
<p> This feature is available in Postfix 2.8 and later. </p>
user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \
- match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c
+ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
+ smtp_reply_footer.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \
- match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o
+ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
+ smtp_reply_footer.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
fold_addr.h header_body_checks.h data_redirect.h match_service.h \
- addr_match_list.h
+ addr_match_list.h smtp_reply_footer.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
delivered_hdr.o: quote_flags.h
delivered_hdr.o: rec_type.h
delivered_hdr.o: record.h
-dict_ldap.o: ../../include/argv.h
-dict_ldap.o: ../../include/binhash.h
-dict_ldap.o: ../../include/dict.h
-dict_ldap.o: ../../include/match_list.h
-dict_ldap.o: ../../include/match_ops.h
-dict_ldap.o: ../../include/msg.h
-dict_ldap.o: ../../include/mymalloc.h
-dict_ldap.o: ../../include/name_code.h
-dict_ldap.o: ../../include/stringops.h
dict_ldap.o: ../../include/sys_defs.h
-dict_ldap.o: ../../include/vbuf.h
-dict_ldap.o: ../../include/vstream.h
-dict_ldap.o: ../../include/vstring.h
-dict_ldap.o: cfg_parser.h
-dict_ldap.o: db_common.h
dict_ldap.o: dict_ldap.c
-dict_ldap.o: dict_ldap.h
-dict_ldap.o: mail_conf.h
-dict_ldap.o: string_list.h
dict_mysql.o: ../../include/sys_defs.h
dict_mysql.o: dict_mysql.c
dict_pgsql.o: ../../include/sys_defs.h
mime_state.o: mime_state.c
mime_state.o: mime_state.h
mime_state.o: rec_type.h
-mkmap_cdb.o: ../../include/argv.h
-mkmap_cdb.o: ../../include/dict.h
-mkmap_cdb.o: ../../include/dict_cdb.h
-mkmap_cdb.o: ../../include/mymalloc.h
mkmap_cdb.o: ../../include/sys_defs.h
-mkmap_cdb.o: ../../include/vbuf.h
-mkmap_cdb.o: ../../include/vstream.h
-mkmap_cdb.o: ../../include/vstring.h
-mkmap_cdb.o: mkmap.h
mkmap_cdb.o: mkmap_cdb.c
mkmap_db.o: ../../include/argv.h
mkmap_db.o: ../../include/dict.h
sent.o: sent.h
sent.o: trace.h
sent.o: verify.h
+smtp_reply_footer.o: ../../include/mac_expand.h
+smtp_reply_footer.o: ../../include/mac_parse.h
+smtp_reply_footer.o: ../../include/msg.h
+smtp_reply_footer.o: ../../include/sys_defs.h
+smtp_reply_footer.o: ../../include/vbuf.h
+smtp_reply_footer.o: ../../include/vstring.h
+smtp_reply_footer.o: dsn_util.h
+smtp_reply_footer.o: smtp_reply_footer.c
+smtp_reply_footer.o: smtp_reply_footer.h
smtp_stream.o: ../../include/iostuff.h
smtp_stream.o: ../../include/msg.h
smtp_stream.o: ../../include/sys_defs.h
/* const char *mail_conf_eval(string)
/* const char *string;
/*
+/* const char *mail_conf_eval_once(string)
+/* const char *string;
+/*
/* const char *mail_conf_lookup_eval(name)
/* const char *name;
/* DESCRIPTION
/* string argument. The result is volatile and should be copied
/* if it is to be used for any appreciable amount of time.
/*
+/* mail_conf_eval_once() non-recursively expands any $parameters
+/* in the string argument. The result is volatile and should
+/* be copied if it is to be used for any appreciable amount
+/* of time.
+/*
/* mail_conf_lookup_eval() looks up the named parameter, and expands any
/* $parameters in the result. The result is volatile and should be
/* copied if it is to be used for any appreciable amount of time.
return (dict_eval(CONFIG_DICT, string, RECURSIVE));
}
+/* mail_conf_eval_once - expand one level of macros in string */
+
+const char *mail_conf_eval_once(const char *string)
+{
+#define NONRECURSIVE 0
+
+ return (dict_eval(CONFIG_DICT, string, NONRECURSIVE));
+}
+
/* mail_conf_lookup - lookup named variable */
const char *mail_conf_lookup(const char *name)
extern void mail_conf_update(const char *, const char *);
extern const char *mail_conf_lookup(const char *);
extern const char *mail_conf_eval(const char *);
+extern const char *mail_conf_eval_once(const char *);
extern const char *mail_conf_lookup_eval(const char *);
/*
#define DEF_PSC_CCONN_LIMIT "$" VAR_SMTPD_CCONN_LIMIT
extern int var_psc_cconn_limit;
+#define VAR_PSC_REJ_FOOTER "postscreen_reject_footer"
+#define DEF_PSC_REJ_FOOTER "$" VAR_SMTPD_REJ_FOOTER
+extern char *var_psc_rej_footer;
+
+#define VAR_PSC_EXP_FILTER "postscreen_expansion_filter"
+#define DEF_PSC_EXP_FILTER "$" VAR_SMTPD_EXP_FILTER
+extern char *var_psc_exp_filter;
+
+#define VAR_PSC_CMD_FILTER "postscreen_command_filter"
+#define DEF_PSC_CMD_FILTER ""
+extern char *var_psc_cmd_filter;
+
#define VAR_DNSBLOG_DELAY "dnsblog_reply_delay"
#define DEF_DNSBLOG_DELAY "0s"
extern int var_dnsblog_delay;
/*
* SMTPD "reject" contact info.
*/
-#define VAR_SMTPD_REJ_CONTACT "smtpd_reject_contact_information"
-#define DEF_SMTPD_REJ_CONTACT ""
-extern char *var_smtpd_rej_contact;
+#define VAR_SMTPD_REJ_FOOTER "smtpd_reject_footer"
+#define DEF_SMTPD_REJ_FOOTER ""
+extern char *var_smtpd_rej_footer;
/* LICENSE
/* .ad
#define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits"
#define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits"
+ /*
+ * SMTP reply footer support.
+ */
+#define MAIL_ATTR_SERVER_NAME "server_name"
+
/* 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 "20110105"
+#define MAIL_RELEASE_DATE "20110108"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
--- /dev/null
+/*++
+/* NAME
+/* smtp_reply_footer 3
+/* SUMMARY
+/* SMTP reply footer text support
+/* SYNOPSIS
+/* #include <smtp_reply_footer.h>
+/*
+/* int smtp_reply_footer(buffer, start, template, filter,
+/* lookup, context)
+/* VSTRING *buffer;
+/* ssize_t start;
+/* char *template;
+/* const char *filter;
+/* const char *(*lookup) (const char *name, char *context);
+/* char *context;
+/* DESCRIPTION
+/* smtp_reply_footer() expands a reply template to an existing
+/* reply text.
+/*
+/* Arguments:
+/* .IP buffer
+/* Result buffer. This should contain a properly formatted
+/* one-line or multi-line SMTP reply, with or without the final
+/* <CR><LF>. The reply code and optional enhanced status code
+/* will be replicated in the footer text. One space character
+/* after the SMTP reply code is replaced by '-'. If the existing
+/* reply ends in <CR><LF>, the result text will also end in
+/* <CR><LF>.
+/* .IP start
+/* The beginning of the SMTP reply that the footer will be
+/* appended to. This supports applications that buffer up
+/* multiple responses in one buffer.
+/* .IP template
+/* Template text, with optional $name attributes that will be
+/* expanded. The two-character sequence "\n" is replaced by a
+/* line break followed by a copy of the original SMTP reply
+/* code and optional enhanced status code.
+/* .IP filter
+/* The set of characters that are allowed in attribute expansion.
+/* .IP lookup
+/* Attribute name/value lookup function. The result value must
+/* be a null for a name that is not found, otherwise a pointer
+/* to null-terminated string.
+/* .IP context
+/* Call-back context for the lookup function.
+/* SEE ALSO
+/* mac_expand(3) macro expansion
+/* DIAGNOSTICS
+/* smtp_reply_footer() returns 0 upon success, -1 if the
+/* existing reply text is malformed.
+/*
+/* Fatal errors: memory allocation problem.
+/* 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 <string.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+
+/* Global library. */
+
+#include <dsn_util.h>
+#include <smtp_reply_footer.h>
+
+/* SLMs. */
+
+#define STR vstring_str
+
+int smtp_reply_footer(VSTRING *buffer, ssize_t start,
+ char *template,
+ const char *filter,
+ MAC_EXP_LOOKUP_FN lookup,
+ char *context)
+{
+ const char *myname = "smtp_reply_footer";
+ char *cp;
+ char *next;
+ char *end;
+ ssize_t dsn_len;
+ int crlf_at_end = 0;
+
+ /*
+ * Sanity check.
+ */
+ if (start < 0 || start > VSTRING_LEN(buffer))
+ msg_panic("%s: bad start: %ld", myname, (long) start);
+ if (*template == 0)
+ msg_panic("%s: empty template", myname);
+
+ /*
+ * Scan and patch the original response. If the response is not what we
+ * expect, we stop making changes.
+ */
+ for (cp = STR(buffer) + start, end = cp + strlen(cp);;) {
+ if (!ISDIGIT(cp[0]) || !ISDIGIT(cp[1]) || !ISDIGIT(cp[2])
+ || (cp[3] != ' ' && cp[3] != '-'))
+ return (-1);
+ cp[3] = '-';
+ if ((next = strstr(cp, "\r\n")) == 0) {
+ next = end;
+ break;
+ }
+ cp = next + 2;
+ if (cp == end) {
+ crlf_at_end = 1;
+ break;
+ }
+ }
+
+ /*
+ * Truncate text after the first null, and truncate the trailing CRLF.
+ */
+ if (next < vstring_end(buffer))
+ vstring_truncate(buffer, next - STR(buffer));
+
+ /*
+ * Append the footer text one line at a time. Caution: before we append
+ * parts from the buffer to itself, we must extend the buffer first,
+ * otherwise we would have a dangling pointer "read" bug.
+ */
+ dsn_len = dsn_valid(STR(buffer) + start + 4);
+ for (cp = template, end = cp + strlen(cp);;) {
+ if ((next = strstr(cp, "\\n")) != 0) {
+ *next = 0;
+ } else {
+ next = end;
+ }
+ /* Append a clone of the SMTP reply code. */
+ vstring_strcat(buffer, "\r\n");
+ VSTRING_SPACE(buffer, 3);
+ vstring_strncat(buffer, STR(buffer) + start, 3);
+ vstring_strcat(buffer, next != end ? "-" : " ");
+ /* Append a clone of the optional enhanced status code. */
+ if (dsn_len > 0) {
+ VSTRING_SPACE(buffer, dsn_len);
+ vstring_strncat(buffer, STR(buffer) + start + 4, (int) dsn_len);
+ vstring_strcat(buffer, " ");
+ }
+ /* Append one line of footer text. */
+ mac_expand(buffer, cp, MAC_EXP_FLAG_APPEND, filter, lookup, context);
+ if (next < end) {
+ *next = '\\';
+ cp = next + 2;
+ } else
+ break;
+ }
+ if (crlf_at_end)
+ vstring_strcat(buffer, "\r\n");
+ return (0);
+}
--- /dev/null
+#ifndef _SMTP_REPLY_FOOTER_H_INCLUDED_
+#define _SMTP_REPLY_FOOTER_H_INCLUDED_
+
+/*++
+/* NAME
+/* smtp_reply_footer 3h
+/* SUMMARY
+/* SMTP reply footer text support
+/* SYNOPSIS
+/* #include <smtp_reply_footer.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+#include <mac_expand.h>
+
+ /*
+ * External interface.
+ */
+extern int smtp_reply_footer(VSTRING *, ssize_t, char *, const char *,
+ MAC_EXP_LOOKUP_FN, char *);
+
+/* 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
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_starttls.c
+ postscreen_starttls.c postscreen_expand.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_starttls.o
+ postscreen_starttls.o postscreen_expand.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
postscreen.o: ../../include/mail_proto.h
postscreen.o: ../../include/mail_server.h
postscreen.o: ../../include/mail_version.h
+postscreen.o: ../../include/maps.h
postscreen.o: ../../include/match_list.h
postscreen.o: ../../include/match_ops.h
postscreen.o: ../../include/msg.h
postscreen_dict.o: ../../include/dict_cache.h
postscreen_dict.o: ../../include/events.h
postscreen_dict.o: ../../include/htable.h
+postscreen_dict.o: ../../include/maps.h
postscreen_dict.o: ../../include/match_list.h
postscreen_dict.o: ../../include/match_ops.h
postscreen_dict.o: ../../include/msg.h
postscreen_dnsbl.o: ../../include/ip_match.h
postscreen_dnsbl.o: ../../include/mail_params.h
postscreen_dnsbl.o: ../../include/mail_proto.h
+postscreen_dnsbl.o: ../../include/maps.h
postscreen_dnsbl.o: ../../include/match_list.h
postscreen_dnsbl.o: ../../include/match_ops.h
postscreen_dnsbl.o: ../../include/msg.h
postscreen_early.o: ../../include/events.h
postscreen_early.o: ../../include/htable.h
postscreen_early.o: ../../include/mail_params.h
+postscreen_early.o: ../../include/maps.h
postscreen_early.o: ../../include/match_list.h
postscreen_early.o: ../../include/match_ops.h
postscreen_early.o: ../../include/msg.h
postscreen_early.o: ../../include/vstring.h
postscreen_early.o: postscreen.h
postscreen_early.o: postscreen_early.c
+postscreen_expand.o: ../../include/addr_match_list.h
+postscreen_expand.o: ../../include/argv.h
+postscreen_expand.o: ../../include/attr.h
+postscreen_expand.o: ../../include/dict.h
+postscreen_expand.o: ../../include/dict_cache.h
+postscreen_expand.o: ../../include/events.h
+postscreen_expand.o: ../../include/htable.h
+postscreen_expand.o: ../../include/iostuff.h
+postscreen_expand.o: ../../include/mail_params.h
+postscreen_expand.o: ../../include/mail_proto.h
+postscreen_expand.o: ../../include/maps.h
+postscreen_expand.o: ../../include/match_list.h
+postscreen_expand.o: ../../include/match_ops.h
+postscreen_expand.o: ../../include/msg.h
+postscreen_expand.o: ../../include/string_list.h
+postscreen_expand.o: ../../include/stringops.h
+postscreen_expand.o: ../../include/sys_defs.h
+postscreen_expand.o: ../../include/vbuf.h
+postscreen_expand.o: ../../include/vstream.h
+postscreen_expand.o: ../../include/vstring.h
+postscreen_expand.o: postscreen.h
+postscreen_expand.o: postscreen_expand.c
postscreen_misc.o: ../../include/addr_match_list.h
postscreen_misc.o: ../../include/argv.h
postscreen_misc.o: ../../include/dict.h
postscreen_misc.o: ../../include/htable.h
postscreen_misc.o: ../../include/iostuff.h
postscreen_misc.o: ../../include/mail_params.h
+postscreen_misc.o: ../../include/maps.h
postscreen_misc.o: ../../include/match_list.h
postscreen_misc.o: ../../include/match_ops.h
postscreen_misc.o: ../../include/msg.h
postscreen_send.o: ../../include/events.h
postscreen_send.o: ../../include/htable.h
postscreen_send.o: ../../include/iostuff.h
+postscreen_send.o: ../../include/mac_expand.h
+postscreen_send.o: ../../include/mac_parse.h
postscreen_send.o: ../../include/mail_params.h
+postscreen_send.o: ../../include/maps.h
postscreen_send.o: ../../include/match_list.h
postscreen_send.o: ../../include/match_ops.h
postscreen_send.o: ../../include/msg.h
+postscreen_send.o: ../../include/smtp_reply_footer.h
postscreen_send.o: ../../include/string_list.h
postscreen_send.o: ../../include/sys_defs.h
postscreen_send.o: ../../include/vbuf.h
postscreen_smtpd.o: ../../include/htable.h
postscreen_smtpd.o: ../../include/iostuff.h
postscreen_smtpd.o: ../../include/is_header.h
+postscreen_smtpd.o: ../../include/lex_822.h
postscreen_smtpd.o: ../../include/mail_params.h
postscreen_smtpd.o: ../../include/mail_proto.h
postscreen_smtpd.o: ../../include/maps.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/maps.h
postscreen_starttls.o: ../../include/match_list.h
postscreen_starttls.o: ../../include/match_ops.h
postscreen_starttls.o: ../../include/msg.h
postscreen_state.o: ../../include/iostuff.h
postscreen_state.o: ../../include/mail_proto.h
postscreen_state.o: ../../include/mail_server.h
+postscreen_state.o: ../../include/maps.h
postscreen_state.o: ../../include/match_list.h
postscreen_state.o: ../../include/match_ops.h
postscreen_state.o: ../../include/msg.h
postscreen_tests.o: ../../include/events.h
postscreen_tests.o: ../../include/htable.h
postscreen_tests.o: ../../include/mail_params.h
+postscreen_tests.o: ../../include/maps.h
postscreen_tests.o: ../../include/match_list.h
postscreen_tests.o: ../../include/match_ops.h
postscreen_tests.o: ../../include/msg.h
/* COMPATIBILITY CONTROLS
/* .ad
/* .fi
+/* .IP "\fBpostscreen_command_filter ($smtpd_command_filter)\fR"
+/* A mechanism to transform commands from remote SMTP clients.
/* .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,
/* .IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
/* Mandatory TLS: announce STARTTLS support to SMTP clients, and
/* require that clients use TLS encryption.
+/* TROUBLE SHOOTING CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBpostscreen_expansion_filter (see 'postconf -d' output)\fR"
+/* List of characters that are permitted in postscreen_reject_footer
+/* attribute expansions.
+/* .IP "\fBpostscreen_reject_footer ($smtpd_reject_footer)\fR"
+/* Optional information that is appended after a 4XX or 5XX server
+/* response.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
/* sub-second delay values.
/* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
/* The location of all postfix administrative commands.
-/* .IP "\fBipc_timeout (3600s)\fR"
-/* The time limit for sending or receiving information over an internal
-/* communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process waits
/* for an incoming connection before terminating voluntarily.
bool var_disable_vrfy_cmd;
bool var_helo_required;
+char *var_smtpd_cmd_filter;
+char *var_psc_cmd_filter;
+
char *var_smtpd_forbid_cmds;
char *var_psc_forbid_cmds;
int var_psc_cmd_count;
char *var_psc_cmd_time;
+char *var_smtpd_rej_footer;
+char *var_psc_rej_footer;
+
int var_smtpd_cconn_limit;
int var_psc_cconn_limit;
+char *var_smtpd_exp_filter;
+char *var_psc_exp_filter;
+
/*
* Global variables.
*/
0, -1,
};
int cache_flags;
+ const char *tmp;
/*
* This routine runs after the skeleton code has entered the chroot jail.
*/
var_use_limit = 0;
+ /*
+ * Workaround for parameters whose values may contain "$", and that have
+ * a default of "$parametername". Not sure if it would be a good idea to
+ * always to this in the mail_conf_raw(3) module.
+ */
+ if (*var_psc_rej_footer == '$'
+ && mail_conf_lookup(var_psc_rej_footer + 1)) {
+ tmp = mail_conf_eval_once(var_psc_rej_footer);
+ myfree(var_psc_rej_footer);
+ var_psc_rej_footer = mystrdup(tmp);
+ }
+ if (*var_psc_exp_filter == '$'
+ && mail_conf_lookup(var_psc_exp_filter + 1)) {
+ tmp = mail_conf_eval_once(var_psc_exp_filter);
+ myfree(var_psc_exp_filter);
+ var_psc_exp_filter = mystrdup(tmp);
+ }
+
/*
* Other one-time initialization.
*/
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_SMTPD_CMD_FILTER, DEF_SMTPD_CMD_FILTER, &var_smtpd_cmd_filter, 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_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,
+ VAR_PSC_CMD_FILTER, DEF_PSC_CMD_FILTER, &var_psc_cmd_filter, 0, 0,
0,
};
static const CONFIG_INT_TABLE int_table[] = {
};
static const CONFIG_RAW_TABLE raw_table[] = {
VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0,
+ VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
+ VAR_PSC_REJ_FOOTER, DEF_PSC_REJ_FOOTER, &var_psc_rej_footer, 0, 0,
+ VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
+ VAR_PSC_EXP_FILTER, DEF_PSC_EXP_FILTER, &var_psc_exp_filter, 1, 0,
0,
};
static const CONFIG_NBOOL_TABLE nbool_table[] = {
*/
#include <addr_match_list.h>
#include <string_list.h>
+#include <maps.h>
/*
* Preliminary stuff, to be fixed.
int read_state; /* command read state machine */
/* smtpd(8) compatibility */
int ehlo_discard_mask; /* EHLO filter */
+ VSTRING *expand_buf; /* macro expansion */
} PSC_STATE;
#define PSC_TIME_STAMP_NEW (0) /* test was never passed */
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 *);
+const char *psc_dict_get(DICT *, const char *);
+const char *psc_maps_find(MAPS *, const char *, int);
/*
* postscreen_dnsbl.c
*/
extern void psc_starttls_open(PSC_STATE *, EVENT_NOTIFY_FN);
+ /*
+ * postscreen_expand.c
+ */
+extern VSTRING *psc_expand_filter;
+extern void psc_expand_init(void);
+extern const char *psc_expand_lookup(const char *, int, char *);
+
/* LICENSE
/* .ad
/* .fi
/* DICT_CACHE *cache;
/* const char *key;
/* const char *value;
+/*
+/* void psc_dict_get(dict, key)
+/* DICT *dict;
+/* const char *key;
+/*
+/* void psc_maps_find(maps, key, flags)
+/* MAPS *maps;
+/* const char *key;
+/* int flags;
/* DESCRIPTION
/* This module implements wrappers around time-critical table
/* access functions. The functions log a warning when table
/*
/* psc_cache_lookup() and psc_cache_update() are wrappers around
/* the corresponding dict_cache() methods.
+/*
+/* psc_dict_get() and psc_maps_find() are wrappers around
+/* dict_get() and maps_find(), respectively.
/* LICENSE
/* .ad
/* .fi
/* Utility library. */
#include <msg.h>
+#include <dict.h>
+
+/* Global library. */
+
+#include <maps.h>
/* Application-specific. */
dict_cache_update(cache, key, value);
PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
}
+
+/* psc_dict_get - time-critical table lookup */
+
+const char *psc_dict_get(DICT *dict, const char *key)
+{
+ const char *myname = "psc_dict_get";
+ const char *result;
+
+ PSC_GET_TIME_BEFORE_LOOKUP;
+ result = dict_get(dict, key);
+ PSC_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup");
+ return (result);
+}
+
+/* psc_maps_find - time-critical table lookup */
+
+const char *psc_maps_find(MAPS *maps, const char *key, int flags)
+{
+ const char *myname = "psc_maps_find";
+ const char *result;
+
+ PSC_GET_TIME_BEFORE_LOOKUP;
+ result = maps_find(maps, key, flags);
+ PSC_CHECK_TIME_AFTER_LOOKUP(maps->title, "lookup");
+ return (result);
+}
#include <postscreen.h>
static char *psc_teaser_greeting;
+static VSTRING *psc_escape_buf;
/* psc_early_event - handle pre-greet, EOF, and DNSBL results. */
return;
}
read_buf[read_count] = 0;
+ escape(psc_escape_buf, read_buf, read_count);
msg_info("PREGREET %d after %s from [%s]:%s: %.100s", read_count,
psc_format_delta_time(psc_temp, state->start_time, &elapsed),
- PSC_CLIENT_ADDR_PORT(state), printable(read_buf, '?'));
+ PSC_CLIENT_ADDR_PORT(state), STR(psc_escape_buf));
PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PREGR_FAIL);
switch (psc_pregr_action) {
case PSC_ACT_DROP:
if (*var_psc_pregr_banner) {
vstring_sprintf(psc_temp, "220-%s\r\n", var_psc_pregr_banner);
psc_teaser_greeting = mystrdup(STR(psc_temp));
+ psc_escape_buf = vstring_alloc(100);
}
}
--- /dev/null
+/*++
+/* NAME
+/* postscreen_expand 3
+/* SUMMARY
+/* SMTP server macro expansion
+/* SYNOPSIS
+/* #include <postscreen.h>
+/*
+/* void psc_expand_init()
+/*
+/* VSTRING *psc_expand_filter;
+/*
+/* const char *psc_expand_lookup(name, unused_mode, context)
+/* const char *name;
+/* int unused_mode;
+/* char *context;
+/* DESCRIPTION
+/* This module expands session-related macros.
+/*
+/* psc_expand_init() performs one-time initialization
+/* of the psc_expand_filter buffer.
+/*
+/* The psc_expand_filter buffer contains the characters
+/* that are allowed in macro expansion, as specified with the
+/* psc_expand_filter configuration parameter.
+/*
+/* psc_expand_lookup() returns the value of the named
+/* macro or a null pointer.
+/*
+/* Arguments:
+/* .IP name
+/* Macro name.
+/* .IP context
+/* Call-back context (a PSC_STATE pointer).
+/* DIAGNOSTICS
+/* Panic: interface violations. Fatal errors: out of memory.
+/* internal protocol errors. postscreen_expand() returns the
+/* binary OR of MAC_PARSE_ERROR (syntax error) and MAC_PARSE_UNDEF
+/* (undefined macro name).
+/* 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 <time.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mail_proto.h>
+
+/* Application-specific. */
+
+#include <postscreen.h>
+
+ /*
+ * Pre-parsed expansion filter.
+ */
+VSTRING *psc_expand_filter;
+
+/* psc_expand_init - initialize once during process lifetime */
+
+void psc_expand_init(void)
+{
+
+ /*
+ * Expand the expansion filter :-)
+ */
+ psc_expand_filter = vstring_alloc(10);
+ unescape(psc_expand_filter, var_psc_exp_filter);
+}
+
+/* psc_expand_lookup - generic SMTP attribute $name expansion */
+
+const char *psc_expand_lookup(const char *name, int unused_mode,
+ char *context)
+{
+ PSC_STATE *state = (PSC_STATE *) context;
+ time_t now;
+ struct tm *lt;
+
+ if (state->expand_buf == 0)
+ state->expand_buf = vstring_alloc(10);
+
+ if (msg_verbose > 1)
+ msg_info("psc_expand_lookup: ${%s}", name);
+
+#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
+#define STREQN(x,y,n) (*(x) == *(y) && strncmp((x), (y), (n)) == 0)
+#define CONST_LEN(x) (sizeof(x) - 1)
+
+ /*
+ * Don't query main.cf parameters, as the result of expansion could
+ * reveal system-internal information in server replies.
+ *
+ * XXX: This said, multiple servers may be behind a single client-visible
+ * name or IP address, and each may generate its own logs. Therefore, it
+ * may be useful to expose the replying MTA id (myhostname) in the
+ * contact footer, to identify the right logs. So while we don't expose
+ * the raw configuration dictionary, we do expose "$myhostname" as
+ * expanded in var_myhostname.
+ *
+ * Return NULL only for non-existent names.
+ */
+ if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
+ return (var_myhostname);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_ADDR)) {
+ return (state->smtp_client_addr);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
+ return (state->smtp_client_port);
+ } if (STREQ(name, MAIL_ATTR_LOCALTIME)) {
+ if (time(&now) == (time_t) - 1)
+ msg_fatal("time lookup failed: %m");
+ lt = localtime(&now);
+ VSTRING_RESET(state->expand_buf);
+ do {
+ VSTRING_SPACE(state->expand_buf, 100);
+ } while (strftime(STR(state->expand_buf),
+ vstring_avail(state->expand_buf),
+ "%b %d %H:%M:%S", lt) == 0);
+ return (STR(state->expand_buf));
+ } else {
+ msg_warn("unknown macro name \"%s\" in expansion request", name);
+ return (0);
+ }
+}
/* Global library. */
#include <mail_params.h>
+#include <smtp_reply_footer.h>
/* Application-specific. */
int psc_send_reply(PSC_STATE *state, const char *text)
{
- int start;
+ ssize_t start;
int ret;
if (msg_verbose)
*/
start = VSTRING_LEN(state->send_buf);
vstring_strcat(state->send_buf, text);
+ if (*var_psc_rej_footer && (*text == '4' || *text == '5'))
+ smtp_reply_footer(state->send_buf, start, var_psc_rej_footer,
+ STR(psc_expand_filter), psc_expand_lookup,
+ (char *) state);
/*
* XXX For soft_bounce support, it is not sufficient to fix replies here.
#include <string_list.h>
#include <maps.h>
#include <ehlo_mask.h>
+#include <lex_822.h>
/* TLS library. */
static MAPS *psc_ehlo_discard_maps;
static int psc_ehlo_discard_mask;
+ /*
+ * Command editing filter.
+ */
+static DICT *psc_cmd_filter;
+
/*
* Encapsulation. We must not forget turn off input/timer events when we
* terminate the SMTP protocol engine.
* 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
+ && (ehlo_words = psc_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_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.
+ * Reset SMTP server state if STARTTLS was successful.
*/
if (state->flags & PSC_STATE_FLAG_USING_TLS) {
PSC_STRING_RESET(state->helo_name);
PSC_STRING_RESET(state->sender);
+#ifdef TODO_SASL_AUTH
+ /* Reset SASL AUTH state. Dovecot responses may change. */
+#endif
}
/*
}
/*
- * Terminate the command line, and reset the command buffer write
- * pointer and state machine in preparation for the next command. For
- * this to work as expected, VSTRING_RESET() must be non-destructive.
+ * Terminate the command buffer, and apply the last-resort command
+ * editing workaround.
*/
VSTRING_TERMINATE(state->cmd_buffer);
+ if (psc_cmd_filter != 0) {
+ const char *cp;
+
+ for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++)
+ /* void */ ;
+ if ((cp = psc_dict_get(psc_cmd_filter, cp)) != 0) {
+ msg_info("[%s]:%s: replacing command \"%.100s\" with \"%.100s\"",
+ state->smtp_client_addr, state->smtp_client_port,
+ STR(state->cmd_buffer), cp);
+ vstring_strcpy(state->cmd_buffer, cp);
+ }
+ }
+
+ /*
+ * Reset the command buffer write pointer and state machine in
+ * preparation for the next command. For this to work as expected,
+ * VSTRING_RESET() must be non-destructive.
+ */
state->read_state = PSC_SMTPD_CMD_ST_ANY;
VSTRING_RESET(state->cmd_buffer);
vstring_sprintf(psc_temp, "421 %s Service unavailable - try again later\r\n",
var_myhostname);
psc_smtpd_421_reply = mystrdup(STR(psc_temp));
+
+ /*
+ * Initialize the reply footer.
+ */
+ if (*var_psc_rej_footer)
+ psc_expand_init();
}
/* psc_smtpd_pre_jail_init - per-process deep protocol test initialization */
*
* 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);
+ if (*var_psc_ehlo_dis_maps)
+ 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);
+
+ /*
+ * Last-resort command editing support.
+ */
+ if (*var_psc_cmd_filter)
+ psc_cmd_filter = dict_open(var_psc_cmd_filter, O_RDONLY,
+ DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
}
state->cmd_buffer = 0;
state->read_state = 0;
state->ehlo_discard_mask = 0; /* XXX Should be ~0 */
+ state->expand_buf = 0;
/*
* Update the stress level.
myfree(state->sender);
if (state->cmd_buffer)
vstring_free(state->cmd_buffer);
+ if (state->expand_buf)
+ vstring_free(state->expand_buf);
myfree((char *) state);
if (psc_check_queue_length < 0 || psc_post_queue_length < 0)
SMTP_RESP_FAKE(&fake, "4.7.5"),
"Server certificate not verified"));
+
+ /* At this point there must not be any pending plaintext. */
+ vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH);
+
/*
* At this point we have to re-negotiate the "EHLO" to reget the
* feature-list.
smtpd_chat.o: ../../include/argv.h
smtpd_chat.o: ../../include/attr.h
smtpd_chat.o: ../../include/cleanup_user.h
-smtpd_chat.o: ../../include/dsn_util.h
smtpd_chat.o: ../../include/int_filt.h
smtpd_chat.o: ../../include/iostuff.h
smtpd_chat.o: ../../include/line_wrap.h
smtpd_chat.o: ../../include/post_mail.h
smtpd_chat.o: ../../include/rec_type.h
smtpd_chat.o: ../../include/record.h
+smtpd_chat.o: ../../include/smtp_reply_footer.h
smtpd_chat.o: ../../include/smtp_stream.h
smtpd_chat.o: ../../include/stringops.h
smtpd_chat.o: ../../include/sys_defs.h
/* and body_checks.
/* .IP "\fBnotify_classes (resource, software)\fR"
/* The list of error classes that are reported to the postmaster.
-/* .IP "\fBsmtpd_reject_contact_information (empty)\fR"
-/* Optional contact information that is appended after each SMTP
-/* server 4XX or 5XX response.
+/* .IP "\fBsmtpd_reject_footer (empty)\fR"
+/* Optional information that is appended after each SMTP server
+/* 4XX or 5XX response.
/* .IP "\fBsoft_bounce (no)\fR"
/* Safety net to keep mail queued that would otherwise be returned to
/* the sender.
bool var_smtpd_tls_wrappermode;
bool var_smtpd_tls_auth_only;
char *var_smtpd_cmd_filter;
-char *var_smtpd_rej_contact;
+char *var_smtpd_rej_footer;
#ifdef USE_TLS
char *var_smtpd_relay_ccerts;
static void smtpd_start_tls(SMTPD_STATE *state)
{
int rate;
+ int cert_present;
+ int requirecert;
+
+#ifdef USE_TLSPROXY
+
+ /*
+ * This is non-production code, for tlsproxy(8) load testing only. It
+ * implements enough to enable some Postfix features that depend on TLS
+ * encryption.
+ *
+ * To insert tlsproxy(8) between this process and the SMTP client, we swap
+ * the file descriptors between the state->tlsproxy and state->client
+ * VSTREAMS, so that we don't lose all the user-configurable
+ * state->client attributes (such as longjump buffers or timeouts).
+ *
+ * As we implement tlsproy support in the Postfix SMTP client we should
+ * develop a usable abstraction that encapsulates this stream plumbing in
+ * a library module.
+ */
+ vstream_control(state->tlsproxy, VSTREAM_CTL_DOUBLE, VSTREAM_CTL_END);
+ vstream_control(state->client, VSTREAM_CTL_SWAP_FD, state->tlsproxy,
+ VSTREAM_CTL_END);
+ (void) vstream_fclose(state->tlsproxy); /* direct-to-client stream! */
+ state->tlsproxy = 0;
+
+ /*
+ * After plumbing the plaintext stream, receive the TLS context object.
+ * For this we must use the same VSTREAM buffer that we also use to
+ * receive subsequent SMTP commands. The attribute protocol is robust
+ * enough that an adversary cannot inject their own bogus TLS context
+ * attributes into the stream.
+ */
+ state->tls_context = tls_proxy_context_receive(state->client);
+
+ /*
+ * XXX Maybe it is better to send this information to tlsproxy(8) when
+ * requesting service, effectively making a remote tls_server_start()
+ * call.
+ */
+ requirecert = (var_smtpd_tls_req_ccert && var_smtpd_enforce_tls);
+
+#else /* USE_TLSPROXY */
TLS_SERVER_START_PROPS props;
static char *cipher_grade;
static VSTRING *cipher_exclusions;
- int cert_present;
/*
* Wrapper mode uses a dedicated port and always requires TLS.
* Perform the TLS handshake now. Check the client certificate
* requirements later, if necessary.
*/
+ requirecert = (var_smtpd_tls_req_ccert && var_smtpd_enforce_tls);
+
state->tls_context =
TLS_SERVER_START(&props,
ctx = smtpd_tls_ctx,
stream = state->client,
log_level = var_smtpd_tls_loglevel,
timeout = var_smtpd_starttls_tmout,
- requirecert = (var_smtpd_tls_req_ccert
- && var_smtpd_enforce_tls),
+ requirecert = requirecert,
serverid = state->service,
namaddr = state->namaddr,
cipher_grade = cipher_grade,
cipher_exclusions = STR(cipher_exclusions),
fpt_dgst = var_smtpd_tls_fpt_dgst);
+#endif /* USE_TLSPROXY */
+
/*
* For new (i.e. not re-used) TLS sessions, increment the client's new
* TLS session rate counter. We enforce the limit here only for human
* here. We have a usable TLS session with the client, so no need to
* disable I/O, ... we can even be polite and send "421 ...".
*/
- if (props.requirecert && TLS_CERT_IS_TRUSTED(state->tls_context) == 0) {
+ if (requirecert && TLS_CERT_IS_TRUSTED(state->tls_context) == 0) {
/*
* Fetch and reject the next command (should be EHLO), then
const char *err;
int rate;
-#ifdef USE_TLSPROXY
- VSTREAM *proxy_stream;
-
-#endif
-
if (argc != 1) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: STARTTLS");
smtpd_chat_reply(state, "502 5.5.1 Error: command not implemented");
return (-1);
}
-#ifndef USE_TLS_PROXY
+#ifdef USE_TLSPROXY
+
+ /*
+ * Note: state->tlsproxy is left open when smtp_flush() calls longjmp(),
+ * so we garbage-collect the VSTREAM in smtpd_state_reset().
+ */
+#define PROXY_OPEN_FLAGS \
+ (TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT)
+
+ state->tlsproxy = tls_proxy_open(PROXY_OPEN_FLAGS, state->client,
+ state->addr, state->port,
+ var_smtpd_tmout);
+ if (state->tlsproxy == 0) {
+ state->error_mask |= MAIL_ERROR_SOFTWARE;
+ /* RFC 4954 Section 6. */
+ smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
+ return (-1);
+ }
+#else /* USE_TLSPROXY */
if (smtpd_tls_ctx == 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
/* RFC 4954 Section 6. */
smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
return (-1);
}
-#endif
+#endif /* USE_TLSPROXY */
/*
* Enforce TLS handshake rate limit when this client negotiated too many
smtpd_chat_reply(state,
"454 4.7.0 Error: too many new TLS sessions from %s",
state->namaddr);
+#ifdef USE_TLSPROXY
+ (void) vstream_fclose(state->tlsproxy);
+ state->tlsproxy = 0;
+#endif
return (-1);
}
-#ifndef USE_TLSPROXY
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
- /* Flush before we switch the stream's read/write routines. */
+ /* Flush before we switch read/write routines or file descriptors. */
smtp_flush(state->client);
- vstream_fpurge(state->client, VSTREAM_PURGE_READ); /* Yay! */
+ /* At this point there must not be any pending plaintext. */
+ vstream_fpurge(state->client, VSTREAM_PURGE_BOTH);
/*
* Reset all inputs to the initial state.
*/
smtpd_start_tls(state);
return (0);
-#else /* USE_TLSPROXY */
-
- /*
- * This is non-production code, for tlsproxy(8) load testing only. It
- * implements enough to enable the Postfix features that depend on TLS
- * encryption.
- */
-#define PROXY_OPEN_FLAGS \
- (TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT)
-
- proxy_stream = tls_proxy_open(PROXY_OPEN_FLAGS, state->client, state->addr,
- state->port, var_smtpd_tmout);
- if (proxy_stream == 0) {
- state->error_mask |= MAIL_ERROR_SOFTWARE;
- /* RFC 4954 Section 6. */
- smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
- return (-1);
- }
- smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
- smtp_flush(state->client);
- vstream_fpurge(state->client, VSTREAM_PURGE_READ);
-
- /*
- * Reset all inputs to the initial state.
- *
- * XXX RFC 2487 does not forbid the use of STARTTLS while mail transfer is
- * in progress, so we have to allow it even when it makes no sense.
- */
- helo_reset(state);
- mail_reset(state);
- rcpt_reset(state);
-#ifdef USE_SASL_AUTH
- if (var_smtpd_sasl_enable) {
- if (smtpd_sasl_is_active(state)) {
- smtpd_sasl_auth_reset(state);
- smtpd_sasl_deactivate(state);
- }
- smtpd_sasl_activate(state, VAR_SMTPD_SASL_TLS_OPTS,
- var_smtpd_sasl_tls_opts);
- }
-#endif
-
- /*
- * To insert tlsproxy(8) between this process and the SMTP client, we
- * swap the file descriptors between the proxy_stream and state->client
- * VSTREAMS, so that we don't have to worry about loss of all the
- * user-configurable state->client attributes (such as longjump buffers).
- */
- vstream_control(proxy_stream, VSTREAM_CTL_DOUBLE, VSTREAM_CTL_END);
- vstream_control(state->client, VSTREAM_CTL_SWAP_FD, proxy_stream,
- VSTREAM_CTL_END);
- (void) vstream_fclose(proxy_stream); /* direct-to-client stream! */
-
- /*
- * After plumbing the plaintext stream, receive the TLS context object.
- * For this we must use the same VSTREAM buffer that we also use to
- * receive subsequent SMTP commands.
- *
- * When the TLS handshake fails, the conversation is in an unknown state.
- * There is nothing we can do except to disconnect from the client.
- */
- state->tls_context = tls_proxy_state_receive(state->client);
- if (state->tls_context == 0)
- vstream_longjmp(state->client, SMTP_ERR_EOF);
-
- return (0);
-#endif /* USE_TLSPROXY */
}
/* tls_reset - undo STARTTLS */
if (vstream_feof(state->client) || vstream_ferror(state->client))
failure = 1;
vstream_fflush(state->client); /* NOT: smtp_flush() */
-#ifndef USE_TLSPROXY
+#ifdef USE_TLSPROXY
+ tls_proxy_context_free(state->tls_context);
+#else
tls_server_stop(smtpd_tls_ctx, state->client, var_smtpd_starttls_tmout,
failure, state->tls_context);
-#else
- tls_proxy_state_free(state->tls_context);
#endif
state->tls_context = 0;
}
#ifdef USE_TLS
if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) {
#ifdef USE_TLSPROXY
- msg_fatal("Wrapper-mode is unimplemented.");
+ /* We garbage-collect the VSTREAM in smtpd_state_reset() */
+ state->tlsproxy = tls_proxy_open(PROXY_OPEN_FLAGS, state->client,
+ state->addr, state->port,
+ var_smtpd_tmout);
+ if (state->tlsproxy == 0) {
+ msg_warn("Wrapper-mode request dropped from %s for service %s."
+ " TLS context initialization failed. For details see"
+ " earlier warnings in your logs.",
+ state->namaddr, state->service);
+ break;
+ }
#else /* USE_TLSPROXY */
if (smtpd_tls_ctx == 0) {
msg_warn("Wrapper-mode request dropped from %s for service %s."
state->namaddr, state->service);
break;
}
+#endif /* USE_TLSPROXY */
if (var_smtpd_cntls_limit > 0
&& !xclient_allowed
&& anvil_clnt
break;
}
smtpd_start_tls(state);
-#endif /* USE_TLSPROXY */
}
#endif
smtp_flush(state->client);
#endif
} else {
-#ifdef PREGREET
- if (*var_stress == 0 && strcmp(state->name, "unknown") == 0) {
- smtpd_chat_reply(state, "220-%s", var_smtpd_banner);
- smtp_flush(state->client);
- if (read_wait(vstream_fileno(state->client), 1) == 0) {
- int n = peekfd(vstream_fileno(state->client));
-
- smtpd_chat_query(state);
- msg_info("PREGREET %d from %s: %s",
- n, state->namaddr, vstring_str(state->buffer));
- state->error_mask |= MAIL_ERROR_POLICY;
- smtpd_chat_reply(state,
- "521 %s ESMTP not accepting connections",
- var_myhostname);
- /* Not: state->error_count++; */
- break;
- }
- }
-#endif
smtpd_chat_reply(state, "220 %s", var_smtpd_banner);
}
}
for (cp = STR(state->buffer); *cp && IS_SPACE_TAB(*cp); cp++)
/* void */ ;
if ((cp = dict_get(smtpd_cmd_filter, cp)) != 0) {
- msg_info("%s: replacing client command \"%s\" with \"%s\"",
+ msg_info("%s: replacing command \"%.100s\" with \"%.100s\"",
state->namaddr, STR(state->buffer), cp);
vstring_strcpy(state->buffer, cp);
}
if (getuid() == 0 || getuid() == var_owner_uid) {
if (var_smtpd_use_tls) {
#ifdef USE_TLS
+#ifndef USE_TLSPROXY
TLS_SERVER_INIT_PROPS props;
const char *cert_file;
int have_server_cert;
fpt_dgst = var_smtpd_tls_fpt_dgst);
else
msg_warn("No server certs available. TLS won't be enabled");
+#endif /* USE_TLSPROXY */
#else
msg_warn("TLS has been selected, but TLS support is not compiled in");
#endif
static const CONFIG_RAW_TABLE raw_table[] = {
VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, 1, 0,
- VAR_SMTPD_REJ_CONTACT, DEF_SMTPD_REJ_CONTACT, &var_smtpd_rej_contact, 0, 0,
+ VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
0,
};
* TLS related state.
*/
#ifdef USE_TLS
+#ifdef USE_TLSPROXY
+ VSTREAM *tlsproxy; /* tlsproxy(8) temp. handle */
+#endif
TLS_SESS_STATE *tls_context; /* TLS session state */
#endif
#include <mail_addr.h>
#include <post_mail.h>
#include <mail_error.h>
-#include <dsn_util.h>
+#include <smtp_reply_footer.h>
/* Application-specific. */
char *cp;
char *next;
char *end;
- ssize_t dsn_len;
/*
* Slow down clients that make errors. Sleep-on-anything slows down
if (state->error_count >= var_smtpd_soft_erlim)
sleep(delay = var_smtpd_err_sleep);
- /*
- * The caller may send multi-line text, so we can't assume that there is
- * only one SMTP reply code at the beginning of the response.
- */
va_start(ap, format);
vstring_vsprintf(state->buffer, format, ap);
va_end(ap);
- /*
- * Append the optional contact footer. Caution: as we append parts from
- * the buffer to itself, extend the buffer before updating it, or else we
- * have a dangling pointer bug.
- */
- if (*var_smtpd_rej_contact
- && (*(cp = STR(state->buffer)) == '4' || *cp == '5')
- && ISDIGIT(cp[1]) && ISDIGIT(cp[2]) && cp[3] == ' ') {
- dsn_len = dsn_valid(cp + 4);
- for (cp = var_smtpd_rej_contact, end = cp + strlen(cp);;) {
- if ((next = strstr(cp, "\\n")) != 0) {
- *next = 0;
- } else {
- next = end;
- }
- /* Append a clone of the SMTP reply code. */
- VSTRING_SPACE(state->buffer, sizeof("\r\n550 "));
- vstring_sprintf_append(state->buffer, "\r\n%.3s ",
- STR(state->buffer));
- /* Append a clone of the optional enhanced status code. */
- if (dsn_len > 0) {
- VSTRING_SPACE(state->buffer, dsn_len + 1);
- vstring_sprintf_append(state->buffer, "%.*s ",
- (int) dsn_len, STR(state->buffer) + 4);
- }
- /* Append the actual contact information. */
- smtpd_expand(state, state->buffer, cp, MAC_EXP_FLAG_APPEND);
- if (next < end) {
- *next = '\\';
- cp = next + 2;
- } else
- break;
- }
- }
+ if (*var_smtpd_rej_footer
+ && (*(cp = STR(state->buffer)) == '4' || *cp == '5'))
+ smtp_reply_footer(state->buffer, 0, var_smtpd_rej_footer,
+ STR(smtpd_expand_filter), smtpd_expand_lookup,
+ (char *) state);
+
/* All 5xx replies must have a 5.xx.xx detail code. */
for (cp = STR(state->buffer), end = cp + strlen(STR(state->buffer));;) {
if (var_soft_bounce) {
* Don't query main.cf parameters, as the result of expansion could
* reveal system-internal information in server replies.
*
+ * XXX: This said, multiple servers may be behind a single client-visible
+ * name or IP address, and each may generate its own logs. Therefore, it
+ * may be useful to expose the replying MTA id (myhostname) in the
+ * contact footer, to identify the right logs. So while we don't expose
+ * the raw configuration dictionary, we do expose "$myhostname" as
+ * expanded in var_myhostname.
+ *
* Return NULL only for non-existent names.
*/
- if (STREQ(name, MAIL_ATTR_ACT_CLIENT)) {
+ if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
+ return (var_myhostname);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT)) {
return (state->namaddr);
} else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
return (state->port);
state->dsn_buf = vstring_alloc(100);
state->dsn_orcpt_buf = vstring_alloc(100);
#ifdef USE_TLS
+#ifdef USE_TLSPROXY
+ state->tlsproxy = 0;
+#endif
state->tls_context = 0;
#endif
vstring_free(state->dsn_buf);
if (state->dsn_orcpt_buf)
vstring_free(state->dsn_orcpt_buf);
+#if (defined(USE_TLS) && defined(USE_TLSPROXY))
+ if (state->tlsproxy) /* still open after longjmp */
+ vstream_fclose(state->tlsproxy);
+#endif
}
extern VSTREAM *tls_proxy_open(int, VSTREAM *, const char *,
const char *, int);
-extern TLS_SESS_STATE *tls_proxy_state_receive(VSTREAM *);
-extern void tls_proxy_state_free(TLS_SESS_STATE *);
-extern int tls_proxy_print_state(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
-extern int tls_proxy_scan_state(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *);
+extern void tls_proxy_context_free(TLS_SESS_STATE *);
+extern int tls_proxy_context_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
#endif
/* const char *peer_port;
/* int timeout;
/*
-/* TLS_SESS_STATE *tls_proxy_state_receive(proxy_stream)
+/* TLS_SESS_STATE *tls_proxy_context_receive(proxy_stream)
/* VSTREAM *proxy_stream;
/*
-/* void tls_proxy_state_free(tls_context)
+/* void tls_proxy_context_free(tls_context)
/* TLS_SESS_STATE *tls_context;
/* DESCRIPTION
/* tls_proxy_open() prepares for inserting the tlsproxy(8)
/* buffer, timeout, etc.). Once the file descriptors are
/* swapped, the proxy stream should be closed.
/*
-/* tls_proxy_state_receive() receives the TLS context object
+/* tls_proxy_context_receive() receives the TLS context object
/* for the named proxy stream. This function must be called
/* only if the TLS_PROXY_SEND_CONTEXT flag was specified in
/* the tls_proxy_open() call. Note that this TLS context object
/* is not compatible with tls_session_free(). It must be given
-/* to tls_proxy_state_free() instead.
+/* to tls_proxy_context_free() instead.
/*
/* After this, the proxy_stream is ready for plain-text I/O.
/*
-/* tls_proxy_state_free() destroys a TLS context object that
-/* was received with tls_proxy_state_receive().
+/* tls_proxy_context_free() destroys a TLS context object that
+/* was received with tls_proxy_context_receive().
/*
/* Arguments:
/* .IP flags
/* .IP proxy_stream
/* Stream from tls_proxy_open().
/* .IP tls_context
-/* TLS session object from tls_proxy_state_receive().
+/* TLS session object from tls_proxy_context_receive().
/* LICENSE
/* .ad
/* .fi
return (tlsproxy_stream);
}
-/* tls_proxy_state_receive - receive TLS session object from tlsproxy(8) */
+/* tls_proxy_context_receive - receive TLS session object from tlsproxy(8) */
-TLS_SESS_STATE *tls_proxy_state_receive(VSTREAM *proxy_stream)
+TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *proxy_stream)
{
TLS_SESS_STATE *tls_context;
tls_context = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context));
if (attr_scan(proxy_stream, ATTR_FLAG_STRICT,
- ATTR_TYPE_FUNC, tls_proxy_scan_state, (char *) tls_context,
+ ATTR_TYPE_FUNC, tls_proxy_context_scan, (char *) tls_context,
ATTR_TYPE_END) != 1) {
- tls_proxy_state_free(tls_context);
+ tls_proxy_context_free(tls_context);
return (0);
} else {
return (tls_context);
}
}
-/* tls_proxy_state_free - destroy object from tls_proxy_state_receive() */
+/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */
-void tls_proxy_state_free(TLS_SESS_STATE *tls_context)
+void tls_proxy_context_free(TLS_SESS_STATE *tls_context)
{
if (tls_context->peer_CN)
myfree(tls_context->peer_CN);
/* SYNOPSIS
/* #include <tls_proxy.h>
/*
-/* int tls_proxy_print_state(print_fn, stream, flags, ptr)
+/* int tls_proxy_context_print(print_fn, stream, flags, ptr)
/* ATTR_PRINT_MASTER_FN print_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
-/* tls_proxy_print_state() writes a TLS_SESS_STATE structure
+/* tls_proxy_context_print() writes a TLS_SESS_STATE structure
/* to the named stream using the specified attribute print
/* routine. TLS_SESS_STATE() is meant to be passed as a call-back
/* to attr_print(), thusly:
/*
-/* ... ATTR_TYPE_FUNC, tls_proxy_print_state, (void *) tls_context, ...
+/* ... ATTR_TYPE_FUNC, tls_proxy_context_print, (void *) tls_context, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE
#include <tls.h>
#include <tls_proxy.h>
-/* tls_proxy_print_state - send TLS session state over stream */
+/* tls_proxy_context_print - send TLS session state over stream */
-int tls_proxy_print_state(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
int flags, void *ptr)
{
TLS_SESS_STATE *tp = (TLS_SESS_STATE *) ptr;
/* SYNOPSIS
/* #include <tls_proxy.h>
/*
-/* int tls_proxy_scan_state(scan_fn, stream, flags, ptr)
+/* int tls_proxy_context_scan(scan_fn, stream, flags, ptr)
/* ATTR_SCAN_MASTER_FN scan_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
-/* tls_proxy_scan_state() reads a TLS_SESS_STATE structure
+/* tls_proxy_context_scan() reads a TLS_SESS_STATE structure
/* from the named stream using the specified attribute scan
-/* routine. tls_proxy_scan_state() is meant to be passed as
+/* routine. tls_proxy_context_scan() is meant to be passed as
/* a call-back to attr_scan(), thusly:
/*
-/* ... ATTR_TYPE_FUNC, tls_proxy_scan_state, (void *) tls_context, ...
+/* ... ATTR_TYPE_FUNC, tls_proxy_context_scan, (void *) tls_context, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE
#include <tls.h>
#include <tls_proxy.h>
-/* tls_proxy_scan_state - receive TLS session state from stream */
+/* tls_proxy_context_scan - receive TLS session state from stream */
-int tls_proxy_scan_state(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
int flags, void *ptr)
{
TLS_SESS_STATE *tls_context = (TLS_SESS_STATE *) ptr;
}
if ((state->req_flags & TLS_PROXY_FLAG_SEND_CONTEXT) != 0
&& (attr_print(state->plaintext_stream, ATTR_FLAG_NONE,
- ATTR_TYPE_FUNC, tls_proxy_print_state,
+ ATTR_TYPE_FUNC, tls_proxy_context_print,
(char *) state->tls_context, ATTR_TYPE_END) != 0
|| vstream_fflush(state->plaintext_stream) != 0)) {
msg_warn("cannot send TLS context: %m");