mirror of
https://github.com/vdukhovni/postfix
synced 2025-09-02 07:05:27 +00:00
postfix-2.7-20090807
This commit is contained in:
committed by
Viktor Dukhovni
parent
24a96550cb
commit
fb6283acfc
@@ -15336,22 +15336,33 @@ Apologies for any names omitted.
|
|||||||
Bugfix: don't panic when an unexpected smtpd access map is
|
Bugfix: don't panic when an unexpected smtpd access map is
|
||||||
specified. File: smtpd/smtpd_check.c.
|
specified. File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20090807
|
||||||
|
|
||||||
Workaround: NS record lookups for certain domains always
|
Workaround: NS record lookups for certain domains always
|
||||||
fail, while other queries for those domains always succeed
|
fail, while other queries for those domains always succeed
|
||||||
(and even return replies with NS records as additional
|
(and even return replies with NS records as additional
|
||||||
information).
|
information).
|
||||||
|
|
||||||
This specific inconsistency would allow spammers to avoid
|
This inconsistency would allow spammers to avoid the Postfix
|
||||||
the Postfix check_{client,helo,sender,etc}_ns_access
|
check_{client,helo,sender,etc}_ns_access restrictions,
|
||||||
restrictions, because those restrictions have effect only
|
because those restrictions have effect only for names that
|
||||||
for NS records that can be looked up in the DNS.
|
are known in the DNS.
|
||||||
|
|
||||||
To address this specific inconsistency, the Postfix
|
To address this specific inconsistency, the Postfix
|
||||||
reject_unknown_helo_hostname, reject_unknown_sender_domain
|
check_{client,etc}_ns_access feature now requires that a
|
||||||
and reject_unknown_recipient_domain restrictions now require
|
known-in-DNS domain name (or parent thereof) resolves to
|
||||||
that a domain has NS records that resolve to at least one
|
at least one name server IP address.
|
||||||
IP address, and they now accept only MX records that resolve
|
|
||||||
to at least one IP address; those addresses may or may not
|
For consistency, check_{client,etc}_mx_access now requires
|
||||||
be "correct". Postfix has no code to determine whether the
|
that a known-in-DNS domain name resolves to at least one
|
||||||
SMTP client name has a resolvable NS or MX record. File:
|
mail server IP address.
|
||||||
smtpd/smtpd_check.c.
|
|
||||||
|
In addition, reject_unknown_helo_hostname,
|
||||||
|
reject_unknown_sender_domain now require that an MX record
|
||||||
|
resolves to at least one IP address. Until now, the existence
|
||||||
|
of an MX record was sufficient.
|
||||||
|
|
||||||
|
The IP addresses thus obtained may or may not be "correct".
|
||||||
|
There is little to stop an uncooperative DNS server from
|
||||||
|
lying, especially when the owner of the domain has no
|
||||||
|
intention to receive email. File: smtpd/smtpd_check.c.
|
||||||
|
@@ -14,22 +14,31 @@ specifies the release date of a stable release or snapshot release.
|
|||||||
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
|
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
|
||||||
before proceeding.
|
before proceeding.
|
||||||
|
|
||||||
Incompatibility with snapshot 20090805
|
Incompatibility with snapshot 20090807
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
With some domain names, NS record lookups always fail while other
|
With some domain names, NS record lookups always fail while other
|
||||||
lookups always succeed (and often return NS records as additional
|
lookups always succeed (and may even return NS records as additional
|
||||||
information). This anomaly could be used by evil elements to skip
|
information). This anomaly could be used by evil elements to skip
|
||||||
Postfix check_{client,helo,sender,recipient}_ns_access checks,
|
Postfix check_{client,helo,sender,recipient}_ns_access checks,
|
||||||
because those apply only domains with an NS record in the DNS.
|
because these apply only to domains that are known in the DNS.
|
||||||
|
|
||||||
To address this specific problem, the reject_unknown_helo_hostname,
|
To address this specific problem, check_{client,etc}_ns_access now
|
||||||
reject_unknown_sender_domain and reject_unknown_recipient_domain
|
requires that a known-in-DNS domain name (or parent thereof) resolves
|
||||||
features now require that a domain name has NS records that resolve
|
to at least one name server IP address.
|
||||||
to at least one IP address, and they now accept only MX records
|
|
||||||
that resolve to at least one IP address; those addresses may or may
|
For consistency, check_{client,etc}_mx_access now requires that a
|
||||||
not be "correct". Postfix has no code to determine whether the
|
known-in-DNS domain name resolves to at least one mail server IP
|
||||||
SMTP client name has a resolvable NS or MX record.
|
address.
|
||||||
|
|
||||||
|
In addition, reject_unknown_helo_hostname, reject_unknown_sender_domain
|
||||||
|
and reject_unknown_recipient_domain now require that an MX record
|
||||||
|
resolves to at least one IP address. Until now, the existence of
|
||||||
|
an MX record was sufficient.
|
||||||
|
|
||||||
|
Keep in mind that these measures provide no hard assurances. There
|
||||||
|
is little to stop an uncooperative DNS server from lying, especially
|
||||||
|
when the owner of the domain has no intention to receive email.
|
||||||
|
|
||||||
Incompatibility with snapshot 20090606
|
Incompatibility with snapshot 20090606
|
||||||
======================================
|
======================================
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20090805"
|
#define MAIL_RELEASE_DATE "20090807"
|
||||||
#define MAIL_VERSION_NUMBER "2.7"
|
#define MAIL_VERSION_NUMBER "2.7"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@@ -1166,12 +1166,12 @@ static int resolve_server_list(const char *name, int type,
|
|||||||
*/
|
*/
|
||||||
dns_status = dns_lookup(domain, type, 0, &server_list,
|
dns_status = dns_lookup(domain, type, 0, &server_list,
|
||||||
(VSTRING *) 0, (VSTRING *) 0);
|
(VSTRING *) 0, (VSTRING *) 0);
|
||||||
if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
|
if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) {
|
||||||
if (type == T_MX) {
|
if (type == T_MX) {
|
||||||
server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
|
server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
|
||||||
domain, strlen(domain) + 1);
|
domain, strlen(domain) + 1);
|
||||||
dns_status = DNS_OK;
|
dns_status = DNS_OK;
|
||||||
} else if (type == T_NS) {
|
} else if (type == T_NS && h_errno == NO_DATA) {
|
||||||
while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
|
while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
|
||||||
domain += 1;
|
domain += 1;
|
||||||
dns_status = dns_lookup(domain, type, 0, &server_list,
|
dns_status = dns_lookup(domain, type, 0, &server_list,
|
||||||
@@ -1232,8 +1232,10 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
|
|||||||
* check_server_access() wants to check.
|
* check_server_access() wants to check.
|
||||||
*/
|
*/
|
||||||
dns_status = resolve_server_list(name, T_MX, reply_name, reply_class);
|
dns_status = resolve_server_list(name, T_MX, reply_name, reply_class);
|
||||||
|
#ifdef REQUIRE_NS_FOR_REJECT_UNKNOWN_DOMAIN_CHECK
|
||||||
if (dns_status == DNS_OK)
|
if (dns_status == DNS_OK)
|
||||||
dns_status = resolve_server_list(name, T_NS, reply_name, reply_class);
|
dns_status = resolve_server_list(name, T_NS, reply_name, reply_class);
|
||||||
|
#endif
|
||||||
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
|
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
|
||||||
if (dns_status != DNS_RETRY)
|
if (dns_status != DNS_RETRY)
|
||||||
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
@@ -1268,8 +1270,10 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
|
|||||||
* check_server_access() wants to check.
|
* check_server_access() wants to check.
|
||||||
*/
|
*/
|
||||||
dns_status = resolve_server_list(name, T_MX, reply_name, reply_class);
|
dns_status = resolve_server_list(name, T_MX, reply_name, reply_class);
|
||||||
|
#ifdef REQUIRE_NS_FOR_REJECT_UNKNOWN_DOMAIN_CHECK
|
||||||
if (dns_status == DNS_OK)
|
if (dns_status == DNS_OK)
|
||||||
dns_status = resolve_server_list(name, T_NS, reply_name, reply_class);
|
dns_status = resolve_server_list(name, T_NS, reply_name, reply_class);
|
||||||
|
#endif
|
||||||
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
|
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
|
||||||
if (dns_status != DNS_RETRY)
|
if (dns_status != DNS_RETRY)
|
||||||
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
@@ -2590,6 +2594,10 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
int status;
|
int status;
|
||||||
INET_PROTO_INFO *proto_info;
|
INET_PROTO_INFO *proto_info;
|
||||||
|
const char *saved_domain;
|
||||||
|
int non_err, soft_err;
|
||||||
|
int known_name_in_dns;
|
||||||
|
int ping_status;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check.
|
* Sanity check.
|
||||||
@@ -2644,15 +2652,26 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
*
|
*
|
||||||
* If the domain name exists but no NS record exists, look up parent domain
|
* If the domain name exists but no NS record exists, look up parent domain
|
||||||
* NS records.
|
* NS records.
|
||||||
|
*
|
||||||
|
* After the initial lookup fails, do one final DNS sanity check. Reject
|
||||||
|
* mail when the name exists, but MX lookup produces no valid response or
|
||||||
|
* NS lookup fails for any reason. Beware, this sanity check provides no
|
||||||
|
* hard assurance. An uncooperative DNS server may lie about everything,
|
||||||
|
* including non-existence.
|
||||||
*/
|
*/
|
||||||
|
#define SOME_DNS_RR_EXISTS(stat, herr) \
|
||||||
|
((stat) == DNS_OK || (stat) == DNS_INVAL || (herr) == NO_DATA)
|
||||||
|
|
||||||
|
saved_domain = domain;
|
||||||
dns_status = dns_lookup(domain, type, 0, &server_list,
|
dns_status = dns_lookup(domain, type, 0, &server_list,
|
||||||
(VSTRING *) 0, (VSTRING *) 0);
|
(VSTRING *) 0, (VSTRING *) 0);
|
||||||
if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
|
known_name_in_dns = SOME_DNS_RR_EXISTS(dns_status, h_errno);
|
||||||
|
if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) {
|
||||||
if (type == T_MX) {
|
if (type == T_MX) {
|
||||||
server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
|
server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
|
||||||
domain, strlen(domain) + 1);
|
domain, strlen(domain) + 1);
|
||||||
dns_status = DNS_OK;
|
dns_status = DNS_OK;
|
||||||
} else if (type == T_NS) {
|
} else if (type == T_NS && h_errno == NO_DATA) {
|
||||||
while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
|
while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
|
||||||
domain += 1;
|
domain += 1;
|
||||||
dns_status = dns_lookup(domain, type, 0, &server_list,
|
dns_status = dns_lookup(domain, type, 0, &server_list,
|
||||||
@@ -2665,6 +2684,22 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
if (dns_status != DNS_OK) {
|
if (dns_status != DNS_OK) {
|
||||||
msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type),
|
msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type),
|
||||||
domain && domain[1] ? domain : name, dns_strerror(h_errno));
|
domain && domain[1] ? domain : name, dns_strerror(h_errno));
|
||||||
|
if (known_name_in_dns == 0) {
|
||||||
|
/* With hostile DNS, an address query is more likely to work. */
|
||||||
|
ping_status = dns_lookup_l(saved_domain, 0, (DNS_RR **) 0,
|
||||||
|
(VSTRING *) 0, (VSTRING *) 0,
|
||||||
|
DNS_REQ_FLAG_STOP_OK,
|
||||||
|
CHECK_RR_ADDR_TYPES, 0);
|
||||||
|
known_name_in_dns = SOME_DNS_RR_EXISTS(ping_status, h_errno);
|
||||||
|
}
|
||||||
|
if (known_name_in_dns)
|
||||||
|
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
|
dns_status == DNS_RETRY ?
|
||||||
|
var_map_defer_code : var_map_reject_code,
|
||||||
|
smtpd_dsn_fix("4.1.8", reply_class),
|
||||||
|
"<%s>: %s rejected: %s",
|
||||||
|
reply_name, reply_class,
|
||||||
|
"Domain not found"));
|
||||||
return (SMTPD_CHECK_DUNNO);
|
return (SMTPD_CHECK_DUNNO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2677,11 +2712,13 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
* Check the hostnames first, then the addresses.
|
* Check the hostnames first, then the addresses.
|
||||||
*/
|
*/
|
||||||
proto_info = inet_proto_info();
|
proto_info = inet_proto_info();
|
||||||
|
non_err = soft_err = 0;
|
||||||
for (server = server_list; server != 0; server = server->next) {
|
for (server = server_list; server != 0; server = server->next) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s hostname check: %s",
|
msg_info("%s: %s hostname check: %s",
|
||||||
myname, dns_strtype(type), (char *) server->data);
|
myname, dns_strtype(type), (char *) server->data);
|
||||||
if (valid_hostaddr((char *) server->data, DONT_GRIPE)) {
|
if (valid_hostaddr((char *) server->data, DONT_GRIPE)) {
|
||||||
|
non_err = 1;
|
||||||
if ((status = check_addr_access(state, table, (char *) server->data,
|
if ((status = check_addr_access(state, table, (char *) server->data,
|
||||||
FULL, &found, reply_name, reply_class,
|
FULL, &found, reply_name, reply_class,
|
||||||
def_acl)) != 0 || found)
|
def_acl)) != 0 || found)
|
||||||
@@ -2697,8 +2734,11 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
msg_warn("Unable to look up %s host %s for %s %s: %s",
|
msg_warn("Unable to look up %s host %s for %s %s: %s",
|
||||||
dns_strtype(type), (char *) server->data,
|
dns_strtype(type), (char *) server->data,
|
||||||
reply_class, reply_name, MAI_STRERROR(aierr));
|
reply_class, reply_name, MAI_STRERROR(aierr));
|
||||||
|
if (aierr == EAI_AGAIN || aierr == EAI_SYSTEM)
|
||||||
|
soft_err = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
non_err = 1;
|
||||||
/* Now we must also free the addrinfo result. */
|
/* Now we must also free the addrinfo result. */
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s host address check: %s",
|
msg_info("%s: %s host address check: %s",
|
||||||
@@ -2722,7 +2762,15 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
}
|
}
|
||||||
freeaddrinfo(res0); /* 200412 */
|
freeaddrinfo(res0); /* 200412 */
|
||||||
}
|
}
|
||||||
CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
|
status = non_err ? SMTPD_CHECK_DUNNO :
|
||||||
|
smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
|
soft_err ? var_map_defer_code :
|
||||||
|
var_map_reject_code,
|
||||||
|
smtpd_dsn_fix("4.1.8", reply_class),
|
||||||
|
"<%s>: %s rejected: %s",
|
||||||
|
reply_name, reply_class,
|
||||||
|
"Domain not found");
|
||||||
|
CHECK_SERVER_RETURN(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check_ccert_access - access for TLS clients by certificate fingerprint */
|
/* check_ccert_access - access for TLS clients by certificate fingerprint */
|
||||||
|
Reference in New Issue
Block a user