mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
postfix-2.3.18
This commit is contained in:
committed by
Viktor Dukhovni
parent
a2a0f3da97
commit
b2aac0b710
@@ -13196,3 +13196,47 @@ Apologies for any names omitted.
|
||||
|
||||
Robustness: don't re-enable SIGTERM if it is ignored in the
|
||||
parent. Files: postsuper/postsuper.c, postdrop/postdrop.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.
|
||||
|
@@ -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.
|
||||
|
||||
Incompatible changes with Postfix 2.3.18
|
||||
----------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
Incompatible changes with Postfix 2.3.7
|
||||
---------------------------------------
|
||||
|
||||
|
@@ -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 "20090511"
|
||||
#define MAIL_VERSION_NUMBER "2.3.17"
|
||||
#define MAIL_RELEASE_DATE "20090826"
|
||||
#define MAIL_VERSION_NUMBER "2.3.18"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
|
||||
|
@@ -1186,7 +1186,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.
|
||||
*/
|
||||
#ifdef SMFIR_QUARANTINE
|
||||
case SMFIR_QUARANTINE:
|
||||
@@ -1195,7 +1196,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;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -2269,8 +2269,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,
|
||||
@@ -2314,8 +2319,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)
|
||||
@@ -2373,8 +2383,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)
|
||||
@@ -2454,6 +2469,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.
|
||||
@@ -2508,15 +2527,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,
|
||||
@@ -2526,9 +2556,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);
|
||||
}
|
||||
|
||||
@@ -2541,10 +2593,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)
|
||||
@@ -2554,8 +2615,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",
|
||||
@@ -2579,7 +2643,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 */
|
||||
|
Reference in New Issue
Block a user