-TCONFIG_BOOL_TABLE
-TCONFIG_INT_FN_TABLE
-TCONFIG_INT_TABLE
+-TCONFIG_LONG_FN_TABLE
+-TCONFIG_LONG_TABLE
-TCONFIG_STR_FN_TABLE
-TCONFIG_STR_TABLE
-TCONFIG_TIME_FN_TABLE
20050706
- Robustness: the connection cache client now disables caching
+ Robustness: the SMTP client now disables connection caching
when it is unable to communicate with the scache(8) server,
instead of looping forever. File: global/scache_clnt.c.
Bugfix: the smtpd_sasl_authenticated_header code did not
check if SASL was actually enabled. File: smtpd/smtpd.c.
+20050720
+
+ Feature: reverse client hostname. This is set at connection
+ time with information from the SMTP client address->name
+ mapping, and can be overruled with the REVERSE_NAME attribute
+ in the XCLIENT command. File: smtpd/smtpd_peer.c.
+
+ Cleanup: renaming of several confusing restriction names:
+ reject_unknown_client -> reject_unknown_client_hostname,
+ reject_unknown_hostname -> reject_unknown_helo_hostname,
+ reject_invalid_hostname -> reject_invalid_helo_hostname,
+ and reject_non_fqdn_hostname -> reject_non_fqdn_helo_hostname.
+ The old names are still recognized and documented. Files:
+ global/mail_params.h, smtpd/smtpd.c, smtpd/smtpd_check.c.
+
+ Feature: reject_unknown_reverse_client_hostname. This rejects
+ clients that have no address to name mapping (unlike the
+ reject_unknown_client_hostname feature which requires that
+ the address->name and name->address mappings resolve to the
+ client IP address). Files: global/mail_params.h,
+ smtpd/smtpd_peer.c, smtpd/smtpd.c, smtpd/smtpd_check.c.
+
Open problems:
+ Med: when the cleanup server bounces local mail that should
+ be content inspected, the resulting DSN should be content
+ inspected, otherwise a local user can bypass content
+ inspection.
+
Look for systems with XPG basename() declared in <libgen.h>,
and prepare for phasing out the Postfix-supplied one.
Beware, however, that XPG basename() takes (char *), and
local(8) delivery agent's mailbox_command_maps feature:
/etc/postfix/main.cf:
- mailbox_command_maps = /etc/postfix/mailbox_commands
+ mailbox_command_maps = hash:/etc/postfix/mailbox_commands
/etc/postfix/mailbox_commands:
you /path/to/maildrop -d ${USER}
P\bPo\bos\bst\btf\bfi\bix\bx r\bre\bes\bst\btr\bri\bic\bct\bti\bio\bon\bn c\bcl\bla\bas\bss\bse\bes\bs
The Postfix SMTP server supports access restrictions such as reject_rbl_client
-or reject_unknown_client on the right-hand side of SMTP server access(5)
-tables. This allows you to implement different junk mail restrictions for
+or reject_unknown_client_hostname on the right-hand side of SMTP server access
+(5) tables. This allows you to implement different junk mail restrictions for
different clients or users.
Having to specify lists of access restrictions for every recipient becomes
/etc/postfix/main.cf:
smtpd_restriction_classes = restrictive, permissive
- restrictive = reject_unknown_sender_domain reject_unknown_client ...
+ # With Postfix < 2.3 specify reject_unknown_client.
+ restrictive = reject_unknown_sender_domain
+ reject_unknown_client_hostname ...
permissive = permit
smtpd_recipient_restrictions =
smtpd_client_restrictions = permit_mynetworks, reject
# Don't talk to mail systems that don't know their own hostname.
- smtpd_helo_restrictions = reject_unknown_hostname
+ # With Postfix < 2.3, specify reject_unknown_hostname.
+ smtpd_helo_restrictions = reject_unknown_helo_hostname
# Don't accept mail from domains that don't exist.
smtpd_sender_restrictions = reject_unknown_sender_domain
2 smtpd_recipient_restrictions =
3 permit_mynetworks
4 check_helo_access hash:/etc/postfix/helo_access
-5 reject_unknown_hostname
+5 reject_unknown_helo_hostname
6 reject_unauth_destination
7
8 /etc/postfix/helo_access:
9 localhost.localdomain PERMIT
Line 5 rejects mail from hosts that don't specify a proper hostname in the HELO
-command. Lines 4 and 9 make an exception to allow mail from some machine that
-announces itself with "HELO localhost.localdomain".
+command (with Postfix < 2.3, specify reject_unknown_hostname). Lines 4 and 9
+make an exception to allow mail from some machine that announces itself with
+"HELO localhost.localdomain".
The problem with this configuration is that smtpd_recipient_restrictions
evaluates to PERMIT for EVERY host that announces itself as
recipient=bar@foo.tld
client_address=1.2.3.4
client_name=another.domain.tld
+ reverse_client_name=another.domain.tld
instance=123.456.7
sasl_method=plain
sasl_username=you
* The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an
IPv6 address in the form 1:2:3::4:5:6.
+ * For a discussion of the differences between reverse and verified
+ client_name information, see the reject_unknown_client_hostname discussion
+ in the postconf(5) document.
+
* An attribute name must not contain "=", null or newline, and an attribute
value must not contain null or newline.
<blockquote>
<pre>
/etc/postfix/main.cf:
- <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a> = /etc/postfix/mailbox_commands
+ <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a> = hash:/etc/postfix/mailbox_commands
/etc/postfix/mailbox_commands:
you /path/to/maildrop -d ${USER}
<h2>Postfix restriction classes</h2>
<p> The Postfix SMTP server supports access restrictions such as
-<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> or <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a> on the right-hand side
+<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> or <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> on the right-hand side
of SMTP server <a href="access.5.html">access(5)</a> tables. This allows you to implement
different junk mail restrictions for different clients or users.
</p>
<pre>
/etc/postfix/main.cf:
<a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> = restrictive, permissive
- restrictive = <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a> ...
+ # With Postfix < 2.3 specify <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client</a>.
+ restrictive = <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> ...
permissive = permit
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, reject
# Don't talk to mail systems that don't know their own hostname.
- <a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
+ # With Postfix < 2.3, specify <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_hostname</a>.
+ <a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a>
# Don't accept mail from domains that don't exist.
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> = <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>
2 <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
3 <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>
4 <a href="postconf.5.html#check_helo_access">check_helo_access</a> hash:/etc/postfix/helo_access
-5 <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
+5 <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a>
6 <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
7
8 /etc/postfix/helo_access:
</pre>
<p> Line 5 rejects mail from hosts that don't specify a proper
-hostname in the HELO command. Lines 4 and 9 make an exception to
+hostname in the HELO command (with Postfix < 2.3, specify
+<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_hostname</a>). Lines 4 and 9 make an exception to
allow mail from some machine that announces itself with "HELO
localhost.localdomain". </p>
recipient=bar@foo.tld
client_address=1.2.3.4
client_name=another.domain.tld
+reverse_client_name=another.domain.tld
instance=123.456.7
sasl_method=plain
sasl_username=you
1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6.
</p>
+ <li> <p> For a discussion of the differences between reverse
+ and verified client_name information, see the
+ <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> discussion in the <a href="postconf.5.html">postconf(5)</a>
+ document. </p>
+
<li> <p> An attribute name must not contain "=", null or newline,
and an attribute value must not contain null or newline. </p>
<dt><b>$client_name</b></dt>
-<dd>The client hostname or "unknown". </dd>
+<dd>The client hostname or "unknown". See <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a>
+for more details. </dd>
+
+<dt><b>$reverse_client_name</b></dt>
+
+<dd>The client hostname from address->name lookup, or "unknown".
+See <a href="postconf.5.html#reject_unknown_reverse_client_hostname">reject_unknown_reverse_client_hostname</a> for more details. </dd>
<dt><b>$helo_name</b></dt>
(default: empty)</b></DT><DD>
<p>
-The names of message delivery transports that should not be delivered
-to unless someone issues "<b>sendmail -q</b>" or equivalent. Specify zero
+The names of message delivery transports that should not deliver mail
+unless someone issues "<b>sendmail -q</b>" or equivalent. Specify zero
or more names of mail delivery transports names that appear in the
first field of master.cf.
</p>
</p>
<p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
</p>
<p>
<p>
The numerical Postfix SMTP server response code when the client
-HELO or EHLO command parameter is rejected by the <a href="postconf.5.html#reject_invalid_hostname">reject_invalid_hostname</a>
+HELO or EHLO command parameter is rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
restriction.
</p>
<p> Examples: </p>
-<p> The Postfix < 2.2 backwards compatible setting: always rewrite
+<p> The Postfix < 2.2 backwards compatible setting: always rewrite
message headers, and always append my own domain to incomplete
header addresses. </p>
<p>
The numerical Postfix SMTP server reply code when a client request
-is rejected by the <a href="postconf.5.html#reject_non_fqdn_hostname">reject_non_fqdn_hostname</a>, <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a>
+is rejected by the <a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>, <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a>
or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a> restriction.
</p>
description above for additional RBL related configuration parameters.
This feature is available in Postfix 2.0 and later. </dd>
-<dt><b><a name="reject_unknown_client">reject_unknown_client</a></b></dt>
-
-<dd>Reject the request when the client IP address has no PTR (address
-to name) record in the DNS, or when the PTR record does not have
-a matching A (name to address) record. <br> The <a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a>
-parameter specifies the response code for rejected requests (default:
-450). The reply is always 450 in case the hostname lookup failed
-due to a temporary problem. </dd>
+<dt><b><a name="reject_unknown_client_hostname">reject_unknown_client_hostname</a></b> (with Postfix < 2.3: reject_unknown_client)</dt>
+
+<dd>Reject the request when 1) the client IP address->name mapping
+fails, 2) the name->address mapping fails, or 3) the name->address
+mapping does not match the client IP address. <br> This is a
+stronger restriction than the <a href="postconf.5.html#reject_unknown_reverse_client_hostname">reject_unknown_reverse_client_hostname</a>
+feature, which triggers only under condition 1) above. <br> The
+<a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> parameter specifies the response code
+for rejected requests (default: 450). The reply is always 450 in
+case the address->name or name->address lookup failed due to
+a temporary problem. </dd>
+
+<dt><b><a name="reject_unknown_reverse_client_hostname">reject_unknown_reverse_client_hostname</a></b></dt>
+
+<dd>Reject the request when the client IP address has no address->name
+mapping. <br> This is a weaker restriction than the
+<a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> feature, which requires not only
+that the address->name and name->address mappings exist, but
+also that the two mappings reproduce the client IP address. <br>
+The <a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> parameter specifies the response
+code for rejected requests (default: 450). The reply is always 450
+in case the address->name lookup failed due to a temporary
+problem. <br> This feature is available in Postfix version 2.3 and
+later. </dd>
</dl>
</p>
<pre>
-<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a>
+<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a>
</pre>
use DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later. </dd>
-<dt><b><a name="reject_invalid_hostname">reject_invalid_hostname</a></b></dt>
+<dt><b><a name="reject_invalid_helo_hostname">reject_invalid_helo_hostname</a></b> (with Postfix < 2.3: reject_invalid_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname syntax is
invalid. <br> The <a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> specifies the response
code to rejected requests (default: 501).</dd>
-<dt><b><a name="reject_non_fqdn_hostname">reject_non_fqdn_hostname</a></b></dt>
+<dt><b><a name="reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a></b> (with Postfix < 2.3: reject_non_fqdn_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname is not in
fully-qualified domain form, as required by the RFC. <br> The
<a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> parameter specifies the response code to
rejected requests (default: 504).</dd>
-<dt><b><a name="reject_unknown_hostname">reject_unknown_hostname</a></b></dt>
+<dt><b><a name="reject_unknown_helo_hostname">reject_unknown_helo_hostname</a></b> (with Postfix < 2.3: reject_unknown_hostname)</dt>
-<dd>Reject the request when the HELO or EHLO hostname has no DNS
-A or MX record. <br> The <a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> specifies
-the response code to rejected requests (default: 450).</dd>
+<dd>Reject the request when the HELO or EHLO hostname has no DNS A
+or MX record. <br> The <a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> specifies the
+response code to rejected requests (default: 450). </dd>
</dl>
</p>
<pre>
-<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_invalid_hostname">reject_invalid_hostname</a>
-<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
+<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
+<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a>
</pre>
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.</dd>
-<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (Postfix 2.0 name: check_recipient_maps)</dt>
+<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
<dd> Reject the request when the RCPT TO address is not listed in
the list of valid recipients for its domain class. See the
<p>
The numerical Postfix SMTP server response code when a client
without valid address <=> name mapping is rejected by the
-<a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a> restriction. The SMTP server always replies
+<a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> restriction. The SMTP server always replies
with 450 when the mapping failed due to a temporary error condition.
</p>
<p>
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the
-<a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a> restriction.
+<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
</p>
<p>
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
The numerical Postfix SMTP server response code
when the client HELO or EHLO command parameter is
- rejected by the <a href="postconf.5.html#reject_invalid_hostname">reject_invalid_hostname</a> restric-
- tion.
+ rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
+ restriction.
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
The numerical Postfix SMTP server response code
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
The numerical Postfix SMTP server reply code when a
client request is rejected by the
- <a href="postconf.5.html#reject_non_fqdn_hostname">reject_non_fqdn_hostname</a>, <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or
- <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a> restriction.
+ <a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
+ <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
+ restriction.
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "reject" restriction.
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a client request is rejected by the
+ The numerical Postfix SMTP server response code
+ when a client request is rejected by the
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender or recipient address is rejected by
+ The numerical Postfix SMTP server response code
+ when a sender or recipient address is rejected by
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a client without valid address <=> name map-
- ping is rejected by the <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a>
- restriction.
+ The numerical Postfix SMTP server response code
+ when a client without valid address <=> name map-
+ ping is rejected by the reject_unknown_client_host-
+ name restriction.
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when the hostname specified with the HELO or EHLO
- command is rejected by the <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
- restriction.
+ The numerical Postfix SMTP server response code
+ when the hostname specified with the HELO or EHLO
+ command is rejected by the
+ <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
- The default SMTP server response template for a
- request that is rejected by an RBL-based restric-
+ The default SMTP server response template for a
+ request that is rejected by an RBL-based restric-
tion.
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
<b>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 main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
and most Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
The internet hostname of this mail system.
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
- The list of "trusted" SMTP clients that have more
+ The list of "trusted" SMTP clients that have more
privileges than "strangers".
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
sions (user+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
- The text that follows the 220 status code in the
+ The text that follows the 220 status code in the
SMTP greeting banner.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
- List of commands that causes the Postfix SMTP
- server to immediately terminate the session with a
+ List of commands that causes the Postfix SMTP
+ server to immediately terminate the session with a
221 code.
<b>SEE ALSO</b>
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
.IP "\fB$client_address\fR"
The client IP address.
.IP "\fB$client_name\fR"
-The client hostname or "unknown".
+The client hostname or "unknown". See reject_unknown_client_hostname
+for more details.
+.IP "\fB$reverse_client_name\fR"
+The client hostname from address->name lookup, or "unknown".
+See reject_unknown_reverse_client_hostname for more details.
.IP "\fB$helo_name\fR"
The hostname given in HELO or EHLO command or empty string.
.IP "\fB$rbl_class\fR"
.PP
This feature is available in Postfix 2.0 and later.
.SH defer_transports (default: empty)
-The names of message delivery transports that should not be delivered
-to unless someone issues "\fBsendmail -q\fR" or equivalent. Specify zero
+The names of message delivery transports that should not deliver mail
+unless someone issues "\fBsendmail -q\fR" or equivalent. Specify zero
or more names of mail delivery transports names that appear in the
first field of master.cf.
.PP
Optional pathname of a mailbox file relative to a \fBlocal\fR(8) user's
home directory.
.PP
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
.PP
The precedence of \fBlocal\fR(8) delivery features from high to low is:
aliases, .forward files, mailbox_transport, mailbox_command_maps,
block all mail to a site.
.SH invalid_hostname_reject_code (default: 501)
The numerical Postfix SMTP server response code when the client
-HELO or EHLO command parameter is rejected by the reject_invalid_hostname
+HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname
restriction.
.PP
Do not change this unless you have a complete understanding of RFC 821.
\fBlocal\fR(8) \fBaliases\fR(5) database.
.SH non_fqdn_reject_code (default: 504)
The numerical Postfix SMTP server reply code when a client request
-is rejected by the reject_non_fqdn_hostname, reject_non_fqdn_sender
+is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender
or reject_non_fqdn_recipient restriction.
.SH notify_classes (default: resource, software)
The list of error classes that are reported to the postmaster. The
any A record under \fIrbl_domain\fR. See the reject_rbl_client
description above for additional RBL related configuration parameters.
This feature is available in Postfix 2.0 and later.
-.IP "\fBreject_unknown_client\fR"
-Reject the request when the client IP address has no PTR (address
-to name) record in the DNS, or when the PTR record does not have
-a matching A (name to address) record.
+.IP "\fBreject_unknown_client_hostname\fR (with Postfix < 2.3: reject_unknown_client)"
+Reject the request when 1) the client IP address->name mapping
+fails, 2) the name->address mapping fails, or 3) the name->address
+mapping does not match the client IP address.
.br
-The unknown_client_reject_code
-parameter specifies the response code for rejected requests (default:
-450). The reply is always 450 in case the hostname lookup failed
-due to a temporary problem.
+This is a
+stronger restriction than the reject_unknown_reverse_client_hostname
+feature, which triggers only under condition 1) above.
+.br
+The
+unknown_client_reject_code parameter specifies the response code
+for rejected requests (default: 450). The reply is always 450 in
+case the address->name or name->address lookup failed due to
+a temporary problem.
+.IP "\fBreject_unknown_reverse_client_hostname\fR"
+Reject the request when the client IP address has no address->name
+mapping.
+.br
+This is a weaker restriction than the
+reject_unknown_client_hostname feature, which requires not only
+that the address->name and name->address mappings exist, but
+also that the two mappings reproduce the client IP address.
+.br
+The unknown_client_reject_code parameter specifies the response
+code for rejected requests (default: 450). The reply is always 450
+in case the address->name lookup failed due to a temporary
+problem.
+.br
+This feature is available in Postfix version 2.3 and
+later.
.PP
In addition, you can use any of the following
generic restrictions. These restrictions are applicable in
.nf
.na
.ft C
-smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
+smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname
.fi
.ad
.ft R
Note: a result of "OK" is not allowed for safety reasons. Instead,
use DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later.
-.IP "\fBreject_invalid_hostname\fR"
+.IP "\fBreject_invalid_helo_hostname\fR (with Postfix < 2.3: reject_invalid_hostname)"
Reject the request when the HELO or EHLO hostname syntax is
invalid.
.br
The invalid_hostname_reject_code specifies the response
code to rejected requests (default: 501).
-.IP "\fBreject_non_fqdn_hostname\fR"
+.IP "\fBreject_non_fqdn_helo_hostname\fR (with Postfix < 2.3: reject_non_fqdn_hostname)"
Reject the request when the HELO or EHLO hostname is not in
fully-qualified domain form, as required by the RFC.
.br
The
non_fqdn_reject_code parameter specifies the response code to
rejected requests (default: 504).
-.IP "\fBreject_unknown_hostname\fR"
-Reject the request when the HELO or EHLO hostname has no DNS
-A or MX record.
+.IP "\fBreject_unknown_helo_hostname\fR (with Postfix < 2.3: reject_unknown_hostname)"
+Reject the request when the HELO or EHLO hostname has no DNS A
+or MX record.
.br
-The unknown_hostname_reject_code specifies
-the response code to rejected requests (default: 450).
+The unknown_hostname_reject_code specifies the
+response code to rejected requests (default: 450).
.PP
Other restrictions that are valid in this context:
.IP \(bu
.nf
.na
.ft C
-smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
-smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
+smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname
+smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname
.fi
.ad
.ft R
The unknown_address_reject_code parameter specifies
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.
-.IP "\fBreject_unlisted_recipient\fR (Postfix 2.0 name: check_recipient_maps)"
+.IP "\fBreject_unlisted_recipient\fR (with Postfix 2.0: check_recipient_maps)"
Reject the request when the RCPT TO address is not listed in
the list of valid recipients for its domain class. See the
smtpd_reject_unlisted_recipient parameter description for details.
.SH unknown_client_reject_code (default: 450)
The numerical Postfix SMTP server response code when a client
without valid address <=> name mapping is rejected by the
-reject_unknown_client restriction. The SMTP server always replies
+reject_unknown_client_hostname restriction. The SMTP server always replies
with 450 when the mapping failed due to a temporary error condition.
.PP
Do not change this unless you have a complete understanding of RFC 821.
.SH unknown_hostname_reject_code (default: 450)
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the
-reject_unknown_hostname restriction.
+reject_unknown_helo_hostname restriction.
.PP
Do not change this unless you have a complete understanding of RFC 821.
.SH unknown_local_recipient_reject_code (default: 550)
client request is rejected by the "defer" restriction.
.IP "\fBinvalid_hostname_reject_code (501)\fR"
The numerical Postfix SMTP server response code when the client
-HELO or EHLO command parameter is rejected by the reject_invalid_hostname
+HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname
restriction.
.IP "\fBmaps_rbl_reject_code (554)\fR"
The numerical Postfix SMTP server response code when a remote SMTP
reject_rhsbl_sender or reject_rhsbl_recipient restriction.
.IP "\fBnon_fqdn_reject_code (504)\fR"
The numerical Postfix SMTP server reply code when a client request
-is rejected by the reject_non_fqdn_hostname, reject_non_fqdn_sender
+is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender
or reject_non_fqdn_recipient restriction.
.IP "\fBreject_code (554)\fR"
The numerical Postfix SMTP server response code when a remote SMTP
.IP "\fBunknown_client_reject_code (450)\fR"
The numerical Postfix SMTP server response code when a client
without valid address <=> name mapping is rejected by the
-reject_unknown_client restriction.
+reject_unknown_client_hostname restriction.
.IP "\fBunknown_hostname_reject_code (450)\fR"
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the
-reject_unknown_hostname restriction.
+reject_unknown_helo_hostname restriction.
.PP
Available in Postfix version 2.0 and later:
.IP "\fBdefault_rbl_reply (see 'postconf -d' output)\fR"
s;\bpermit_sasl_authenticated\b;<a href="postconf.5.html#permit_sasl_authenticated">$&</a>;g;
s;\bpermit_tls_clientcerts\b;<a href="postconf.5.html#permit_tls_clientcerts">$&</a>;g;
s;\bpermit_tls_all_clientcerts\b;<a href="postconf.5.html#permit_tls_all_clientcerts">$&</a>;g;
- s;\breject_unknown_client\b;<a href="postconf.5.html#reject_unknown_client">$&</a>;g;
+ s;\breject_unknown_client_hostname\b;<a href="postconf.5.html#reject_unknown_client_hostname">$&</a>;g;
+ s;\breject_unknown_client\b;<a href="postconf.5.html#reject_unknown_client_hostname">$&</a>;g;
+ s;\breject_unknown_reverse_client_hostname\b;<a href="postconf.5.html#reject_unknown_reverse_client_hostname">$&</a>;g;
+ s;\breject_unknown_forward_client_hostname\b;<a href="postconf.5.html#reject_unknown_forward_client_hostname">$&</a>;g;
s;\breject_rbl_client\b;<a href="postconf.5.html#reject_rbl_client">$&</a>;g;
s;\breject_rhsbl_client\b;<a href="postconf.5.html#reject_rhsbl_client">$&</a>;g;
# Access restrictions - helo
s;\bcheck_helo_access\b;<a href="postconf.5.html#check_helo_access">$&</a>;g;
- s;\breject_invalid_hostname\b;<a href="postconf.5.html#reject_invalid_hostname">$&</a>;g;
- s;\breject_non_fqdn_hostname\b;<a href="postconf.5.html#reject_non_fqdn_hostname">$&</a>;g;
- s;\breject_unknown_hostname\b;<a href="postconf.5.html#reject_unknown_hostname">$&</a>;g;
+ s;\breject_invalid_helo_hostname\b;<a href="postconf.5.html#reject_invalid_helo_hostname">$&</a>;g;
+ s;\breject_invalid_hostname\b;<a href="postconf.5.html#reject_invalid_helo_hostname">$&</a>;g;
+ s;\breject_non_fqdn_helo_hostname\b;<a href="postconf.5.html#reject_non_fqdn_helo_hostname">$&</a>;g;
+ s;\breject_non_fqdn_hostname\b;<a href="postconf.5.html#reject_non_fqdn_helo_hostname">$&</a>;g;
+ s;\breject_unknown_helo_hostname\b;<a href="postconf.5.html#reject_unknown_helo_hostname">$&</a>;g;
+ s;\breject_unknown_hostname\b;<a href="postconf.5.html#reject_unknown_helo_hostname">$&</a>;g;
# Access restrictions - sender
<blockquote>
<pre>
/etc/postfix/main.cf:
- mailbox_command_maps = /etc/postfix/mailbox_commands
+ mailbox_command_maps = hash:/etc/postfix/mailbox_commands
/etc/postfix/mailbox_commands:
you /path/to/maildrop -d ${USER}
<h2>Postfix restriction classes</h2>
<p> The Postfix SMTP server supports access restrictions such as
-reject_rbl_client or reject_unknown_client on the right-hand side
+reject_rbl_client or reject_unknown_client_hostname on the right-hand side
of SMTP server access(5) tables. This allows you to implement
different junk mail restrictions for different clients or users.
</p>
<pre>
/etc/postfix/main.cf:
smtpd_restriction_classes = restrictive, permissive
- restrictive = reject_unknown_sender_domain reject_unknown_client ...
+ # With Postfix < 2.3 specify reject_unknown_client.
+ restrictive = reject_unknown_sender_domain reject_unknown_client_hostname ...
permissive = permit
smtpd_recipient_restrictions =
smtpd_client_restrictions = permit_mynetworks, reject
# Don't talk to mail systems that don't know their own hostname.
- smtpd_helo_restrictions = reject_unknown_hostname
+ # With Postfix < 2.3, specify reject_unknown_hostname.
+ smtpd_helo_restrictions = reject_unknown_helo_hostname
# Don't accept mail from domains that don't exist.
smtpd_sender_restrictions = reject_unknown_sender_domain
2 smtpd_recipient_restrictions =
3 permit_mynetworks
4 check_helo_access hash:/etc/postfix/helo_access
-5 reject_unknown_hostname
+5 reject_unknown_helo_hostname
6 reject_unauth_destination
7
8 /etc/postfix/helo_access:
</pre>
<p> Line 5 rejects mail from hosts that don't specify a proper
-hostname in the HELO command. Lines 4 and 9 make an exception to
+hostname in the HELO command (with Postfix < 2.3, specify
+reject_unknown_hostname). Lines 4 and 9 make an exception to
allow mail from some machine that announces itself with "HELO
localhost.localdomain". </p>
recipient=bar@foo.tld
client_address=1.2.3.4
client_name=another.domain.tld
+reverse_client_name=another.domain.tld
instance=123.456.7
sasl_method=plain
sasl_username=you
1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6.
</p>
+ <li> <p> For a discussion of the differences between reverse
+ and verified client_name information, see the
+ reject_unknown_client_hostname discussion in the postconf(5)
+ document. </p>
+
<li> <p> An attribute name must not contain "=", null or newline,
and an attribute value must not contain null or newline. </p>
<dt><b>$client_name</b></dt>
-<dd>The client hostname or "unknown". </dd>
+<dd>The client hostname or "unknown". See reject_unknown_client_hostname
+for more details. </dd>
+
+<dt><b>$reverse_client_name</b></dt>
+
+<dd>The client hostname from address->name lookup, or "unknown".
+See reject_unknown_reverse_client_hostname for more details. </dd>
+
+#<dt><b>$forward_client_name</b></dt>
+#
+#<dd>The client hostname from address->name lookup followed by
+#name->address lookup, or "unknown". See
+#reject_unknown_forward_client_hostname for more details. </dd>
<dt><b>$helo_name</b></dt>
%PARAM defer_transports
<p>
-The names of message delivery transports that should not be delivered
-to unless someone issues "<b>sendmail -q</b>" or equivalent. Specify zero
+The names of message delivery transports that should not deliver mail
+unless someone issues "<b>sendmail -q</b>" or equivalent. Specify zero
or more names of mail delivery transports names that appear in the
first field of master.cf.
</p>
</p>
<p>
-Specify a pathname ending "/" for qmail-style delivery.
+Specify a pathname ending in "/" for qmail-style delivery.
</p>
<p>
<p>
The numerical Postfix SMTP server response code when the client
-HELO or EHLO command parameter is rejected by the reject_invalid_hostname
+HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname
restriction.
</p>
description above for additional RBL related configuration parameters.
This feature is available in Postfix 2.0 and later. </dd>
-<dt><b><a name="reject_unknown_client">reject_unknown_client</a></b></dt>
-
-<dd>Reject the request when the client IP address has no PTR (address
-to name) record in the DNS, or when the PTR record does not have
-a matching A (name to address) record. <br> The unknown_client_reject_code
-parameter specifies the response code for rejected requests (default:
-450). The reply is always 450 in case the hostname lookup failed
-due to a temporary problem. </dd>
+<dt><b><a name="reject_unknown_client_hostname">reject_unknown_client_hostname</a></b> (with Postfix < 2.3: reject_unknown_client)</dt>
+
+<dd>Reject the request when 1) the client IP address->name mapping
+fails, 2) the name->address mapping fails, or 3) the name->address
+mapping does not match the client IP address. <br> This is a
+stronger restriction than the reject_unknown_reverse_client_hostname
+feature, which triggers only under condition 1) above. <br> The
+unknown_client_reject_code parameter specifies the response code
+for rejected requests (default: 450). The reply is always 450 in
+case the address->name or name->address lookup failed due to
+a temporary problem. </dd>
+
+<dt><b><a name="reject_unknown_reverse_client_hostname">reject_unknown_reverse_client_hostname</a></b></dt>
+
+<dd>Reject the request when the client IP address has no address->name
+mapping. <br> This is a weaker restriction than the
+reject_unknown_client_hostname feature, which requires not only
+that the address->name and name->address mappings exist, but
+also that the two mappings reproduce the client IP address. <br>
+The unknown_client_reject_code parameter specifies the response
+code for rejected requests (default: 450). The reply is always 450
+in case the address->name lookup failed due to a temporary
+problem. <br> This feature is available in Postfix version 2.3 and
+later. </dd>
+
+#<dt><b><a name="reject_unknown_forward_client_hostname">reject_unknown_forward_client_hostname</a></b></dt>
+#
+#<dd>Reject the request when the client IP address has no address->name
+#or name ->address mapping. <br> This is a weaker restriction
+#than the reject_unknown_client_hostname feature, which requires not
+#only that the address->name and name->address mappings exist,
+#but also that the two mappings reproduce the client IP address.
+#<br> The unknown_client_reject_code parameter specifies the response
+#code for rejected requests (default: 450). The reply is always 450
+#in case the address->name or name ->address lookup failed due
+#to a temporary problem. <br> This feature is available in Postfix
+#version 2.3 and later. </dd>
</dl>
</p>
<pre>
-smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
+smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname
</pre>
%CLASS smtpd-tarpit Tarpit features
use DUNNO in order to exclude specific hosts from blacklists. This
feature is available in Postfix 2.1 and later. </dd>
-<dt><b><a name="reject_invalid_hostname">reject_invalid_hostname</a></b></dt>
+<dt><b><a name="reject_invalid_helo_hostname">reject_invalid_helo_hostname</a></b> (with Postfix < 2.3: reject_invalid_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname syntax is
invalid. <br> The invalid_hostname_reject_code specifies the response
code to rejected requests (default: 501).</dd>
-<dt><b><a name="reject_non_fqdn_hostname">reject_non_fqdn_hostname</a></b></dt>
+<dt><b><a name="reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a></b> (with Postfix < 2.3: reject_non_fqdn_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname is not in
fully-qualified domain form, as required by the RFC. <br> The
non_fqdn_reject_code parameter specifies the response code to
rejected requests (default: 504).</dd>
-<dt><b><a name="reject_unknown_hostname">reject_unknown_hostname</a></b></dt>
+<dt><b><a name="reject_unknown_helo_hostname">reject_unknown_helo_hostname</a></b> (with Postfix < 2.3: reject_unknown_hostname)</dt>
-<dd>Reject the request when the HELO or EHLO hostname has no DNS
-A or MX record. <br> The unknown_hostname_reject_code specifies
-the response code to rejected requests (default: 450).</dd>
+<dd>Reject the request when the HELO or EHLO hostname has no DNS A
+or MX record. <br> The unknown_hostname_reject_code specifies the
+response code to rejected requests (default: 450). </dd>
</dl>
</p>
<pre>
-smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
-smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
+smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname
+smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname
</pre>
%PARAM smtpd_history_flush_threshold 100
the response code for rejected requests (default: 450). The response
is always 450 in case of a temporary DNS error.</dd>
-<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (Postfix 2.0 name: check_recipient_maps)</dt>
+<dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
<dd> Reject the request when the RCPT TO address is not listed in
the list of valid recipients for its domain class. See the
<p>
The numerical Postfix SMTP server response code when a client
without valid address <=> name mapping is rejected by the
-reject_unknown_client restriction. The SMTP server always replies
+reject_unknown_client_hostname restriction. The SMTP server always replies
with 450 when the mapping failed due to a temporary error condition.
</p>
<p>
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the
-reject_unknown_hostname restriction.
+reject_unknown_helo_hostname restriction.
</p>
<p>
<p>
The numerical Postfix SMTP server reply code when a client request
-is rejected by the reject_non_fqdn_hostname, reject_non_fqdn_sender
+is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender
or reject_non_fqdn_recipient restriction.
</p>
<p> Examples: </p>
-<p> The Postfix < 2.2 backwards compatible setting: always rewrite
+<p> The Postfix < 2.2 backwards compatible setting: always rewrite
message headers, and always append my own domain to incomplete
header addresses. </p>
ehlo_mask.c \
wildcard_inet_addr.c valid_mailhost_addr.c dsn_util.c dsn_mask.c \
dsn_attr_map.c dsn.c dsn_buf.c rcpt_buf.c rcpt_print.c dsn_print.c \
- dsb_scan.c
+ dsb_scan.c mail_conf_long.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 debug_peer.o debug_process.o defer.o db_common.o \
ehlo_mask.o \
wildcard_inet_addr.o valid_mailhost_addr.o dsn_util.o dsn_mask.o \
dsn_attr_map.o dsn.o dsn_buf.o rcpt_buf.o rcpt_print.o dsn_print.o \
- dsb_scan.o
+ dsb_scan.o mail_conf_long.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 \
debug_peer.h debug_process.h defer.h deliver_completed.h \
mail_conf_int.o: ../../include/vstring.h
mail_conf_int.o: mail_conf.h
mail_conf_int.o: mail_conf_int.c
+mail_conf_long.o: ../../include/argv.h
+mail_conf_long.o: ../../include/dict.h
+mail_conf_long.o: ../../include/msg.h
+mail_conf_long.o: ../../include/mymalloc.h
+mail_conf_long.o: ../../include/stringops.h
+mail_conf_long.o: ../../include/sys_defs.h
+mail_conf_long.o: ../../include/vbuf.h
+mail_conf_long.o: ../../include/vstream.h
+mail_conf_long.o: ../../include/vstring.h
+mail_conf_long.o: mail_conf.h
+mail_conf_long.o: mail_conf_long.c
mail_conf_raw.o: ../../include/msg.h
mail_conf_raw.o: ../../include/mymalloc.h
mail_conf_raw.o: ../../include/sys_defs.h
*/
extern char *get_mail_conf_str(const char *, const char *, int, int);
extern int get_mail_conf_int(const char *, int, int, int);
+extern long get_mail_conf_long(const char *, long, long, long);
extern int get_mail_conf_bool(const char *, int);
extern int get_mail_conf_time(const char *, const char *, int, int);
extern char *get_mail_conf_raw(const char *, const char *, int, int);
extern int get_mail_conf_int2(const char *, const char *, int, int, int);
+extern long get_mail_conf_long2(const char *, const char *, long, long, long);
extern int get_mail_conf_time2(const char *, const char *, const char *, int, int);
/*
*/
extern char *get_mail_conf_str_fn(const char *, const char *(*) (void), int, int);
extern int get_mail_conf_int_fn(const char *, int (*) (void), int, int);
+extern long get_mail_conf_long_fn(const char *, long (*) (void), long, long);
extern int get_mail_conf_bool_fn(const char *, int (*) (void));
extern int get_mail_conf_time_fn(const char *, const char *(*) (void), int, int, int);
extern char *get_mail_conf_raw_fn(const char *, const char *(*) (void), int, int);
*/
extern void set_mail_conf_str(const char *, const char *);
extern void set_mail_conf_int(const char *, int);
+extern void set_mail_conf_long(const char *, long);
extern void set_mail_conf_bool(const char *, int);
extern void set_mail_conf_time(const char *, const char *);
char **target; /* pointer to global variable */
int min; /* min length or zero */
int max; /* max length or zero */
-} CONFIG_RAW_TABLE;
+} CONFIG_RAW_TABLE;
typedef struct {
const char *name; /* config variable name */
int max; /* upper bound or zero */
} CONFIG_INT_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ long defval; /* default value */
+ long *target; /* pointer to global variable */
+ long min; /* lower bound or zero */
+ long max; /* upper bound or zero */
+} CONFIG_LONG_TABLE;
+
typedef struct {
const char *name; /* config variable name */
int defval; /* default value */
extern void get_mail_conf_str_table(CONFIG_STR_TABLE *);
extern void get_mail_conf_int_table(CONFIG_INT_TABLE *);
+extern void get_mail_conf_long_table(CONFIG_LONG_TABLE *);
extern void get_mail_conf_bool_table(CONFIG_BOOL_TABLE *);
extern void get_mail_conf_time_table(CONFIG_TIME_TABLE *);
extern void get_mail_conf_raw_table(CONFIG_RAW_TABLE *);
char **target; /* pointer to global variable */
int min; /* lower bound or zero */
int max; /* upper bound or zero */
-} CONFIG_RAW_FN_TABLE;
+} CONFIG_RAW_FN_TABLE;
typedef struct {
const char *name; /* config variable name */
int max; /* upper bound or zero */
} CONFIG_INT_FN_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ long (*defval) (void); /* default value provider */
+ long *target; /* pointer to global variable */
+ long min; /* lower bound or zero */
+ long max; /* upper bound or zero */
+} CONFIG_LONG_FN_TABLE;
+
typedef struct {
const char *name; /* config variable name */
int (*defval) (void); /* default value provider */
extern void get_mail_conf_str_fn_table(CONFIG_STR_FN_TABLE *);
extern void get_mail_conf_int_fn_table(CONFIG_INT_FN_TABLE *);
+extern void get_mail_conf_long_fn_table(CONFIG_LONG_FN_TABLE *);
extern void get_mail_conf_bool_fn_table(CONFIG_BOOL_FN_TABLE *);
extern void get_mail_conf_raw_fn_table(CONFIG_RAW_FN_TABLE *);
--- /dev/null
+/*++
+/* NAME
+/* mail_conf_long 3
+/* SUMMARY
+/* long integer-valued configuration parameter support
+/* SYNOPSIS
+/* #include <mail_conf.h>
+/*
+/* int get_mail_conf_long(name, defval, min, max);
+/* const char *name;
+/* long defval;
+/* long min;
+/* long max;
+/*
+/* int get_mail_conf_long_fn(name, defval, min, max);
+/* const char *name;
+/* long (*defval)(void);
+/* long min;
+/* long max;
+/*
+/* void set_mail_conf_long(name, value)
+/* const char *name;
+/* long value;
+/*
+/* void get_mail_conf_long_table(table)
+/* CONFIG_LONG_TABLE *table;
+/*
+/* void get_mail_conf_long_fn_table(table)
+/* CONFIG_LONG_TABLE *table;
+/* AUXILIARY FUNCTIONS
+/* int get_mail_conf_long2(name1, name2, defval, min, max);
+/* const char *name1;
+/* const char *name2;
+/* long defval;
+/* long min;
+/* long max;
+/* DESCRIPTION
+/* This module implements configuration parameter support
+/* for long integer values.
+/*
+/* get_mail_conf_long() looks up the named entry in the global
+/* configuration dictionary. The default value is returned
+/* when no value was found.
+/* \fImin\fR is zero or specifies a lower limit on the long
+/* integer value; \fImax\fR is zero or specifies an upper limit
+/* on the long integer value.
+/*
+/* get_mail_conf_long_fn() is similar but specifies a function that
+/* provides the default value. The function is called only
+/* when the default value is needed.
+/*
+/* set_mail_conf_long() updates the named entry in the global
+/* configuration dictionary. This has no effect on values that
+/* have been looked up earlier via the get_mail_conf_XXX() routines.
+/*
+/* get_mail_conf_long_table() and get_mail_conf_long_fn_table() initialize
+/* lists of variables, as directed by their table arguments. A table
+/* must be terminated by a null entry.
+/*
+/* get_mail_conf_long2() concatenates the two names and is otherwise
+/* identical to get_mail_conf_long().
+/* DIAGNOSTICS
+/* Fatal errors: malformed numerical value.
+/* SEE ALSO
+/* config(3) general configuration
+/* mail_conf_str(3) string-valued configuration parameters
+/* 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 <stdlib.h>
+#include <stdio.h> /* sscanf() */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <dict.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include "mail_conf.h"
+
+/* convert_mail_conf_long - look up and convert integer parameter value */
+
+static int convert_mail_conf_long(const char *name, long *longval)
+{
+ const char *strval;
+ char junk;
+
+ if ((strval = mail_conf_lookup_eval(name)) != 0) {
+ if (sscanf(strval, "%ld%c", longval, &junk) != 1)
+ msg_fatal("bad numerical configuration: %s = %s", name, strval);
+ return (1);
+ }
+ return (0);
+}
+
+/* check_mail_conf_long - validate integer value */
+
+static void check_mail_conf_long(const char *name, long longval, long min, long max)
+{
+ if (min && longval < min)
+ msg_fatal("invalid %s parameter value %ld < %ld", name, longval, min);
+ if (max && longval > max)
+ msg_fatal("invalid %s parameter value %ld > %ld", name, longval, max);
+}
+
+/* get_mail_conf_long - evaluate integer-valued configuration variable */
+
+long get_mail_conf_long(const char *name, long defval, long min, long max)
+{
+ long longval;
+
+ if (convert_mail_conf_long(name, &longval) == 0)
+ set_mail_conf_long(name, longval = defval);
+ check_mail_conf_long(name, longval, min, max);
+ return (longval);
+}
+
+/* get_mail_conf_long2 - evaluate integer-valued configuration variable */
+
+long get_mail_conf_long2(const char *name1, const char *name2, long defval,
+ long min, long max)
+{
+ long longval;
+ char *name;
+
+ name = concatenate(name1, name2, (char *) 0);
+ if (convert_mail_conf_long(name, &longval) == 0)
+ set_mail_conf_long(name, longval = defval);
+ check_mail_conf_long(name, longval, min, max);
+ myfree(name);
+ return (longval);
+}
+
+/* get_mail_conf_long_fn - evaluate integer-valued configuration variable */
+
+typedef long (*stupid_indent_long) (void);
+
+long get_mail_conf_long_fn(const char *name, stupid_indent_long defval,
+ long min, long max)
+{
+ long longval;
+
+ if (convert_mail_conf_long(name, &longval) == 0)
+ set_mail_conf_long(name, longval = defval());
+ check_mail_conf_long(name, longval, min, max);
+ return (longval);
+}
+
+/* set_mail_conf_long - update integer-valued configuration dictionary entry */
+
+void set_mail_conf_long(const char *name, long value)
+{
+ char buf[BUFSIZ]; /* yeah! crappy code! */
+
+ sprintf(buf, "%ld", value); /* yeah! more crappy code! */
+ mail_conf_update(name, buf);
+}
+
+/* get_mail_conf_long_table - look up table of integers */
+
+void get_mail_conf_long_table(CONFIG_LONG_TABLE *table)
+{
+ while (table->name) {
+ table->target[0] = get_mail_conf_long(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
+
+/* get_mail_conf_long_fn_table - look up integers, defaults are functions */
+
+void get_mail_conf_long_fn_table(CONFIG_LONG_FN_TABLE *table)
+{
+ while (table->name) {
+ table->target[0] = get_mail_conf_long_fn(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
#define SLEEP "sleep"
#define REJECT_UNKNOWN_CLIENT "reject_unknown_client"
+#define REJECT_UNKNOWN_CLIENT_HOSTNAME "reject_unknown_client_hostname"
+#define REJECT_UNKNOWN_REVERSE_HOSTNAME "reject_unknown_reverse_client_hostname"
+#define REJECT_UNKNOWN_FORWARD_HOSTNAME "reject_unknown_forward_client_hostname"
#define VAR_UNK_CLIENT_CODE "unknown_client_reject_code"
#define DEF_UNK_CLIENT_CODE 450
extern int var_unk_client_code;
#define PERMIT_NAKED_IP_ADDR "permit_naked_ip_address"
+#define REJECT_INVALID_HELO_HOSTNAME "reject_invalid_helo_hostname"
#define REJECT_INVALID_HOSTNAME "reject_invalid_hostname"
#define VAR_BAD_NAME_CODE "invalid_hostname_reject_code"
#define DEF_BAD_NAME_CODE 501 /* SYNTAX */
extern int var_bad_name_code;
+#define REJECT_UNKNOWN_HELO_HOSTNAME "reject_unknown_helo_hostname"
#define REJECT_UNKNOWN_HOSTNAME "reject_unknown_hostname"
#define VAR_UNK_NAME_CODE "unknown_hostname_reject_code"
#define DEF_UNK_NAME_CODE 450
extern int var_unk_name_code;
+#define REJECT_NON_FQDN_HELO_HOSTNAME "reject_non_fqdn_helo_hostname"
#define REJECT_NON_FQDN_HOSTNAME "reject_non_fqdn_hostname"
#define REJECT_NON_FQDN_SENDER "reject_non_fqdn_sender"
#define REJECT_NON_FQDN_RCPT "reject_non_fqdn_recipient"
#define MAIL_ATTR_ENC_8BIT "8bit" /* 8BITMIME equivalent */
#define MAIL_ATTR_ENC_7BIT "7bit" /* 7BIT equivalent */
#define MAIL_ATTR_ENC_NONE "" /* encoding unknown */
-#define MAIL_ATTR_CLIENT "client" /* client name[addr] */
+#define MAIL_ATTR_CLIENT "client"/* client name[addr] */
#define MAIL_ATTR_CLIENT_NAME "client_name" /* client hostname */
+#define MAIL_ATTR_REVERSE_CLIENT_NAME "reverse_client_name"
+#define MAIL_ATTR_FORWARD_CLIENT_NAME "forward_client_name"
#define MAIL_ATTR_CLIENT_ADDR "client_address" /* client address */
#define MAIL_ATTR_HELO_NAME "helo_name" /* SMTP helo name */
#define MAIL_ATTR_PROTO_NAME "protocol_name" /* SMTP/ESMTP/QMQP/... */
*/
#define XCLIENT_CMD "XCLIENT" /* XCLIENT command */
#define XCLIENT_NAME "NAME" /* client name */
+#define XCLIENT_REVERSE_NAME "REVERSE_NAME" /* reverse client name */
+#define XCLIENT_FORWARD_NAME "FORWARD_NAME" /* forward client name */
#define XCLIENT_ADDR "ADDR" /* client address */
#define XCLIENT_PROTO "PROTO" /* client protocol */
#define XCLIENT_HELO "HELO" /* client helo */
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20050716"
+#define MAIL_RELEASE_DATE "20050724"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT
/* QMGR_QUEUE *qmgr_queue_select(transport)
/* QMGR_TRANSPORT *transport;
/*
-/* void qmgr_queue_throttle(queue, del_stat)
+/* void qmgr_queue_throttle(queue, dsn)
/* QMGR_QUEUE *queue;
-/* DEL_STAT *del_stat;
+/* DSN *dsn;
/*
/* void qmgr_queue_unthrottle(queue)
/* QMGR_QUEUE *queue;
/* QMGR_TRANSPORT *transport;
/* void (*notify)(QMGR_TRANSPORT *transport, VSTREAM *fp);
/*
-/* void qmgr_transport_throttle(transport, del_stat)
+/* void qmgr_transport_throttle(transport, dsn)
/* QMGR_TRANSPORT *transport;
-/* DEL_STAT *del_stat;
+/* DSN *dsn;
/*
/* void qmgr_transport_unthrottle(transport)
/* QMGR_TRANSPORT *transport;
/* QMGR_TRANSPORT *transport;
/* const char *name;
/*
-/* void qmgr_queue_throttle(queue, del_stat)
+/* void qmgr_queue_throttle(queue, dsn)
/* QMGR_QUEUE *queue;
-/* DEL_STAT *del_stat;
+/* DSN *dsn;
/*
/* void qmgr_queue_unthrottle(queue)
/* QMGR_QUEUE *queue;
/* QMGR_TRANSPORT *transport;
/* void (*notify)(QMGR_TRANSPORT *transport, VSTREAM *fp);
/*
-/* void qmgr_transport_throttle(transport, del_stat)
+/* void qmgr_transport_throttle(transport, dsn)
/* QMGR_TRANSPORT *transport;
-/* DEL_STAT *del_stat;
+/* DSN *dsn;
/*
/* void qmgr_transport_unthrottle(transport)
/* QMGR_TRANSPORT *transport;
msg_fatal("%s: cannot convert %s from string to binary: %s",
myname, state->addr, MAI_STRERROR(aierr));
sa_len = res0->ai_addrlen;
+ if (sa_len > sizeof(ss))
+ sa_len = sizeof(ss);
memcpy((char *) sa, res0->ai_addr, sa_len);
freeaddrinfo(res0);
}
/* client request is rejected by the "defer" restriction.
/* .IP "\fBinvalid_hostname_reject_code (501)\fR"
/* The numerical Postfix SMTP server response code when the client
-/* HELO or EHLO command parameter is rejected by the reject_invalid_hostname
+/* HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname
/* restriction.
/* .IP "\fBmaps_rbl_reject_code (554)\fR"
/* The numerical Postfix SMTP server response code when a remote SMTP
/* reject_rhsbl_sender or reject_rhsbl_recipient restriction.
/* .IP "\fBnon_fqdn_reject_code (504)\fR"
/* The numerical Postfix SMTP server reply code when a client request
-/* is rejected by the reject_non_fqdn_hostname, reject_non_fqdn_sender
+/* is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender
/* or reject_non_fqdn_recipient restriction.
/* .IP "\fBreject_code (554)\fR"
/* The numerical Postfix SMTP server response code when a remote SMTP
/* .IP "\fBunknown_client_reject_code (450)\fR"
/* The numerical Postfix SMTP server response code when a client
/* without valid address <=> name mapping is rejected by the
-/* reject_unknown_client restriction.
+/* reject_unknown_client_hostname restriction.
/* .IP "\fBunknown_hostname_reject_code (450)\fR"
/* The numerical Postfix SMTP server response code when the hostname
/* specified with the HELO or EHLO command is rejected by the
-/* reject_unknown_hostname restriction.
+/* reject_unknown_helo_hostname restriction.
/* .PP
/* Available in Postfix version 2.0 and later:
/* .IP "\fBdefault_rbl_reply (see 'postconf -d' output)\fR"
if (xclient_allowed)
ENQUEUE_FIX_REPLY(state, reply_buf, XCLIENT_CMD
" " XCLIENT_NAME " " XCLIENT_ADDR
- " " XCLIENT_PROTO " " XCLIENT_HELO);
+ " " XCLIENT_PROTO " " XCLIENT_HELO
+ " " XCLIENT_REVERSE_NAME
+ " " XCLIENT_FORWARD_NAME);
if ((discard_mask & EHLO_MASK_XFORWARD) == 0)
if (xforward_allowed)
ENQUEUE_FIX_REPLY(state, reply_buf, XFORWARD_CMD
const char *bare_value;
char *attr_name;
int update_namaddr = 0;
- int peer_code;
+ int name_status;
static NAME_CODE peer_codes[] = {
XCLIENT_UNAVAILABLE, SMTPD_PEER_CODE_PERM,
XCLIENT_TEMPORARY, SMTPD_PEER_CODE_TEMP,
printable(attr_value, '?');
/*
- * NAME=substitute SMTP client hostname. Also updates the client
- * hostname lookup status code.
+ * NAME=substitute SMTP client hostname (and reverse/forward name, in
+ * case of success). Also updates the client hostname lookup status
+ * code.
*/
if (STREQ(attr_name, XCLIENT_NAME)) {
- peer_code = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
- if (peer_code != SMTPD_PEER_CODE_OK) {
+ name_status = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
+ if (name_status != SMTPD_PEER_CODE_OK) {
attr_value = CLIENT_NAME_UNKNOWN;
} else {
if (!valid_hostname(attr_value, DONT_GRIPE)) {
return (-1);
}
}
- state->peer_code = peer_code;
+ state->name_status = name_status;
UPDATE_STR(state->name, attr_value);
update_namaddr = 1;
+ if (name_status == SMTPD_PEER_CODE_OK) {
+ UPDATE_STR(state->reverse_name, attr_value);
+ state->reverse_name_status = name_status;
+#ifdef FORWARD_CLIENT_NAME
+ UPDATE_STR(state->forward_name, attr_value);
+ state->forward_name_status = name_status;
+#endif
+ }
+ }
+
+ /*
+ * REVERSE_NAME=substitute SMTP client reverse hostname. Also updates
+ * the client reverse hostname lookup status code.
+ */
+ if (STREQ(attr_name, XCLIENT_REVERSE_NAME)) {
+ name_status = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
+ if (name_status != SMTPD_PEER_CODE_OK) {
+ attr_value = CLIENT_NAME_UNKNOWN;
+ } else {
+ if (!valid_hostname(attr_value, DONT_GRIPE)) {
+ state->error_mask |= MAIL_ERROR_PROTOCOL;
+ smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s",
+ XCLIENT_REVERSE_NAME, attr_value);
+ return (-1);
+ }
+ }
+ state->reverse_name_status = name_status;
+ UPDATE_STR(state->reverse_name, attr_value);
}
+ /*
+ * FORWARD_NAME=substitute SMTP client forward hostname. Also updates
+ * the client forward hostname lookup status code.
+ */
+#ifdef FORWARD_CLIENT_NAME
+ if (STREQ(attr_name, XCLIENT_FORWARD_NAME)) {
+ name_status = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value);
+ if (name_status != SMTPD_PEER_CODE_OK) {
+ attr_value = CLIENT_NAME_UNKNOWN;
+ } else {
+ if (!valid_hostname(attr_value, DONT_GRIPE)) {
+ state->error_mask |= MAIL_ERROR_PROTOCOL;
+ smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s",
+ XCLIENT_FORWARD_NAME, attr_value);
+ return (-1);
+ }
+ }
+ state->forward_name_status = name_status;
+ UPDATE_STR(state->forward_name, attr_value);
+ }
+#endif
+
/*
* ADDR=substitute SMTP client network address.
*/
VSTRING *addr_buf; /* internalized address buffer */
char *service; /* for event rate control */
time_t time; /* start of MAIL FROM transaction */
- char *name; /* client hostname */
+ char *name; /* verified client hostname */
+ char *reverse_name; /* unverified client hostname */
+#ifdef FORWARD_CLIENT_NAME
+ char *forward_name; /* unverified client hostname */
+#endif
char *addr; /* client host address string */
char *namaddr; /* combined name and address */
char *rfc_addr; /* address for RFC 2821 */
struct sockaddr_storage sockaddr; /* binary client endpoint */
- int peer_code; /* 2=ok, 4=soft, 5=hard */
+ int name_status; /* 2=ok, 4=soft, 5=hard */
+ int reverse_name_status; /* 2=ok, 4=soft, 5=hard */
+#ifdef FORWARD_CLIENT_NAME
+ int forward_name_status; /* 2=ok, 4=soft, 5=hard */
+#endif
int error_count; /* reset after DOT */
int error_mask; /* client errors */
int notify_mask; /* what to report to postmaster */
return (result);
}
+/* reject_unknown_reverse_name - fail if reverse client hostname is unknown */
+
+static int reject_unknown_reverse_name(SMTPD_STATE *state)
+{
+ char *myname = "reject_unknown_reverse_name";
+
+ if (msg_verbose)
+ msg_info("%s: %s", myname, state->reverse_name);
+
+ if (state->reverse_name_status != SMTPD_PEER_CODE_OK)
+ return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+ state->reverse_name_status == SMTPD_PEER_CODE_PERM ?
+ var_unk_client_code : 450, "4.7.1",
+ "Client host rejected: cannot find your reverse hostname, [%s]",
+ state->addr));
+ return (SMTPD_CHECK_DUNNO);
+}
+
+#ifdef FORWARD_CLIENT_NAME
+
+/* reject_unknown_forward_name - fail if reverse client hostname is unknown */
+
+static int reject_unknown_forward_name(SMTPD_STATE *state)
+{
+ char *myname = "reject_unknown_forward_name";
+
+ if (msg_verbose)
+ msg_info("%s: %s", myname, state->forward_name);
+
+ if (state->forward_name_status != SMTPD_PEER_CODE_OK)
+ return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+ state->forward_name_status == SMTPD_PEER_CODE_PERM ?
+ var_unk_client_code : 450, "4.7.1",
+ "Client host rejected: cannot find your forward hostname, [%s]",
+ state->addr));
+ return (SMTPD_CHECK_DUNNO);
+}
+
+#endif
+
/* reject_unknown_client - fail if client hostname is unknown */
static int reject_unknown_client(SMTPD_STATE *state)
if (msg_verbose)
msg_info("%s: %s %s", myname, state->name, state->addr);
- if (strcasecmp(state->name, "unknown") == 0)
+ if (state->name_status != SMTPD_PEER_CODE_OK)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- state->peer_code == SMTPD_PEER_CODE_PERM ?
+ state->name_status == SMTPD_PEER_CODE_PERM ?
var_unk_client_code : 450, "4.7.1",
"Client host rejected: cannot find your hostname, [%s]",
state->addr));
return (state->addr);
} else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
return (state->name);
+ } else if (STREQ(name, MAIL_ATTR_REVERSE_CLIENT_NAME)) {
+ return (state->reverse_name);
+#ifdef FORWARD_CLIENT_NAME
+ } else if (STREQ(name, MAIL_ATTR_FORWARD_CLIENT_NAME)) {
+ return (state->forward_name);
+#endif
} else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
return (state->helo_name ? state->helo_name : "");
} else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, state->protocol,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, state->addr,
ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, state->name,
+ ATTR_TYPE_STR, MAIL_ATTR_REVERSE_CLIENT_NAME,
+ state->reverse_name,
+#ifdef FORWARD_CLIENT_NAME
+ ATTR_TYPE_STR, MAIL_ATTR_FORWARD_CLIENT_NAME,
+ state->forward_name,
+#endif
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME,
state->helo_name ? state->helo_name : "",
ATTR_TYPE_STR, MAIL_ATTR_SENDER,
/*
* Client name/address restrictions.
*/
- else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
+ else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT_HOSTNAME) == 0
+ || strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
status = reject_unknown_client(state);
+ } else if (strcasecmp(name, REJECT_UNKNOWN_REVERSE_HOSTNAME) == 0) {
+ status = reject_unknown_reverse_name(state);
+#ifdef FORWARD_CLIENT_NAME
+ } else if (strcasecmp(name, REJECT_UNKNOWN_FORWARD_HOSTNAME) == 0) {
+ status = reject_unknown_forward_name(state);
+#endif
} else if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) {
status = permit_inet_interfaces(state);
} else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
status = check_domain_access(state, *cpp, state->helo_name,
FULL, &found, state->helo_name,
SMTPD_NAME_HELO, def_acl);
- } else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
+ } else if (strcasecmp(name, REJECT_INVALID_HELO_HOSTNAME) == 0
+ || strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_invalid_hostname(state, state->helo_name,
status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
}
- } else if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
+ } else if (strcasecmp(name, REJECT_UNKNOWN_HELO_HOSTNAME) == 0
+ || strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_unknown_hostname(state, state->helo_name,
SMTPD_NAME_HELO, def_acl);
forbid_whitelist(state, name, status, state->helo_name);
}
- } else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
+ } else if (strcasecmp(name, REJECT_NON_FQDN_HELO_HOSTNAME) == 0
+ ||strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
status = reject_non_fqdn_hostname(state, state->helo_name,
if (strcasecmp(args->argv[0], "client") == 0) {
state.where = "CONNECT";
UPDATE_STRING(state.name, args->argv[1]);
+ UPDATE_STRING(state.reverse_name, args->argv[1]);
+#ifdef FORWARD_CLIENT_NAME
+ UPDATE_STRING(state.forward_name, args->argv[1]);
+#endif
UPDATE_STRING(state.addr, args->argv[2]);
if (args->argc == 4)
- state.peer_code = atoi(args->argv[3]);
+ state.name_status =
+ state.reverse_name_status =
+#ifdef FORWARD_CLIENT_NAME
+ state.forward_name_status =
+#endif
+ atoi(args->argv[3]);
else
- state.peer_code = SMTPD_PEER_CODE_OK;
+ state.name_status =
+ state.reverse_name_status =
+#ifdef FORWARD_CLIENT_NAME
+ state.forward_name_status =
+#endif
+ SMTPD_PEER_CODE_OK;
if (state.namaddr)
myfree(state.namaddr);
state.namaddr = concatenate(state.name, "[", state.addr,
/* Where information is unavailable, the name and/or address
/* are set to "unknown".
/*
+/* This module uses the local name service via getaddrinfo()
+/* and getnameinfo(). It does not query the DNS directly.
+/*
/* smtpd_peer_init() updates the following fields:
/* .IP name
-/* The client hostname. An unknown name is represented by the
-/* string "unknown". This includes names that could not be
-/* verified with forward DNS lookups.
+/* The verified client hostname. This name is represented by
+/* the string "unknown" when 1) the address->name lookup failed,
+/* 2) the name->address mapping fails, or 3) the name->address
+/* does not produce the client IP address.
+/* .IP reverse_name
+/* The unverified client hostname as found with address->name
+/* lookup; it is not verified for consistency with the client
+/* IP address result from name->address lookup.
+/* .IP forward_name
+/* The unverified client hostname as found with address->name
+/* lookup followed by name->address lookup; it is not verified
+/* for consistency with the result from address->name lookup.
+/* For example, when the address->name lookup produces as
+/* hostname an alias, the name->address lookup will produce
+/* as hostname the expansion of that alias, so that the two
+/* lookups produce different names.
/* .IP addr
/* Printable representation of the client address.
/* .IP namaddr
/* String of the form: "name[addr]".
-/* .IP peer_code
-/* The peer_code result field specifies how the client name
+/* .IP rfc_addr
+/* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
+/* in Received: message headers.
+/* .IP name_status
+/* The name_status result field specifies how the name
/* information should be interpreted:
/* .RS
/* .IP 2
-/* Both name lookup and name verification succeeded.
+/* The address->name lookup and name->address lookup produced
+/* the client IP address.
+/* .IP 4
+/* The address->name lookup or name->address lookup failed
+/* with a recoverable error.
+/* .IP 5
+/* The address->name lookup or name->address lookup failed
+/* with an unrecoverable error, or the result did not match
+/* the client IP address.
+/* .RE
+/* .IP reverse_name_status
+/* The reverse_name_status result field specifies how the
+/* reverse_name information should be interpreted:
+/* .RS .IP 2
+/* The address->name lookup succeeded.
/* .IP 4
-/* The name lookup or name verification failed with a recoverable
-/* error (no address->name mapping or no name->address mapping).
+/* The address->name lookup failed with a recoverable error.
/* .IP 5
-/* The name lookup or verification failed with an unrecoverable
-/* error (no address->name mapping, bad hostname syntax, no
-/* name->address mapping, client address not listed for hostname).
+/* The address->name lookup failed with an unrecoverable error.
+/* .RE .IP forward_name_status
+/* The forward_name_status result field specifies how the
+/* forward_name information should be interpreted:
+/* .RS .IP 2
+/* The address->name and name->address lookup succeeded.
+/* .IP 4
+/* The address->name lookup or name->address failed with a
+/* recoverable error.
+/* .IP 5
+/* The address->name lookup or name->address failed with an
+/* unrecoverable error.
/* .RE
/* .PP
/* smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
*/
if (errno == ECONNRESET || errno == ECONNABORTED) {
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+ state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
+#endif
state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
- state->peer_code = SMTPD_PEER_CODE_PERM;
+ state->name_status = SMTPD_PEER_CODE_PERM;
+ state->reverse_name_status = SMTPD_PEER_CODE_PERM;
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name_status = SMTPD_PEER_CODE_PERM;
+#endif
}
/*
msg_fatal("%s: cannot convert %s from string to binary: %s",
myname, state->addr, MAI_STRERROR(aierr));
sa_len = res0->ai_addrlen;
+ if (sa_len > sizeof(state->sockaddr))
+ sa_len = sizeof(state->sockaddr);
memcpy((char *) sa, res0->ai_addr, sa_len);
freeaddrinfo(res0); /* 200412 */
}
#define REJECT_PEER_NAME(state, code) { \
myfree(state->name); \
state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
- state->peer_code = code; \
+ state->name_status = code; \
}
if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
- state->peer_code = (TEMP_AI_ERROR(aierr) ?
- SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+ state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
+#endif
+ state->name_status = (TEMP_AI_ERROR(aierr) ?
+ SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+ state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
+ SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name_status = (TEMP_AI_ERROR(aierr) ?
+ SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+#endif
} else {
struct addrinfo *res0;
struct addrinfo *res;
state->name = mystrdup(client_name.buf);
- state->peer_code = SMTPD_PEER_CODE_OK;
+ state->reverse_name = mystrdup(client_name.buf);
+ state->name_status = SMTPD_PEER_CODE_OK;
+ state->reverse_name_status = SMTPD_PEER_CODE_OK;
/*
* Reject the hostname if it does not list the peer address.
if (aierr) {
msg_warn("%s: hostname %s verification failed: %s",
state->addr, state->name, MAI_STRERROR(aierr));
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
+ state->forward_name_status = (TEMP_AI_ERROR(aierr) ?
+ SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+#endif
REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
} else {
+#ifdef FORWARD_CLIENT_NAME
+ if (res0) {
+ state->forward_name = mystrdup(res0->ai_canonname);
+ state->forward_name_status = SMTPD_PEER_CODE_OK;
+ } else {
+ state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
+ state->forward_name_status = SMTPD_PEER_CODE_PERM;
+ }
+#endif
for (res = res0; /* void */ ; res = res->ai_next) {
if (res == 0) {
msg_warn("%s: address not listed for hostname %s",
*/
else {
state->name = mystrdup("localhost");
+ state->reverse_name = mystrdup("localhost");
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name = mystrdup("localhost");
+#endif
state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
- state->peer_code = SMTPD_PEER_CODE_OK;
+ state->name_status = SMTPD_PEER_CODE_OK;
+ state->reverse_name_status = SMTPD_PEER_CODE_OK;
+#ifdef FORWARD_CLIENT_NAME
+ state->forward_name_status = SMTPD_PEER_CODE_OK;
+#endif
}
/*
void smtpd_peer_reset(SMTPD_STATE *state)
{
myfree(state->name);
+ myfree(state->reverse_name);
+#ifdef FORWARD_CLIENT_NAME
+ myfree(state->forward_name);
+#endif
myfree(state->addr);
myfree(state->namaddr);
myfree(state->rfc_addr);
msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
myfree(buf);
sa = (struct sockaddr *) & ss;
+ if (res->ai_addrlen > sizeof(ss))
+ msg_fatal("address length %d > buffer length %d",
+ (int) res->ai_addrlen, (int) sizeof(ss));
memcpy((char *) sa, res->ai_addr, res->ai_addrlen);
sa_length = res->ai_addrlen;
#ifdef HAS_SA_LEN
msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
myfree(buf);
sa = (struct sockaddr *) & ss;
+ if (res->ai_addrlen > sizeof(ss))
+ msg_fatal("address length %d > buffer length %d",
+ (int) res->ai_addrlen, (int) sizeof(ss));
memcpy((char *) sa, res->ai_addr, res->ai_addrlen);
sa_length = res->ai_addrlen;
#ifdef HAS_SA_LEN
/*
/* ssize_t vstream_fwrite(stream, buf, len)
/* VSTREAM *stream;
-/* char *buf;
+/* const char *buf;
/* ssize_t len;
/*
/* void vstream_control(stream, name, ...)
*
* The length overflow tests here and in vstring_alloc() should protect us
* against all length overflow problems within vstring library routines.
+ * (The tests are redundant as long as mymalloc() and myrealloc() reject
+ * negative length parameters).
*/
new_len = bp->len + (bp->len > incr ? bp->len : incr);
if (new_len < 0)