]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.10.4 v3.10.4
authorWietse Z Venema <wietse@porcupine.org>
Mon, 18 Aug 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Tue, 19 Aug 2025 14:41:46 +0000 (00:41 +1000)
20 files changed:
postfix/HISTORY
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/master/event_server.c
postfix/src/master/multi_server.c
postfix/src/postscreen/postscreen.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_tls_policy.c
postfix/src/tls/tls_client.c
postfix/src/tls/tls_verify.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/tlsproxy/tlsproxy_state.c
postfix/src/util/dict.c
postfix/src/util/dict_db.c
postfix/src/util/dict_dbm.c
postfix/src/util/dict_lmdb.c
postfix/src/util/dict_sdbm.c

index 6206bed1638de293b8f7d72ff41974bec5cac6b6..78726ec06f1fa492839cd8d1c6f68658751208b9 100644 (file)
@@ -29054,3 +29054,71 @@ Apologies for any names omitted.
        with "TLS-Required: no". This could result in unnecessary
        failures. Fix by Viktor Dukhovni & Wietse. Files: smtp/smtp.h,
        smtp/smtp_policy.c, smtp/smtp_connect.c.
+
+20250710
+
+       Bugfix (defect introduced: postfix-2.2, date 20050203):
+       after detecting a lookup table change, and after starting
+       a new postscreen process, the old postscreen process logged
+       an ENOTSOCK error while attempting to accept a connection
+       on a socket that it was no longer listening on. This error
+       was introduced first in the multi_server skeleton code, and
+       was five years later duplicated in the event_server skeleton
+       that was created for postscreen. Problem reported by Florian
+       Piekert. Files: master/multi_server.c, master/event_server.c.
+
+20250714
+
+       Deleted an <openssl/engine.h> dependency, because the feature is
+       being removed from OpenSSL, and Postfix no longer needs it. File:
+       posttls-finger/posttls-finger.c.
+
+20250716
+
+       Bugfix (defect introduced: Postfix 2.8, date 20101230):
+       after detecting a cache table change and before starting a
+       new postscreen process, the old postscreen process did not
+       close the postscreen_cache_map, and therefore kept an
+       exclusive lock that could prevent a new postscreen process
+       from starting. Problem reported by Florian Piekert. File:
+       postscreen/postscreen.c.
+
+20250717
+
+       Workaround: Postfix daemons no longer automatically restart
+       after a btree:, dbm:, hash:, lmdb:, or sdbm: table file
+       modification time change, when they opened that table for
+       writing. Files: util/dict.c, util/dict_db.c, util/dict_dbm.c,
+       util/dict_lmdb.c, util/dict_sdbm.c.
+
+20250730
+
+       Bugfix (defect introduced: Postfix 3.6, date 20200710):
+       Postfix TLS client code logged "Untrusted TLS connection"
+       (wrong) instead of "Trusted TLS connection" (right), for a
+       new or resumed TLS session, when a server offered a trusted
+       (valid PKI trust chain) certificate that did not match the
+       expected server name pattern. Viktor Dukhovni. Files:
+       tls/tls_client.c, tls/tls_verify.c.
+
+20250801
+
+       Bugfix (defect introduced: Postfix 3.7): incorrect backwards
+       compatible support for the legacy configuration parameters
+       tlsproxy_client_level and tlsproxy_client_policy. This
+       disabled the tlsproxy TLS client role when a legacy parameter
+       was set. Reported by John Doe, diagnosed by Viktor Dukhovni.
+       File: global/mail_params.h.
+
+       Bugfix (defect introduced: Postfix 3.4): with the TLS client
+       role disabled by configuration, the tlsproxy daemon
+       dereferenced a null pointer while handling a tlsproxy client
+       request. Reported by John Doe. File: tlsproxy/tlsproxy.c.
+
+20250803
+
+       Cleanup: with "tls_required_enable = yes", the Postfix SMTP
+       client will no longer maintain TLSRPT statistics for
+       messages that contain a "TLS-Required: no" header. This
+       can prevent TLSRPT notifications for TLSRPT notifications.
+       Files: smtp/smtp_connect.c, smtp_tls_policy.c.
index 0aa05ba0024e95c930eae61dfe705c3d4c661355..375a35eadfb903f2747b11027d586d2667aeb2f4 100644 (file)
@@ -4171,7 +4171,9 @@ extern bool var_tlsp_clnt_enforce_tls;
 /* Migrate an incorrect name. */
 #define OBS_TLSP_CLNT_LEVEL            "tlsproxy_client_level"
 #define VAR_TLSP_CLNT_LEVEL            "tlsproxy_client_security_level"
-#define DEF_TLSP_CLNT_LEVEL            "${" OBS_TLSP_CLNT_LEVEL ":$" VAR_SMTP_TLS_LEVEL "}"
+#define DEF_TLSP_CLNT_LEVEL            "${" OBS_TLSP_CLNT_LEVEL "?{$" \
+                                       OBS_TLSP_CLNT_LEVEL "}:{$" \
+                                       VAR_SMTP_TLS_LEVEL "}}"
 extern char *var_tlsp_clnt_level;
 
 #define VAR_TLSP_CLNT_PER_SITE         "tlsproxy_client_per_site"
@@ -4181,7 +4183,9 @@ extern char *var_tlsp_clnt_per_site;
 /* Migrate an incorrect name. */
 #define OBS_TLSP_CLNT_POLICY           "tlsproxy_client_policy"
 #define VAR_TLSP_CLNT_POLICY           "tlsproxy_client_policy_maps"
-#define DEF_TLSP_CLNT_POLICY           "${" OBS_TLSP_CLNT_POLICY ":$" VAR_SMTP_TLS_POLICY "}"
+#define DEF_TLSP_CLNT_POLICY           "${" OBS_TLSP_CLNT_POLICY "?{$" \
+                                       OBS_TLSP_CLNT_POLICY "}:{$" \
+                                       VAR_SMTP_TLS_POLICY "}}"
 extern char *var_tlsp_clnt_policy;
 
  /*
index 81a59fc3762c6aa665b4affc211025f429fa4400..9770f7448d0034fe4eaf738bda90c37a1038ce40 100644 (file)
@@ -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      "20250710"
-#define MAIL_VERSION_NUMBER    "3.10.3"
+#define MAIL_RELEASE_DATE      "20250818"
+#define MAIL_VERSION_NUMBER    "3.10.4"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 9802bdf2f02d368b5112b70a515f854d8ea82b0d..ff280db571c598edb9ad56a39a726e934730a4b6 100644 (file)
@@ -273,6 +273,7 @@ static unsigned event_server_generation;
 static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
 static void (*event_server_slow_exit) (char *, char **);
 static int event_server_watchdog = 1000;
+static int event_server_drain_was_called = 0;
 
 /* event_server_exit - normal termination */
 
@@ -327,6 +328,9 @@ int     event_server_drain(void)
     const char *myname = "event_server_drain";
     int     fd;
 
+    if (event_server_drain_was_called)
+       return (0);
+
     switch (fork()) {
        /* Try again later. */
     case -1:
@@ -343,6 +347,7 @@ int     event_server_drain(void)
                msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
        }
        var_use_limit = 1;
+       event_server_drain_was_called = 1;
        return (0);
        /* Let the master start a new process. */
     default:
@@ -445,6 +450,9 @@ static void event_server_accept_local(int unused_event, void *context)
     int     time_left = -1;
     int     fd;
 
+    if (event_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -457,6 +465,8 @@ static void event_server_accept_local(int unused_event, void *context)
 
     if (event_server_pre_accept)
        event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+       return;
     fd = LOCAL_ACCEPT(listen_fd);
     if (event_server_lock != 0
        && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -483,6 +493,9 @@ static void event_server_accept_pass(int unused_event, void *context)
     int     fd;
     HTABLE *attr = 0;
 
+    if (event_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -495,6 +508,8 @@ static void event_server_accept_pass(int unused_event, void *context)
 
     if (event_server_pre_accept)
        event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+       return;
     fd = pass_accept_attr(listen_fd, &attr);
     if (event_server_lock != 0
        && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -520,6 +535,9 @@ static void event_server_accept_inet(int unused_event, void *context)
     int     time_left = -1;
     int     fd;
 
+    if (event_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -532,6 +550,8 @@ static void event_server_accept_inet(int unused_event, void *context)
 
     if (event_server_pre_accept)
        event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+       return;
     fd = inet_accept(listen_fd);
     if (event_server_lock != 0
        && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
index 6150f229aeb537442d50fba8ea6970aa41b4b580..4e744d4d116bd348b7b571fbdb92e5c7c2060571 100644 (file)
@@ -260,6 +260,7 @@ static VSTREAM *multi_server_lock;
 static int multi_server_in_flow_delay;
 static unsigned multi_server_generation;
 static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
+static int multi_server_drain_was_called = 0;
 
 /* multi_server_exit - normal termination */
 
@@ -295,6 +296,9 @@ int     multi_server_drain(void)
     const char *myname = "multi_server_drain";
     int     fd;
 
+    if (multi_server_drain_was_called)
+       return (0);
+
     switch (fork()) {
        /* Try again later. */
     case -1:
@@ -311,6 +315,7 @@ int     multi_server_drain(void)
                msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
        }
        var_use_limit = 1;
+       multi_server_drain_was_called = 1;
        return (0);
        /* Let the master start a new process. */
     default:
@@ -429,6 +434,9 @@ static void multi_server_accept_local(int unused_event, void *context)
     int     time_left = -1;
     int     fd;
 
+    if (multi_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -441,6 +449,8 @@ static void multi_server_accept_local(int unused_event, void *context)
 
     if (multi_server_pre_accept)
        multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+       return;
     fd = LOCAL_ACCEPT(listen_fd);
     if (multi_server_lock != 0
        && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -467,6 +477,9 @@ static void multi_server_accept_pass(int unused_event, void *context)
     int     fd;
     HTABLE *attr = 0;
 
+    if (multi_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -479,6 +492,8 @@ static void multi_server_accept_pass(int unused_event, void *context)
 
     if (multi_server_pre_accept)
        multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+       return;
     fd = pass_accept_attr(listen_fd, &attr);
     if (multi_server_lock != 0
        && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -504,6 +519,9 @@ static void multi_server_accept_inet(int unused_event, void *context)
     int     time_left = -1;
     int     fd;
 
+    if (multi_server_drain_was_called)
+       return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -516,6 +534,8 @@ static void multi_server_accept_inet(int unused_event, void *context)
 
     if (multi_server_pre_accept)
        multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+       return;
     fd = inet_accept(listen_fd);
     if (multi_server_lock != 0
        && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
index ebb680c06805588f38c248eb9c8aa0840d178613..2744dd15f2f0619502415befb92ad7acac117009 100644 (file)
@@ -996,7 +996,7 @@ static void pre_accept(char *unused_name, char **unused_argv)
     if (new_event_time >= last_event_time + 1
        && (name = dict_changed_name()) != 0) {
        msg_info("table %s has changed - finishing in the background", name);
-       event_server_drain();
+       psc_drain(unused_name, unused_argv);
     } else {
        last_event_time = new_event_time;
     }
index dc25a3e095230629b02bdd28abc71322e3f82509..baa5ca81b357fae62d8ab5c368214e8efd75ede4 100644 (file)
 
 #ifdef USE_TLS
 #include <tls_proxy.h>
-#include <openssl/engine.h>
 #endif
 
  /*
index 44add46b25cf306dc3e40fe44041456bcf42d522..f8cde6978f4f750a9a31b15410ef04bb7b7e0517 100644 (file)
@@ -113,6 +113,7 @@ smtp.o: ../../include/nvtable.h
 smtp.o: ../../include/recipient_list.h
 smtp.o: ../../include/resolve_clnt.h
 smtp.o: ../../include/scache.h
+smtp.o: ../../include/sendopts.h
 smtp.o: ../../include/sock_addr.h
 smtp.o: ../../include/string_list.h
 smtp.o: ../../include/stringops.h
@@ -158,6 +159,7 @@ smtp_addr.o: ../../include/own_inet_addr.h
 smtp_addr.o: ../../include/recipient_list.h
 smtp_addr.o: ../../include/resolve_clnt.h
 smtp_addr.o: ../../include/scache.h
+smtp_addr.o: ../../include/sendopts.h
 smtp_addr.o: ../../include/sock_addr.h
 smtp_addr.o: ../../include/string_list.h
 smtp_addr.o: ../../include/stringops.h
@@ -304,6 +306,7 @@ smtp_key.o: ../../include/nvtable.h
 smtp_key.o: ../../include/recipient_list.h
 smtp_key.o: ../../include/resolve_clnt.h
 smtp_key.o: ../../include/scache.h
+smtp_key.o: ../../include/sendopts.h
 smtp_key.o: ../../include/sock_addr.h
 smtp_key.o: ../../include/string_list.h
 smtp_key.o: ../../include/sys_defs.h
@@ -344,6 +347,7 @@ smtp_map11.o: ../../include/quote_flags.h
 smtp_map11.o: ../../include/recipient_list.h
 smtp_map11.o: ../../include/resolve_clnt.h
 smtp_map11.o: ../../include/scache.h
+smtp_map11.o: ../../include/sendopts.h
 smtp_map11.o: ../../include/sock_addr.h
 smtp_map11.o: ../../include/string_list.h
 smtp_map11.o: ../../include/sys_defs.h
@@ -384,6 +388,7 @@ smtp_misc.o: ../../include/quote_flags.h
 smtp_misc.o: ../../include/recipient_list.h
 smtp_misc.o: ../../include/resolve_clnt.h
 smtp_misc.o: ../../include/scache.h
+smtp_misc.o: ../../include/sendopts.h
 smtp_misc.o: ../../include/sock_addr.h
 smtp_misc.o: ../../include/string_list.h
 smtp_misc.o: ../../include/sys_defs.h
@@ -491,6 +496,7 @@ smtp_rcpt.o: ../../include/nvtable.h
 smtp_rcpt.o: ../../include/recipient_list.h
 smtp_rcpt.o: ../../include/resolve_clnt.h
 smtp_rcpt.o: ../../include/scache.h
+smtp_rcpt.o: ../../include/sendopts.h
 smtp_rcpt.o: ../../include/sent.h
 smtp_rcpt.o: ../../include/sock_addr.h
 smtp_rcpt.o: ../../include/string_list.h
@@ -530,6 +536,7 @@ smtp_reuse.o: ../../include/nvtable.h
 smtp_reuse.o: ../../include/recipient_list.h
 smtp_reuse.o: ../../include/resolve_clnt.h
 smtp_reuse.o: ../../include/scache.h
+smtp_reuse.o: ../../include/sendopts.h
 smtp_reuse.o: ../../include/sock_addr.h
 smtp_reuse.o: ../../include/string_list.h
 smtp_reuse.o: ../../include/stringops.h
@@ -572,6 +579,7 @@ smtp_sasl_auth_cache.o: ../../include/nvtable.h
 smtp_sasl_auth_cache.o: ../../include/recipient_list.h
 smtp_sasl_auth_cache.o: ../../include/resolve_clnt.h
 smtp_sasl_auth_cache.o: ../../include/scache.h
+smtp_sasl_auth_cache.o: ../../include/sendopts.h
 smtp_sasl_auth_cache.o: ../../include/sock_addr.h
 smtp_sasl_auth_cache.o: ../../include/string_list.h
 smtp_sasl_auth_cache.o: ../../include/stringops.h
@@ -613,6 +621,7 @@ smtp_sasl_glue.o: ../../include/nvtable.h
 smtp_sasl_glue.o: ../../include/recipient_list.h
 smtp_sasl_glue.o: ../../include/resolve_clnt.h
 smtp_sasl_glue.o: ../../include/scache.h
+smtp_sasl_glue.o: ../../include/sendopts.h
 smtp_sasl_glue.o: ../../include/smtp_stream.h
 smtp_sasl_glue.o: ../../include/sock_addr.h
 smtp_sasl_glue.o: ../../include/split_at.h
@@ -657,6 +666,7 @@ smtp_sasl_proto.o: ../../include/recipient_list.h
 smtp_sasl_proto.o: ../../include/resolve_clnt.h
 smtp_sasl_proto.o: ../../include/sasl_mech_filter.h
 smtp_sasl_proto.o: ../../include/scache.h
+smtp_sasl_proto.o: ../../include/sendopts.h
 smtp_sasl_proto.o: ../../include/sock_addr.h
 smtp_sasl_proto.o: ../../include/string_list.h
 smtp_sasl_proto.o: ../../include/stringops.h
@@ -697,6 +707,7 @@ smtp_session.o: ../../include/nvtable.h
 smtp_session.o: ../../include/recipient_list.h
 smtp_session.o: ../../include/resolve_clnt.h
 smtp_session.o: ../../include/scache.h
+smtp_session.o: ../../include/sendopts.h
 smtp_session.o: ../../include/sock_addr.h
 smtp_session.o: ../../include/string_list.h
 smtp_session.o: ../../include/stringops.h
@@ -737,6 +748,7 @@ smtp_state.o: ../../include/nvtable.h
 smtp_state.o: ../../include/recipient_list.h
 smtp_state.o: ../../include/resolve_clnt.h
 smtp_state.o: ../../include/scache.h
+smtp_state.o: ../../include/sendopts.h
 smtp_state.o: ../../include/sock_addr.h
 smtp_state.o: ../../include/string_list.h
 smtp_state.o: ../../include/sys_defs.h
@@ -778,6 +790,7 @@ smtp_tls_policy.o: ../../include/recipient_list.h
 smtp_tls_policy.o: ../../include/resolve_clnt.h
 smtp_tls_policy.o: ../../include/sane_strtol.h
 smtp_tls_policy.o: ../../include/scache.h
+smtp_tls_policy.o: ../../include/sendopts.h
 smtp_tls_policy.o: ../../include/sock_addr.h
 smtp_tls_policy.o: ../../include/string_list.h
 smtp_tls_policy.o: ../../include/stringops.h
@@ -821,6 +834,7 @@ smtp_tlsrpt.o: ../../include/nvtable.h
 smtp_tlsrpt.o: ../../include/recipient_list.h
 smtp_tlsrpt.o: ../../include/resolve_clnt.h
 smtp_tlsrpt.o: ../../include/scache.h
+smtp_tlsrpt.o: ../../include/sendopts.h
 smtp_tlsrpt.o: ../../include/sock_addr.h
 smtp_tlsrpt.o: ../../include/string_list.h
 smtp_tlsrpt.o: ../../include/stringops.h
@@ -864,6 +878,7 @@ smtp_trouble.o: ../../include/nvtable.h
 smtp_trouble.o: ../../include/recipient_list.h
 smtp_trouble.o: ../../include/resolve_clnt.h
 smtp_trouble.o: ../../include/scache.h
+smtp_trouble.o: ../../include/sendopts.h
 smtp_trouble.o: ../../include/smtp_stream.h
 smtp_trouble.o: ../../include/sock_addr.h
 smtp_trouble.o: ../../include/string_list.h
@@ -903,6 +918,7 @@ smtp_unalias.o: ../../include/nvtable.h
 smtp_unalias.o: ../../include/recipient_list.h
 smtp_unalias.o: ../../include/resolve_clnt.h
 smtp_unalias.o: ../../include/scache.h
+smtp_unalias.o: ../../include/sendopts.h
 smtp_unalias.o: ../../include/sock_addr.h
 smtp_unalias.o: ../../include/string_list.h
 smtp_unalias.o: ../../include/sys_defs.h
index 7214661a64ad12d6748be484b4936a16a219e8ca..af118926d33d6915a3b623d78584eff4358592b5 100644 (file)
@@ -32,6 +32,7 @@
 #include <tok822.h>
 #include <dsn_buf.h>
 #include <header_body_checks.h>
+#include <sendopts.h>
 
  /*
   * Postfix TLS library.
@@ -59,9 +60,6 @@ typedef struct SMTP_ITERATOR {
     VSTRING *host;                     /* hostname or empty */
     VSTRING *addr;                     /* printable address or empty */
     unsigned port;                     /* network byte order or null */
-#ifdef USE_TLS
-    int     tlsreqno;                  /* "TLS-Required: no" */
-#endif
     struct DNS_RR *rr;                 /* DNS resource record or null */
     struct DNS_RR *mx;                 /* DNS resource record or null */
     /* Private members. */
@@ -69,18 +67,11 @@ typedef struct SMTP_ITERATOR {
     struct SMTP_STATE *parent;         /* parent linkage */
 } SMTP_ITERATOR;
 
-#ifdef USE_TLS
-#define IF_USE_TLS(...) (__VA_ARGS__)
-#else
-#define IF_USE_TLS(...)
-#endif
-
 #define SMTP_ITER_INIT(iter, _dest, _host, _addr, _port, state) do { \
        vstring_strcpy((iter)->dest, (_dest)); \
        vstring_strcpy((iter)->host, (_host)); \
        vstring_strcpy((iter)->addr, (_addr)); \
        (iter)->port = (_port); \
-       IF_USE_TLS((iter)->tlsreqno = 0); \
        (iter)->mx = (iter)->rr = 0; \
        vstring_strcpy((iter)->saved_dest, ""); \
        (iter)->parent = (state); \
@@ -248,6 +239,12 @@ typedef struct SMTP_STATE {
     unsigned logged_line_length_limit:1;
 } SMTP_STATE;
 
+#ifdef USE_TLS
+#define STATE_TLS_NOT_REQUIRED(state) \
+       (var_tls_required_enable && \
+           ((state)->request->sendopts & SOPT_REQUIRETLS_HEADER))
+#endif
+
  /*
   * Primitives to enable/disable/test connection caching and reuse based on
   * the delivery request next-hop destination (i.e. not smtp_fallback_relay).
index e4b60791a582d8d8d92a8e28aad6b162340578cf..38e28b7674b8338852e1cc0bf46b4e8593cfa9b5 100644 (file)
@@ -507,24 +507,6 @@ static int smtp_get_effective_tls_level(DSN_BUF *why, SMTP_STATE *state)
     SMTP_ITERATOR *iter = state->iterator;
     SMTP_TLS_POLICY *tls = state->tls;
 
-    /*
-     * If the message contains a "TLS-Required: no" header, update the
-     * iterator to limit the policy at TLS_LEV_MAY.
-     * 
-     * We must do this early to avoid possible failure if TLSA record lookups
-     * fail, or if TLSA records are found, but can't be activated because the
-     * security level has been reset to "may".
-     * 
-     * Note that the REQUIRETLS verb in ESMTP overrides the "TLS-Required: no"
-     * header.
-     */
-#ifdef USE_TLS
-    if (var_tls_required_enable
-       && (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
-       iter->tlsreqno = 1;
-    }
-#endif
-
     /*
      * Determine the TLS level for this destination.
      */
@@ -976,9 +958,15 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
         * level of "may" to "encrypt"? This would disable falling back to
         * plaintext, and could break interoperability with receivers that
         * crank up security up to 11.
+        * 
+        * With "TLS-Required: no" in effect, the SMTP client ignores the
+        * recipient-side policy mechanism TLSRPT, in addition to the already
+        * ignored DANE and MTA-STS mechanisms. This prevents TLSRPT
+        * notifications for all SMTP deliveries that do not require TLS.
         */
 #ifdef USE_TLSRPT
        if (smtp_mode && var_smtp_tlsrpt_enable
+           && STATE_TLS_NOT_REQUIRED(state) == 0
            && tls_level_lookup(var_smtp_tls_level) > TLS_LEV_NONE
            && !valid_hostaddr(domain, DONT_GRIPE))
            smtp_tlsrpt_create_wrapper(state, domain);
index 6b9ee66e6fdbf51910e345eb2b5c301e302592ba..809ffea05349c8c6db443051fce4c1c0caa145a2 100644 (file)
@@ -647,11 +647,18 @@ static void *policy_create(const char *unused_key, void *context)
      * Compute the per-site TLS enforcement level. For compatibility with the
      * original TLS patch, this algorithm is gives equal precedence to host
      * and next-hop policies.
+     * 
+     * When "TLS-Required: no" is in effect, skip TLS policy lookup and limit
+     * the security level to "may". Do not reset the security level after
+     * policy lookup, as that would result in errors. For example, when TLSA
+     * records are looked up for security level "dane", and then the security
+     * level is reset to "may", the activation of those TLSA records will
+     * fail.
      */
     tls->level = global_tls_level();
     site_level = TLS_LEV_NOTFOUND;
 
-    if (iter->tlsreqno) {
+    if (STATE_TLS_NOT_REQUIRED(iter->parent)) {
        if (msg_verbose)
            msg_info("%s: no tls policy lookup", __func__);
        if (tls->level > TLS_LEV_MAY)
index 55d336602c2514ea546ed5d92850c0d64d3d52b5..a7b511f7a644a260befb64600e227b850e030bcb 100644 (file)
@@ -313,6 +313,7 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext)
 static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
                                const TLS_CLIENT_START_PROPS *props)
 {
+    int     x509_err = SSL_get_verify_result(TLScontext->con);
 
     /*
      * On exit both peer_CN and issuer_CN should be set.
@@ -324,7 +325,7 @@ static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
      * Is the certificate trust chain trusted and matched?  Any required name
      * checks are now performed internally in OpenSSL.
      */
-    if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) {
+    if (x509_err == X509_V_OK) {
        TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
        if (TLScontext->must_fail) {
            msg_panic("%s: cert valid despite trust init failure",
@@ -356,6 +357,13 @@ static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
                tls_dane_log(TLScontext);
            }
        }
+    } else if (TLS_MUST_MATCH(TLScontext->level) &&
+              x509_err == X509_V_ERR_HOSTNAME_MISMATCH) {
+       /*
+        * If the only error is a hostname mismatch, the certificate must have
+        * been trusted.
+        */
+       TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
     }
 
     /*
index 6725dc41e57ee2cf694977df4f4a3e3f74cb3e45..9c7191c456eeeb166064647023ce61452975112e 100644 (file)
 
 /* update_error_state - safely stash away error state */
 
-static void update_error_state(TLS_SESS_STATE *TLScontext, int depth,
-                                      X509 *errorcert, int errorcode)
+static void update_error_state(X509_STORE_CTX *ctx, TLS_SESS_STATE *TLScontext,
+                                 int depth, X509 *errorcert, int errorcode)
 {
-    /* No news is good news */
-    if (TLScontext->errordepth >= 0 && TLScontext->errordepth <= depth)
-       return;
+
+    /*
+     * Report the error that is closest to the leaf certificate, any errors
+     * higher up the chain are immaterial until the "inner" errors are fixed.
+     * 
+     * We special-case "X509_V_ERR_HOSTNAME_MISMATCH" (at depth 0) in order to
+     * distinguish between untrusted certificates and trusted certificates
+     * with a hostname mismatch.  Any other error has a higher priority.
+     */
+    if (TLScontext->errordepth >= 0) {
+       if ((TLScontext->errordepth <= depth &&
+            TLScontext->errorcode != X509_V_ERR_HOSTNAME_MISMATCH) ||
+           errorcode == X509_V_ERR_HOSTNAME_MISMATCH) {
+           X509_STORE_CTX_set_error(ctx, TLScontext->errorcode);
+           return;
+       }
+    }
 
     /*
      * The certificate pointer is stable during the verification callback,
@@ -179,12 +193,12 @@ int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
     if (TLScontext->must_fail) {
        if (depth == 0) {
            X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_UNSPECIFIED);
-           update_error_state(TLScontext, depth, cert, err);
+           update_error_state(ctx, TLScontext, depth, cert, err);
        }
        return (1);
     }
     if (ok == 0)
-       update_error_state(TLScontext, depth, cert, err);
+       update_error_state(ctx, TLScontext, depth, cert, err);
 
     if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
        if (cert) {
index 5159d54a802c61ba21eb5b2132ed092decc57402..4084e234143ad465b5490135bcc30a6da372fdf7 100644 (file)
@@ -1267,6 +1267,12 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
     init_buf = vstring_alloc(100);
     init_key = tls_proxy_client_init_serialize(attr_print_plain, init_buf,
                                               init_props);
+#define TLSP_CLIENT_INIT_RETURN(retval) do { \
+       vstring_free(init_buf); \
+       vstring_free(param_buf); \
+       return (retval); \
+    } while (0)
+
     if (tlsp_pre_jail_done == 0) {
        if (tlsp_pre_jail_client_param_key == 0
            || tlsp_pre_jail_client_init_key == 0) {
@@ -1284,9 +1290,12 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
      * TLS_APPL_STATE instance; this makes a mismatch of TLS_CLIENT_PARAMS
      * settings problematic.
      */
-    if (tlsp_pre_jail_done
-       && !been_here_fixed(tlsp_params_mismatch_filter, param_key)
-       && strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) {
+    else if (tlsp_pre_jail_client_param_key == 0
+            || tlsp_pre_jail_client_init_key == 0) {
+       msg_warn("TLS client role is disabled by configuration");
+       TLSP_CLIENT_INIT_RETURN(0);
+    } else if (!been_here_fixed(tlsp_params_mismatch_filter, param_key)
+              && strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) {
        msg_warn("request from tlsproxy client with unexpected settings");
        tlsp_log_config_diff(tlsp_pre_jail_client_param_key, param_key);
        log_hints = 1;
@@ -1361,9 +1370,7 @@ static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params,
                         SSL_MODE_ENABLE_PARTIAL_WRITE
                         | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
     }
-    vstring_free(init_buf);
-    vstring_free(param_buf);
-    return (appl_state);
+    TLSP_CLIENT_INIT_RETURN(appl_state);
 }
 
 /* tlsp_close_event - pre-handshake plaintext-client close event */
@@ -1497,6 +1504,7 @@ static void tlsp_get_request_event(int event, void *context)
                                TLSP_INIT_TIMEOUT, (void *) state);
        return;
     } else {
+       state->flags |= TLSP_FLAG_DO_HANDSHAKE;
        tlsp_request_read_event(plaintext_fd, tlsp_get_fd_event,
                                TLSP_INIT_TIMEOUT, (void *) state);
        return;
index df6cbda1de0dd4b4c367cc55df665f87813c8db9..4a08d17fedd2016be9d5d59f3760c44709611e9a 100644 (file)
@@ -105,7 +105,7 @@ TLSP_STATE *tlsp_state_create(const char *service,
 {
     TLSP_STATE *state = (TLSP_STATE *) mymalloc(sizeof(*state));
 
-    state->flags = TLSP_FLAG_DO_HANDSHAKE;
+    state->flags = 0;
     state->service = mystrdup(service);
     state->plaintext_stream = plaintext_stream;
     state->plaintext_buf = 0;
index 35c02db050195afa4bc8aa53d4bbef36aa998a67..3a553f8ceb9735c04c2201c7dc175ba96c5b4e98 100644 (file)
 /* .IP "char *context"
 /*     Application context from the caller.
 /* .PP
-/*     dict_changed_name() returns non-zero when any dictionary needs to
-/*     be re-opened because it has changed or because it was unlinked.
+/*     dict_changed_name() returns non-zero when any dictionary is
+/*     opened read-only and has changed, or because it was unlinked.
 /*     A non-zero result is the name of a changed dictionary.
 /*
 /*     dict_load_file_xt() reads name-value entries from the named file.
@@ -601,11 +601,12 @@ const char *dict_changed_name(void)
        dict = ((DICT_NODE *) h->value)->dict;
        if (dict->stat_fd < 0)                  /* not file-based */
            continue;
-       if (dict->mtime == 0)                   /* not bloody likely */
-           msg_warn("%s: table %s: null time stamp", myname, h->key);
+       if (dict->mtime < 0)                    /* not bloody likely */
+           msg_warn("%s: table %s: negative time stamp", myname, h->key);
        if (fstat(dict->stat_fd, &st) < 0)
            msg_fatal("%s: fstat: %m", myname);
        if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
+            && dict->mtime > 0
             && st.st_mtime != dict->mtime)
            || st.st_nlink == 0)
            status = h->key;
index b2d0c336f3bc441a88d86a9efa3404363b6d094b..0a760c6b9963cd075dfd4abf38a87c49567a69cc 100644 (file)
@@ -789,7 +789,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
     dict_db->dict.stat_fd = dbfd;
     if (fstat(dict_db->dict.stat_fd, &st) < 0)
        msg_fatal("dict_db_open: fstat: %m");
-    dict_db->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_db->dict.mtime = st.st_mtime;
     dict_db->dict.owner.uid = st.st_uid;
     dict_db->dict.owner.status = (st.st_uid != 0);
 
index e47b7eedff978df23c35ba622343df59d084c2c6..b3bbe8510adbb5111b8cd1bc014f275fd22420e8 100644 (file)
@@ -472,7 +472,8 @@ DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
        msg_fatal("open database %s: cannot support GDBM", path);
     if (fstat(dict_dbm->dict.stat_fd, &st) < 0)
        msg_fatal("dict_dbm_open: fstat: %m");
-    dict_dbm->dict.mtime = st.st_mtime;
+    if (open_mode == O_RDONLY)
+       dict_dbm->dict.mtime = st.st_mtime;
     dict_dbm->dict.owner.uid = st.st_uid;
     dict_dbm->dict.owner.status = (st.st_uid != 0);
 
index bed20e0c450c1571b4fd33a6d389ffb753774fc8..6f4f276ca529648b2e3bf9b68887e036ed33545a 100644 (file)
@@ -653,7 +653,8 @@ DICT   *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
        msg_fatal("dict_lmdb_open: fstat: %m");
     dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd;
     dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL;
-    dict_lmdb->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_lmdb->dict.mtime = st.st_mtime;
     dict_lmdb->dict.owner.uid = st.st_uid;
     dict_lmdb->dict.owner.status = (st.st_uid != 0);
 
index 23371dc7c72efd46df8d0da70d6eafa981af7e9b..fcb2556e8c09bc7534afe443e3e6d190968d2fc5 100644 (file)
@@ -449,7 +449,8 @@ DICT   *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
     dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
     if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
        msg_fatal("dict_sdbm_open: fstat: %m");
-    dict_sdbm->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_sdbm->dict.mtime = st.st_mtime;
     dict_sdbm->dict.owner.uid = st.st_uid;
     dict_sdbm->dict.owner.status = (st.st_uid != 0);