diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 0cdf6722e..5a3608b54 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -29,6 +29,8 @@ -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 diff --git a/postfix/HISTORY b/postfix/HISTORY index 97dd138dc..a2c77fa9f 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -10969,7 +10969,7 @@ Apologies for any names omitted. 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. @@ -11028,8 +11028,35 @@ Apologies for any names omitted. 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 , and prepare for phasing out the Postfix-supplied one. Beware, however, that XPG basename() takes (char *), and diff --git a/postfix/README_FILES/MAILDROP_README b/postfix/README_FILES/MAILDROP_README index 36afd1e06..ca8580847 100644 --- a/postfix/README_FILES/MAILDROP_README +++ b/postfix/README_FILES/MAILDROP_README @@ -100,7 +100,7 @@ To enable maildrop delivery for specific users only, you can use the Postfix 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} diff --git a/postfix/README_FILES/RESTRICTION_CLASS_README b/postfix/README_FILES/RESTRICTION_CLASS_README index be15bc968..884c7112f 100644 --- a/postfix/README_FILES/RESTRICTION_CLASS_README +++ b/postfix/README_FILES/RESTRICTION_CLASS_README @@ -5,8 +5,8 @@ PPoossttffiixx PPeerr--CClliieenntt//UUsseerr//eettcc. PPoossttffiixx rreessttrriiccttiioonn ccllaasssseess 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 @@ -23,7 +23,9 @@ Example: /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 = diff --git a/postfix/README_FILES/SMTPD_ACCESS_README b/postfix/README_FILES/SMTPD_ACCESS_README index 41d51813d..d6f2786c3 100644 --- a/postfix/README_FILES/SMTPD_ACCESS_README +++ b/postfix/README_FILES/SMTPD_ACCESS_README @@ -117,7 +117,8 @@ Examples of simple restriction lists are: 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 @@ -221,15 +222,16 @@ access permission: 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 diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README index c2c714c36..d690a47ff 100644 --- a/postfix/README_FILES/SMTPD_POLICY_README +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -48,6 +48,7 @@ a delegated SMTPD access policy request: 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 @@ -75,6 +76,10 @@ Notes: * 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. diff --git a/postfix/html/MAILDROP_README.html b/postfix/html/MAILDROP_README.html index bdf121caa..1216218c4 100644 --- a/postfix/html/MAILDROP_README.html +++ b/postfix/html/MAILDROP_README.html @@ -149,7 +149,7 @@ use the Postfix local(8) delivery agent's 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} diff --git a/postfix/html/RESTRICTION_CLASS_README.html b/postfix/html/RESTRICTION_CLASS_README.html index c27f5f060..528a263f3 100644 --- a/postfix/html/RESTRICTION_CLASS_README.html +++ b/postfix/html/RESTRICTION_CLASS_README.html @@ -21,7 +21,7 @@ Per-Client/User/etc. Access Control

Postfix restriction classes

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.

@@ -43,7 +43,8 @@ care about these low-level details.

 /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 = 
diff --git a/postfix/html/SMTPD_ACCESS_README.html b/postfix/html/SMTPD_ACCESS_README.html
index 84621f45c..3d542816a 100644
--- a/postfix/html/SMTPD_ACCESS_README.html
+++ b/postfix/html/SMTPD_ACCESS_README.html
@@ -172,7 +172,8 @@ described in the postconf(5) manual page. 

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 @@ -307,7 +308,7 @@ in too much access permission:

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: @@ -315,7 +316,8 @@ in too much access permission:

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".

diff --git a/postfix/html/SMTPD_POLICY_README.html b/postfix/html/SMTPD_POLICY_README.html index e4ee237aa..325e7e8f7 100644 --- a/postfix/html/SMTPD_POLICY_README.html +++ b/postfix/html/SMTPD_POLICY_README.html @@ -80,6 +80,7 @@ sender=foo@bar.tld 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 @@ -115,6 +116,11 @@ size=12345 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.

    diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 0194bfc38..63556b069 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -1696,7 +1696,13 @@ The template is subject to exactly one level of $name substitution:
    $client_name
    -
    The client hostname or "unknown".
    +
    The client hostname or "unknown". See reject_unknown_client_hostname +for more details.
    + +
    $reverse_client_name
    + +
    The client hostname from address->name lookup, or "unknown". +See reject_unknown_reverse_client_hostname for more details.
    $helo_name
    @@ -1879,8 +1885,8 @@ This feature is available in Postfix 2.0 and later. (default: empty)

    -The names of message delivery transports that should not be delivered -to unless someone issues "sendmail -q" or equivalent. Specify zero +The names of message delivery transports that should not deliver mail +unless someone issues "sendmail -q" or equivalent. Specify zero or more names of mail delivery transports names that appear in the first field of master.cf.

    @@ -2567,7 +2573,7 @@ home directory.

    -Specify a pathname ending "/" for qmail-style delivery. +Specify a pathname ending in "/" for qmail-style delivery.

    @@ -2816,7 +2822,7 @@ block all mail to a site.

    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.

    @@ -3373,7 +3379,7 @@ is suitable for, e.g., pop-before-smtp lookup tables.

    Examples:

    -

    The Postfix < 2.2 backwards compatible setting: always rewrite +

    The Postfix < 2.2 backwards compatible setting: always rewrite message headers, and always append my own domain to incomplete header addresses.

    @@ -4450,7 +4456,7 @@ Sendmail compatibility feature that specifies the location of the

    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.

    @@ -7273,14 +7279,30 @@ any A record under rbl_domain. See the reject_unknown_client +
    reject_unknown_client_hostname (with Postfix < 2.3: reject_unknown_client)
    -
    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.
    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.
    +
    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.
    This is a +stronger restriction than the reject_unknown_reverse_client_hostname +feature, which triggers only under condition 1) above.
    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.
    + +
    reject_unknown_reverse_client_hostname
    + +
    Reject the request when the client IP address has no address->name +mapping.
    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.
    +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.
    This feature is available in Postfix version 2.3 and +later.
    @@ -7404,7 +7426,7 @@ Example:

    -smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
    +smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname
     
    @@ -7745,24 +7767,24 @@ 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. -
    reject_invalid_hostname
    +
    reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname)
    Reject the request when the HELO or EHLO hostname syntax is invalid.
    The invalid_hostname_reject_code specifies the response code to rejected requests (default: 501).
    -
    reject_non_fqdn_hostname
    +
    reject_non_fqdn_helo_hostname (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.
    The non_fqdn_reject_code parameter specifies the response code to rejected requests (default: 504).
    -
    reject_unknown_hostname
    +
    reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname)
    -
    Reject the request when the HELO or EHLO hostname has no DNS -A or MX record.
    The unknown_hostname_reject_code specifies -the response code to rejected requests (default: 450).
    +
    Reject the request when the HELO or EHLO hostname has no DNS A +or MX record.
    The unknown_hostname_reject_code specifies the +response code to rejected requests (default: 450).
    @@ -7792,8 +7814,8 @@ Examples:

    -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
     
    @@ -8116,7 +8138,7 @@ address.
    The unknown_ the response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error. -
    reject_unlisted_recipient (Postfix 2.0 name: check_recipient_maps)
    +
    reject_unlisted_recipient (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 @@ -9438,7 +9460,7 @@ Do not change this unless you have a complete understanding of 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.

    @@ -9455,7 +9477,7 @@ Do not change this unless you have a complete understanding of reject_unknown_hostname restriction. +reject_unknown_helo_hostname restriction.

    diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 37208aa0a..142aa8884 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -781,8 +781,8 @@ SMTPD(8) SMTPD(8) invalid_hostname_reject_code (501) The numerical Postfix SMTP server response code when the client HELO or EHLO command parameter is - rejected by the reject_invalid_hostname restric- - tion. + rejected by the reject_invalid_helo_hostname + restriction. maps_rbl_reject_code (554) The numerical Postfix SMTP server response code @@ -794,46 +794,47 @@ SMTPD(8) SMTPD(8) non_fqdn_reject_code (504) The numerical Postfix SMTP server reply code when a client request is rejected by the - reject_non_fqdn_hostname, reject_non_fqdn_sender or - reject_non_fqdn_recipient restriction. + reject_non_fqdn_helo_hostname, + reject_non_fqdn_sender or reject_non_fqdn_recipient + restriction. reject_code (554) - 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. relay_domains_reject_code (554) - 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 reject_unauth_destination recipient restriction. unknown_address_reject_code (450) - 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 reject_unknown_sender_domain or reject_unknown_recipient_domain restriction. unknown_client_reject_code (450) - The numerical Postfix SMTP server response code - when a client without valid address <=> name map- - ping is rejected by the reject_unknown_client - 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. unknown_hostname_reject_code (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. + The numerical Postfix SMTP server response code + when the hostname specified with the HELO or EHLO + command is rejected by the + reject_unknown_helo_hostname restriction. Available in Postfix version 2.0 and later: default_rbl_reply (see 'postconf -d' output) - 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. multi_recipient_bounce_reject_code (550) - The numerical Postfix SMTP server response code + The numerical Postfix SMTP server response code when a remote SMTP client request is blocked by the reject_multi_recipient_bounce restriction. @@ -842,16 +843,16 @@ SMTPD(8) SMTPD(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - 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. command_directory (see 'postconf -d' output) - The location of all postfix administrative com- + The location of all postfix administrative com- mands. double_bounce_sender (double-bounce) @@ -872,36 +873,36 @@ SMTPD(8) SMTPD(8) and most Postfix daemon processes. max_idle (100s) - 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. max_use (100) - The maximal number of connection requests before a + The maximal number of connection requests before a Postfix daemon process terminates. myhostname (see 'postconf -d' output) The internet hostname of this mail system. mynetworks (see 'postconf -d' output) - The list of "trusted" SMTP clients that have more + The list of "trusted" SMTP clients that have more privileges than "strangers". myorigin ($myhostname) 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. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. queue_directory (see 'postconf -d' output) - The location of the Postfix top-level queue direc- + The location of the Postfix top-level queue direc- tory. recipient_delimiter (empty) @@ -909,22 +910,22 @@ SMTPD(8) SMTPD(8) sions (user+foo). smtpd_banner ($myhostname ESMTP $mail_name) - The text that follows the 220 status code in the + The text that follows the 220 status code in the SMTP greeting banner. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (postfix) - 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: smtpd_forbidden_commands (CONNECT, GET, POST) - 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. SEE ALSO @@ -953,7 +954,7 @@ SMTPD(8) SMTPD(8) XFORWARD_README, Postfix XFORWARD extension LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index be80a2de3..9963a365f 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -921,7 +921,11 @@ The client hostname and IP address, formatted as name[address]. .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" @@ -1016,8 +1020,8 @@ of failed delivery attempts and generates non-delivery notifications. .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 @@ -1343,7 +1347,7 @@ This feature is available in Postfix 2.0 and later. 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, @@ -1504,7 +1508,7 @@ Warning: with concurrency of 1, one bad message can be enough to 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. @@ -2434,7 +2438,7 @@ Sendmail compatibility feature that specifies the location of the \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 @@ -4103,15 +4107,36 @@ the request when the reversed client network address is listed with 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 @@ -4211,7 +4236,7 @@ Example: .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 @@ -4405,25 +4430,25 @@ for the HELO or EHLO hostname, and execute the corresponding action. 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 @@ -4445,8 +4470,8 @@ Examples: .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 @@ -4630,7 +4655,7 @@ address. 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. @@ -5450,14 +5475,14 @@ Do not change this unless you have a complete understanding of RFC 821. .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) diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index a07f82035..f4ea87057 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -632,7 +632,7 @@ The numerical Postfix SMTP server response code when a remote SMTP 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 @@ -640,7 +640,7 @@ client request is blocked by the reject_rbl_client, reject_rhsbl_client, 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 @@ -656,11 +656,11 @@ or reject_unknown_recipient_domain restriction. .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" diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 885f5e713..aef029374 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -605,16 +605,22 @@ while (<>) { s;\bpermit_sasl_authenticated\b;$&;g; s;\bpermit_tls_clientcerts\b;$&;g; s;\bpermit_tls_all_clientcerts\b;$&;g; - s;\breject_unknown_client\b;$&;g; + s;\breject_unknown_client_hostname\b;$&;g; + s;\breject_unknown_client\b;$&;g; + s;\breject_unknown_reverse_client_hostname\b;$&;g; + s;\breject_unknown_forward_client_hostname\b;$&;g; s;\breject_rbl_client\b;$&;g; s;\breject_rhsbl_client\b;$&;g; # Access restrictions - helo s;\bcheck_helo_access\b;$&;g; - s;\breject_invalid_hostname\b;$&;g; - s;\breject_non_fqdn_hostname\b;$&;g; - s;\breject_unknown_hostname\b;$&;g; + s;\breject_invalid_helo_hostname\b;$&;g; + s;\breject_invalid_hostname\b;$&;g; + s;\breject_non_fqdn_helo_hostname\b;$&;g; + s;\breject_non_fqdn_hostname\b;$&;g; + s;\breject_unknown_helo_hostname\b;$&;g; + s;\breject_unknown_hostname\b;$&;g; # Access restrictions - sender diff --git a/postfix/proto/MAILDROP_README.html b/postfix/proto/MAILDROP_README.html index 8ce2c402f..e41e127f5 100644 --- a/postfix/proto/MAILDROP_README.html +++ b/postfix/proto/MAILDROP_README.html @@ -149,7 +149,7 @@ use the Postfix 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}
    diff --git a/postfix/proto/RESTRICTION_CLASS_README.html b/postfix/proto/RESTRICTION_CLASS_README.html
    index c3d85dd15..93ab72983 100644
    --- a/postfix/proto/RESTRICTION_CLASS_README.html
    +++ b/postfix/proto/RESTRICTION_CLASS_README.html
    @@ -21,7 +21,7 @@ Per-Client/User/etc. Access Control
     

    Postfix restriction classes

    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.

    @@ -43,7 +43,8 @@ care about these low-level details.

     /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 = 
    diff --git a/postfix/proto/SMTPD_ACCESS_README.html b/postfix/proto/SMTPD_ACCESS_README.html
    index c5176b41b..c97e34b36 100644
    --- a/postfix/proto/SMTPD_ACCESS_README.html
    +++ b/postfix/proto/SMTPD_ACCESS_README.html
    @@ -172,7 +172,8 @@ described in the postconf(5) manual page. 

    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 @@ -307,7 +308,7 @@ in too much access permission:

    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: @@ -315,7 +316,8 @@ in too much access permission:

    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".

    diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html index fb2bcb83e..884d0de52 100644 --- a/postfix/proto/SMTPD_POLICY_README.html +++ b/postfix/proto/SMTPD_POLICY_README.html @@ -80,6 +80,7 @@ sender=foo@bar.tld 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 @@ -115,6 +116,11 @@ size=12345 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.

    diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 5068d3fdd..09b0a5569 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -978,7 +978,19 @@ The template is subject to exactly one level of $name substitution:
    $client_name
    -
    The client hostname or "unknown".
    +
    The client hostname or "unknown". See reject_unknown_client_hostname +for more details.
    + +
    $reverse_client_name
    + +
    The client hostname from address->name lookup, or "unknown". +See reject_unknown_reverse_client_hostname for more details.
    + +#
    $forward_client_name
    +# +#
    The client hostname from address->name lookup followed by +#name->address lookup, or "unknown". See +#reject_unknown_forward_client_hostname for more details.
    $helo_name
    @@ -1121,8 +1133,8 @@ Do not change this unless you have a complete understanding of RFC 821. %PARAM defer_transports

    -The names of message delivery transports that should not be delivered -to unless someone issues "sendmail -q" or equivalent. Specify zero +The names of message delivery transports that should not deliver mail +unless someone issues "sendmail -q" or equivalent. Specify zero or more names of mail delivery transports names that appear in the first field of master.cf.

    @@ -1545,7 +1557,7 @@ home directory.

    -Specify a pathname ending "/" for qmail-style delivery. +Specify a pathname ending in "/" for qmail-style delivery.

    @@ -1751,7 +1763,7 @@ block all mail to a site.

    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.

    @@ -4476,14 +4488,43 @@ any A record under rbl_domain. See the reject_rbl_client description above for additional RBL related configuration parameters. This feature is available in Postfix 2.0 and later.
  • -
    reject_unknown_client
    +
    reject_unknown_client_hostname (with Postfix < 2.3: reject_unknown_client)
    -
    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.
    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.
    +
    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.
    This is a +stronger restriction than the reject_unknown_reverse_client_hostname +feature, which triggers only under condition 1) above.
    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.
    + +
    reject_unknown_reverse_client_hostname
    + +
    Reject the request when the client IP address has no address->name +mapping.
    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.
    +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.
    This feature is available in Postfix version 2.3 and +later.
    + +#
    reject_unknown_forward_client_hostname
    +# +#
    Reject the request when the client IP address has no address->name +#or name ->address mapping.
    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. +#
    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.
    This feature is available in Postfix +#version 2.3 and later.
    @@ -4607,7 +4648,7 @@ Example:

    -smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
    +smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname
     
    %CLASS smtpd-tarpit Tarpit features @@ -4839,24 +4880,24 @@ 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. -
    reject_invalid_hostname
    +
    reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname)
    Reject the request when the HELO or EHLO hostname syntax is invalid.
    The invalid_hostname_reject_code specifies the response code to rejected requests (default: 501).
    -
    reject_non_fqdn_hostname
    +
    reject_non_fqdn_helo_hostname (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.
    The non_fqdn_reject_code parameter specifies the response code to rejected requests (default: 504).
    -
    reject_unknown_hostname
    +
    reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname)
    -
    Reject the request when the HELO or EHLO hostname has no DNS -A or MX record.
    The unknown_hostname_reject_code specifies -the response code to rejected requests (default: 450).
    +
    Reject the request when the HELO or EHLO hostname has no DNS A +or MX record.
    The unknown_hostname_reject_code specifies the +response code to rejected requests (default: 450).
    @@ -4886,8 +4927,8 @@ Examples:

    -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
     
    %PARAM smtpd_history_flush_threshold 100 @@ -5115,7 +5156,7 @@ address.
    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. -
    reject_unlisted_recipient (Postfix 2.0 name: check_recipient_maps)
    +
    reject_unlisted_recipient (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 @@ -5694,7 +5735,7 @@ Do not change this unless you have a complete understanding of RFC 821.

    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.

    @@ -5707,7 +5748,7 @@ Do not change this unless you have a complete understanding of RFC 821.

    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.

    @@ -6757,7 +6798,7 @@ local(8) aliases(5) database.

    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.

    @@ -7798,7 +7839,7 @@ is suitable for, e.g., pop-before-smtp lookup tables.

    Examples:

    -

    The Postfix < 2.2 backwards compatible setting: always rewrite +

    The Postfix < 2.2 backwards compatible setting: always rewrite message headers, and always append my own domain to incomplete header addresses.

    diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index cdb30dae0..e950671e5 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -27,7 +27,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ 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 \ @@ -56,7 +56,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.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 \ @@ -968,6 +968,17 @@ mail_conf_int.o: ../../include/vstream.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 diff --git a/postfix/src/global/mail_conf.h b/postfix/src/global/mail_conf.h index 25406e8da..29a2830f1 100644 --- a/postfix/src/global/mail_conf.h +++ b/postfix/src/global/mail_conf.h @@ -46,11 +46,13 @@ extern const char *mail_conf_lookup_eval(const char *); */ 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); /* @@ -58,6 +60,7 @@ extern int get_mail_conf_time2(const char *, const char *, const char *, int, in */ 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); @@ -67,6 +70,7 @@ 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 *); @@ -88,7 +92,7 @@ typedef struct { 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 */ @@ -98,6 +102,14 @@ typedef struct { 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 */ @@ -114,6 +126,7 @@ typedef struct { 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 *); @@ -136,7 +149,7 @@ typedef struct { 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 */ @@ -146,6 +159,14 @@ typedef struct { 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 */ @@ -154,6 +175,7 @@ typedef struct { 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 *); diff --git a/postfix/src/global/mail_conf_long.c b/postfix/src/global/mail_conf_long.c new file mode 100644 index 000000000..91e488a55 --- /dev/null +++ b/postfix/src/global/mail_conf_long.c @@ -0,0 +1,193 @@ +/*++ +/* NAME +/* mail_conf_long 3 +/* SUMMARY +/* long integer-valued configuration parameter support +/* SYNOPSIS +/* #include +/* +/* 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 +#include +#include /* sscanf() */ + +/* Utility library. */ + +#include +#include +#include +#include + +/* 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++; + } +} diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 2ce578b70..077816e27 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1586,6 +1586,9 @@ extern int var_defer_code; #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; @@ -1596,16 +1599,19 @@ 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" diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 53ca483a8..fda95bf63 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -159,8 +159,10 @@ extern char *mail_pathname(const char *, const char *); #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/... */ @@ -174,6 +176,8 @@ extern char *mail_pathname(const char *, const char *); */ #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 */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 0fd214c72..9e97d7f5f 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * 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 diff --git a/postfix/src/oqmgr/qmgr_queue.c b/postfix/src/oqmgr/qmgr_queue.c index 0354a972b..5571ae24e 100644 --- a/postfix/src/oqmgr/qmgr_queue.c +++ b/postfix/src/oqmgr/qmgr_queue.c @@ -23,9 +23,9 @@ /* 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; diff --git a/postfix/src/oqmgr/qmgr_transport.c b/postfix/src/oqmgr/qmgr_transport.c index c757178bf..756dd4809 100644 --- a/postfix/src/oqmgr/qmgr_transport.c +++ b/postfix/src/oqmgr/qmgr_transport.c @@ -18,9 +18,9 @@ /* 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; diff --git a/postfix/src/qmgr/qmgr_queue.c b/postfix/src/qmgr/qmgr_queue.c index 78bf7b212..eeb886ae8 100644 --- a/postfix/src/qmgr/qmgr_queue.c +++ b/postfix/src/qmgr/qmgr_queue.c @@ -20,9 +20,9 @@ /* 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; diff --git a/postfix/src/qmgr/qmgr_transport.c b/postfix/src/qmgr/qmgr_transport.c index a94021d6d..036d15b20 100644 --- a/postfix/src/qmgr/qmgr_transport.c +++ b/postfix/src/qmgr/qmgr_transport.c @@ -18,9 +18,9 @@ /* 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; diff --git a/postfix/src/qmqpd/qmqpd_peer.c b/postfix/src/qmqpd/qmqpd_peer.c index d785d97ed..332c94f06 100644 --- a/postfix/src/qmqpd/qmqpd_peer.c +++ b/postfix/src/qmqpd/qmqpd_peer.c @@ -138,6 +138,8 @@ void qmqpd_peer_init(QMQPD_STATE *state) 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); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 62636081b..c25b592d4 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -584,7 +584,7 @@ /* 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 @@ -592,7 +592,7 @@ /* 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 @@ -608,11 +608,11 @@ /* .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" @@ -1211,7 +1211,9 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) 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 @@ -2590,7 +2592,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) 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, @@ -2646,12 +2648,13 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) 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)) { @@ -2661,11 +2664,61 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) 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. */ diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index f4682414d..6c3800895 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -74,12 +74,20 @@ typedef struct SMTPD_STATE { 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 */ diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index b2b2065ed..9a44c443f 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -915,6 +915,46 @@ static const char *check_mail_addr_find(SMTPD_STATE *state, 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) @@ -924,9 +964,9 @@ 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)); @@ -2700,6 +2740,12 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode, 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))) { @@ -3143,6 +3189,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, 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, @@ -3356,8 +3408,15 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, /* * 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) { @@ -3399,7 +3458,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, 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, @@ -3408,7 +3468,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, 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, @@ -3440,7 +3501,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, 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, @@ -4873,11 +4935,25 @@ int main(int argc, char **argv) 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, diff --git a/postfix/src/smtpd/smtpd_peer.c b/postfix/src/smtpd/smtpd_peer.c index dc6b08e8b..0eba3b07f 100644 --- a/postfix/src/smtpd/smtpd_peer.c +++ b/postfix/src/smtpd/smtpd_peer.c @@ -17,28 +17,69 @@ /* 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 name lookup or name verification failed with a recoverable -/* error (no address->name mapping or no name->address mapping). +/* The address->name lookup or name->address 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 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 address->name lookup failed with a recoverable error. +/* .IP 5 +/* 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(). @@ -106,9 +147,17 @@ void smtpd_peer_init(SMTPD_STATE *state) */ 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 } /* @@ -153,6 +202,8 @@ void smtpd_peer_init(SMTPD_STATE *state) 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 */ } @@ -197,20 +248,32 @@ void smtpd_peer_init(SMTPD_STATE *state) #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. @@ -222,9 +285,23 @@ void smtpd_peer_init(SMTPD_STATE *state) 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", @@ -251,9 +328,17 @@ void smtpd_peer_init(SMTPD_STATE *state) */ 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 } /* @@ -268,6 +353,10 @@ void smtpd_peer_init(SMTPD_STATE *state) 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); diff --git a/postfix/src/smtpstone/qmqp-source.c b/postfix/src/smtpstone/qmqp-source.c index 628ebd2a7..7ff27bf83 100644 --- a/postfix/src/smtpstone/qmqp-source.c +++ b/postfix/src/smtpstone/qmqp-source.c @@ -543,6 +543,9 @@ int main(int argc, char **argv) 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 diff --git a/postfix/src/smtpstone/smtp-source.c b/postfix/src/smtpstone/smtp-source.c index ed796a74a..2b665d363 100644 --- a/postfix/src/smtpstone/smtp-source.c +++ b/postfix/src/smtpstone/smtp-source.c @@ -924,6 +924,9 @@ int main(int argc, char **argv) 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 diff --git a/postfix/src/util/vstream.c b/postfix/src/util/vstream.c index d395d3176..826fc4c8f 100644 --- a/postfix/src/util/vstream.c +++ b/postfix/src/util/vstream.c @@ -65,7 +65,7 @@ /* /* ssize_t vstream_fwrite(stream, buf, len) /* VSTREAM *stream; -/* char *buf; +/* const char *buf; /* ssize_t len; /* /* void vstream_control(stream, name, ...) diff --git a/postfix/src/util/vstring.c b/postfix/src/util/vstring.c index c4a4a9114..b73983b36 100644 --- a/postfix/src/util/vstring.c +++ b/postfix/src/util/vstring.c @@ -285,6 +285,8 @@ static void vstring_extend(VBUF *bp, ssize_t incr) * * 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)