Re-indented the source code after deleting 'stat' and adding
missing types to .indent.pro.
+20260524
+
+ Bugfix (defect introduced: Postfix 3.1, date 20150607):
+ null pointer dereference and heap data overread in the
+ Postfix SMTP client's smtp_dns_reply_filter (this is disabled
+ by default), when the Postfix SMTP client is configured to
+ use opportunistic or mandatory DANE authentication (this
+ is disabled by default); and the destination domain publishes
+ a TLSA record that is empty or shorter than 20 bytes; and
+ the OS is configured to use a resolver that passes such a
+ TLSA record. For example, a zero-length TLSA record is
+ blocked by BIND, Google DNS, OpenDNS, and by configurations
+ that use systemd-resolved (the default on many LINUX systems);
+ it is passed by Cloudflare, Quad9 DNS, and unbound, if these
+ resolvers are used without systemd-resolved.
+
+ The root cause is a missing 'break' statement after the
+ code that converts a TLSA record to string, resulting in a
+ null pointer crash when the record length is zero; or a
+ data overread (or rarely, a segfault) with 0 < record length
+ < 20 bytes. The overread content is not disclosed.
+
+ The impact of crashes is easily overstated. That said,
+ crashes must be eliminated regardless of their impact.
+
+ On systems that deliver fewer than one message per minute,
+ a null pointer or other segfault crash can result in a delay
+ of up to one minute for email delivery to other destination
+ domains.
+
+ On systems with a larger traffic volume, the impact of a
+ null pointer or other segfault crash on deliveries to other
+ destination domains is minor because Postfix reuses SMTP
+ client processes and replaces a failed process within seconds
+ (self-healing); the practical impact is believed to be no
+ worse than that of an uncooperative receiver that tarpits
+ SMTP connections from Postfix to one or more destination
+ domains under their control (by replying within Postfix
+ SMTP client read time limits which are several minutes by
+ default).
+
+ Problem reported by TristanInSec, found with ASAN. Also
+ reported by other people. Reproduction and real-world impact
+ researched by Wietse. File: dns/dns_strrecord.c.
+
+20260529
+
+ Robustness: Postfix SMTP server will no longer receive (and
+ discard) an unlimited amount of text while receiving a long
+ SMTP command line. Problem introduced: Postfix 2.9, date:
+ 20110205; reported by Michael Wollner. Under high load
+ conditions, the amount of text was already limited by a
+ 10-second deadline to receive an SMTP command. Files:
+ global/smtp_stream.c, smtpd/smtpd.c, smtpd/smtpd_chat.h.
+
+ Robustness: with the above change the Postfix SMTP client
+ will no longer receive (and discard) an unlimited amount
+ of text while receiving a long SMTP response line.
+
+ Robustness: do not receive (and discard) unlimited amounts
+ of data with BDAT commands. Problem introduced: Postfix
+ 3.4, date: 20180825; found during code maintenance. File:
+ smtpd/smtpd.c.
+
+20260531
+
+ Bugfix: (defect introduced: Postfix 3.6, date: 20200710):
+ panic() while parsing a TLSA record with length 3. Found
+ during code maintenance. File: tls/tls_dane.c.
+
TODO
Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc.
off_t done;
off_t len;
+ /*
+ * Skip inputs below 1.5 times the message size limit, staying in sync
+ * with the remote SMTP client. Otherwise, force a negative chunk_size
+ * value to disable reading and discarding input here, and to force a
+ * "lost connection" condition upon a later read operation.
+ */
+ if (ENFORCING_SIZE_LIMIT(var_message_limit)
+ && state->act_size / 1.5 > var_message_limit - chunk_size / 1.5) {
+ chunk_size = -1;
+ } else if (state->act_size > OFF_T_MAX - chunk_size) {
+ state->act_size = OFF_T_MAX;
+ } else {
+ state->act_size += chunk_size;
+ }
+
/*
* Read and discard content from the remote SMTP client. TODO: drop the
* connection in case of overload.
vsmtpd_chat_reply(state, format, ap);
va_end(ap);
+ /*
+ * Force a "lost connection" condition upon the next read operation.
+ */
+ if (chunk_size < 0) {
+ msg_warn("%s: too much BDAT content -- disabling further input from %s",
+ state->queue_id ? state->queue_id : "NOQUEUE",
+ state->namaddr);
+ shutdown(vstream_fileno(state->client), SHUT_RD);
+ }
+
/*
* Reset state, or drop subsequent BDAT payloads until BDAT LAST or RSET.
*/
break;
}
watchdog_pat();
- smtpd_chat_query(state);
+ if (!smtpd_chat_query(state)) {
+ state->error_mask |= MAIL_ERROR_PROTOCOL;
+ smtpd_chat_reply(state, "500 5.5.2 %s Error: command too long",
+ var_myhostname);
+ continue;
+ }
if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) {
log_whatsup(state, "reject", "bare <LF> received");
state->error_mask |= MAIL_ERROR_PROTOCOL;
/* void tls_dane_log(TLScontext)
/* TLS_SESS_STATE *TLScontext;
/*
-/* int tls_dane_unusable(dane)
-/* const TLS_DANE *dane;
-/*
/* int tls_dane_notfound(dane)
/* const TLS_DANE *dane;
/* DESCRIPTION
/* tls_dane_log() logs successful verification via DNS-based or
/* synthetic DANE TLSA RRs (fingerprint or "tafile").
/*
-/* tls_dane_unusable() checks whether a cached TLS_DANE record is
-/* the result of a validated RRset, with no usable elements. In
-/* this case, TLS is mandatory, but certificate verification is
-/* not DANE-based.
-/*
/* tls_dane_notfound() checks whether a cached TLS_DANE record is
/* the result of a validated DNS lookup returning NODATA. In
/* this case, TLS is not required by RFC, though users may elect
q, a, r, rr->type);
/* Drop truncated records */
- if ((dlen = rr->data_len - 3) < 0) {
+ if ((dlen = rr->data_len - 3) <= 0) {
msg_warn("%s%s%s: truncated TLSA RR length == %u",
q, a, r, (unsigned) rr->data_len);
return (0);