mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 18:07:41 +00:00
postfix-3.9-20240227
This commit is contained in:
parent
03382b275a
commit
f38f9d82f3
@ -27756,10 +27756,11 @@ Apologies for any names omitted.
|
||||
or access control limitations. Files: smtpd/smtpd.[hc],
|
||||
util/argv.[hc].
|
||||
|
||||
Workaround: some OS lies under load: it says that a socket
|
||||
is readable, then it says that the socket has unread data,
|
||||
and then it says that read returns EOF, causing Postfix to
|
||||
spam the log with a warning message. File: tlsmgr/tlsmgr.c.
|
||||
Workaround: tlsmgr logfile spam. Some OS lies under load:
|
||||
it says that a socket is readable, then it says that the
|
||||
socket has unread data, and then it says that read returns
|
||||
EOF, causing Postfix to spam the log with a warning message.
|
||||
File: tlsmgr/tlsmgr.c.
|
||||
|
||||
20240125
|
||||
|
||||
@ -27829,17 +27830,6 @@ Apologies for any names omitted.
|
||||
|
||||
20240209
|
||||
|
||||
Safety: enforce a sane but generous upper bound (100) for
|
||||
the number of DNS resource records that the Postfix DNS
|
||||
client library will admit into a list. This is 20x the
|
||||
default smtp_mx_address_limit value for the number of DNS
|
||||
records that the Postfix SMTP client is willing to consider.
|
||||
Log a warning "dropping records after qname=X qtype=Y" when
|
||||
a list cannot accept more elements. This prevents a tail
|
||||
recursion crash that degrades mail delivery performance.
|
||||
Problem report by Toshifumi Sakaguchi. Files: dns/dns_rr.[hc],
|
||||
global/mail_params.h.
|
||||
|
||||
Performance: eliminate worst-case behavior where the queue
|
||||
manager deferred delivery to all destinations over a specific
|
||||
delivery transport, after only a single delivery agent
|
||||
@ -27920,3 +27910,27 @@ Apologies for any names omitted.
|
||||
status. Files: postconf/postconf.c, postconf/postconf_dbms.c,
|
||||
postconf/postconf.h, conf/postfix-script, conf/post-install,
|
||||
postfix-install.
|
||||
|
||||
20240221
|
||||
|
||||
Documentation: the text for TLS loglevel 2 was incomplete.
|
||||
File: proto/postconf.proto.
|
||||
|
||||
20240226
|
||||
|
||||
Safety: drop and log over-size DNS responses resulting in
|
||||
more than 100 records. This 20x larger than the number of
|
||||
server addresses that the Postfix SMTP client is willing
|
||||
to consider when delivering mail, and is well below the
|
||||
number of records that could cause a tail recursion crash
|
||||
in dns_rr_append() as reported by Toshifumi Sakaguchi. This
|
||||
also limits the number of DNS requests from check_*_*_access
|
||||
restrictions. 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.
|
||||
|
||||
20240227
|
||||
|
||||
Documentation: document the need to disable regular expression
|
||||
special characters when using $name inside an inlined
|
||||
pattern. Files: proto/pcre_table, proto/regexp_table.
|
||||
|
@ -191,8 +191,12 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
|
||||
Postfix parses the result as if it is a file in /etc/postfix.
|
||||
|
||||
Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
|
||||
do <i>$name</i> expansion as it evaluates a parameter value.
|
||||
Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
|
||||
trying to do <i>$name</i> expansion as it evaluates a parameter value.
|
||||
|
||||
Note: when using <i>$name</i> inside an inlined pattern, use \Q<i>$name</i>\E to dis-
|
||||
able metacharacters such as '.' in the <i>$name</i> expansion. Otherwise, the
|
||||
pattern may have unexpected matches.
|
||||
|
||||
<b>EXAMPLE SMTPD ACCESS MAP</b>
|
||||
# Protect your outgoing majordomo exploders
|
||||
|
@ -13597,7 +13597,9 @@ verification errors if server certificate verification is not required.
|
||||
With Postfix 2.8 and earlier, log the summary message and unconditionally
|
||||
log trust-chain verification errors. </dd>
|
||||
|
||||
<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
|
||||
<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake. </dd>
|
||||
|
||||
<dt> </dt> <dd> 3 Also log the hexadecimal and ASCII dump of the
|
||||
TLS negotiation process. </dd>
|
||||
@ -18851,7 +18853,9 @@ if client certificate verification is not required. With Postfix 2.8 and
|
||||
earlier, log the summary message, peer certificate summary information
|
||||
and unconditionally log trust-chain verification errors. </dd>
|
||||
|
||||
<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
|
||||
<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake. </dd>
|
||||
|
||||
<dt> </dt> <dd> 3 Also log hexadecimal and ASCII dump of TLS negotiation
|
||||
process. </dd>
|
||||
|
@ -148,8 +148,12 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
|
||||
Postfix parses the result as if it is a file in /etc/postfix.
|
||||
|
||||
Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
|
||||
do <i>$name</i> expansion as it evaluates a parameter value.
|
||||
Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
|
||||
trying to do <i>$name</i> expansion as it evaluates a parameter value.
|
||||
|
||||
Note: when using <i>$name</i> inside an inlined pattern, this will not disable
|
||||
metacharacters such as '.' in the <i>$name</i> expansion. To prevent unex-
|
||||
pected matches, use a <a href="pcre_table.5.html">pcre</a>: table, and specify \Q<i>$name</i>\E.
|
||||
|
||||
<b>EXAMPLE SMTPD ACCESS MAP</b>
|
||||
# Disallow sender-specified routing. This is a must if you relay mail
|
||||
|
@ -206,9 +206,14 @@ in\-memory file:
|
||||
|
||||
Postfix parses the result as if it is a file in /etc/postfix.
|
||||
|
||||
Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
|
||||
Postfix from trying to do \fI$name\fR expansion as it
|
||||
evaluates a parameter value.
|
||||
Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
|
||||
to keep Postfix from trying to do \fI$name\fR expansion as
|
||||
it evaluates a parameter value.
|
||||
|
||||
Note: when using \fI$name\fR inside an inlined pattern, use
|
||||
\eQ\fI$name\fR\eE to disable metacharacters such as '.' in
|
||||
the \fI$name\fR expansion. Otherwise, the pattern may have
|
||||
unexpected matches.
|
||||
.SH "EXAMPLE SMTPD ACCESS MAP"
|
||||
.na
|
||||
.nf
|
||||
|
@ -9025,7 +9025,9 @@ With Postfix 2.8 and earlier, log the summary message and unconditionally
|
||||
log trust\-chain verification errors.
|
||||
.br
|
||||
.IP ""
|
||||
2 Also log levels during TLS negotiation.
|
||||
2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake.
|
||||
.br
|
||||
.IP ""
|
||||
3 Also log the hexadecimal and ASCII dump of the
|
||||
@ -13412,7 +13414,9 @@ earlier, log the summary message, peer certificate summary information
|
||||
and unconditionally log trust\-chain verification errors.
|
||||
.br
|
||||
.IP ""
|
||||
2 Also log levels during TLS negotiation.
|
||||
2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake.
|
||||
.br
|
||||
.IP ""
|
||||
3 Also log hexadecimal and ASCII dump of TLS negotiation
|
||||
|
@ -163,9 +163,14 @@ in\-memory file:
|
||||
|
||||
Postfix parses the result as if it is a file in /etc/postfix.
|
||||
|
||||
Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
|
||||
Postfix from trying to do \fI$name\fR expansion as it
|
||||
evaluates a parameter value.
|
||||
Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
|
||||
to keep Postfix from trying to do \fI$name\fR expansion as
|
||||
it evaluates a parameter value.
|
||||
|
||||
Note: when using \fI$name\fR inside an inlined pattern,
|
||||
this will not disable metacharacters such as '.' in the
|
||||
\fI$name\fR expansion. To prevent unexpected matches, use
|
||||
a pcre: table, and specify \eQ\fI$name\fR\eE.
|
||||
.SH "EXAMPLE SMTPD ACCESS MAP"
|
||||
.na
|
||||
.nf
|
||||
|
@ -190,9 +190,14 @@
|
||||
#
|
||||
# Postfix parses the result as if it is a file in /etc/postfix.
|
||||
#
|
||||
# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
|
||||
# Postfix from trying to do \fI$name\fR expansion as it
|
||||
# evaluates a parameter value.
|
||||
# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
|
||||
# to keep Postfix from trying to do \fI$name\fR expansion as
|
||||
# it evaluates a parameter value.
|
||||
#
|
||||
# Note: when using \fI$name\fR inside an inlined pattern, use
|
||||
# \eQ\fI$name\fR\eE to disable metacharacters such as '.' in
|
||||
# the \fI$name\fR expansion. Otherwise, the pattern may have
|
||||
# unexpected matches.
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Protect your outgoing majordomo exploders
|
||||
# /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead
|
||||
|
@ -9798,7 +9798,9 @@ if client certificate verification is not required. With Postfix 2.8 and
|
||||
earlier, log the summary message, peer certificate summary information
|
||||
and unconditionally log trust-chain verification errors. </dd>
|
||||
|
||||
<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
|
||||
<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake. </dd>
|
||||
|
||||
<dt> </dt> <dd> 3 Also log hexadecimal and ASCII dump of TLS negotiation
|
||||
process. </dd>
|
||||
@ -10285,7 +10287,9 @@ verification errors if server certificate verification is not required.
|
||||
With Postfix 2.8 and earlier, log the summary message and unconditionally
|
||||
log trust-chain verification errors. </dd>
|
||||
|
||||
<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
|
||||
<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
|
||||
library, log session cache operations, and enable OpenSSL logging
|
||||
of the progress of the SSL handshake. </dd>
|
||||
|
||||
<dt> </dt> <dd> 3 Also log the hexadecimal and ASCII dump of the
|
||||
TLS negotiation process. </dd>
|
||||
|
@ -147,9 +147,14 @@
|
||||
#
|
||||
# Postfix parses the result as if it is a file in /etc/postfix.
|
||||
#
|
||||
# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
|
||||
# Postfix from trying to do \fI$name\fR expansion as it
|
||||
# evaluates a parameter value.
|
||||
# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
|
||||
# to keep Postfix from trying to do \fI$name\fR expansion as
|
||||
# it evaluates a parameter value.
|
||||
#
|
||||
# Note: when using \fI$name\fR inside an inlined pattern,
|
||||
# this will not disable metacharacters such as '.' in the
|
||||
# \fI$name\fR expansion. To prevent unexpected matches, use
|
||||
# a pcre: table, and specify \eQ\fI$name\fR\eE.
|
||||
# EXAMPLE SMTPD ACCESS MAP
|
||||
# # Disallow sender-specified routing. This is a must if you relay mail
|
||||
# # for other domains.
|
||||
|
@ -1602,3 +1602,4 @@ GmbH
|
||||
Hamid
|
||||
LLC
|
||||
Maadani
|
||||
GTEST
|
||||
|
@ -116,3 +116,5 @@ proto proto aliases proto virtual proto ADDRESS_REWRITING_README html
|
||||
status Files postconf postconf c postconf postconf_dbms c
|
||||
postconf postconf h conf postfix script conf post install
|
||||
postconf postconf c postconf postconf_dbms c
|
||||
File tlsmgr tlsmgr c
|
||||
restrictions Files dns dns h dns dns_lookup c dns dns_rr c
|
||||
|
@ -357,3 +357,4 @@ the form of a domain name hostname hostname service hostname service
|
||||
expected to become a list of comma separated names br br This
|
||||
Postfix Postfix can use MongoDB as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated noSQL database with fine grained access controls By not storing it
|
||||
CCARGS CCARGS DHAS_MONGODB I usr include libmongoc 1 0
|
||||
dt dt dd 2 Also enable verbose logging in the Postfix TLS
|
||||
|
@ -11,7 +11,8 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||
INCL =
|
||||
LIB = lib$(LIB_PREFIX)dns$(LIB_SUFFIX)
|
||||
TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa
|
||||
TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa \
|
||||
dns_rr_test
|
||||
LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
|
||||
../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
|
||||
LIB_DIR = ../../lib
|
||||
@ -31,7 +32,7 @@ test: $(TESTPROG)
|
||||
tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \
|
||||
dns_rr_eq_sa_test no-a-test no-aaaa-test no-mx-test \
|
||||
error-filter-test nullmx_test nxdomain_test mxonly_test \
|
||||
dnsbl_tests
|
||||
dnsbl_tests dns_rr_tests
|
||||
|
||||
dnsbl_tests: \
|
||||
dnsbl_ttl_127.0.0.2_bind_plain_test \
|
||||
@ -240,6 +241,12 @@ dnsbl_ttl_127.0.0.2_priv_ncache_test: test_dns_lookup dnsbl_ttl_127.0.0.2_bind_p
|
||||
diff dnsbl_ttl_127.0.0.2_bind_plain.ref dnsbl_ttl_127.0.0.2_priv_ncache.tmp
|
||||
rm -f dnsbl_ttl_127.0.0.2_priv_ncache.tmp
|
||||
|
||||
dns_rr_tests: dns_rr_test
|
||||
$(SHLIB_ENV) $(VALGRIND) ./dns_rr_test
|
||||
|
||||
dns_rr_test: dns_rr_test.o $(LIB) $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||
|
||||
printfck: $(OBJS) $(PROG)
|
||||
rm -rf printfck
|
||||
mkdir printfck
|
||||
@ -286,7 +293,6 @@ dns_lookup.o: ../../include/vstring.h
|
||||
dns_lookup.o: dns.h
|
||||
dns_lookup.o: dns_lookup.c
|
||||
dns_rr.o: ../../include/check_arg.h
|
||||
dns_rr.o: ../../include/mail_params.h
|
||||
dns_rr.o: ../../include/msg.h
|
||||
dns_rr.o: ../../include/myaddrinfo.h
|
||||
dns_rr.o: ../../include/mymalloc.h
|
||||
@ -320,6 +326,19 @@ dns_rr_filter.o: ../../include/vstream.h
|
||||
dns_rr_filter.o: ../../include/vstring.h
|
||||
dns_rr_filter.o: dns.h
|
||||
dns_rr_filter.o: dns_rr_filter.c
|
||||
dns_rr_test.o: ../../include/check_arg.h
|
||||
dns_rr_test.o: ../../include/msg.h
|
||||
dns_rr_test.o: ../../include/msg_vstream.h
|
||||
dns_rr_test.o: ../../include/myaddrinfo.h
|
||||
dns_rr_test.o: ../../include/mymalloc.h
|
||||
dns_rr_test.o: ../../include/sock_addr.h
|
||||
dns_rr_test.o: ../../include/stringops.h
|
||||
dns_rr_test.o: ../../include/sys_defs.h
|
||||
dns_rr_test.o: ../../include/vbuf.h
|
||||
dns_rr_test.o: ../../include/vstream.h
|
||||
dns_rr_test.o: ../../include/vstring.h
|
||||
dns_rr_test.o: dns.h
|
||||
dns_rr_test.o: dns_rr_test.c
|
||||
dns_rr_to_pa.o: ../../include/check_arg.h
|
||||
dns_rr_to_pa.o: ../../include/msg.h
|
||||
dns_rr_to_pa.o: ../../include/myaddrinfo.h
|
||||
|
@ -164,9 +164,14 @@ typedef struct DNS_RR {
|
||||
struct DNS_RR *next; /* linkage */
|
||||
size_t data_len; /* actual data size */
|
||||
char *data; /* a bunch of data */
|
||||
int flags; /* DNS_RR_FLAG_XX, see below */
|
||||
/* Add new fields at the end, for ABI forward compatibility. */
|
||||
} DNS_RR;
|
||||
|
||||
#define DNS_RR_FLAG_TRUNCATED (1<<0)
|
||||
|
||||
#define DNS_RR_IS_TRUNCATED(rr) ((rr)->flags & DNS_RR_FLAG_TRUNCATED)
|
||||
|
||||
/*
|
||||
* dns_strerror.c
|
||||
*/
|
||||
@ -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 DNS_RR *dns_rr_shuffle(DNS_RR *);
|
||||
extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
|
||||
extern int var_dns_rr_list_limit;
|
||||
|
||||
/*
|
||||
* dns_rr_to_pa.c
|
||||
|
@ -984,6 +984,8 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
|
||||
resource_found++;
|
||||
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
|
||||
*rrlist = dns_rr_append(*rrlist, rr);
|
||||
if (DNS_RR_IS_TRUNCATED(*rrlist))
|
||||
break;
|
||||
} else if (status == DNS_NULLMX || status == DNS_NULLSRV) {
|
||||
CORRUPT(status); /* TODO: use better name */
|
||||
} 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));
|
||||
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
||||
fqdn, why, rcode, lflags);
|
||||
if (rrlist && rr)
|
||||
if (rrlist && rr) {
|
||||
*rrlist = dns_rr_append(*rrlist, rr);
|
||||
if (DNS_RR_IS_TRUNCATED(*rrlist))
|
||||
break;
|
||||
}
|
||||
if (status == DNS_OK) {
|
||||
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
||||
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));
|
||||
status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
|
||||
fqdn, why, rcode, lflags);
|
||||
if (rrlist && rr)
|
||||
if (rrlist && rr) {
|
||||
*rrlist = dns_rr_append(*rrlist, rr);
|
||||
if (DNS_RR_IS_TRUNCATED(*rrlist))
|
||||
break;
|
||||
}
|
||||
if (status == DNS_OK) {
|
||||
if (lflags & DNS_REQ_FLAG_STOP_OK)
|
||||
break;
|
||||
|
@ -97,12 +97,17 @@
|
||||
/*
|
||||
/* dns_rr_copy() makes a copy of a resource record.
|
||||
/*
|
||||
/* dns_rr_append() appends a resource record to a (list of) resource
|
||||
/* record(s).
|
||||
/* 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
|
||||
/* elements (default: 100).
|
||||
/* dns_rr_append() appends an input resource record list to
|
||||
/* an output list. Null arguments are explicitly allowed.
|
||||
/* When the result would be longer than var_dns_rr_list_limit
|
||||
/* (default: 100), dns_rr_append() logs a warning, flags the
|
||||
/* output list as truncated, and discards the excess elements.
|
||||
/* Once an output list is flagged as truncated (test with
|
||||
/* DNS_RR_IS_TRUNCATED()), the caller is expected to stop
|
||||
/* trying to append records to that list. Note: the 'truncated'
|
||||
/* flag is transitive, i.e. when appending a input list that
|
||||
/* was flagged as truncated to an output list, the output list
|
||||
/* will also be flagged as truncated.
|
||||
/*
|
||||
/* dns_rr_sort() sorts a list of resource records into ascending
|
||||
/* order according to a user-specified criterion. The result is the
|
||||
@ -151,18 +156,19 @@
|
||||
#include <mymalloc.h>
|
||||
#include <myrand.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_params.h>
|
||||
|
||||
/* DNS library. */
|
||||
|
||||
#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 */
|
||||
|
||||
@ -195,6 +201,7 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname,
|
||||
}
|
||||
rr->data_len = data_len;
|
||||
rr->next = 0;
|
||||
rr->flags = 0;
|
||||
return (rr);
|
||||
}
|
||||
|
||||
@ -234,36 +241,58 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
|
||||
|
||||
/* 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)
|
||||
static void 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.
|
||||
* Pre: list != 0, all lists are concatenated with dns_rr_append().
|
||||
*
|
||||
* Post: all elements have the DNS_RR_FLAG_TRUNCATED flag value set, or all
|
||||
* elements have it cleared, so that there is no need to update code in
|
||||
* legacy stable releases that deletes or reorders elements.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
if (limit <= 1) {
|
||||
if (list->next || rr) {
|
||||
msg_warn("DNS record count limit (%d) exceeded -- dropping"
|
||||
" excess record(s) after qname=%s qtype=%s",
|
||||
var_dns_rr_list_limit, list->qname,
|
||||
dns_strtype(list->type));
|
||||
list->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
dns_rr_free(list->next);
|
||||
dns_rr_free(rr);
|
||||
list->next = 0;
|
||||
}
|
||||
} else {
|
||||
if (list->next == 0 && rr) {
|
||||
list->next = rr;
|
||||
rr = 0;
|
||||
}
|
||||
if (list->next) {
|
||||
dns_rr_append_with_limit(list->next, rr, limit - 1);
|
||||
list->flags |= list->next->flags;
|
||||
}
|
||||
}
|
||||
return (list);
|
||||
}
|
||||
|
||||
/* dns_rr_append - append resource record to list */
|
||||
/* dns_rr_append - append resource record(s) to list, or discard */
|
||||
|
||||
DNS_RR *dns_rr_append(DNS_RR *list, DNS_RR *rr)
|
||||
{
|
||||
return (dns_rr_append_with_limit(list, rr, var_dns_rr_list_limit));
|
||||
|
||||
/*
|
||||
* Note: rr is not length checked; when multiple lists are concatenated,
|
||||
* the output length may be a small multiple of var_dns_rr_list_limit.
|
||||
*/
|
||||
if (rr == 0)
|
||||
return (list);
|
||||
if (list == 0)
|
||||
return (rr);
|
||||
if (!DNS_RR_IS_TRUNCATED(list)) {
|
||||
dns_rr_append_with_limit(list, rr, var_dns_rr_list_limit);
|
||||
} else {
|
||||
dns_rr_free(rr);
|
||||
}
|
||||
return (list);
|
||||
}
|
||||
|
||||
/* dns_rr_compare_pref_ipv6 - compare records by preference, ipv6 preferred */
|
||||
|
433
postfix/src/dns/dns_rr_test.c
Normal file
433
postfix/src/dns/dns_rr_test.c
Normal file
@ -0,0 +1,433 @@
|
||||
/*
|
||||
* System library.
|
||||
*/
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <msg.h>
|
||||
#include <msg_vstream.h>
|
||||
#include <mymalloc.h>
|
||||
#include <stringops.h>
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* DNS library.
|
||||
*/
|
||||
#include <dns.h>
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/*
|
||||
* Test helpers. TODO: move eq_dns_rr() to testing/dns_rr_testers.c; need to
|
||||
* verify that the expected difference is reported, or use a GTEST matcher.
|
||||
*/
|
||||
|
||||
/* print_dns_rr - format as { qname, reply, flags } */
|
||||
|
||||
static char *print_dns_rr(VSTRING *buf, DNS_RR *rr)
|
||||
{
|
||||
static VSTRING *tmp;
|
||||
|
||||
if (tmp == 0)
|
||||
tmp = vstring_alloc(100);
|
||||
vstring_sprintf(buf, "{qname=%s, reply='%s', flags=0x%x}",
|
||||
rr->qname, dns_strrecord(tmp, rr), rr->flags);
|
||||
return (STR(buf));
|
||||
}
|
||||
|
||||
/* eq_dns_rr - predicate that two lists are equivalent */
|
||||
|
||||
static int eq_dns_rr(DNS_RR *got, DNS_RR *want)
|
||||
{
|
||||
VSTRING *got_buf = 0;
|
||||
VSTRING *want_buf = 0;
|
||||
|
||||
#define EQ_DNS_RR_RETURN(val) do { \
|
||||
if (got_buf) \
|
||||
vstring_free(got_buf); \
|
||||
if (want_buf) \
|
||||
vstring_free(want_buf); \
|
||||
return (val); \
|
||||
} while (0)
|
||||
|
||||
/* Same length. */
|
||||
if (got == 0 && want == 0)
|
||||
EQ_DNS_RR_RETURN(1);
|
||||
if (want == 0) {
|
||||
msg_warn("got %s, want null",
|
||||
print_dns_rr(got_buf = vstring_alloc(100), got));
|
||||
}
|
||||
if (got == 0) {
|
||||
msg_warn("got null, want %s",
|
||||
print_dns_rr(want_buf = vstring_alloc(100), want));
|
||||
EQ_DNS_RR_RETURN(0);
|
||||
}
|
||||
/* Same query name, resource record, flags. */
|
||||
if (strcmp(print_dns_rr(got_buf = vstring_alloc(100), got),
|
||||
print_dns_rr(want_buf = vstring_alloc(100), want)) != 0) {
|
||||
msg_warn("got %s, want %s", STR(want_buf), STR(got_buf));
|
||||
EQ_DNS_RR_RETURN(0);
|
||||
}
|
||||
/* Same children. */
|
||||
EQ_DNS_RR_RETURN(eq_dns_rr(got->next, want->next));
|
||||
}
|
||||
|
||||
static int eq_dns_rr_free(DNS_RR *got, DNS_RR *want)
|
||||
{
|
||||
int res = eq_dns_rr(got, want);
|
||||
|
||||
dns_rr_free(got);
|
||||
dns_rr_free(want);
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests and test cases.
|
||||
*/
|
||||
typedef struct TEST_CASE {
|
||||
const char *label; /* identifies test case */
|
||||
int (*fn) (void);
|
||||
} TEST_CASE;
|
||||
|
||||
#define PASS (0)
|
||||
#define FAIL (1)
|
||||
|
||||
/*
|
||||
* Begin helper tests. TODO: move these to testing/dns_rr_testers_test.c.
|
||||
*/
|
||||
|
||||
static int eq_dns_rr_qname_differ(void)
|
||||
{
|
||||
DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 3);
|
||||
DNS_RR *want = dns_rr_copy(got);
|
||||
|
||||
myfree(want->qname);
|
||||
want->qname = mystrdup("qb");
|
||||
return (!eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int eq_dns_rr_reply_differ(void)
|
||||
{
|
||||
DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 3);
|
||||
DNS_RR *want = dns_rr_copy(got);
|
||||
|
||||
want->port += 1;
|
||||
return (!eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
/*
|
||||
* End helper tests.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Begin DNS_RR tests.
|
||||
*/
|
||||
|
||||
static int eq_dns_rr_flags_differ(void)
|
||||
{
|
||||
DNS_RR *got = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *want = dns_rr_copy(got);
|
||||
|
||||
want->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
return (!eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_null_from_null(void)
|
||||
{
|
||||
DNS_RR *got = dns_rr_append((DNS_RR *) 0, (DNS_RR *) 0);
|
||||
DNS_RR *want = 0;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_elem_from_null(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append(dns_rr_copy(a), (DNS_RR *) 0);
|
||||
|
||||
want = a;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int appent_to_null_from_elem(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append((DNS_RR *) 0, dns_rr_copy(a));
|
||||
|
||||
want = a;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_elem_from_elem(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
|
||||
|
||||
(want = a)->next = b;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_elem_from_list(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append(dns_rr_copy(a),
|
||||
dns_rr_append(dns_rr_copy(b),
|
||||
dns_rr_copy(c)));
|
||||
|
||||
((want = a)->next = b)->next = c;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_elem(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
|
||||
dns_rr_copy(b)),
|
||||
dns_rr_copy(c));
|
||||
|
||||
((want = a)->next = b)->next = c;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_list(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
|
||||
dns_rr_copy(b)),
|
||||
dns_rr_append(dns_rr_copy(c),
|
||||
dns_rr_copy(d)));
|
||||
|
||||
(((want = a)->next = b)->next = c)->next = d;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_propagates_flags(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
|
||||
DNS_RR *left = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
|
||||
DNS_RR *rite = dns_rr_append(dns_rr_copy(c), dns_rr_copy(d));
|
||||
DNS_RR *got, *want, *rr;
|
||||
|
||||
for (rr = rite; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
got = dns_rr_append(left, rite);
|
||||
|
||||
(((want = a)->next = b)->next = c)->next = d;
|
||||
for (rr = want; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_list_truncate(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
|
||||
DNS_RR *got, *want, *rr;
|
||||
|
||||
var_dns_rr_list_limit = 3;
|
||||
|
||||
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
|
||||
for (rr = want; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
got = dns_rr_append(dns_rr_append(a, b),
|
||||
dns_rr_append(c, d));
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_elem_elem_truncate(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 3);
|
||||
DNS_RR *got, *want, *rr;
|
||||
|
||||
var_dns_rr_list_limit = 2;
|
||||
|
||||
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
|
||||
for (rr = want; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
got = dns_rr_append(a, b);
|
||||
got = dns_rr_append(got, c); /* should be logged */
|
||||
got = dns_rr_append(got, d); /* should be silent */
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_elem_truncate(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want, *rr;
|
||||
|
||||
var_dns_rr_list_limit = 2;
|
||||
|
||||
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
|
||||
for (rr = want; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
got = dns_rr_append(dns_rr_append(a, b), c);
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_elem_from_list_truncate(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want, *rr;
|
||||
|
||||
var_dns_rr_list_limit = 2;
|
||||
|
||||
(want = dns_rr_copy(a))->next = dns_rr_copy(b);
|
||||
for (rr = want; rr; rr = rr->next)
|
||||
rr->flags |= DNS_RR_FLAG_TRUNCATED;
|
||||
|
||||
got = dns_rr_append(a, dns_rr_append(b, c));
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_list_from_elem_exact_fit(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
var_dns_rr_list_limit = 3;
|
||||
|
||||
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
|
||||
|
||||
got = dns_rr_append(dns_rr_append(a, b), c);
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
static int append_to_elem_from_list_exact_fit(void)
|
||||
{
|
||||
DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 3);
|
||||
DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 3);
|
||||
DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 3);
|
||||
DNS_RR *got, *want;
|
||||
|
||||
var_dns_rr_list_limit = 3;
|
||||
|
||||
((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
|
||||
|
||||
got = dns_rr_append(a, dns_rr_append(b, c));
|
||||
|
||||
return (eq_dns_rr_free(got, want));
|
||||
}
|
||||
|
||||
/*
|
||||
* The test cases.
|
||||
*/
|
||||
static const TEST_CASE test_cases[] = {
|
||||
|
||||
/*
|
||||
* Test eq_dns_rr; TODO: move to testing/dns_rr_testers_test.c
|
||||
*/
|
||||
"eq_dns_rr qname differ", eq_dns_rr_qname_differ,
|
||||
"eq_dns_rr reply differ", eq_dns_rr_reply_differ,
|
||||
"eq_dns_rr flags differ", eq_dns_rr_flags_differ,
|
||||
|
||||
/*
|
||||
* Test dns_rr_append() without truncation.
|
||||
*/
|
||||
"append to null from null", append_to_null_from_null,
|
||||
"append to null from element", appent_to_null_from_elem,
|
||||
"append to element from null", append_to_elem_from_null,
|
||||
"append to element from element", append_to_elem_from_elem,
|
||||
"append to element from list", append_to_elem_from_list,
|
||||
"append to list from element", append_to_list_from_elem,
|
||||
"append to list from list", append_to_list_from_list,
|
||||
|
||||
/*
|
||||
* Test dns_rr_append() flag propagation.
|
||||
*/
|
||||
"append propagates flags", append_propagates_flags,
|
||||
|
||||
/*
|
||||
* Test dns_rr_append() with truncation.
|
||||
*/
|
||||
"append to list from list truncate", append_to_list_from_list_truncate,
|
||||
"append to list from element element truncate", append_to_list_from_elem_elem_truncate,
|
||||
"append to list from element truncate", append_to_list_from_elem_truncate,
|
||||
"append to element from list truncate", append_to_elem_from_list_truncate,
|
||||
"append to list from element exact fit", append_to_list_from_elem_exact_fit,
|
||||
"append to element from list exact fit", append_to_elem_from_list_exact_fit,
|
||||
|
||||
/*
|
||||
* TODO: tests dns_rr_sort(), dns_rr_srv_sort(), dns_rr_remove(),
|
||||
* dns_rr_shuffle(), etc.
|
||||
*/
|
||||
0,
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const TEST_CASE *tp;
|
||||
int pass = 0;
|
||||
int fail = 0;
|
||||
VSTRING *res_buf = vstring_alloc(100);
|
||||
int saved_limit = var_dns_rr_list_limit;
|
||||
|
||||
msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
|
||||
|
||||
for (tp = test_cases; tp->label != 0; tp++) {
|
||||
msg_info("RUN %s", tp->label);
|
||||
if (tp->fn() == 0) {
|
||||
fail++;
|
||||
msg_info("FAIL %s", tp->label);
|
||||
} else {
|
||||
msg_info("PASS %s", tp->label);
|
||||
pass++;
|
||||
}
|
||||
var_dns_rr_list_limit = saved_limit;
|
||||
}
|
||||
msg_info("PASS=%d FAIL=%d", pass, fail);
|
||||
vstring_free(res_buf);
|
||||
exit(fail != 0);
|
||||
}
|
@ -78,11 +78,12 @@ char *dns_strrecord(VSTRING *buf, DNS_RR *rr)
|
||||
vstring_sprintf_append(buf, "%s", rr->data);
|
||||
break;
|
||||
case T_MX:
|
||||
vstring_sprintf_append(buf, "%u %s.", rr->pref, rr->data);
|
||||
vstring_sprintf_append(buf, "%u %.*s.", rr->pref,
|
||||
(int) rr->data_len, rr->data);
|
||||
break;
|
||||
case T_SRV:
|
||||
vstring_sprintf_append(buf, "%u %u %u %s.", rr->pref, rr->weight,
|
||||
rr->port, rr->data);
|
||||
vstring_sprintf_append(buf, "%u %u %u %.*s.", rr->pref, rr->weight,
|
||||
rr->port, (int) rr->data_len, rr->data);
|
||||
break;
|
||||
case T_TLSA:
|
||||
if (rr->data_len >= 3) {
|
||||
|
@ -124,9 +124,11 @@ int main(int argc, char **argv)
|
||||
vstream_printf("%s: fqdn: %s\n", name, vstring_str(fqdn));
|
||||
buf = vstring_alloc(100);
|
||||
print_rr(buf, rr);
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
if (DNS_RR_IS_TRUNCATED(rr))
|
||||
msg_warn("one or more excess DNS_RR records were dropped");
|
||||
dns_rr_free(rr);
|
||||
vstring_free(buf);
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
}
|
||||
}
|
||||
myfree((void *) types);
|
||||
|
@ -4384,16 +4384,6 @@ extern int var_idna2003_compat;
|
||||
#define DEF_DNS_NCACHE_TTL_FIX 0
|
||||
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.
|
||||
*/
|
||||
|
@ -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 "20240218"
|
||||
#define MAIL_RELEASE_DATE "20240227"
|
||||
#define MAIL_VERSION_NUMBER "3.9"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -1280,6 +1280,8 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
|
||||
msg_fatal("host %s: conversion error for address family %d: %m",
|
||||
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
|
||||
addr_list = dns_rr_append(addr_list, addr);
|
||||
if (DNS_RR_IS_TRUNCATED(addr_list))
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
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);
|
||||
addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
|
||||
rr->pref, rr->port);
|
||||
if (addr_list && DNS_RR_IS_TRUNCATED(addr_list))
|
||||
break;
|
||||
}
|
||||
return (addr_list);
|
||||
}
|
||||
|
@ -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)
|
||||
msg_fatal("host %s: conversion error for address family "
|
||||
"%d: %m", host, res0->ai_addr->sa_family);
|
||||
addr_list = dns_rr_append(addr_list, addr);
|
||||
addr->pref = pref;
|
||||
addr->port = port;
|
||||
if (msg_verbose)
|
||||
addr_list = dns_rr_append(addr_list, addr);
|
||||
if (msg_verbose && !DNS_RR_IS_TRUNCATED(addr_list))
|
||||
msg_info("%s: using numerical host %s", myname, host);
|
||||
freeaddrinfo(res0);
|
||||
return (addr_list);
|
||||
@ -262,6 +262,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
|
||||
msg_fatal("host %s: conversion error for address family "
|
||||
"%d: %m", host, res0->ai_addr->sa_family);
|
||||
addr_list = dns_rr_append(addr_list, addr);
|
||||
if (DNS_RR_IS_TRUNCATED(addr_list))
|
||||
break;
|
||||
if (msg_verbose) {
|
||||
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);
|
||||
addr_list = smtp_addr_one(addr_list, (char *) rr->data, res_opt,
|
||||
rr->pref, rr->port, why);
|
||||
if (addr_list && DNS_RR_IS_TRUNCATED(addr_list))
|
||||
break;
|
||||
}
|
||||
return (addr_list);
|
||||
}
|
||||
@ -420,6 +424,13 @@ static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags,
|
||||
* relative list order is unchanged, but some elements are removed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure that dns_rr_append() won't interfere with the protocol
|
||||
* balancing goals.
|
||||
*/
|
||||
if (addr_limit > var_dns_rr_list_limit)
|
||||
addr_limit = var_dns_rr_list_limit;
|
||||
|
||||
/*
|
||||
* Count the number of IPv6 and IPv4 addresses.
|
||||
*/
|
||||
|
@ -3021,6 +3021,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
||||
struct addrinfo *res;
|
||||
int status;
|
||||
const INET_PROTO_INFO *proto_info;
|
||||
int server_addr_count = 0;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
@ -3172,6 +3173,15 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|
||||
msg_info("%s: %s host address check: %s",
|
||||
myname, dns_strtype(type), (char *) server->data);
|
||||
for (res = res0; res != 0; res = res->ai_next) {
|
||||
server_addr_count += 1;
|
||||
if (server_addr_count > var_dns_rr_list_limit) {
|
||||
msg_warn("%s: %s server address count limit (%d) exceeded"
|
||||
" for %s %s -- ignoring the remainder", myname,
|
||||
dns_strtype(type), var_dns_rr_list_limit,
|
||||
reply_class, reply_name);
|
||||
freeaddrinfo(res0);
|
||||
CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
|
||||
}
|
||||
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("skipping address family %d for host %s",
|
||||
|
Loading…
x
Reference in New Issue
Block a user