mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 22:25:24 +00:00
postfix-3.9-20240222-nonprod
This commit is contained in:
committed by
Viktor Dukhovni
parent
03382b275a
commit
02bb17535f
@@ -27920,3 +27920,14 @@ Apologies for any names omitted.
|
|||||||
status. Files: postconf/postconf.c, postconf/postconf_dbms.c,
|
status. Files: postconf/postconf.c, postconf/postconf_dbms.c,
|
||||||
postconf/postconf.h, conf/postfix-script, conf/post-install,
|
postconf/postconf.h, conf/postfix-script, conf/post-install,
|
||||||
postfix-install.
|
postfix-install.
|
||||||
|
|
||||||
|
20240222
|
||||||
|
|
||||||
|
Safety: drop and log over-size DNS responses resulting in
|
||||||
|
more than 100 records. This prevents a tail recursion error
|
||||||
|
in dns_rr_append(), reported by Toshifumi Sakaguchi, and
|
||||||
|
prevents DNS request multiplication in check_xx_yy_access.
|
||||||
|
Files: dns/dns.h, dns/dns_lookup.c, dns/dns_rr.c,
|
||||||
|
dns/test_dns_lookup.c, posttls-finger/posttls-finger.c,
|
||||||
|
smtp/smtp_addr.c, smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
@@ -973,7 +973,7 @@ CCARGS="$CCARGS -DSNAPSHOT"
|
|||||||
|
|
||||||
# Non-production: needs thorough testing, or major changes are still
|
# Non-production: needs thorough testing, or major changes are still
|
||||||
# needed before the code stabilizes.
|
# needed before the code stabilizes.
|
||||||
#CCARGS="$CCARGS -DNONPROD"
|
CCARGS="$CCARGS -DNONPROD"
|
||||||
|
|
||||||
# Workaround: prepend Postfix include files before other include files.
|
# Workaround: prepend Postfix include files before other include files.
|
||||||
CCARGS="-I. -I../../include $CCARGS"
|
CCARGS="-I. -I../../include $CCARGS"
|
||||||
|
@@ -286,7 +286,6 @@ dns_lookup.o: ../../include/vstring.h
|
|||||||
dns_lookup.o: dns.h
|
dns_lookup.o: dns.h
|
||||||
dns_lookup.o: dns_lookup.c
|
dns_lookup.o: dns_lookup.c
|
||||||
dns_rr.o: ../../include/check_arg.h
|
dns_rr.o: ../../include/check_arg.h
|
||||||
dns_rr.o: ../../include/mail_params.h
|
|
||||||
dns_rr.o: ../../include/msg.h
|
dns_rr.o: ../../include/msg.h
|
||||||
dns_rr.o: ../../include/myaddrinfo.h
|
dns_rr.o: ../../include/myaddrinfo.h
|
||||||
dns_rr.o: ../../include/mymalloc.h
|
dns_rr.o: ../../include/mymalloc.h
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <arpa/nameser_compat.h>
|
#include <arpa/nameser_compat.h>
|
||||||
#endif
|
#endif
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
|
#include <limits.h> /* INT_MAX */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name server compatibility. These undocumented macros appear in the file
|
* Name server compatibility. These undocumented macros appear in the file
|
||||||
@@ -164,9 +165,12 @@ typedef struct DNS_RR {
|
|||||||
struct DNS_RR *next; /* linkage */
|
struct DNS_RR *next; /* linkage */
|
||||||
size_t data_len; /* actual data size */
|
size_t data_len; /* actual data size */
|
||||||
char *data; /* a bunch of data */
|
char *data; /* a bunch of data */
|
||||||
|
int len; /* list length or DNS_RR_DISCARDED */
|
||||||
/* Add new fields at the end, for ABI forward compatibility. */
|
/* Add new fields at the end, for ABI forward compatibility. */
|
||||||
} DNS_RR;
|
} DNS_RR;
|
||||||
|
|
||||||
|
#define DNS_RR_DISCARDED INT_MAX /* sentinel */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dns_strerror.c
|
* dns_strerror.c
|
||||||
*/
|
*/
|
||||||
@@ -207,6 +211,7 @@ extern DNS_RR *dns_rr_create(const char *, const char *,
|
|||||||
extern void dns_rr_free(DNS_RR *);
|
extern void dns_rr_free(DNS_RR *);
|
||||||
extern DNS_RR *dns_rr_copy(DNS_RR *);
|
extern DNS_RR *dns_rr_copy(DNS_RR *);
|
||||||
extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
|
extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
|
||||||
|
extern DNS_RR *dns_rr_append_discard(DNS_RR *, DNS_RR *);
|
||||||
extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
|
extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
|
||||||
extern DNS_RR *dns_srv_rr_sort(DNS_RR *);
|
extern DNS_RR *dns_srv_rr_sort(DNS_RR *);
|
||||||
extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *);
|
extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *);
|
||||||
@@ -215,6 +220,7 @@ extern int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *);
|
|||||||
extern int dns_rr_compare_pref(DNS_RR *, DNS_RR *);
|
extern int dns_rr_compare_pref(DNS_RR *, DNS_RR *);
|
||||||
extern DNS_RR *dns_rr_shuffle(DNS_RR *);
|
extern DNS_RR *dns_rr_shuffle(DNS_RR *);
|
||||||
extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
|
extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
|
||||||
|
extern int var_dns_rr_list_limit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dns_rr_to_pa.c
|
* dns_rr_to_pa.c
|
||||||
|
@@ -983,7 +983,9 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
|
|||||||
&fixed)) == DNS_OK) {
|
&fixed)) == DNS_OK) {
|
||||||
resource_found++;
|
resource_found++;
|
||||||
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
|
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
|
||||||
*rrlist = dns_rr_append(*rrlist, rr);
|
*rrlist = dns_rr_append_discard(*rrlist, rr);
|
||||||
|
if (*rrlist && (*rrlist)->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
} else if (status == DNS_NULLMX || status == DNS_NULLSRV) {
|
} else if (status == DNS_NULLMX || status == DNS_NULLSRV) {
|
||||||
CORRUPT(status); /* TODO: use better name */
|
CORRUPT(status); /* TODO: use better name */
|
||||||
} else if (not_found_status != DNS_RETRY)
|
} else if (not_found_status != DNS_RETRY)
|
||||||
@@ -1214,8 +1216,11 @@ int dns_lookup_rl(const char *name, unsigned flags, DNS_RR **rrlist,
|
|||||||
name, dns_strtype(type), dns_str_resflags(flags));
|
name, dns_strtype(type), dns_str_resflags(flags));
|
||||||
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
||||||
fqdn, why, rcode, lflags);
|
fqdn, why, rcode, lflags);
|
||||||
if (rrlist && rr)
|
if (rrlist && rr) {
|
||||||
*rrlist = dns_rr_append(*rrlist, rr);
|
*rrlist = dns_rr_append_discard(*rrlist, rr);
|
||||||
|
if (*rrlist && (*rrlist)->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (status == DNS_OK) {
|
if (status == DNS_OK) {
|
||||||
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
||||||
break;
|
break;
|
||||||
@@ -1266,8 +1271,11 @@ int dns_lookup_rv(const char *name, unsigned flags, DNS_RR **rrlist,
|
|||||||
name, dns_strtype(type), dns_str_resflags(flags));
|
name, dns_strtype(type), dns_str_resflags(flags));
|
||||||
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
||||||
fqdn, why, rcode, lflags);
|
fqdn, why, rcode, lflags);
|
||||||
if (rrlist && rr)
|
if (rrlist && rr) {
|
||||||
*rrlist = dns_rr_append(*rrlist, rr);
|
*rrlist = dns_rr_append_discard(*rrlist, rr);
|
||||||
|
if (*rrlist && (*rrlist)->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (status == DNS_OK) {
|
if (status == DNS_OK) {
|
||||||
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
||||||
break;
|
break;
|
||||||
|
@@ -29,6 +29,10 @@
|
|||||||
/* DNS_RR *list;
|
/* DNS_RR *list;
|
||||||
/* DNS_RR *record;
|
/* DNS_RR *record;
|
||||||
/*
|
/*
|
||||||
|
/* DNS_RR *dns_rr_append_discard(list, record)
|
||||||
|
/* DNS_RR *list;
|
||||||
|
/* DNS_RR *record;
|
||||||
|
/*
|
||||||
/* DNS_RR *dns_rr_sort(list, compar)
|
/* DNS_RR *dns_rr_sort(list, compar)
|
||||||
/* DNS_RR *list
|
/* DNS_RR *list
|
||||||
/* int (*compar)(DNS_RR *, DNS_RR *);
|
/* int (*compar)(DNS_RR *, DNS_RR *);
|
||||||
@@ -100,9 +104,16 @@
|
|||||||
/* dns_rr_append() appends a resource record to a (list of) resource
|
/* dns_rr_append() appends a resource record to a (list of) resource
|
||||||
/* record(s).
|
/* record(s).
|
||||||
/* A null input list is explicitly allowed.
|
/* A null input list is explicitly allowed.
|
||||||
/* This function will log a warning and will discard the
|
/*
|
||||||
/* resource record, when a list already contains var_dns_rr_list_limit
|
/* dns_rr_append_discard() appends of discards a resource
|
||||||
/* elements (default: 100).
|
/* record list. When the existing list already contains
|
||||||
|
/* var_dns_rr_list_limit elements (default: 100),
|
||||||
|
/* dns_rr_append_discard() logs a warning, sets the existing
|
||||||
|
/* list length to the sentinel value DNS_RR_DISCARDED and
|
||||||
|
/* discards the new resource record(s) instead of appending
|
||||||
|
/* them. Once a list length is set to DNS_RR_DISCARDED, the
|
||||||
|
/* caller is expected to stop trying to append records to that
|
||||||
|
/* list.
|
||||||
/*
|
/*
|
||||||
/* dns_rr_sort() sorts a list of resource records into ascending
|
/* dns_rr_sort() sorts a list of resource records into ascending
|
||||||
/* order according to a user-specified criterion. The result is the
|
/* order according to a user-specified criterion. The result is the
|
||||||
@@ -151,18 +162,19 @@
|
|||||||
#include <mymalloc.h>
|
#include <mymalloc.h>
|
||||||
#include <myrand.h>
|
#include <myrand.h>
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include <mail_params.h>
|
|
||||||
|
|
||||||
/* DNS library. */
|
/* DNS library. */
|
||||||
|
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global, to make code testable.
|
* A generous safety limit for the number of DNS resource records that the
|
||||||
|
* Postfix DNS client library will admit into a list. The default value 100
|
||||||
|
* is 20x the default limit on the number address records that the Postfix
|
||||||
|
* SMTP client is willing to consider.
|
||||||
|
*
|
||||||
|
* Mutable, to make code testable.
|
||||||
*/
|
*/
|
||||||
int var_dns_rr_list_limit = DEF_DNS_RR_LIST_LIMIT;
|
int var_dns_rr_list_limit = 100;
|
||||||
|
|
||||||
/* dns_rr_create - fill in resource record structure */
|
/* dns_rr_create - fill in resource record structure */
|
||||||
|
|
||||||
@@ -195,6 +207,7 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname,
|
|||||||
}
|
}
|
||||||
rr->data_len = data_len;
|
rr->data_len = data_len;
|
||||||
rr->next = 0;
|
rr->next = 0;
|
||||||
|
rr->len = 1;
|
||||||
return (rr);
|
return (rr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,38 +245,49 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
|
|||||||
return (dst);
|
return (dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dns_rr_append_with_limit - append resource record to limited list */
|
|
||||||
|
|
||||||
static DNS_RR *dns_rr_append_with_limit(DNS_RR *list, DNS_RR *rr, int limit)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To avoid log spam, remember a limited amount of information about a
|
|
||||||
* past warning. When anomalies happen frequently, then it is OK that
|
|
||||||
* some anomaly will not be logged, as long as the limit is enforced.
|
|
||||||
*/
|
|
||||||
if (list == 0) {
|
|
||||||
list = rr;
|
|
||||||
} else if (limit > 1) {
|
|
||||||
list->next = dns_rr_append_with_limit(list->next, rr, limit - 1);
|
|
||||||
} else {
|
|
||||||
static DNS_RR *logged_node;
|
|
||||||
|
|
||||||
if (logged_node != list) {
|
|
||||||
logged_node = list;
|
|
||||||
msg_warn("dns_rr_append: dropping records after qname=%s qtype=%s",
|
|
||||||
list->qname, dns_strtype(list->type));
|
|
||||||
}
|
|
||||||
dns_rr_free(rr);
|
|
||||||
}
|
|
||||||
return (list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dns_rr_append - append resource record to list */
|
/* dns_rr_append - append resource record to list */
|
||||||
|
|
||||||
DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
|
DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
|
||||||
{
|
{
|
||||||
return (dns_rr_append_with_limit(list, rr, var_dns_rr_list_limit));
|
if (rr == 0)
|
||||||
|
return (list);
|
||||||
|
if (list == 0) {
|
||||||
|
list = rr;
|
||||||
|
} else {
|
||||||
|
list->next = dns_rr_append(list->next, rr);
|
||||||
|
/* Non-sentinel lengths are o(100) an are always safe to add. */
|
||||||
|
if (list->len == DNS_RR_DISCARDED || rr->len == DNS_RR_DISCARDED)
|
||||||
|
list->len = DNS_RR_DISCARDED;
|
||||||
|
else
|
||||||
|
list->len += rr->len;
|
||||||
|
}
|
||||||
|
return (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dns_rr_append_discard - append resource record to list, or discard */
|
||||||
|
|
||||||
|
DNS_RR *dns_rr_append_discard(DNS_RR *list, DNS_RR *rr)
|
||||||
|
{
|
||||||
|
if (rr == 0)
|
||||||
|
return (list);
|
||||||
|
if (list == 0) {
|
||||||
|
list = rr;
|
||||||
|
} else if (list->len < var_dns_rr_list_limit) {
|
||||||
|
list->next = dns_rr_append(list->next, rr);
|
||||||
|
/* Non-sentinel lengths are o(100) an are always safe to add. */
|
||||||
|
if (rr->len == DNS_RR_DISCARDED)
|
||||||
|
list->len = DNS_RR_DISCARDED;
|
||||||
|
else
|
||||||
|
list->len += rr->len;
|
||||||
|
} else {
|
||||||
|
if (list->len != DNS_RR_DISCARDED) {
|
||||||
|
msg_warn("dropping excess records for qname=%s qtype=%s",
|
||||||
|
rr->qname, dns_strtype(rr->type));
|
||||||
|
list->len = DNS_RR_DISCARDED;
|
||||||
|
}
|
||||||
|
dns_rr_free(rr);
|
||||||
|
}
|
||||||
|
return (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dns_rr_compare_pref_ipv6 - compare records by preference, ipv6 preferred */
|
/* dns_rr_compare_pref_ipv6 - compare records by preference, ipv6 preferred */
|
||||||
|
@@ -124,9 +124,11 @@ int main(int argc, char **argv)
|
|||||||
vstream_printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
|
vstream_printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
|
||||||
buf = vstring_alloc(100);
|
buf = vstring_alloc(100);
|
||||||
print_rr(buf, rr);
|
print_rr(buf, rr);
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
if (rr && rr->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("one or more excess DNS_RR records were dropped");
|
||||||
dns_rr_free(rr);
|
dns_rr_free(rr);
|
||||||
vstring_free(buf);
|
vstring_free(buf);
|
||||||
vstream_fflush(VSTREAM_OUT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
myfree((void *) types);
|
myfree((void *) types);
|
||||||
|
@@ -4384,16 +4384,6 @@ extern int var_idna2003_compat;
|
|||||||
#define DEF_DNS_NCACHE_TTL_FIX 0
|
#define DEF_DNS_NCACHE_TTL_FIX 0
|
||||||
extern bool var_dns_ncache_ttl_fix;
|
extern bool var_dns_ncache_ttl_fix;
|
||||||
|
|
||||||
/*
|
|
||||||
* A generous safety limit for the number of DNS resource records that the
|
|
||||||
* Postfix DNS client library will admit into a list. The default is 20x the
|
|
||||||
* default limit on the number address records that the Postfix SMTP client
|
|
||||||
* is willing to consider.
|
|
||||||
*/
|
|
||||||
#define VAR_DNS_RR_LIST_LIMIT "dns_resource_list_limit"
|
|
||||||
#define DEF_DNS_RR_LIST_LIMIT 100
|
|
||||||
extern int var_dns_rr_list_limit;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Logging. As systems evolve over time, logging becomes more challenging.
|
* Logging. As systems evolve over time, logging becomes more challenging.
|
||||||
*/
|
*/
|
||||||
|
@@ -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 "20240218"
|
#define MAIL_RELEASE_DATE "20240222"
|
||||||
#define MAIL_VERSION_NUMBER "3.9"
|
#define MAIL_VERSION_NUMBER "3.9"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@@ -1207,7 +1207,7 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
|
|||||||
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
|
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
|
||||||
addr->pref = pref;
|
addr->pref = pref;
|
||||||
addr->port = port;
|
addr->port = port;
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
}
|
}
|
||||||
@@ -1227,7 +1227,7 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
|
|||||||
rr->pref = pref;
|
rr->pref = pref;
|
||||||
rr->port = port;
|
rr->port = port;
|
||||||
}
|
}
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
default:
|
default:
|
||||||
dsb_status(why, "4.4.3");
|
dsb_status(why, "4.4.3");
|
||||||
@@ -1279,7 +1279,9 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
|
|||||||
if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
|
if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
|
||||||
msg_fatal("host %s: conversion error for address family %d: %m",
|
msg_fatal("host %s: conversion error for address family %d: %m",
|
||||||
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
|
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
@@ -1317,6 +1319,8 @@ static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names)
|
|||||||
msg_panic("%s: bad resource type: %d", myname, rr->type);
|
msg_panic("%s: bad resource type: %d", myname, rr->type);
|
||||||
addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
|
addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
|
||||||
rr->pref, rr->port);
|
rr->pref, rr->port);
|
||||||
|
if (addr_list && addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
}
|
}
|
||||||
@@ -1361,6 +1365,10 @@ static DNS_RR *domain_addr(STATE *state, char *domain)
|
|||||||
dsb_status(state->why, "5.4.3");
|
dsb_status(state->why, "5.4.3");
|
||||||
break;
|
break;
|
||||||
case DNS_OK:
|
case DNS_OK:
|
||||||
|
if (mx_names && mx_names->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up MX records for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
|
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
|
||||||
addr_list = mx_addr_list(state, mx_names);
|
addr_list = mx_addr_list(state, mx_names);
|
||||||
state->mx = dns_rr_copy(mx_names);
|
state->mx = dns_rr_copy(mx_names);
|
||||||
@@ -1369,6 +1377,10 @@ static DNS_RR *domain_addr(STATE *state, char *domain)
|
|||||||
msg_warn("no MX host for %s has a valid address record", domain);
|
msg_warn("no MX host for %s has a valid address record", domain);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up MX host addresses for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
#define COMPARE_ADDR(flags) \
|
#define COMPARE_ADDR(flags) \
|
||||||
((flags & MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
|
((flags & MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
|
||||||
(flags & MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
|
(flags & MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
|
||||||
@@ -1433,6 +1445,10 @@ static DNS_RR *service_addr(STATE *state, const char *domain,
|
|||||||
dsb_status(state->why, "5.4.3");
|
dsb_status(state->why, "5.4.3");
|
||||||
break;
|
break;
|
||||||
case DNS_OK:
|
case DNS_OK:
|
||||||
|
if (srv_names && srv_names->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up SRV records for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
/* Shuffle then sort the SRV rr records by priority and weight. */
|
/* Shuffle then sort the SRV rr records by priority and weight. */
|
||||||
srv_names = dns_srv_rr_sort(srv_names);
|
srv_names = dns_srv_rr_sort(srv_names);
|
||||||
addr_list = mx_addr_list(state, srv_names);
|
addr_list = mx_addr_list(state, srv_names);
|
||||||
@@ -1443,6 +1459,10 @@ static DNS_RR *service_addr(STATE *state, const char *domain,
|
|||||||
str_srv_qname);
|
str_srv_qname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up SRV host addresses for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
/* TODO: sort by priority, weight, and address family preference. */
|
/* TODO: sort by priority, weight, and address family preference. */
|
||||||
break;
|
break;
|
||||||
case DNS_NOTFOUND:
|
case DNS_NOTFOUND:
|
||||||
@@ -1482,6 +1502,11 @@ static DNS_RR *host_addr(STATE *state, const char *host)
|
|||||||
#define PREF0 0
|
#define PREF0 0
|
||||||
#define NOPORT 0
|
#define NOPORT 0
|
||||||
addr_list = addr_one(state, (DNS_RR *) 0, ahost, res_opt, PREF0, NOPORT);
|
addr_list = addr_one(state, (DNS_RR *) 0, ahost, res_opt, PREF0, NOPORT);
|
||||||
|
if (addr_list && addr_list->len == DNS_RR_DISCARDED) {
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up addresses for host %s",
|
||||||
|
var_dns_rr_list_limit, ahost);
|
||||||
|
}
|
||||||
if (addr_list && addr_list->next) {
|
if (addr_list && addr_list->next) {
|
||||||
addr_list = dns_rr_shuffle(addr_list);
|
addr_list = dns_rr_shuffle(addr_list);
|
||||||
if (inet_proto_info()->ai_family_list[1] != 0)
|
if (inet_proto_info()->ai_family_list[1] != 0)
|
||||||
|
@@ -179,10 +179,10 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
|
|||||||
if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
|
if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
|
||||||
msg_fatal("host %s: conversion error for address family "
|
msg_fatal("host %s: conversion error for address family "
|
||||||
"%d: %m", host, res0->ai_addr->sa_family);
|
"%d: %m", host, res0->ai_addr->sa_family);
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
|
||||||
addr->pref = pref;
|
addr->pref = pref;
|
||||||
addr->port = port;
|
addr->port = port;
|
||||||
if (msg_verbose)
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
|
if (msg_verbose && addr_list->len != DNS_RR_DISCARDED)
|
||||||
msg_info("%s: using numerical host %s", myname, host);
|
msg_info("%s: using numerical host %s", myname, host);
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
@@ -206,7 +206,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
|
|||||||
rr->pref = pref;
|
rr->pref = pref;
|
||||||
rr->port = port;
|
rr->port = port;
|
||||||
}
|
}
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
default:
|
default:
|
||||||
dsb_status(why, "4.4.3");
|
dsb_status(why, "4.4.3");
|
||||||
@@ -261,7 +261,9 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
|
|||||||
if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
|
if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
|
||||||
msg_fatal("host %s: conversion error for address family "
|
msg_fatal("host %s: conversion error for address family "
|
||||||
"%d: %m", host, res0->ai_addr->sa_family);
|
"%d: %m", host, res0->ai_addr->sa_family);
|
||||||
addr_list = dns_rr_append(addr_list, addr);
|
addr_list = dns_rr_append_discard(addr_list, addr);
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
if (msg_verbose) {
|
if (msg_verbose) {
|
||||||
MAI_HOSTADDR_STR hostaddr_str;
|
MAI_HOSTADDR_STR hostaddr_str;
|
||||||
|
|
||||||
@@ -327,6 +329,8 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
|
|||||||
msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
|
msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
|
||||||
addr_list = smtp_addr_one(addr_list, (char *) rr->data, res_opt,
|
addr_list = smtp_addr_one(addr_list, (char *) rr->data, res_opt,
|
||||||
rr->pref, rr->port, why);
|
rr->pref, rr->port, why);
|
||||||
|
if (addr_list && addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (addr_list);
|
return (addr_list);
|
||||||
}
|
}
|
||||||
@@ -496,6 +500,14 @@ static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags,
|
|||||||
msg_panic("%s: unexpected record type: %s",
|
msg_panic("%s: unexpected record type: %s",
|
||||||
myname, dns_strtype(rr->type));
|
myname, dns_strtype(rr->type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addr_list is the concatenation of multi-element lists, and may
|
||||||
|
* be longer than var_dns_rr_limit. When both the addr_list
|
||||||
|
* length and addr_limit are > var_dns_rr_limit, calling
|
||||||
|
* dns_rr_append_discard() below could discard inputs and violate
|
||||||
|
* an invariant of the balancing algorithm. Let's keep it simple.
|
||||||
|
*/
|
||||||
if (*p > 0) {
|
if (*p > 0) {
|
||||||
stripped_list = dns_rr_append(stripped_list, rr);
|
stripped_list = dns_rr_append(stripped_list, rr);
|
||||||
*p -= 1;
|
*p -= 1;
|
||||||
@@ -618,6 +630,10 @@ DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags,
|
|||||||
addr_list = smtp_host_addr(aname, misc_flags, why);
|
addr_list = smtp_host_addr(aname, misc_flags, why);
|
||||||
break;
|
break;
|
||||||
case DNS_OK:
|
case DNS_OK:
|
||||||
|
if (mx_names && mx_names->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up MX records for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
|
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
|
||||||
best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE);
|
best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE);
|
||||||
addr_list = smtp_addr_list(mx_names, why);
|
addr_list = smtp_addr_list(mx_names, why);
|
||||||
@@ -637,6 +653,10 @@ DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags,
|
|||||||
msg_warn("no MX host for %s has a valid address record", name);
|
msg_warn("no MX host for %s has a valid address record", name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up MX host addresses for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);
|
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
smtp_print_addr(name, addr_list);
|
smtp_print_addr(name, addr_list);
|
||||||
@@ -709,6 +729,10 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
|
|||||||
*/
|
*/
|
||||||
#define PREF0 0
|
#define PREF0 0
|
||||||
addr_list = smtp_addr_one((DNS_RR *) 0, ahost, res_opt, PREF0, 0, why);
|
addr_list = smtp_addr_one((DNS_RR *) 0, ahost, res_opt, PREF0, 0, why);
|
||||||
|
if (addr_list && addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up host addresses for %s",
|
||||||
|
var_dns_rr_list_limit, ahost);
|
||||||
if (addr_list
|
if (addr_list
|
||||||
&& (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
|
&& (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
|
||||||
&& smtp_find_self(addr_list) != 0) {
|
&& smtp_find_self(addr_list) != 0) {
|
||||||
@@ -797,6 +821,10 @@ DNS_RR *smtp_service_addr(const char *name, const char *service, DNS_RR **mxrr,
|
|||||||
dsb_status(why, "5.1.0");
|
dsb_status(why, "5.1.0");
|
||||||
break;
|
break;
|
||||||
case DNS_OK:
|
case DNS_OK:
|
||||||
|
if (srv_names && srv_names->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up SRV records for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
/* Shuffle then sort the SRV rr records by priority and weight. */
|
/* Shuffle then sort the SRV rr records by priority and weight. */
|
||||||
srv_names = dns_srv_rr_sort(srv_names);
|
srv_names = dns_srv_rr_sort(srv_names);
|
||||||
best_pref = (srv_names ? srv_names->pref : IMPOSSIBLE_PREFERENCE);
|
best_pref = (srv_names ? srv_names->pref : IMPOSSIBLE_PREFERENCE);
|
||||||
@@ -809,6 +837,10 @@ DNS_RR *smtp_service_addr(const char *name, const char *service, DNS_RR **mxrr,
|
|||||||
str_srv_qname);
|
str_srv_qname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (addr_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up SRV host addresses for domain %s",
|
||||||
|
var_dns_rr_list_limit, aname);
|
||||||
/* Optional loop prevention, similar to smtp_domain_addr(). */
|
/* Optional loop prevention, similar to smtp_domain_addr(). */
|
||||||
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);
|
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
|
@@ -3021,6 +3021,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
int status;
|
int status;
|
||||||
const INET_PROTO_INFO *proto_info;
|
const INET_PROTO_INFO *proto_info;
|
||||||
|
int server_addr_count = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check.
|
* Sanity check.
|
||||||
@@ -3133,6 +3134,11 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
return (SMTPD_CHECK_DUNNO);
|
return (SMTPD_CHECK_DUNNO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (server_list && server_list->len == DNS_RR_DISCARDED)
|
||||||
|
msg_warn("DNS resource record limit (%d) exceeded"
|
||||||
|
"while looking up %s records for %s",
|
||||||
|
var_dns_rr_list_limit, dns_strtype(type),
|
||||||
|
domain && domain[1] ? domain : name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No bare returns after this point or we have a memory leak.
|
* No bare returns after this point or we have a memory leak.
|
||||||
@@ -3172,6 +3178,14 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
|||||||
msg_info("%s: %s host address check: %s",
|
msg_info("%s: %s host address check: %s",
|
||||||
myname, dns_strtype(type), (char *) server->data);
|
myname, dns_strtype(type), (char *) server->data);
|
||||||
for (res = res0; res != 0; res = res->ai_next) {
|
for (res = res0; res != 0; res = res->ai_next) {
|
||||||
|
server_addr_count += 1;
|
||||||
|
if (server_addr_count > var_dns_rr_list_limit) {
|
||||||
|
msg_warn("Host address count limit (%d) exceeded"
|
||||||
|
"while looking up host addresses for %s",
|
||||||
|
var_dns_rr_list_limit, (char *) server->data);
|
||||||
|
freeaddrinfo(res0);
|
||||||
|
CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
|
||||||
|
}
|
||||||
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
|
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("skipping address family %d for host %s",
|
msg_info("skipping address family %d for host %s",
|
||||||
|
Reference in New Issue
Block a user