[exim-cvs] Support REQUIRETLS

Inizio della pagina
Delete this message
Reply to this message
Autore: Exim Git Commits Mailing List
Data:  
To: exim-cvs
Oggetto: [exim-cvs] Support REQUIRETLS
Gitweb: https://git.exim.org/exim.git/commitdiff/8ac90765750f87c573300b9e953af3d8090cab8b
Commit:     8ac90765750f87c573300b9e953af3d8090cab8b
Parent:     8d3dc2397dd769bf4654b0678be8d2acf0956ddd
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Fri Jul 27 17:56:39 2018 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Jul 27 17:56:39 2018 +0100


    Support REQUIRETLS
---
 doc/doc-docbook/spec.xfpt             |  11 ++-
 doc/doc-txt/NewStuff                  |   2 +
 doc/doc-txt/OptionLists.txt           |   1 +
 doc/doc-txt/experimental-spec.txt     |  31 ++++++++
 src/src/EDITME                        |   5 ++
 src/src/acl.c                         |  20 +++++
 src/src/child.c                       |  21 +++++-
 src/src/config.h.defaults             |   1 +
 src/src/deliver.c                     |   5 ++
 src/src/exim.c                        |  15 +++-
 src/src/expand.c                      |   3 +
 src/src/globals.c                     |   5 ++
 src/src/globals.h                     |   5 ++
 src/src/host.c                        |   2 +-
 src/src/macro_predef.c                |   3 +
 src/src/macros.h                      |   8 ++
 src/src/readconf.c                    |   3 +
 src/src/routers/dnslookup.c           |   4 +-
 src/src/smtp_in.c                     |  86 +++++++++++++++++++---
 src/src/spool_in.c                    |  39 ++++++----
 src/src/spool_out.c                   |   6 +-
 src/src/tls-openssl.c                 |   2 +-
 src/src/transports/smtp.c             |  74 +++++++++++++++++--
 src/src/transports/smtp.h             |   4 +-
 src/src/verify.c                      |  14 +++-
 test/aux-var-src/tls_conf_prefix      |   4 +
 test/confs/0900                       |   7 +-
 test/confs/2108                       |   1 -
 test/confs/5650                       |   2 +-
 test/confs/5910                       | 133 ++++++++++++++++++++++++++++++++++
 test/confs/5911                       |   1 +
 test/confs/5912                       |   1 +
 test/log/5910                         |  23 ++++++
 test/log/5911                         |  72 ++++++++++++++++++
 test/log/5912                         |  10 +++
 test/mail/3700.smtps                  |   2 +-
 test/mail/3700.x                      |   2 +-
 test/mail/5910.dump                   |  20 +++++
 test/mail/5911.CALLER                 |  62 ++++++++++++++++
 test/rejectlog/5911                   |   3 +
 test/rejectlog/5912                   |   2 +
 test/runtest                          |  13 +++-
 test/scripts/4500-DKIM/4521           |   6 +-
 test/scripts/5650-OCSP-GnuTLS/5650    |   8 +-
 test/scripts/5910-REQUIRETLS/5910     |  64 ++++++++++++++++
 test/scripts/5910-REQUIRETLS/5911     | 125 ++++++++++++++++++++++++++++++++
 test/scripts/5910-REQUIRETLS/5912     |  37 ++++++++++
 test/scripts/5910-REQUIRETLS/REQUIRES |   2 +
 test/stdout/5910                      |  60 +++++++++++++++
 test/stdout/5911                      | 101 ++++++++++++++++++++++++++
 test/stdout/5912                      |  22 ++++++
 51 files changed, 1093 insertions(+), 60 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 21c4943..d0e3358 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -3966,8 +3966,17 @@ the messages are active, their status is not altered. This option can be used
only by an admin user or by the user who originally caused the message to be
placed on the queue.

+. .new
+. .vitem &%-MS%&
+. .oindex "&%-MS%&"
+. .cindex REQUIRETLS
+. This option is used to request REQUIRETLS processing on the message.
+. It is used internally by Exim in conjunction with -E when generating
+. a bounce message.
+. .wen
+
 .vitem &%-Mset%&&~<&'message&~id'&>
-.oindex "&%-Mset%&
+.oindex "&%-Mset%&"
 .cindex "testing" "string expansion"
 .cindex "expansion" "testing"
 This option is useful only in conjunction with &%-be%& (that is, when testing
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 7c922cc..4039895 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -17,6 +17,8 @@ Version 4.92
  2. The ${readsocket } expansion item now takes a "tls" option, doing the
     obvious thing.


+ 3. EXPERIMENTAL_REQUIRETLS. See the experimental.spec file.
+
Version 4.91
--------------

diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt
index 0a6a320..05e47c0 100644
--- a/doc/doc-txt/OptionLists.txt
+++ b/doc/doc-txt/OptionLists.txt
@@ -569,6 +569,7 @@ timeout_defer                        boolean         false         pipe
 timeout_frozen_after                 time            0s            main              3.20
 timezone                             string          +             main              3.15
 tls_advertise_hosts                  host list       *             main              3.20
+tls_advertise_requiretls             host list       *             main              4.92 if experimental_requiretls
 tls_certificate                      string*         unset         main              3.20
                                                      unset         smtp              3.20
 tls_dh_max_bits                      integer         2236          main              4.80
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index aa93e07..43f1423 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -860,6 +860,37 @@ used via the transport in question.




+
+REQUIRETLS support
+------------------
+Ref: https://tools.ietf.org/html/draft-ietf-uta-smtp-require-tls-03
+
+If compiled with EXPERIMENTAL_REQUIRETLS support is included for this
+feature, where a REQUIRETLS option is added to the MAIL command.
+The client may not retry in clear if the MAIL+REQUIRETLS fails (or was never
+offered), and the server accepts an obligation that any onward transmission
+by SMTP of the messages accepted will also use REQUIRETLS - or generate a
+fail DSN.
+
+The Exim implementation includes
+- a main-part option tls_advertise_requiretls; host list, default "*"
+- an observability variable $requiretls returning yes/no
+- an ACL "control = requiretls" modifier for setting the requirement
+- Log lines and Received: headers capitalise the S in the protocol
+ element: "P=esmtpS"
+
+Differences from spec:
+- we support upgrading the requirement for REQUIRETLS, including adding
+ it from cold, withing an MTA. The spec only define the sourcing MUA
+ as being able to source the requirement, and makes no mention of upgrade.
+- No support is coded for the RequireTLS header (which can be used
+ to annul DANE and/or STS policiy). [can this be done in ACL?]
+
+Note that REQUIRETLS is only advertised once a TLS connection is acheived
+(in contrast to STARTTLS). If you want to check the advertising, do something
+like "swaks -s 127.0.0.1 -tls -q HELO".
+
+
--------------------------------------------------------------
End of file
--------------------------------------------------------------
diff --git a/src/src/EDITME b/src/src/EDITME
index bd5151d..cbb0805 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -511,6 +511,11 @@ DISABLE_MAL_MKS=yes
# Uncomment the following line to add queuefile transport support
# EXPERIMENTAL_QUEUEFILE=yes

+# Uncomment the following to add REQUIRETLS support.
+# You must also have SUPPORT_TLS enabled.
+# Ref: https://datatracker.ietf.org/doc/draft-fenton-smtp-require-tls
+# EXPERIMENTAL_REQUIRETLS=yes
+
 ###############################################################################
 #                 THESE ARE THINGS YOU MIGHT WANT TO SPECIFY                  #
 ###############################################################################
diff --git a/src/src/acl.c b/src/src/acl.c
index 1fa5c1f..4f335df 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -367,6 +367,9 @@ enum {
   CONTROL_NO_PIPELINING,


   CONTROL_QUEUE_ONLY,
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+  CONTROL_REQUIRETLS,
+#endif
   CONTROL_SUBMISSION,
   CONTROL_SUPPRESS_LOCAL_FIXUPS,
 #ifdef SUPPORT_I18N
@@ -510,6 +513,18 @@ static control_def controls_list[] = {
         // ACL_BIT_PRDR|    /* Not allow one user to freeze for all */
         ACL_BIT_NOTSMTP | ACL_BIT_MIME)
   },
+
+
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+[CONTROL_REQUIRETLS] =
+  { US"requiretls",         FALSE,
+      (unsigned)
+      ~(ACL_BIT_MAIL | ACL_BIT_RCPT | ACL_BIT_PREDATA |
+        ACL_BIT_DATA | ACL_BIT_MIME |
+        ACL_BIT_NOTSMTP)
+  },
+#endif
+
 [CONTROL_SUBMISSION] =
   { US"submission",              TRUE,
       (unsigned)
@@ -3163,6 +3178,11 @@ for (; cb; cb = cb->next)
     cancel_cutthrough_connection(TRUE, US"queueing forced");
     break;


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    case CONTROL_REQUIRETLS:
+    tls_requiretls |= REQUIRETLS_MSG;
+    break;
+#endif
     case CONTROL_SUBMISSION:
     originator_name = US"";
     submission_mode = TRUE;
diff --git a/src/src/child.c b/src/src/child.c
index de12c44..ad625ae 100644
--- a/src/src/child.c
+++ b/src/src/child.c
@@ -10,6 +10,10 @@


static void (*oldsignal)(int);

+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+static uschar tls_requiretls_copy = 0;
+#endif
+

 /*************************************************
 *          Ensure an fd has a given value        *
@@ -73,8 +77,13 @@ child_exec_exim(int exec_type, BOOL kill_v, int *pcount, BOOL minimal,
 int first_special = -1;
 int n = 0;
 int extra = pcount ? *pcount : 0;
-uschar **argv =
-  store_get((extra + acount + MAX_CLMACROS + 18) * sizeof(char *));
+uschar **argv;
+
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+if (tls_requiretls) extra++;
+#endif
+
+argv = store_get((extra + acount + MAX_CLMACROS + 18) * sizeof(char *));


 /* In all case, the list starts out with the path, any macros, and a changed
 config file. */
@@ -120,6 +129,11 @@ if (!minimal)
     }
   }


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+if (tls_requiretls_copy & REQUIRETLS_MSG)
+ argv[n++] = US"-MS";
+#endif
+
/* Now add in any others that are in the call. Remember which they were,
for more helpful diagnosis on failure. */

@@ -229,6 +243,9 @@ occur. */

 if (pid == 0)
   {
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+  tls_requiretls_copy = tls_requiretls;
+#endif
   force_fd(pfd[pipe_read], 0);
   (void)close(pfd[pipe_write]);
   if (debug_fd > 0) force_fd(debug_fd, 2);
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 0f348fa..4fb30dd 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -198,6 +198,7 @@ Do not put spaces between # and the 'define'.
 #define EXPERIMENTAL_DMARC
     #define DMARC_TLD_FILE "/etc/exim/opendmarc.tlds"
 #define EXPERIMENTAL_LMDB
+#define EXPERIMENTAL_REQUIRETLS
 #define EXPERIMENTAL_QUEUEFILE
 #define EXPERIMENTAL_SRS


diff --git a/src/src/deliver.c b/src/src/deliver.c
index 68152d5..0b9e551 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -8454,6 +8454,11 @@ if (!regex_AUTH) regex_AUTH =
#ifdef SUPPORT_TLS
if (!regex_STARTTLS) regex_STARTTLS =
regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
+
+# ifdef EXPERIMENTAL_REQUIRETLS
+if (!regex_REQUIRETLS) regex_REQUIRETLS =
+ regex_must_compile(US"\\n250[\\s\\-]REQUIRETLS(\\s|\\n|$)", FALSE, TRUE);
+# endif
#endif

if (!regex_CHUNKING) regex_CHUNKING =
diff --git a/src/src/exim.c b/src/src/exim.c
index 2b4ecbc..1410359 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -898,6 +898,9 @@ fprintf(f, "Support for:");
#ifdef EXPERIMENTAL_DSN_INFO
fprintf(f, " Experimental_DSN_info");
#endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+ fprintf(f, " Experimental_REQUIRETLS");
+#endif
fprintf(f, "\n");

fprintf(f, "Lookups (built-in):");
@@ -2783,9 +2786,19 @@ for (i = 1; i < argc; i++)

     default:  badarg = TRUE; break;
     }
-    break;
+      break;
       }


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    /* -MS   set REQUIRETLS on (new) message */
+
+    else if (*argrest == 'S')
+      {
+      tls_requiretls |= REQUIRETLS_MSG;
+      break;
+      }
+#endif
+
     /* -M[x]: various operations on the following list of message ids:
        -M    deliver the messages, ignoring next retry times and thawing
        -Mc   deliver the messages, checking next retry times, no thawing
diff --git a/src/src/expand.c b/src/src/expand.c
index 2feaf95..b6ff96a 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -660,6 +660,9 @@ static var_entry var_table[] = {
   { "regex_match_string",  vtype_stringptr,   &regex_match_string },
 #endif
   { "reply_address",       vtype_reply,       NULL },
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+  { "requiretls",          vtype_bool,        &tls_requiretls },
+#endif
   { "return_path",         vtype_stringptr,   &return_path },
   { "return_size_limit",   vtype_int,         &bounce_return_size_limit },
   { "router_name",         vtype_stringptr,   &router_name },
diff --git a/src/src/globals.c b/src/src/globals.c
index 3fa0e3e..10045f4 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -161,6 +161,11 @@ uschar *tls_ocsp_file          = NULL;
 uschar *tls_privatekey         = NULL;
 BOOL    tls_remember_esmtp     = FALSE;
 uschar *tls_require_ciphers    = NULL;
+# ifdef EXPERIMENTAL_REQUIRETLS
+uschar  tls_requiretls         = 0;    /* REQUIRETLS_MSG etc. bit #defines */
+uschar *tls_advertise_requiretls = US"*";
+const pcre *regex_REQUIRETLS   = NULL;
+# endif
 uschar *tls_try_verify_hosts   = NULL;
 uschar *tls_verify_certificates= US"system";
 uschar *tls_verify_hosts       = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index ef5b3a5..b28aa5e 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -120,6 +120,11 @@ extern uschar *tls_eccurve;            /* EC curve */
 extern uschar *tls_ocsp_file;          /* OCSP stapling proof file */
 # endif
 extern uschar *tls_privatekey;         /* Private key file */
+# ifdef EXPERIMENTAL_REQUIRETLS
+extern uschar  tls_requiretls;         /* REQUIRETLS active for this message */
+extern uschar *tls_advertise_requiretls; /* hosts for which REQUIRETLS adv */
+extern const pcre *regex_REQUIRETLS;   /* for recognising the command */
+# endif
 extern BOOL    tls_remember_esmtp;     /* For YAEB */
 extern uschar *tls_require_ciphers;    /* So some can be avoided */
 extern uschar *tls_try_verify_hosts;   /* Optional client verification */
diff --git a/src/src/host.c b/src/src/host.c
index d426742..7118221 100644
--- a/src/src/host.c
+++ b/src/src/host.c
@@ -2859,7 +2859,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
   block. Otherwise, add a new block in the correct place; if it has to be
   before the first block, copy the first block's data to a new second block. */


-  if (last == NULL)
+  if (!last)
     {
     host->name = string_copy_dnsdomain(data);
     host->address = NULL;
diff --git a/src/src/macro_predef.c b/src/src/macro_predef.c
index 32c05a8..1073e45 100644
--- a/src/src/macro_predef.c
+++ b/src/src/macro_predef.c
@@ -198,6 +198,9 @@ due to conflicts with other common macros. */
 #ifdef EXPERIMENTAL_DSN_INFO
   builtin_macro_create(US"_HAVE_DSN_INFO");
 #endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+  builtin_macro_create(US"_HAVE_REQTLS");
+#endif


 #ifdef LOOKUP_LSEARCH
   builtin_macro_create(US"_HAVE_LOOKUP_LSEARCH");
diff --git a/src/src/macros.h b/src/src/macros.h
index f22fe8c..e755034 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -550,6 +550,9 @@ table exim_errstrings[] in log.c */
 #ifdef SUPPORT_I18N
 # define ERRNO_UTF8_FWD      (-49)   /* target not supporting SMTPUTF8 */
 #endif
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+# define ERRNO_REQUIRETLS    (-50)   /* REQUIRETLS session not started */
+#endif


/* These must be last, so all retry deferments can easily be identified */

@@ -1014,6 +1017,11 @@ enum { FILTER_UNSET, FILTER_FORWARD, FILTER_EXIM, FILTER_SIEVE };
 #define OPTION_PIPE    BIT(5)
 #define OPTION_SIZE    BIT(6)
 #define OPTION_CHUNKING    BIT(7)
+#define OPTION_REQUIRETLS BIT(8)
+
+/* Codes for tls_requiretls requests (usually by sender) */
+
+#define REQUIRETLS_MSG        BIT(0)    /* REQUIRETLS onward use */


/* Argument for *_getc */

diff --git a/src/src/readconf.c b/src/src/readconf.c
index 3f307fd..fbf6d6b 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -348,6 +348,9 @@ static optionlist optionlist_config[] = {
   { "timezone",                 opt_stringptr,   &timezone_string },
   { "tls_advertise_hosts",      opt_stringptr,   &tls_advertise_hosts },
 #ifdef SUPPORT_TLS
+# ifdef EXPERIMENTAL_REQUIRETLS
+  { "tls_advertise_requiretls", opt_stringptr,   &tls_advertise_requiretls },
+# endif
   { "tls_certificate",          opt_stringptr,   &tls_certificate },
   { "tls_crl",                  opt_stringptr,   &tls_crl },
   { "tls_dh_max_bits",          opt_int,         &tls_dh_max_bits },
diff --git a/src/src/routers/dnslookup.c b/src/src/routers/dnslookup.c
index 6ab08d7..a3b0d35 100644
--- a/src/src/routers/dnslookup.c
+++ b/src/src/routers/dnslookup.c
@@ -300,7 +300,9 @@ for (;;)


   rc = host_find_bydns(&h, CUS rblock->ignore_target_hosts, flags,
     srv_service, ob->srv_fail_domains, ob->mx_fail_domains,
-    &rblock->dnssec, &fully_qualified_name, &removed);
+    &rblock->dnssec,
+    &fully_qualified_name, &removed);
+
   if (removed) setflag(addr, af_local_host_removed);


   /* If host found with only address records, test for the domain's being in
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index ff0f6ac..d1c19ea 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -135,6 +135,9 @@ static auth_instance *authenticated_by;
 static BOOL auth_advertised;
 #ifdef SUPPORT_TLS
 static BOOL tls_advertised;
+# ifdef EXPERIMENTAL_REQUIRETLS
+static BOOL requiretls_advertised;
+# endif
 #endif
 static BOOL dsn_advertised;
 static BOOL esmtp;
@@ -256,6 +259,9 @@ enum {
 #ifdef SUPPORT_I18N
   ENV_MAIL_OPT_UTF8,
 #endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+  ENV_MAIL_OPT_REQTLS,
+#endif
   };
 typedef struct {
   uschar *   name;  /* option requested during MAIL cmd */
@@ -275,6 +281,10 @@ static env_mail_type_t env_mail_type_list[] = {
 #ifdef SUPPORT_I18N
     { US"SMTPUTF8",ENV_MAIL_OPT_UTF8,  FALSE },        /* rfc6531 */
 #endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+    /* https://tools.ietf.org/html/draft-ietf-uta-smtp-require-tls-03 */
+    { US"REQUIRETLS",ENV_MAIL_OPT_REQTLS,  FALSE },
+#endif
     /* keep this the last entry */
     { US"NULL",   ENV_MAIL_OPT_NULL,   FALSE },
   };
@@ -2437,6 +2447,9 @@ tls_in.ourcert = tls_in.peercert = NULL;
 tls_in.sni = NULL;
 tls_in.ocsp = OCSP_NOT_REQ;
 tls_advertised = FALSE;
+# ifdef EXPERIMENTAL_REQUIRETLS
+requiretls_advertised = FALSE;
+# endif
 #endif
 dsn_advertised = FALSE;
 #ifdef SUPPORT_I18N
@@ -4172,6 +4185,9 @@ while (done <= 0)
     pipelining_advertised = FALSE;
 #ifdef SUPPORT_TLS
     tls_advertised = FALSE;
+# ifdef EXPERIMENTAL_REQUIRETLS
+    requiretls_advertised = FALSE;
+# endif
 #endif
     dsn_advertised = FALSE;
 #ifdef SUPPORT_I18N
@@ -4371,6 +4387,17 @@ while (done <= 0)
         g = string_catn(g, US"-STARTTLS\r\n", 11);
         tls_advertised = TRUE;
         }
+
+# ifdef EXPERIMENTAL_REQUIRETLS
+      /* Advertise REQUIRETLS only once we are in a secure connection */
+      if (  tls_in.active.sock >= 0
+         && verify_check_host(&tls_advertise_requiretls) != FAIL)
+    {
+    g = string_catn(g, smtp_code, 3);
+    g = string_catn(g, US"-REQUIRETLS\r\n", 13);
+    requiretls_advertised = TRUE;
+    }
+# endif
 #endif


 #ifndef DISABLE_PRDR
@@ -4453,14 +4480,14 @@ while (done <= 0)
       break;
       }


-    if (sender_address != NULL)
+    if (sender_address)
       {
       done = synprot_error(L_smtp_protocol_error, 503, NULL,
         US"sender already given");
       break;
       }


-    if (smtp_cmd_data[0] == 0)
+    if (!*smtp_cmd_data)
       {
       done = synprot_error(L_smtp_protocol_error, 501, NULL,
         US"MAIL must have an address operand");
@@ -4557,7 +4584,7 @@ while (done <= 0)
             /* Check if RET has already been set */
             if (dsn_ret > 0)
           {
-              synprot_error(L_smtp_syntax_error, 501, NULL,
+              done = synprot_error(L_smtp_syntax_error, 501, NULL,
                 US"RET can be specified once only");
               goto COMMAND_LOOP;
           }
@@ -4570,7 +4597,7 @@ while (done <= 0)
             /* Check for invalid invalid value, and exit with error */
             if (dsn_ret == 0)
           {
-              synprot_error(L_smtp_syntax_error, 501, NULL,
+              done = synprot_error(L_smtp_syntax_error, 501, NULL,
                 US"Value for RET is invalid");
               goto COMMAND_LOOP;
           }
@@ -4582,7 +4609,7 @@ while (done <= 0)
             /* Check if the dsn envid has been already set */
             if (dsn_envid)
           {
-              synprot_error(L_smtp_syntax_error, 501, NULL,
+              done = synprot_error(L_smtp_syntax_error, 501, NULL,
                 US"ENVID can be specified once only");
               goto COMMAND_LOOP;
           }
@@ -4671,7 +4698,7 @@ while (done <= 0)
         case ENV_MAIL_OPT_UTF8:
       if (!smtputf8_advertised)
         {
-        synprot_error(L_smtp_syntax_error, 501, NULL,
+        done = synprot_error(L_smtp_syntax_error, 501, NULL,
           US"SMTPUTF8 used when not advertised");
         goto COMMAND_LOOP;
         }
@@ -4687,6 +4714,32 @@ while (done <= 0)
         }
       break;
 #endif
+
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+        case ENV_MAIL_OPT_REQTLS:
+      {
+      const uschar * list = value;
+      int sep = ',';
+      const uschar * opt;
+      uschar * r, * t;
+
+      if (!requiretls_advertised)
+        {
+        done = synprot_error(L_smtp_syntax_error, 555, NULL,
+          US"unadvertised MAIL option: REQUIRETLS");
+        goto COMMAND_LOOP;
+        }
+
+      DEBUG(D_receive) debug_printf("requiretls requested\n");
+      tls_requiretls = REQUIRETLS_MSG;
+
+      r = string_copy_malloc(received_protocol);
+      if ((t = Ustrrchr(r, 's'))) *t = 'S';
+      received_protocol = r;
+      }
+      break;
+#endif
+
         /* No valid option. Stick back the terminator characters and break
         the loop.  Do the name-terminator second as extract_option sets
         value==name when it found no equal-sign.
@@ -4704,6 +4757,17 @@ while (done <= 0)
       if (arg_error) break;
       }


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    if (tls_requiretls & REQUIRETLS_MSG)
+      {
+      /* Ensure headers-only bounces whether a RET option was given or not. */
+
+      DEBUG(D_receive) if (dsn_ret == dsn_ret_full)
+    debug_printf("requiretls override: dsn_ret_full -> dsn_ret_hdrs\n");
+      dsn_ret = dsn_ret_hdrs;
+      }
+#endif
+
     /* If we have passed the threshold for rate limiting, apply the current
     delay, and update it for next time, provided this is a limited host. */


@@ -4780,8 +4844,7 @@ while (done <= 0)
     in which case just qualify the address. The flag is set above at the start
     of the SMTP connection. */


-    if (sender_domain == 0 && sender_address[0] != 0)
-      {
+    if (!sender_domain && *sender_address)
       if (allow_unqualified_sender)
         {
         sender_domain = Ustrlen(sender_address) + 1;
@@ -4802,7 +4865,6 @@ while (done <= 0)
         sender_address = NULL;
         break;
         }
-      }


     /* Apply an ACL check if one is defined, before responding. Afterwards,
     when pipelining is not advertised, do another sync check in case the ACL
@@ -4907,7 +4969,7 @@ while (done <= 0)
         /* Check whether orcpt has been already set */
         if (orcpt)
       {
-          synprot_error(L_smtp_syntax_error, 501, NULL,
+          done = synprot_error(L_smtp_syntax_error, 501, NULL,
             US"ORCPT can be specified once only");
           goto COMMAND_LOOP;
           }
@@ -4920,7 +4982,7 @@ while (done <= 0)
         /* Check if the notify flags have been already set */
         if (flags > 0)
       {
-          synprot_error(L_smtp_syntax_error, 501, NULL,
+          done = synprot_error(L_smtp_syntax_error, 501, NULL,
               US"NOTIFY can be specified once only");
           goto COMMAND_LOOP;
           }
@@ -4952,7 +5014,7 @@ while (done <= 0)
             else
           {
               /* Catch any strange values */
-              synprot_error(L_smtp_syntax_error, 501, NULL,
+              done = synprot_error(L_smtp_syntax_error, 501, NULL,
                 US"Invalid value for NOTIFY parameter");
               goto COMMAND_LOOP;
               }
diff --git a/src/src/spool_in.c b/src/src/spool_in.c
index cd74d1e..0b3490b 100644
--- a/src/src/spool_in.c
+++ b/src/src/spool_in.c
@@ -287,6 +287,9 @@ tls_free_cert(&tls_in.peercert);
 tls_in.peerdn = NULL;
 tls_in.sni = NULL;
 tls_in.ocsp = OCSP_NOT_REQ;
+# if defined(EXPERIMENTAL_REQUIRETLS) && !defined(COMPILE_UTILITY)
+tls_requiretls = 0;
+# endif
 #endif


#ifdef WITH_CONTENT_SCAN
@@ -649,22 +652,30 @@ for (;;)

 #ifdef SUPPORT_TLS
     case 't':
-    if (Ustrncmp(p, "ls_certificate_verified", 23) == 0)
-      tls_in.certificate_verified = TRUE;
-    else if (Ustrncmp(p, "ls_cipher", 9) == 0)
-      tls_in.cipher = string_copy(big_buffer + 12);
+    if (Ustrncmp(p, "ls_", 3) == 0)
+      {
+      uschar * q = p + 3;
+      if (Ustrncmp(q, "certificate_verified", 20) == 0)
+    tls_in.certificate_verified = TRUE;
+      else if (Ustrncmp(q, "cipher", 6) == 0)
+    tls_in.cipher = string_copy(big_buffer + 12);
 # ifndef COMPILE_UTILITY    /* tls support fns not built in */
-    else if (Ustrncmp(p, "ls_ourcert", 10) == 0)
-      (void) tls_import_cert(big_buffer + 13, &tls_in.ourcert);
-    else if (Ustrncmp(p, "ls_peercert", 11) == 0)
-      (void) tls_import_cert(big_buffer + 14, &tls_in.peercert);
+      else if (Ustrncmp(q, "ourcert", 7) == 0)
+    (void) tls_import_cert(big_buffer + 13, &tls_in.ourcert);
+      else if (Ustrncmp(q, "peercert", 8) == 0)
+    (void) tls_import_cert(big_buffer + 14, &tls_in.peercert);
 # endif
-    else if (Ustrncmp(p, "ls_peerdn", 9) == 0)
-      tls_in.peerdn = string_unprinting(string_copy(big_buffer + 12));
-    else if (Ustrncmp(p, "ls_sni", 6) == 0)
-      tls_in.sni = string_unprinting(string_copy(big_buffer + 9));
-    else if (Ustrncmp(p, "ls_ocsp", 7) == 0)
-      tls_in.ocsp = big_buffer[10] - '0';
+      else if (Ustrncmp(q, "peerdn", 6) == 0)
+    tls_in.peerdn = string_unprinting(string_copy(big_buffer + 12));
+      else if (Ustrncmp(q, "sni", 3) == 0)
+    tls_in.sni = string_unprinting(string_copy(big_buffer + 9));
+      else if (Ustrncmp(q, "ocsp", 4) == 0)
+    tls_in.ocsp = big_buffer[10] - '0';
+# if defined(EXPERIMENTAL_REQUIRETLS) && !defined(COMPILE_UTILITY)
+      else if (Ustrncmp(q, "requiretls", 10) == 0)
+    tls_requiretls = strtol(CS big_buffer+16, NULL, 0);
+# endif
+      }
     break;
 #endif


diff --git a/src/src/spool_out.c b/src/src/spool_out.c
index a6ab375..52f079c 100644
--- a/src/src/spool_out.c
+++ b/src/src/spool_out.c
@@ -252,6 +252,10 @@ if (tls_in.ourcert)
   fprintf(f, "-tls_ourcert %s\n", CS big_buffer);
   }
 if (tls_in.ocsp)     fprintf(f, "-tls_ocsp %d\n",   tls_in.ocsp);
+
+# ifdef EXPERIMENTAL_REQUIRETLS
+if (tls_requiretls)     fprintf(f, "-tls_requiretls 0x%x\n", tls_requiretls);
+# endif
 #endif


#ifdef SUPPORT_I18N
@@ -267,7 +271,7 @@ if (message_smtputf8)
DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_envid %s\n", dsn_envid);
if (dsn_envid) fprintf(f, "-dsn_envid %s\n", dsn_envid);
DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_ret %d\n", dsn_ret);
-if (dsn_ret != 0) fprintf(f, "-dsn_ret %d\n", dsn_ret);
+if (dsn_ret) fprintf(f, "-dsn_ret %d\n", dsn_ret);

 /* To complete the envelope, write out the tree of non-recipients, followed by
 the list of recipients. These won't be disjoint the first time, when no
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index d8c8101..9e1fc91 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -2156,7 +2156,7 @@ int rc;
 if (  (  !ob->tls_verify_hosts
       && (!ob->tls_try_verify_hosts || !*ob->tls_try_verify_hosts)
       )
-   || (verify_check_given_host(&ob->tls_verify_hosts, host) == OK)
+   || verify_check_given_host(&ob->tls_verify_hosts, host) == OK
    )
   client_verify_optional = FALSE;
 else if (verify_check_given_host(&ob->tls_try_verify_hosts, host) == OK)
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index ae4385a..08d1810 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1336,8 +1336,8 @@ return Ustrcmp(current_local_identity, message_local_identity) == 0;




-static uschar
-ehlo_response(uschar * buf, uschar checks)
+static unsigned
+ehlo_response(uschar * buf, unsigned checks)
{
size_t bsize = Ustrlen(buf);

@@ -1345,6 +1345,12 @@ size_t bsize = Ustrlen(buf);
 if (  checks & OPTION_TLS
    && pcre_exec(regex_STARTTLS, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
   checks &= ~OPTION_TLS;
+
+# ifdef EXPERIMENTAL_REQUIRETLS
+if (  checks & OPTION_REQUIRETLS
+   && pcre_exec(regex_REQUIRETLS, NULL, CS buf,bsize, 0, PCRE_EOPT, NULL,0) < 0)
+  checks &= ~OPTION_REQUIRETLS;
+# endif
 #endif


if ( checks & OPTION_IGNQ
@@ -1533,7 +1539,8 @@ sx->utf8_needed = FALSE;
sx->dsn_all_lasthop = TRUE;
#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
sx->dane = FALSE;
-sx->dane_required = verify_check_given_host(&sx->ob->hosts_require_dane, sx->host) == OK;
+sx->dane_required =
+ verify_check_given_host(&sx->ob->hosts_require_dane, sx->host) == OK;
#endif

 if ((sx->max_rcpt = sx->tblock->max_addresses) == 0) sx->max_rcpt = 999999;
@@ -2078,10 +2085,17 @@ else if (  sx->smtps
 # ifdef SUPPORT_DANE
     || sx->dane
 # endif
+# ifdef EXPERIMENTAL_REQUIRETLS
+    || tls_requiretls & REQUIRETLS_MSG
+# endif
     || verify_check_given_host(&sx->ob->hosts_require_tls, sx->host) == OK
     )
   {
-  errno = ERRNO_TLSREQUIRED;
+  errno =
+# ifdef EXPERIMENTAL_REQUIRETLS
+      tls_requiretls & REQUIRETLS_MSG ? ERRNO_REQUIRETLS :
+# endif
+      ERRNO_TLSREQUIRED;
   message = string_sprintf("a TLS session is required, but %s",
     smtp_peer_options & OPTION_TLS
     ? "an attempt to start TLS failed" : "the server did not offer TLS support");
@@ -2122,6 +2136,9 @@ if (continue_hostname == NULL
     | OPTION_DSN
     | OPTION_PIPE
     | (sx->ob->size_addition >= 0 ? OPTION_SIZE : 0)
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    | (tls_requiretls & REQUIRETLS_MSG ? OPTION_REQUIRETLS : 0)
+#endif
       );


     /* Set for IGNOREQUOTA if the response to LHLO specifies support and the
@@ -2166,6 +2183,16 @@ if (continue_hostname == NULL
     DEBUG(D_transport) debug_printf("%susing DSN\n",
             sx->peer_offered & OPTION_DSN ? "" : "not ");


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+    if (sx->peer_offered & OPTION_REQUIRETLS)
+      {
+      smtp_peer_options |= OPTION_REQUIRETLS;
+      DEBUG(D_transport) debug_printf(
+    tls_requiretls & REQUIRETLS_MSG
+    ? "using REQUIRETLS\n" : "REQUIRETLS offered\n");
+      }
+#endif
+
     /* Note if the response to EHLO specifies support for the AUTH extension.
     If it has, check that this host is one we want to authenticate to, and do
     the business. The host name and address must be available when the
@@ -2206,6 +2233,22 @@ if (sx->utf8_needed && !(sx->peer_offered & OPTION_UTF8))
   }
 #endif


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+  /*XXX should tls_requiretls actually be per-addr? */
+
+if (  tls_requiretls & REQUIRETLS_MSG
+   && !(sx->peer_offered & OPTION_REQUIRETLS)
+   )
+  {
+  sx->setting_up = TRUE;
+  errno = ERRNO_REQUIRETLS;
+  message = US"REQUIRETLS support is required from the server"
+    " but it was not offered";
+  DEBUG(D_transport) debug_printf("%s\n", message);
+  goto TLS_FAILED;
+  }
+#endif
+
 return OK;



@@ -2216,6 +2259,7 @@ return OK;
     message = NULL;
     sx->send_quit = check_response(sx->host, &errno, sx->addrlist->more_errno,
       sx->buffer, &code, &message, &pass_message);
+    yield = DEFER;
     goto FAILED;


   SEND_FAILED:
@@ -2223,6 +2267,7 @@ return OK;
     message = US string_sprintf("send() to %s [%s] failed: %s",
       sx->host->name, sx->host->address, strerror(errno));
     sx->send_quit = FALSE;
+    yield = DEFER;
     goto FAILED;


   EHLOHELO_FAILED:
@@ -2230,6 +2275,7 @@ return OK;
     message = string_sprintf("Remote host closed connection in response to %s"
       " (EHLO response was: %s)", smtp_command, sx->buffer);
     sx->send_quit = FALSE;
+    yield = DEFER;
     goto FAILED;


/* This label is jumped to directly when a TLS negotiation has failed,
@@ -2239,7 +2285,13 @@ return OK;

 #ifdef SUPPORT_TLS
   TLS_FAILED:
-    code = '4';
+# ifdef EXPERIMENTAL_REQUIRETLS
+    if (errno == ERRNO_REQUIRETLS)
+      code = '5', yield = FAIL;
+      /*XXX DSN will be labelled 500; prefer 530 5.7.4 */
+    else
+# endif
+      code = '4', yield = DEFER;
     goto FAILED;
 #endif


@@ -2272,7 +2324,6 @@ FAILED:
         , sx->smtp_greeting, sx->helo_response
 #endif
         );
-  yield = DEFER;
   }



@@ -2378,6 +2429,11 @@ if ( sx->peer_offered & OPTION_UTF8
Ustrcpy(p, " SMTPUTF8"), p += 9;
#endif

+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+if (tls_requiretls & REQUIRETLS_MSG)
+  Ustrcpy(p, " REQUIRETLS") , p += 11;
+#endif
+
 /* check if all addresses have DSN-lasthop flag; do not send RET and ENVID if so */
 for (sx->dsn_all_lasthop = TRUE, addr = addrlist, address_count = 0;
      addr && address_count < sx->max_rcpt;
@@ -3862,6 +3918,12 @@ same one in order to be passed to a single transport - or if the transport has
 a host list with hosts_override set, use the host list supplied with the
 transport. It is an error for this not to exist. */


+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+if (tls_requiretls & REQUIRETLS_MSG)
+  ob->tls_tempfail_tryclear = FALSE;    /*XXX surely we should have a local for this
+                      rather than modifying the transport? */
+#endif
+
 if (!hostlist || (ob->hosts_override && ob->hosts))
   {
   if (!ob->hosts)
diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h
index a33ef43..34c49d9 100644
--- a/src/src/transports/smtp.h
+++ b/src/src/transports/smtp.h
@@ -133,8 +133,8 @@ typedef struct {
   int        max_rcpt;
   int        cmd_count;


-  uschar    peer_offered;
-  uschar    avoid_option;
+  unsigned    peer_offered;
+  unsigned    avoid_option;
   uschar *    igquotstr;
   uschar *    helo_data;
 #ifdef EXPERIMENTAL_DSN_INFO
diff --git a/src/src/verify.c b/src/src/verify.c
index a892b05..35b21a5 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -172,7 +172,6 @@ else
     if (  cache_record->result == ccache_reject
        || *from_address == 0 && cache_record->result == ccache_reject_mfnull)
       {
-      setflag(addr, af_verify_nsfail);
       HDEBUG(D_verify)
     debug_printf("callout cache: domain gave initial rejection, or "
       "does not accept HELO or MAIL FROM:<>\n");
@@ -991,6 +990,13 @@ no_conn:
     }
     break;
 #endif
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+      case ERRNO_REQUIRETLS:
+        addr->user_message = US"530 5.7.4 REQUIRETLS support required";
+    yield = FAIL;
+    done = TRUE;
+    break;
+#endif
       case ECONNREFUSED:
     sx.send_quit = FALSE;
     break;
@@ -1901,16 +1907,16 @@ while (addr_new)
                 (void)host_find_byname(host, NULL, flags, NULL, TRUE);
               else
         {
-        dnssec_domains * dnssec_domains = NULL;
+        const dnssec_domains * dsp = NULL;
         if (Ustrcmp(tp->driver_name, "smtp") == 0)
           {
           smtp_transport_options_block * ob =
               (smtp_transport_options_block *) tp->options_block;
-          dnssec_domains = &ob->dnssec;
+          dsp = &ob->dnssec;
           }


                 (void) host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
-          dnssec_domains, NULL, NULL);
+          dsp, NULL, NULL);
         }
               }
             }
diff --git a/test/aux-var-src/tls_conf_prefix b/test/aux-var-src/tls_conf_prefix
index e357b99..aa29a2c 100644
--- a/test/aux-var-src/tls_conf_prefix
+++ b/test/aux-var-src/tls_conf_prefix
@@ -13,3 +13,7 @@ gecos_pattern = ""
 gecos_name = CALLER_NAME
 dns_cname_loops = 9
 chunking_advertise_hosts =
+
+.ifdef _HAVE_REQTLS
+tls_advertise_requiretls =
+.endif
diff --git a/test/confs/0900 b/test/confs/0900
index 9a85689..869084d 100644
--- a/test/confs/0900
+++ b/test/confs/0900
@@ -13,6 +13,9 @@ gecos_pattern = ""
 gecos_name = CALLER_NAME
 chunking_advertise_hosts = *
 tls_advertise_hosts = ${if eq {SRV}{tls} {*}}
+.ifdef _HAVE_REQTLS
+tls_advertise_requiretls = :
+.endif



 # ----- Main settings -----
@@ -64,7 +67,7 @@ begin routers
 to_server:
   driver = accept
   condition =    ${if !eq {SERVER}{server}}
-  transport =    remote_smtp${if eq {OPT}{dkim} {_dkim}}
+  transport =    remote_smtp${if eq {SRV}{dkim} {_dkim}}
   errors_to =    ""


fail_remote_domains:
@@ -109,7 +112,7 @@ remote_smtp_dkim:
command_timeout = 2s
final_timeout = 2s

-.ifdef OPT
+.ifdef SRV
   dkim_domain =        test.ex
   dkim_selector =    sel
   dkim_private_key =    DIR/aux-fixed/dkim/dkim.private
diff --git a/test/confs/2108 b/test/confs/2108
index f09213b..9b926bf 100644
--- a/test/confs/2108
+++ b/test/confs/2108
@@ -22,7 +22,6 @@ tls_advertise_hosts = *


tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}

-
# ------ ACL ------

begin acl
diff --git a/test/confs/5650 b/test/confs/5650
index ef73220..840b74c 100644
--- a/test/confs/5650
+++ b/test/confs/5650
@@ -23,7 +23,7 @@ tls_advertise_hosts = *
tls_certificate = DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.pem
tls_privatekey = DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.unlocked.key
tls_crl = CRL
-tls_ocsp_file = OPT
+tls_ocsp_file = OPTION

 #tls_verify_hosts = HOSTIPV4
 #tls_try_verify_hosts = *
diff --git a/test/confs/5910 b/test/confs/5910
new file mode 100644
index 0000000..2437758
--- /dev/null
+++ b/test/confs/5910
@@ -0,0 +1,133 @@
+# Exim test configuration 5910
+
+SERVER=
+
+# advertise REQUIRETLS unless commandline override
+SRV= *
+# set on commandline to add an extra rcpt-time acl condition
+ACL=
+
+exim_path = EXIM_PATH
+keep_environment =
+host_lookup_order = bydns
+spool_directory = DIR/spool
+
+.ifdef SERVER
+log_file_path = DIR/spool/log/SERVER%slog
+.else
+log_file_path = DIR/spool/log/%slog
+.endif
+
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+chunking_advertise_hosts =
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+acl_smtp_mail = m
+acl_smtp_rcpt = r
+acl_not_smtp = n
+
+log_selector =  +tls_peerdn +received_recipients
+
+queue_only
+queue_run_in_order
+
+tls_advertise_hosts = *
+tls_advertise_requiretls = SRV
+
+# Set certificate only if server
+
+tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
+tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
+
+#tls_verify_hosts = *
+#tls_verify_certificates = ${if eq {SERVER}{server}{DIR/aux-fixed/cert2}fail}
+
+
+# ----- ACL -----
+
+begin acl
+
+m:
+  accept        senders = :
+  deny        condition = ${if eq {SERVER}{server}}
+        !sender_domains = test.ex : myhost.test.ex
+  accept
+ 
+r:
+  warn        condition = ${if eq {SERVER}{server}}
+        logwrite = requiretls: $requiretls
+
+# define this to upgrade messages to REQUIRETLS
+.ifdef OPT
+  warn
+        condition = ${if !bool{$requiretls}}
+        logwrite = upgrading
+        control = requiretls
+.endif
+  accept    ACL
+
+n:
+.ifdef OPT
+  accept
+        condition = ${if !bool{$requiretls}}
+        logwrite = upgrading
+        control = requiretls
+.endif
+  accept
+# ----- Routers -----
+
+begin routers
+
+bounces:
+  driver = redirect
+  condition = ${if !def:sender_address}
+  condition = ${if first_delivery}
+  data = :defer:
+  allow_defer
+
+final:
+  driver = accept
+  condition = ${if eq {$received_ip_address}{HOSTIPV4} {yes}{no}}
+  transport = file_a_bounce
+
+client:
+  driver = accept
+  transport = send_to_server
+
+
+# ----- Transports -----
+
+begin transports
+
+file_a_bounce:
+  driver = appendfile
+  delivery_date_add
+  envelope_to_add
+  file = DIR/test-mail/$local_part
+  return_path_add
+  user = CALLER
+
+send_to_server:
+  driver = smtp
+  allow_localhost
+  hosts = HOSTIPV4
+  port = PORT_D
+  tls_certificate = DIR/aux-fixed/cert2
+  tls_privatekey = DIR/aux-fixed/cert2
+  tls_verify_certificates = DIR/aux-fixed/cert2
+  tls_try_verify_hosts = :
+
+
+# ----- Retry -----
+
+
+begin retry
+
+* * F,5d,10s
+
+
+# End
diff --git a/test/confs/5911 b/test/confs/5911
new file mode 120000
index 0000000..0cfc513
--- /dev/null
+++ b/test/confs/5911
@@ -0,0 +1 @@
+5910
\ No newline at end of file
diff --git a/test/confs/5912 b/test/confs/5912
new file mode 120000
index 0000000..0cfc513
--- /dev/null
+++ b/test/confs/5912
@@ -0,0 +1 @@
+5910
\ No newline at end of file
diff --git a/test/log/5910 b/test/log/5910
new file mode 100644
index 0000000..3442b6e
--- /dev/null
+++ b/test/log/5910
@@ -0,0 +1,23 @@
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaX-0005vi-00 => dump@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaY-0005vi-00 => dump <dump@???> R=final T=file_a_bounce
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 upgrading
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? U=CALLER P=local-smtp S=sss for b@???
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => b@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= a@??? H=(test.ex) [127.0.0.1] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss for dump@???
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= a@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss for dump@???
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss id=E10HmaZ-0005vi-00@??? for b@???
diff --git a/test/log/5911 b/test/log/5911
new file mode 100644
index 0000000..974888d
--- /dev/null
+++ b/test/log/5911
@@ -0,0 +1,72 @@
+1999-03-02 09:44:33 upgrading
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? U=CALLER P=local-smtp S=sss for a@???
+1999-03-02 09:44:33 10HmaX-0005vi-00 ** a@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]: a TLS session is required, but the server did not offer TLS support
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss for CALLER@???
+1999-03-02 09:44:33 10HmaY-0005vi-00 == CALLER@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaY-0005vi-00 => CALLER@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmaZ-0005vi-00"
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 upgrading
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? U=CALLER P=local-smtp S=sss for b@???
+1999-03-02 09:44:33 10HmbA-0005vi-00 ** b@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock": REQUIRETLS support is required from the server but it was not offered
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= <> R=10HmbA-0005vi-00 U=EXIMUSER P=local S=sss for CALLER@???
+1999-03-02 09:44:33 10HmbB-0005vi-00 == CALLER@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == CALLER@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** CALLER@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock": REQUIRETLS support is required from the server but it was not offered
+1999-03-02 09:44:33 10HmbB-0005vi-00 Frozen (delivery error message)
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => CALLER <CALLER@???> R=final T=file_a_bounce
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** d@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock": REQUIRETLS support is required from the server but it was not offered
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= <> R=10HmbC-0005vi-00 U=EXIMUSER P=local S=sss for b@???
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 10HmbD-0005vi-00 == b@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbE-0005vi-00 upgrading
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= a@??? U=root P=local S=sss for c@???
+1999-03-02 09:44:33 10HmbE-0005vi-00 ** c@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock": SMTP error from remote mail server after pipelined MAIL FROM:<a@???> SIZE=ssss REQUIRETLS: 550 Administrative prohibition
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= <> R=10HmbE-0005vi-00 U=EXIMUSER P=local S=sss for a@???
+1999-03-02 09:44:33 10HmbF-0005vi-00 == a@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 10HmbD-0005vi-00 => b@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmbG-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 10HmbF-0005vi-00 => a@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmbH-0005vi-00"
+1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 Message is frozen
+1999-03-02 09:44:33 10HmbG-0005vi-00 == b@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 10HmbH-0005vi-00 == a@??? R=bounces defer (-1): 
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss id=E10HmaY-0005vi-00@??? for CALLER@???
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1224
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= b@??? H=(test.ex) [127.0.0.1] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss for d@???
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no rejected MAIL <a@???>
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss id=E10HmbD-0005vi-00@??? for b@???
+1999-03-02 09:44:33 requiretls: yes
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtpS X=TLS_proto_and_cipher CV=no S=sss id=E10HmbF-0005vi-00@??? for a@???
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
diff --git a/test/log/5912 b/test/log/5912
new file mode 100644
index 0000000..72e9c45
--- /dev/null
+++ b/test/log/5912
@@ -0,0 +1,10 @@
+1999-03-02 09:44:33 upgrading
+1999-03-02 09:44:33 U=CALLER F=<CALLER@???> rejected RCPT <a@???>: ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] : a TLS session is required, but the server did not offer TLS support
+1999-03-02 09:44:33 upgrading
+1999-03-02 09:44:33 U=CALLER F=<CALLER@???> rejected RCPT <b@???>: ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] : REQUIRETLS support is required from the server but it was not offered
+1999-03-02 09:44:33 upgrading
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 requiretls: yes
diff --git a/test/mail/3700.smtps b/test/mail/3700.smtps
index eea1419..e00ff4d 100644
--- a/test/mail/3700.smtps
+++ b/test/mail/3700.smtps
@@ -3,7 +3,7 @@ Authentication-Results: myhost.test.ex;
     iprev=pass (localhost) smtp.client-ip=127.0.0.1;
     auth=pass (tls) x509.auth="Phil Pennock"
 Received: from localhost ([127.0.0.1] helo=myhost.test.ex)
-    by myhost.test.ex with esmtpsa (TLSv1:ke-RSA-AES256-SHA:xxx)
+    by myhost.test.ex with esmtpsa (TLS_proto_and_cipher)
     (Exim x.yz)
     (envelope-from <ok@???>)
     id 10HmbA-0005vi-00
diff --git a/test/mail/3700.x b/test/mail/3700.x
index 9413a73..138bcfb 100644
--- a/test/mail/3700.x
+++ b/test/mail/3700.x
@@ -3,7 +3,7 @@ Authentication-Results: myhost.test.ex;
     iprev=pass (localhost) smtp.client-ip=127.0.0.1;
     auth=pass (tls) x509.auth="Phil Pennock"
 Received: from localhost ([127.0.0.1] helo=myhost.test.ex)
-    by myhost.test.ex with esmtpsa (TLSv1:ke-RSA-AES256-SHA:xxx)
+    by myhost.test.ex with esmtpsa (TLS_proto_and_cipher)
     (Exim x.yz)
     (envelope-from <ok@???>)
     id 10HmaZ-0005vi-00
diff --git a/test/mail/5910.dump b/test/mail/5910.dump
new file mode 100644
index 0000000..08957f3
--- /dev/null
+++ b/test/mail/5910.dump
@@ -0,0 +1,20 @@
+From a@??? Tue Mar 02 09:44:33 1999
+Return-path: <a@???>
+Envelope-to: dump@???
+Delivery-date: Tue, 2 Mar 1999 09:44:33 +0000
+Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
+    by myhost.test.ex with esmtpS (TLS_proto_and_cipher)
+    (Exim x.yz)
+    (envelope-from <a@???>)
+    id 10HmaY-0005vi-00
+    for dump@???; Tue, 2 Mar 1999 09:44:33 +0000
+Received: from [127.0.0.1] (helo=test.ex)
+    by myhost.test.ex with esmtpS (TLS_proto_and_cipher)
+    (Exim x.yz)
+    (envelope-from <a@???>)
+    id 10HmaX-0005vi-00
+    for dump@???; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: foo
+
+content
+
diff --git a/test/mail/5911.CALLER b/test/mail/5911.CALLER
new file mode 100644
index 0000000..5410100
--- /dev/null
+++ b/test/mail/5911.CALLER
@@ -0,0 +1,62 @@
+From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+Return-path: <>
+Envelope-to: CALLER@???
+Delivery-date: Tue, 2 Mar 1999 09:44:33 +0000
+Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
+    by myhost.test.ex with esmtpS (TLS_proto_and_cipher)
+    (Exim x.yz)
+    id 10HmaZ-0005vi-00
+    for CALLER@???; Tue, 2 Mar 1999 09:44:33 +0000
+Received: from EXIMUSER by myhost.test.ex with local (Exim x.yz)
+    id 10HmaY-0005vi-00
+    for CALLER@???; Tue, 2 Mar 1999 09:44:33 +0000
+X-Failed-Recipients: a@???
+Auto-Submitted: auto-replied
+From: Mail Delivery System <Mailer-Daemon@???>
+To: CALLER@???
+Content-Type: multipart/report; report-type=delivery-status; boundary=NNNNNNNNNN-eximdsn-MMMMMMMMMM
+MIME-Version: 1.0
+Subject: Mail delivery failed: returning message to sender
+Message-Id: <E10HmaY-0005vi-00@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: text/plain; charset=us-ascii
+
+This message was created automatically by mail delivery software.
+
+A message that you sent could not be delivered to one or more of its
+recipients. This is a permanent error. The following address(es) failed:
+
+  a@???
+  host ipv4.ipv4.ipv4.ipv4 [ipv4.ipv4.ipv4.ipv4]
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/delivery-status
+
+Reporting-MTA: dns; myhost.test.ex
+
+Action: failed
+Final-Recipient: rfc822;a@???
+Status: 5.0.0
+Remote-MTA: dns; ip4.ip4.ip4.ip4
+Remote-MTA: X-ip; [ip4.ip4.ip4.ip4]:1111
+X-Remote-MTA-smtp-greeting: X-str; 220 Hi there
+X-Remote-MTA-helo-response: X-str; 250 wotcher
+X-Exim-Diagnostic: X-str; a TLS session is required, but the server did not offer TLS support
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/rfc822
+
+Return-path: <CALLER@???>
+Received: from CALLER by myhost.test.ex with local-smtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaX-0005vi-00
+    for a@???; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmaX-0005vi-00@???>
+From: CALLER_NAME <CALLER@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM--
+
diff --git a/test/rejectlog/5911 b/test/rejectlog/5911
new file mode 100644
index 0000000..68f7409
--- /dev/null
+++ b/test/rejectlog/5911
@@ -0,0 +1,3 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] X=TLS_proto_and_cipher CV=no rejected MAIL <a@???>
diff --git a/test/rejectlog/5912 b/test/rejectlog/5912
new file mode 100644
index 0000000..dcd1505
--- /dev/null
+++ b/test/rejectlog/5912
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 U=CALLER F=<CALLER@???> rejected RCPT <a@???>: ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] : a TLS session is required, but the server did not offer TLS support
+1999-03-02 09:44:33 U=CALLER F=<CALLER@???> rejected RCPT <b@???>: ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] : REQUIRETLS support is required from the server but it was not offered
diff --git a/test/runtest b/test/runtest
index 102ec9f..9f55666 100755
--- a/test/runtest
+++ b/test/runtest
@@ -1101,6 +1101,9 @@ RESET_AFTER_EXTRA_LINE_READ:
     # Experimental_International
     next if / in smtputf8_advertise_hosts\? no \(option unset\)/;


+    # Experimental_REQUIRETLS
+    next if / in tls_advertise_requiretls?\? no \(end of list\)/;
+
     # Environment cleaning
     next if /\w+ in keep_environment\? (yes|no)/;


@@ -1584,7 +1587,15 @@ $munges =
     { 'stderr' => 's/(1[5-9]|23\d)\d\d msec/ssss msec/' },


     'tls_anycipher' =>
-    { 'mainlog' => 's/ X=TLS\S+ / X=TLS_proto_and_cipher /' },
+    { 'mainlog'   => 's! X=TLS\S+ ! X=TLS_proto_and_cipher !;
+              s! DN="C=! DN="/C=!;
+              s! DN="[^,"]*\K,!/!;
+              s! DN="[^,"]*\K,!/!;
+              s! DN="[^,"]*\K,!/!;
+             ',
+      'rejectlog' => 's/ X=TLS\S+ / X=TLS_proto_and_cipher /',
+      'mail'      => 's/ \(TLS[^)]*\)/ (TLS_proto_and_cipher)/',
+    },


     'debug_pid' =>
     { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d{1,5}/ppppp/g' },
diff --git a/test/scripts/4500-DKIM/4521 b/test/scripts/4500-DKIM/4521
index 7b34152..3a78b02 100644
--- a/test/scripts/4500-DKIM/4521
+++ b/test/scripts/4500-DKIM/4521
@@ -1,10 +1,10 @@
-# DKIM signing, with CHUNKING, stdin
+# DKIM signing, with CHUNKING
 #
 exim -bd -DSERVER=server -oX PORT_S
 ****
 #
 # single header signed, short message
-exim -DOPT=dkim -DLIST=From -odf -oMt sender -f sender a@???
+exim -DSRV=dkim -DLIST=From -odf -oMt sender -f sender a@???
 From: nobody@???
 From: second@???


@@ -12,7 +12,7 @@ content
****
#
# single header signed, long message
-exim -DOPT=dkim -DLIST=From -odf -oMt sender -f sender b@???
+exim -DSRV=dkim -DLIST=From -odf -oMt sender -f sender b@???
From: nobody@???
From: second@???

diff --git a/test/scripts/5650-OCSP-GnuTLS/5650 b/test/scripts/5650-OCSP-GnuTLS/5650
index f671114..78c0afd 100644
--- a/test/scripts/5650-OCSP-GnuTLS/5650
+++ b/test/scripts/5650-OCSP-GnuTLS/5650
@@ -6,7 +6,7 @@ exim -z '1: Server sends good staple on request'
****
#
exim -bd -oX PORT_D -DSERVER=server \
- -DOPT=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.good.resp
+ -DOPTION=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.good.resp
****
client-gnutls \
-ocsp aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem \
@@ -36,7 +36,7 @@ exim -z '2: Server does not staple an outdated response'
****
#
exim -bd -oX PORT_D -DSERVER=server \
- -DOPT=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.dated.resp
+ -DOPTION=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.dated.resp
****
# XXX test sequence might not be quite right; this is for a server refusal
# and we're expecting a client refusal.
@@ -62,7 +62,7 @@ exim -z '3: Server does not staple a response for a revoked cert'
****
#
exim -bd -oX PORT_D -DSERVER=server \
- -DOPT=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.revoked.resp
+ -DOPTION=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.revoked.resp
****
client-gnutls \
-ocsp aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem \
@@ -88,7 +88,7 @@ exim -z '4: Connection functions when server is prepared to staple but client do
****
#
exim -bd -oX PORT_D -DSERVER=server \
- -DOPT=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.good.resp
+ -DOPTION=DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.example.com.ocsp.good.resp
****
#
client-gnutls \
diff --git a/test/scripts/5910-REQUIRETLS/5910 b/test/scripts/5910-REQUIRETLS/5910
new file mode 100644
index 0000000..d1bbb61
--- /dev/null
+++ b/test/scripts/5910-REQUIRETLS/5910
@@ -0,0 +1,64 @@
+# REQUIRETLS basics
+#
+munge tls_anycipher
+#
+# Server advertises feature, onward transmission, observability
+exim -DSERVER=server -bd -oX PORT_D
+****
+#
+client-ssl 127.0.0.1 PORT_D
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-REQUIRETLS
+??? 250 HELP
+MAIL FROM:<a@???> REQUIRETLS
+??? 250
+RCPT TO:<dump@???>
+??? 250
+DATA
+??? 354
+Subject: foo
+
+content
+.
+??? 250
+QUIT
+??? 221
+****
+#
+exim -q
+****
+exim -q
+****
+#
+#
+# upgrade in-MTA
+exim -DOPT=y -bs
+MAIL FROM:<a@???>
+RCPT TO:<b@???>
+DATA
+Subject: foo
+
+content
+.
+QUIT
+****
+#
+exim -q
+****
+#
+killdaemon
+no_msglog_check
diff --git a/test/scripts/5910-REQUIRETLS/5911 b/test/scripts/5910-REQUIRETLS/5911
new file mode 100644
index 0000000..c744d8a
--- /dev/null
+++ b/test/scripts/5910-REQUIRETLS/5911
@@ -0,0 +1,125 @@
+# REQUIRETLS bounce cases
+#
+munge tls_anycipher
+#
+# Server does not offer STARTTLS
+server PORT_D
+220 Hi there
+EHLO
+250 wotcher
+QUIT
+*eof
+****
+exim -DOPT=requiretls -odf -bs
+MAIL FROM:<a@???>
+RCPT TO:<a@???>
+DATA
+
+.
+QUIT
+****
+# ... the resulting bounce must be delivered with REQUIRETLS
+exim -DSERVER=server -bd -oX PORT_D
+****
+exim -qf
+****
+killdaemon
+#
+#
+# Server does not offer REQUIRETLS
+# Client message upgraded in-MTA for "require"
+exim -DSERVER=server -DSRV='' -bd -oX PORT_D
+****
+exim -DOPT=requiretls -odf -bs
+MAIL FROM:<b@???>
+RCPT TO:<b@???>
+DATA
+
+.
+QUIT
+****
+exim -qf
+****
+exim -qf
+****
+killdaemon
+#
+#
+# Server does not offer REQUIRETLS
+# Client message received with REQUIRETLS
+exim -DSERVER=server -bd -oX PORT_S
+****
+client-ssl 127.0.0.1 PORT_S
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-STARTTLS
+??? 250 HELP
+STARTTLS
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-REQUIRETLS
+??? 250 HELP
+MAIL FROM:<b@???> REQUIRETLS
+??? 250
+RCPT TO:<d@???>
+??? 250
+DATA
+??? 354
+Subject: foo
+
+content
+.
+??? 250
+QUIT
+??? 221
+****
+killdaemon
+exim -DSERVER=server -DSRV='' -bd -oX PORT_D
+****
+exim -qf
+****
+exim -qf
+****
+killdaemon
+#
+#
+# Server refuses MAIL
+exim -DSERVER=server -bd -oX PORT_D
+****
+sudo exim -DOPT=requiretls -odf -f a@??? c@???
+
+****
+exim -qf
+****
+exim -qf
+****
+killdaemon
+#
+# Server does not advertise REQUIRETLS, client tries to use it anyway
+exim -DSERVER=server -bd -oX PORT_D
+****
+client-ssl 127.0.0.1 PORT_D
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-SIZE
+??? 250-8BITMIME
+??? 250-PIPELINING
+??? 250-STARTTLS
+??? 250 HELP
+MAIL FROM:<d@???> REQUIRETLS
+??? 555
+QUIT
+??? 221
+???*eof
+****
+killdaemon
+no_msglog_check
diff --git a/test/scripts/5910-REQUIRETLS/5912 b/test/scripts/5910-REQUIRETLS/5912
new file mode 100644
index 0000000..87fe85e
--- /dev/null
+++ b/test/scripts/5910-REQUIRETLS/5912
@@ -0,0 +1,37 @@
+# REQUIRETLS smtp-time fails
+# Test these by having the MTA do a receipient-verify callout
+#
+# Server does not offer STARTTLS
+server PORT_D
+220 Hi there
+EHLO
+250 wotcher
+QUIT
+*eof
+****
+exim -DOPT=requiretls -DACL=verify=recipient/callout -odf -bs
+MAIL FROM:<CALLER@???>
+RCPT TO:<a@???>
+QUIT
+****
+#
+# Sever does not offer REQUIRETLS
+exim -DSERVER=server -DSRV='' -bd -oX PORT_D
+****
+exim -DOPT=requiretls -DACL=verify=recipient/callout -odf -bs
+MAIL FROM:<CALLER@???>
+RCPT TO:<b@???>
+QUIT
+****
+killdaemon
+#
+# Accepted callout
+exim -DSERVER=server -bd -oX PORT_D
+****
+exim -DOPT=requiretls -DACL=verify=recipient/callout -odf -bs
+MAIL FROM:<CALLER@???>
+RCPT TO:<c@???>
+QUIT
+****
+killdaemon
+#
diff --git a/test/scripts/5910-REQUIRETLS/REQUIRES b/test/scripts/5910-REQUIRETLS/REQUIRES
new file mode 100644
index 0000000..9632335
--- /dev/null
+++ b/test/scripts/5910-REQUIRETLS/REQUIRES
@@ -0,0 +1,2 @@
+support Experimental_REQUIRETLS
+running IPv4
diff --git a/test/stdout/5910 b/test/stdout/5910
new file mode 100644
index 0000000..692038d
--- /dev/null
+++ b/test/stdout/5910
@@ -0,0 +1,60 @@
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+SSL connection using ke-RSA-AES256-SHA
+Succeeded in starting TLS
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-REQUIRETLS
+<<< 250-REQUIRETLS
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<a@???> REQUIRETLS
+??? 250
+<<< 250 OK
+>>> RCPT TO:<dump@???>
+??? 250
+<<< 250 Accepted
+>>> DATA
+??? 354
+<<< 354 Enter message, ending with "." on a line by itself
+>>> Subject: foo
+>>>
+>>> content
+>>> .
+??? 250
+<<< 250 OK id=10HmaX-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmaZ-0005vi-00
+221 myhost.test.ex closing connection
diff --git a/test/stdout/5911 b/test/stdout/5911
new file mode 100644
index 0000000..fb126b3
--- /dev/null
+++ b/test/stdout/5911
@@ -0,0 +1,101 @@
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmaX-0005vi-00
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbA-0005vi-00
+221 myhost.test.ex closing connection
+Connecting to 127.0.0.1 port 1224 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> STARTTLS
+??? 220
+<<< 220 TLS go ahead
+Attempting to start TLS
+SSL connection using ke-RSA-AES256-SHA
+Succeeded in starting TLS
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-REQUIRETLS
+<<< 250-REQUIRETLS
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<b@???> REQUIRETLS
+??? 250
+<<< 250 OK
+>>> RCPT TO:<d@???>
+??? 250
+<<< 250 Accepted
+>>> DATA
+??? 354
+<<< 354 Enter message, ending with "." on a line by itself
+>>> Subject: foo
+>>>
+>>> content
+>>> .
+??? 250
+<<< 250 OK id=10HmbC-0005vi-00
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-SIZE
+<<< 250-SIZE 52428800
+??? 250-8BITMIME
+<<< 250-8BITMIME
+??? 250-PIPELINING
+<<< 250-PIPELINING
+??? 250-STARTTLS
+<<< 250-STARTTLS
+??? 250 HELP
+<<< 250 HELP
+>>> MAIL FROM:<d@???> REQUIRETLS
+??? 555
+<<< 555 unadvertised MAIL option: REQUIRETLS
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+???*eof
+Expected EOF read
+End of script
+
+******** SERVER ********
+Listening on port 1225 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 Hi there
+EHLO myhost.test.ex
+250 wotcher
+QUIT
+Expected EOF read from client
+End of script
diff --git a/test/stdout/5912 b/test/stdout/5912
new file mode 100644
index 0000000..5dddcc0
--- /dev/null
+++ b/test/stdout/5912
@@ -0,0 +1,22 @@
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+530 5.7.4 REQUIRETLS support required
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+530 5.7.4 REQUIRETLS support required
+221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250 OK
+250 Accepted
+221 myhost.test.ex closing connection
+
+******** SERVER ********
+Listening on port 1225 ...
+Connection request from [ip4.ip4.ip4.ip4]
+220 Hi there
+EHLO myhost.test.ex
+250 wotcher
+QUIT
+Expected EOF read from client
+End of script