Bugfix (introduced: Postfix 3.3.13): part of a memory leak
fix was backported to the wrong place. File: tls/tls_misc.c.
+
+20200830
+
+ Bugfix (introduced: Postfix 2.0): smtp_sasl_mechanism_filter
+ ignored table lookup errors, treating them as 'not found'.
+ Found during Postfix 3.6 development. File: smtp/smtp_sasl_proto.c.
+
+202000920
+
+ Bugfix (introduced: Postfix 2.3): when deleting a recipient
+ with a milter, delete the recipient from the duplicate
+ filter, so that the recipient can be added back. Backported
+ from Postfix 3.6. Files: global/been_here.[hc],
+ cleanup/cleanup_milter.c.
+
+20200925
+
+ Bugfix (introduced: before Postfix alpha): the code that
+ looks for Delivered-To: headers ignored headers longer than
+ $line_length_limit. Backported from Postfix 3.6. File:
+ global/delivered_hdr.c.
+
+20201011
+
+ Bugfix (introduced: Postfix 2.8): save a copy of the
+ postscreen_dnsbl_reply_map lookup result. This has no effect
+ when the recommended texthash: look table is used, but it
+ may avoid stale data with other lookup tables. File:
+ postscreen/postscreen_dnsbl.c.
+
+20201022
+
+ Bugfix (introduced: Postfix 2.2): after processing an
+ XCCLIENT command, the smtps service was waiting for a TLS
+ handshake. Found by Aki Tuomi. File: smtpd/smtpd.c.
+
+20201025
+
+ Bugfix (introduced: Postfix 2.3): static maps did not free
+ their casefolding buffer. File: util/dict_static.c.
}
count++;
}
+ if (var_enable_orcpt)
+ been_here_drop(state->dups, "%s\n%d\n%s\n%s",
+ dsn_orcpt ? dsn_orcpt : "", dsn_notify,
+ orig_rcpt ? orig_rcpt : "", STR(int_rcpt_buf));
/* FALLTHROUGH */
case REC_TYPE_DRCP: /* canceled recipient */
case REC_TYPE_DONE: /* can't happen */
break;
}
}
+ if (var_enable_orcpt == 0 && count > 0)
+ been_here_drop_fixed(state->dups, STR(int_rcpt_buf));
if (msg_verbose)
msg_info("%s: deleted %d records for recipient \"%s\"",
/* BH_TABLE *dup_filter;
/* char *format;
/*
+/* int been_here_drop_fixed(dup_filter, string)
+/* BH_TABLE *dup_filter;
+/* char *string;
+/*
+/* int been_here_drop(dup_filter, format, ...)
+/* BH_TABLE *dup_filter;
+/* char *format;
+/*
/* void been_here_free(dup_filter)
/* BH_TABLE *dup_filter;
/* DESCRIPTION
/* been_here_check_fixed() and been_here_check() are similar
/* but do not update the duplicate filter.
/*
+/* been_here_drop_fixed() looks up a fixed string in the given
+/* table, and deletes the entry if the string was found. The
+/* result is non-zero (true) if the string was found, zero
+/* (false) otherwise.
+/*
+/* been_here_drop() formats its arguments, looks up the result
+/* in the given table, and removes the entry if the formatted
+/* result was found. The result is non-zero (true) if the
+/* formatted result was found, zero (false) otherwise.
+/*
/* been_here_free() releases storage for a duplicate filter.
/*
/* Arguments:
return (status);
}
+
+/* been_here_drop - remove filter entry with finer control */
+
+int been_here_drop(BH_TABLE *dup_filter, const char *fmt,...)
+{
+ VSTRING *buf = vstring_alloc(100);
+ int status;
+ va_list ap;
+
+ /*
+ * Construct the string to be dropped.
+ */
+ va_start(ap, fmt);
+ vstring_vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ /*
+ * Drop the filter entry.
+ */
+ status = been_here_drop_fixed(dup_filter, vstring_str(buf));
+
+ /*
+ * Cleanup.
+ */
+ vstring_free(buf);
+ return (status);
+}
+
+/* been_here_drop_fixed - remove filter entry */
+
+int been_here_drop_fixed(BH_TABLE *dup_filter, const char *string)
+{
+ VSTRING *folded_string;
+ const char *lookup_key;
+ int status;
+
+ /*
+ * Special processing: case insensitive lookup.
+ */
+ if (dup_filter->flags & BH_FLAG_FOLD) {
+ folded_string = vstring_alloc(100);
+ lookup_key = casefold(folded_string, string);
+ } else {
+ folded_string = 0;
+ lookup_key = string;
+ }
+
+ /*
+ * Drop the filter entry.
+ */
+ if ((status = been_here_check_fixed(dup_filter, lookup_key)) != 0)
+ htable_delete(dup_filter->table, lookup_key, (void (*) (void *)) 0);
+
+ /*
+ * Cleanup.
+ */
+ if (folded_string)
+ vstring_free(folded_string);
+
+ return (status);
+}
extern int PRINTFLIKE(2, 3) been_here(BH_TABLE *, const char *,...);
extern int been_here_check_fixed(BH_TABLE *, const char *);
extern int PRINTFLIKE(2, 3) been_here_check(BH_TABLE *, const char *,...);
+extern int been_here_drop_fixed(BH_TABLE *, const char *);
+extern int PRINTFLIKE(2, 3) been_here_drop(BH_TABLE *, const char *,...);
/* LICENSE
/* .ad
char *cp;
DELIVERED_HDR_INFO *info;
const HEADER_OPTS *hdr;
+ int curr_type;
+ int prev_type;
/*
* Sanity check.
/*
* XXX Assume that mail_copy() produces delivered-to headers that fit in
- * a REC_TYPE_NORM record. Lowercase the delivered-to addresses for
- * consistency.
+ * a REC_TYPE_NORM or REC_TYPE_CONT record. Lowercase the delivered-to
+ * addresses for consistency.
*
* XXX Don't get bogged down by gazillions of delivered-to headers.
*/
#define DELIVERED_HDR_LIMIT 1000
- while (rec_get(fp, info->buf, 0) == REC_TYPE_NORM
- && info->table->used < DELIVERED_HDR_LIMIT) {
+ for (prev_type = REC_TYPE_NORM;
+ info->table->used < DELIVERED_HDR_LIMIT
+ && ((curr_type = rec_get(fp, info->buf, 0)) == REC_TYPE_NORM
+ || curr_type == REC_TYPE_CONT);
+ prev_type = curr_type) {
+ if (prev_type != REC_TYPE_NORM)
+ continue;
if (is_header(STR(info->buf))) {
if ((hdr = header_opts_find(STR(info->buf))) != 0
&& hdr->type == HDR_DELIVERED_TO) {
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20200726"
-#define MAIL_VERSION_NUMBER "3.2.19"
+#define MAIL_RELEASE_DATE "20201107"
+#define MAIL_VERSION_NUMBER "3.2.20"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
int weight;
HTABLE_INFO *ht;
char *parse_err;
+ const char *safe_dnsbl;
/*
* Parse the required DNSBL domain name, the optional reply filter and
ht = htable_enter(dnsbl_site_cache, saved_site, (void *) head);
/* Translate the DNSBL name into a safe name if available. */
if (psc_dnsbl_reply == 0
- || (head->safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0)
- head->safe_dnsbl = ht->key;
+ || (safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0)
+ safe_dnsbl = ht->key;
+ head->safe_dnsbl = mystrdup(safe_dnsbl);
if (psc_dnsbl_reply && psc_dnsbl_reply->error)
msg_fatal("%s:%s lookup error", psc_dnsbl_reply->type,
psc_dnsbl_reply->name);
if (VSTRING_LEN(buf) > 0)
VSTRING_ADDCH(buf, ' ');
vstring_strcat(buf, mech);
+ } else if (smtp_sasl_mechs->error) {
+ msg_fatal("SASL mechanism filter failed for: '%s'", mech);
}
}
myfree(save_mech);
* obsolete, so we don't have to provide perfect support.
*/
#ifdef USE_TLS
- if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) {
+ if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode
+ && state->tls_context == 0) {
#ifdef USE_TLSPROXY
/* We garbage-collect the VSTREAM in smtpd_state_reset() */
state->tlsproxy = tls_proxy_open(var_tlsproxy_service,
static void dict_static_close(DICT *dict)
{
+ if (dict->fold_buf)
+ vstring_free(dict->fold_buf);
dict_free(dict);
}