2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 14:17:41 +00:00

postfix-2.5.8

This commit is contained in:
Wietse Venema
2009-08-26 00:00:00 -05:00
committed by Viktor Dukhovni
parent 9dd2815512
commit 6e28833db0
5 changed files with 153 additions and 13 deletions

View File

@@ -14514,3 +14514,47 @@ Apologies for any names omitted.
Bugfix: don't disable MIME parsing with smtp_header_checks,
smtp_mime_header_checks, smtp_nested_header_checks or with
smtp_body_checks. Bug reported by Victor. File: smtp/smtp_proto.c.
20090710
Bugfix (introduced Postfix 2.3): Postfix got out of sync
with a Milter application after the application sent a
"quarantine" request at end-of-message time. The milter
application would still be in the end-of-message state,
while Postfix would already be working on the next SMTP
event (typically, QUIT or MAIL FROM). Problem diagnosed
with help from Alban Deniz. File: milter/milter8.c.
20090805
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 in DNS lookup results would allow spammers
to circumvent the Postfix check_{client,helo,sender,etc}_ns_access
restrictions, because those restrictions have effect only
for NS records that can be looked up in the DNS.
To address this inconsistency, check_{client,etc}_ns_access
now require that a known-in-DNS domain name (or parent
thereof) always resolves to at least one name server IP
address.
For consistency, check_{client,etc}_mx_access now require
that a known-in-DNS domain name always resolves to at least
one mail server IP address.
These measures merely raise the difficulty level for spammers.
The IP address information thus obtained is not necessarily
"correct". There is little to stop an uncooperative DNS
server from lying, especially when the owner of the domain
has no desire to receive email. File: smtpd/smtpd_check.c.
Problem reported by MXTools.com.

View File

@@ -11,6 +11,28 @@ instead, a new snapshot is released.
The mail_release_date configuration parameter (format: yyyymmdd)
specifies the release date of a stable release or snapshot release.
Incompatibility with Postfix 2.5.8
==================================
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 NS records that are found 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) always
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 always resolves to at least one mail server
IP address.
These measures provide no hard assurances that the IP address
information thus obtained is correct. There is little to stop an
uncooperative DNS server from lying, especially when the owner of
the domain has no desire to receive email.
Incompatibility with Postfix 2.5.3
==================================

View File

@@ -20,8 +20,8 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20090512"
#define MAIL_VERSION_NUMBER "2.5.7"
#define MAIL_RELEASE_DATE "20090826"
#define MAIL_VERSION_NUMBER "2.5.8"
#ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@@ -1292,7 +1292,8 @@ static const char *milter8_event(MILTER8 *milter, int event,
/*
* Decision: quarantine. In Sendmail 8.13 this does not imply a
* transition in the receiver state (reply, reject, tempfail,
* accept, discard).
* accept, discard). We should not transition, either, otherwise
* we get out of sync.
*/
case SMFIR_QUARANTINE:
/* XXX What to do with the "reason" text? */
@@ -1300,7 +1301,8 @@ static const char *milter8_event(MILTER8 *milter, int event,
MILTER8_DATA_BUFFER, milter->buf,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
MILTER8_EVENT_BREAK("H");
milter8_def_reply(milter, "H");
continue;
/*
* Decision: skip further events of this type.

View File

@@ -2295,8 +2295,13 @@ static int check_access(SMTPD_STATE *state, const char *table, const char *name,
if (msg_verbose)
msg_info("%s: %s", myname, name);
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if ((dict = dict_handle(table)) == 0) {
msg_warn("%s: unexpected dictionary: %s", myname, table);
value = "451 4.3.5 Server configuration error";
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
reply_name, reply_class,
def_acl), FOUND);
}
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
@@ -2340,8 +2345,13 @@ static int check_domain_access(SMTPD_STATE *state, const char *table,
*/
#define CHK_DOMAIN_RETURN(x,y) { *found = y; return(x); }
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if ((dict = dict_handle(table)) == 0) {
msg_warn("%s: unexpected dictionary: %s", myname, table);
value = "451 4.3.5 Server configuration error";
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
domain, reply_name, reply_class,
def_acl), FOUND);
}
for (name = domain; *name != 0; name = next) {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, name)) != 0)
@@ -2399,8 +2409,13 @@ static int check_addr_access(SMTPD_STATE *state, const char *table,
#endif
delim = '.';
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if ((dict = dict_handle(table)) == 0) {
msg_warn("%s: unexpected dictionary: %s", myname, table);
value = "451 4.3.5 Server configuration error";
CHK_ADDR_RETURN(check_table_result(state, table, value, address,
reply_name, reply_class,
def_acl), FOUND);
}
do {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, addr)) != 0)
@@ -2480,6 +2495,10 @@ 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.
@@ -2534,15 +2553,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
* 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);
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) {
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) {
} 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,
@@ -2552,9 +2582,31 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
}
}
}
#ifndef VAR_MAP_DEFER_CODE
#define var_map_reject_code var_reject_code
#define var_map_defer_code var_defer_code
#endif
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,
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);
}
@@ -2567,10 +2619,19 @@ 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)
CHECK_SERVER_RETURN(status);
continue;
}
if ((status = check_domain_access(state, table, (char *) server->data,
FULL, &found, reply_name, reply_class,
def_acl)) != 0 || found)
@@ -2580,8 +2641,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",
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",
@@ -2605,7 +2669,15 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
}
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 */