From: Wietse Venema Date: Fri, 28 Aug 2009 05:00:00 +0000 (-0500) Subject: postfix-2.7-20090828 X-Git-Tag: v2.7.0-RC1~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=abb5e151b26b560aad7723a2ce658d108775f415;p=thirdparty%2Fpostfix.git postfix-2.7-20090828 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index b7925f75c..9bb8ec263 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -15335,34 +15335,3 @@ Apologies for any names omitted. Bugfix: don't panic when an unexpected smtpd access map is specified. File: smtpd/smtpd_check.c. - -20090807 - - Workaround: NS record lookups for certain domains always - fail, while other queries for those domains always succeed - (and even return replies with NS records as additional - information). - - This inconsistency would allow spammers to avoid the Postfix - check_{client,helo,sender,etc}_ns_access restrictions, - because those restrictions have effect only for names that - are known in the DNS. - - To address this specific inconsistency, the Postfix - check_{client,etc}_ns_access feature now requires that a - known-in-DNS domain name (or parent thereof) resolves to - at least one name server IP address. - - For consistency, check_{client,etc}_mx_access now requires - that a known-in-DNS domain name resolves to at least one - mail server IP address. - - 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. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 8875c6b3c..620a44132 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -14,32 +14,6 @@ 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 before proceeding. -Incompatibility with snapshot 20090807 -====================================== - -With some domain names, NS record lookups always fail while other -lookups always succeed (and may even return NS records as additional -information). This anomaly could be used by evil elements to skip -Postfix check_{client,helo,sender,recipient}_ns_access checks, -because these apply only to domains that are known in the DNS. - -To address this specific problem, check_{client,etc}_ns_access now -requires that a known-in-DNS domain name (or parent thereof) resolves -to at least one name server IP address. - -For consistency, check_{client,etc}_mx_access now requires that a -known-in-DNS domain name resolves to at least one mail server IP -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 ====================================== diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index b4977fc56..27aab4fb8 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 "20090807" +#define MAIL_RELEASE_DATE "20090828" #define MAIL_VERSION_NUMBER "2.7" #ifdef SNAPSHOT diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 939429dee..9b5e522fc 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -354,19 +354,6 @@ static int unk_addr_tf_act; static int unv_rcpt_tf_act; static int unv_from_tf_act; - /* - * What address types to query for when we determine domain existence. - * - * XXX Should we accept mail from a domain that has IPv6 addresses only, when - * the local system has IPv4 only? This can happen when the receiving system - * uses an IPv6-enabled relayhost. - */ -#ifdef T_AAAA -#define CHECK_RR_ADDR_TYPES T_A, T_AAAA -#else -#define CHECK_RR_ADDR_TYPES T_A -#endif - /* * YASLM. */ @@ -1148,94 +1135,29 @@ static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name, return (stat); } -/* resolve_server_list - check if at least some name resolves */ - -static int resolve_server_list(const char *name, int type, - const char *reply_name, - const char *reply_class) -{ - const char *myname = "resolve_server_list"; - const char *domain = name; - DNS_RR *server_list; - DNS_RR *server; - int dns_status; - int soft_err = 0; - - /* - * Require that at least one server record exists. - */ - dns_status = dns_lookup(domain, type, 0, &server_list, - (VSTRING *) 0, (VSTRING *) 0); - if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) { - if (type == T_MX) { - server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0, - domain, strlen(domain) + 1); - dns_status = DNS_OK; - } else if (type == T_NS && h_errno == NO_DATA) { - while ((domain = strchr(domain, '.')) != 0 && domain[1]) { - domain += 1; - dns_status = dns_lookup(domain, type, 0, &server_list, - (VSTRING *) 0, (VSTRING *) 0); - if (dns_status != DNS_NOTFOUND || h_errno != NO_DATA) - break; - } - } - } - if (dns_status != DNS_OK) { - msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type), - domain && domain[1] ? domain : name, dns_strerror(h_errno)); - return (dns_status); - } - - /* - * Require that at least one server record resolves to an IP address. - */ - for (server = server_list; server != 0; server = server->next) { - if (msg_verbose) - msg_info("%s: %s hostname check: %s", - myname, dns_strtype(type), (char *) server->data); - if (valid_hostaddr((char *) server->data, DONT_GRIPE)) { - soft_err = 0; - break; - } - dns_status = dns_lookup_l((char *) server->data, 0, (DNS_RR **) 0, - (VSTRING *) 0, (VSTRING *) 0, - DNS_REQ_FLAG_STOP_OK, - CHECK_RR_ADDR_TYPES, 0); - if (dns_status == DNS_OK) { - soft_err = 0; - break; - } - msg_warn("Unable to look up %s host %s for %s %s: %s", - dns_strtype(type), (char *) server->data, - reply_class, reply_name, dns_strerror(h_errno)); - if (dns_status == DNS_RETRY) - soft_err = 1; - } - dns_rr_free(server_list); - return (soft_err ? DNS_RETRY : dns_status); -} - -/* reject_unknown_hostname - fail if name has no NS, A, AAAA or MX record */ +/* reject_unknown_hostname - fail if name has no A, AAAA or MX record */ static int reject_unknown_hostname(SMTPD_STATE *state, char *name, char *reply_name, char *reply_class) { const char *myname = "reject_unknown_hostname"; int dns_status; + DNS_RR *dummy; if (msg_verbose) msg_info("%s: %s", myname, name); - /* - * Require that at least one record exists of each type that - * check_server_access() wants to check. - */ - 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) - dns_status = resolve_server_list(name, T_NS, reply_name, reply_class); +#ifdef T_AAAA +#define RR_ADDR_TYPES T_A, T_AAAA +#else +#define RR_ADDR_TYPES T_A #endif + + dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0, + (VSTRING *) 0, DNS_REQ_FLAG_STOP_OK, + RR_ADDR_TYPES, T_MX, 0); + if (dummy) + dns_rr_free(dummy); if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ if (dns_status != DNS_RETRY) return (smtpd_check_reject(state, MAIL_ERROR_POLICY, @@ -1254,26 +1176,25 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name, return (SMTPD_CHECK_DUNNO); } -/* reject_unknown_mailhost - fail if name has no NS, A, AAAA or MX record */ +/* reject_unknown_mailhost - fail if name has no A, AAAA or MX record */ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name, const char *reply_name, const char *reply_class) { const char *myname = "reject_unknown_mailhost"; int dns_status; + DNS_RR *dummy; if (msg_verbose) msg_info("%s: %s", myname, name); - /* - * Require that at least one record exists of each type that - * check_server_access() wants to check. - */ - 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) - dns_status = resolve_server_list(name, T_NS, reply_name, reply_class); -#endif +#define MAILHOST_LOOKUP_FLAGS (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL) + + dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0, + (VSTRING *) 0, MAILHOST_LOOKUP_FLAGS, + T_MX, RR_ADDR_TYPES, 0); + if (dummy) + dns_rr_free(dummy); if (dns_status != DNS_OK) { /* incl. DNS_INVAL */ if (dns_status != DNS_RETRY) return (smtpd_check_reject(state, MAIL_ERROR_POLICY, @@ -2594,10 +2515,6 @@ static int check_server_access(SMTPD_STATE *state, const char *table, struct addrinfo *res; int status; INET_PROTO_INFO *proto_info; - const char *saved_domain; - int non_err, soft_err; - int known_name_in_dns; - int ping_status; /* * Sanity check. @@ -2652,20 +2569,9 @@ 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 * 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, (VSTRING *) 0, (VSTRING *) 0); - 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) { server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0, @@ -2684,22 +2590,6 @@ static int check_server_access(SMTPD_STATE *state, const char *table, if (dns_status != DNS_OK) { msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type), 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); } @@ -2712,13 +2602,11 @@ static int check_server_access(SMTPD_STATE *state, const char *table, * Check the hostnames first, then the addresses. */ proto_info = inet_proto_info(); - non_err = soft_err = 0; for (server = server_list; server != 0; server = server->next) { if (msg_verbose) msg_info("%s: %s hostname check: %s", myname, dns_strtype(type), (char *) server->data); if (valid_hostaddr((char *) server->data, DONT_GRIPE)) { - non_err = 1; if ((status = check_addr_access(state, table, (char *) server->data, FULL, &found, reply_name, reply_class, def_acl)) != 0 || found) @@ -2734,11 +2622,8 @@ static int check_server_access(SMTPD_STATE *state, const char *table, msg_warn("Unable to look up %s host %s for %s %s: %s", dns_strtype(type), (char *) server->data, reply_class, reply_name, MAI_STRERROR(aierr)); - if (aierr == EAI_AGAIN || aierr == EAI_SYSTEM) - soft_err = 1; continue; } - non_err = 1; /* Now we must also free the addrinfo result. */ if (msg_verbose) msg_info("%s: %s host address check: %s", @@ -2762,15 +2647,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table, } freeaddrinfo(res0); /* 200412 */ } - 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_SERVER_RETURN(SMTPD_CHECK_DUNNO); } /* check_ccert_access - access for TLS clients by certificate fingerprint */