[exim-cvs] GnuTLS: Move to more-modern stapling API

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] GnuTLS: Move to more-modern stapling API
Gitweb: https://git.exim.org/exim.git/commitdiff/e54893330b92ed765b6872a1c47ba61d5e20ff7c
Commit:     e54893330b92ed765b6872a1c47ba61d5e20ff7c
Parent:     5c03403d88afcde2bb3f543296b0fca6f05c9f2c
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Tue Aug 27 17:24:23 2019 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Sep 20 14:30:21 2019 +0100


    GnuTLS: Move to more-modern stapling API
---
 doc/doc-docbook/spec.xfpt          |   1 +
 src/src/tls-gnu.c                  | 138 ++++++++++++++++++++++++++++++-------
 src/src/tls-openssl.c              |   3 +-
 test/confs/5651                    |  15 +++-
 test/confs/5653                    |  84 ++++++++++++++++++++++
 test/confs/5730                    |  13 +++-
 test/log/5650                      |   6 +-
 test/log/5652                      |   4 +-
 test/log/5653                      |   9 +++
 test/log/5890                      |  32 ++++-----
 test/scripts/5650-OCSP-GnuTLS/5650 |   6 +-
 test/scripts/5650-OCSP-GnuTLS/5652 |   2 +-
 test/scripts/5650-OCSP-GnuTLS/5653 |  23 +++++++
 test/stdout/5650                   |  14 ++--
 14 files changed, 288 insertions(+), 62 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index f7e930c..e4dfb98 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -17820,6 +17820,7 @@ For GnuTLS 3.5.6 or later the expanded value of this option can be a list
of files, to match a list given for the &%tls_certificate%& option.
The ordering of the two lists must match.

+The file(s) should be in DER format

.option tls_on_connect_ports main "string list" unset
.cindex SSMTP
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index bbc75b6..a45dd65 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -225,6 +225,7 @@ static BOOL exim_gnutls_base_init_done = FALSE;

#ifndef DISABLE_OCSP
static BOOL gnutls_buggy_ocsp = FALSE;
+static BOOL exim_testharness_disable_ocsp_validity_check = FALSE;
#endif

#ifdef EXPERIMENTAL_TLS_RESUME
@@ -287,11 +288,16 @@ static void exim_gnutls_logger_cb(int level, const char *message);

static int exim_sni_handling_cb(gnutls_session_t session);

-#ifndef DISABLE_OCSP
+#if !defined(DISABLE_OCSP)
static int server_ocsp_stapling_cb(gnutls_session_t session, void * ptr,
gnutls_datum_t * ocsp_response);
#endif

+#ifdef EXPERIMENTAL_TLS_RESUME
+static int
+tls_server_ticket_cb(gnutls_session_t sess, u_int htype, unsigned when,
+ unsigned incoming, const gnutls_datum_t * msg);
+#endif


 /* Daemon one-time initialisation */
@@ -858,6 +864,9 @@ static int
 tls_add_certfile(exim_gnutls_state_st * state, const host_item * host,
   uschar * certfile, uschar * keyfile, uschar ** errstr)
 {
+/*XXX returns certs index for gnutls_certificate_set_x509_key_file(),
+given suitable flags set */
+
 int rc = gnutls_certificate_set_x509_key_file(state->x509_cred,
     CS certfile, CS keyfile, GNUTLS_X509_FMT_PEM);
 if (rc < 0)
@@ -868,6 +877,78 @@ return -rc;
 }



+/* Make a note that we saw a status-request */
+static int
+tls_server_clienthello_ext(void * ctx, unsigned tls_id,
+  const unsigned char *data, unsigned size)
+{
+/* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */
+if (tls_id == 5)    /* status_request */
+  {
+  DEBUG(D_tls) debug_printf("Seen status_request extension\n");
+  tls_in.ocsp = OCSP_NOT_RESP;
+  }
+return 0;
+}
+
+/* Callback for client-hello, on server, if we think we might serve stapled-OCSP */
+static int
+tls_server_clienthello_cb(gnutls_session_t session, unsigned int htype,
+  unsigned when, unsigned int incoming, const gnutls_datum_t * msg)
+{
+/* Call fn for each extension seen.  3.6.3 onwards */
+return gnutls_ext_raw_parse(NULL, tls_server_clienthello_ext, msg,
+               GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
+}
+
+/* Callback for certificate-status, on server. We sent stapled OCSP. */
+static int
+tls_server_certstatus_cb(gnutls_session_t session, unsigned int htype,
+  unsigned when, unsigned int incoming, const gnutls_datum_t * msg)
+{
+DEBUG(D_tls) debug_printf("Sending certificate-status\n");
+#ifdef SUPPORT_SRV_OCSP_STACK
+tls_in.ocsp = exim_testharness_disable_ocsp_validity_check
+  ? OCSP_VFY_NOT_TRIED : OCSP_VFIED;    /* We know that GnuTLS verifies responses */
+#else
+tls_in.ocsp = OCSP_VFY_NOT_TRIED;
+#endif
+return 0;
+}
+
+/* Callback for handshake messages, on server */
+static int
+tls_server_hook_cb(gnutls_session_t sess, u_int htype, unsigned when,
+  unsigned incoming, const gnutls_datum_t * msg)
+{
+switch (htype)
+  {
+  case GNUTLS_HANDSHAKE_CLIENT_HELLO:
+    return tls_server_clienthello_cb(sess, htype, when, incoming, msg);
+  case GNUTLS_HANDSHAKE_CERTIFICATE_STATUS:
+    return tls_server_certstatus_cb(sess, htype, when, incoming, msg);
+#ifdef EXPERIMENTAL_TLS_RESUME
+  case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:
+    return tls_server_ticket_cb(sess, htype, when, incoming, msg);
+#endif
+  default:
+    return 0;
+  }
+}
+
+
+static void
+tls_server_testharness_ocsp_fiddle(void)
+{
+extern char ** environ;
+if (environ) for (uschar ** p = USS environ; *p; p++)
+  if (Ustrncmp(*p, "EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK", 42) == 0)
+    {
+    DEBUG(D_tls) debug_printf("Permitting known bad OCSP response\n");
+    exim_testharness_disable_ocsp_validity_check = TRUE;
+    }
+}
+
 /*************************************************
 *       Variables re-expanded post-SNI           *
 *************************************************/
@@ -1002,12 +1083,13 @@ if (state->exp_tls_certificate && *state->exp_tls_certificate)
       else
     {
     int gnutls_cert_index = -rc;
-    DEBUG(D_tls) debug_printf("TLS: cert/key %s registered\n", cfile);
+    DEBUG(D_tls) debug_printf("TLS: cert/key %d %s registered\n", gnutls_cert_index, cfile);


     /* Set the OCSP stapling server info */


 #ifndef DISABLE_OCSP
     if (tls_ocsp_file)
+      {
       if (gnutls_buggy_ocsp)
         {
         DEBUG(D_tls)
@@ -1015,37 +1097,45 @@ if (state->exp_tls_certificate && *state->exp_tls_certificate)
         }
       else if ((ofile = string_nextinlist(&olist, &osep, NULL, 0)))
         {
-        /* Use the full callback method for stapling just to get
-        observability.  More efficient would be to read the file once only,
-        if it never changed (due to SNI). Would need restart on file update,
-        or watch datestamp.  */
+        DEBUG(D_tls) debug_printf("OCSP response file = %s\n", ofile);


 # ifdef SUPPORT_SRV_OCSP_STACK
-        if ((rc = gnutls_certificate_set_ocsp_status_request_function2(
-            state->x509_cred, gnutls_cert_index,
-            server_ocsp_stapling_cb, ofile)))
-          return tls_error_gnu(
-              US"gnutls_certificate_set_ocsp_status_request_function2",
-              rc, host, errstr);
-# else
-        if (cnt++ > 0)
+        if (f.running_in_test_harness) tls_server_testharness_ocsp_fiddle();
+
+        if (!exim_testharness_disable_ocsp_validity_check)
           {
-          DEBUG(D_tls)
-        debug_printf("oops; multiple OCSP files not supported\n");
-          break;
+          if  ((rc = gnutls_certificate_set_ocsp_status_request_file2(
+              state->x509_cred, CCS ofile, gnutls_cert_index,
+              GNUTLS_X509_FMT_DER)) < 0)
+        return tls_error_gnu(
+            US"gnutls_certificate_set_ocsp_status_request_file2",
+            rc, host, errstr);
+
+          /* Arrange callbacks for OCSP request observability */
+
+          gnutls_handshake_set_hook_function(state->session,
+        GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, tls_server_hook_cb);
           }
-          gnutls_certificate_set_ocsp_status_request_function(
-        state->x509_cred, server_ocsp_stapling_cb, ofile);
+        else
 # endif
-
-        DEBUG(D_tls) debug_printf("OCSP response file = %s\n", ofile);
+          {
+          if (cnt++ > 0)
+        {
+        DEBUG(D_tls)
+          debug_printf("oops; multiple OCSP files not supported\n");
+        break;
+        }
+        gnutls_certificate_set_ocsp_status_request_function(
+          state->x509_cred, server_ocsp_stapling_cb, ofile);
+          }
         }
       else
         DEBUG(D_tls) debug_printf("ran out of OCSP response files in list\n");
 #endif
+      }
     }
     }
-  else
+  else    /* client */
     {
     if (0 < (rc = tls_add_certfile(state, host,
         state->exp_tls_certificate, state->exp_tls_privatekey, errstr)))
@@ -1983,7 +2073,7 @@ return 0;




-#ifndef DISABLE_OCSP
+#if !defined(DISABLE_OCSP)

static int
server_ocsp_stapling_cb(gnutls_session_t session, void * ptr,
@@ -2133,7 +2223,7 @@ if (verify_check_host(&tls_resumption_hosts) == OK)

   /* Try to tell if we see a ticket request */
   gnutls_handshake_set_hook_function(state->session,
-    GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, GNUTLS_HOOK_POST, tls_server_ticket_cb);
+    GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, tls_server_hook_cb);
   }
 }


diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 541c45a..dc87291 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1312,7 +1312,8 @@ if (!OCSP_check_validity(thisupd, nextupd, EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX
}

 supply_response:
-  cbinfo->u_ocsp.server.response = resp;    /*XXX stack?*/
+  /*XXX stack? (these tag points are for multiple leaf-cert support for ocsp */
+  cbinfo->u_ocsp.server.response = resp;
 return;


bad:
diff --git a/test/confs/5651 b/test/confs/5651
index 5803c3c..01fa455 100644
--- a/test/confs/5651
+++ b/test/confs/5651
@@ -3,10 +3,21 @@

SERVER =

-.include DIR/aux-var/tls_conf_prefix
-
+exim_path = EXIM_PATH
+keep_environment = ^EXIM_TESTHARNESS_DISABLE_[O]CSPVALIDITYCHECK$
+host_lookup_order = bydns
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+chunking_advertise_hosts =
primary_hostname = server1.example.com

+.ifdef _HAVE_DMARC
+dmarc_tld_file =
+.endif
+
+
# ----- Main settings -----

 domainlist local_domains = test.ex : *.test.ex
diff --git a/test/confs/5653 b/test/confs/5653
new file mode 100644
index 0000000..5b29f5b
--- /dev/null
+++ b/test/confs/5653
@@ -0,0 +1,84 @@
+# Exim test configuration 5652
+# OCSP stapling, server, multiple certs
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = server1.example.com
+
+# ----- Main settings -----
+
+acl_smtp_mail = check_mail
+acl_smtp_rcpt = check_recipient
+
+log_selector = +tls_peerdn
+
+queue_only
+queue_run_in_order
+
+tls_advertise_hosts = *
+
+CADIR = DIR/aux-fixed/exim-ca
+DRSA = CADIR/example.com
+DECDSA = CADIR/example_ec.com
+
+tls_certificate = DRSA/server1.example.com/server1.example.com.pem \
+          : DECDSA/server1.example_ec.com/server1.example_ec.com.pem
+tls_privatekey =  DRSA/server1.example.com/server1.example.com.unlocked.key \
+          : DECDSA/server1.example_ec.com/server1.example_ec.com.unlocked.key
+tls_ocsp_file =   DRSA/server1.example.com/server1.example.com.ocsp.good.resp \
+          : DECDSA/server1.example_ec.com/server1.example_ec.com.ocsp.good.resp
+
+
+tls_require_ciphers = NORMAL:!VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.0
+
+# ------ ACL ------
+
+begin acl
+
+check_mail:
+  accept   logwrite = acl_mail: ocsp in status: $tls_in_ocsp \
+    (${listextract {${eval:$tls_in_ocsp+1}} \
+        {notreq:notresp:vfynotdone:failed:verified}})
+
+check_recipient:
+  accept
+
+
+# ----- Routers -----
+
+begin routers
+
+client:
+  driver = manualroute
+  condition = ${if !eq {SERVER}{server}}
+  route_list = * 127.0.0.1
+  self = send
+  transport = remote_delivery
+  errors_to = ""
+
+srvr:
+  driver = accept
+  retry_use_local_part
+  transport = local_delivery
+
+
+# ----- Transports -----
+
+begin transports
+
+remote_delivery:
+  driver =            smtp
+  port =            PORT_D
+  hosts_require_tls =        *
+  tls_require_ciphers =        OPT
+  hosts_require_ocsp =        *
+  tls_verify_certificates =    CERT
+  tls_verify_cert_hostnames =    :
+
+local_delivery:
+  driver = appendfile
+  file = DIR/test-mail/$local_part
+  headers_add = TLS: cipher=$tls_cipher peerdn=$tls_peerdn
+  user = CALLER
+
+# End
diff --git a/test/confs/5730 b/test/confs/5730
index 625dece..2b32008 100644
--- a/test/confs/5730
+++ b/test/confs/5730
@@ -3,9 +3,20 @@


SERVER =

-.include DIR/aux-var/tls_conf_prefix
+exim_path = EXIM_PATH
+keep_environment = ^EXIM_TESTHARNESS_DISABLE_[O]CSPVALIDITYCHECK$
+host_lookup_order = bydns
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+chunking_advertise_hosts =

primary_hostname = server1.example.com
+
+.ifdef _HAVE_DMARC
+dmarc_tld_file =
+.endif


# ----- Main settings -----
diff --git a/test/log/5650 b/test/log/5650
index 75428e2..7f46ba1 100644
--- a/test/log/5650
+++ b/test/log/5650
@@ -6,12 +6,12 @@
******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 acl_conn: ocsp in status: 0 (notreq)
-1999-03-02 09:44:33 acl_mail: ocsp in status: 2 (vfynotdone)
+1999-03-02 09:44:33 acl_mail: ocsp in status: 1 (notresp)
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 acl_conn: ocsp in status: 0 (notreq)
-1999-03-02 09:44:33 TLS error on connection from [ip4.ip4.ip4.ip4] (recv): The TLS connection was non-properly terminated.
+1999-03-02 09:44:33 TLS error on connection from (rhu.barb) [ip4.ip4.ip4.ip4] (gnutls_certificate_set_ocsp_status_request_file2): The session or certificate has expired.
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 acl_conn: ocsp in status: 0 (notreq)
-1999-03-02 09:44:33 TLS error on connection from [ip4.ip4.ip4.ip4] (recv): The TLS connection was non-properly terminated.
+1999-03-02 09:44:33 TLS error on connection from (rhu.barb) [ip4.ip4.ip4.ip4] (gnutls_certificate_set_ocsp_status_request_file2): The session or certificate has expired.
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 acl_conn: ocsp in status: 0 (notreq)
diff --git a/test/log/5652 b/test/log/5652
index 4803444..cf31aa3 100644
--- a/test/log/5652
+++ b/test/log/5652
@@ -9,8 +9,8 @@

 ******** SERVER ********
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 2 (vfynotdone)
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@???
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 2 (vfynotdone)
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@???
diff --git a/test/log/5653 b/test/log/5653
new file mode 100644
index 0000000..82d2e7a
--- /dev/null
+++ b/test/log/5653
@@ -0,0 +1,9 @@
+1999-03-02 09:44:33 1: Server sends good staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@??? R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@???
diff --git a/test/log/5890 b/test/log/5890
index 324e5a4..5ffb9cc 100644
--- a/test/log/5890
+++ b/test/log/5890
@@ -180,7 +180,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    4
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@??? for getticket@???
@@ -191,7 +191,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke--AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke--AES256-SHAnnn:xxx* CV=no S=sss id=E10HmaZ-0005vi-00@??? for resume@??? xyz@???
@@ -203,7 +203,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    4
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@??? for abcd@???
@@ -214,7 +214,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke--AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke--AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbC-0005vi-00@??? for renewal@???
@@ -225,7 +225,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke--AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke--AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbE-0005vi-00@??? for postrenewal@???
@@ -236,7 +236,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    4
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbG-0005vi-00@??? for timeout@???
@@ -247,7 +247,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    4
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbI-0005vi-00@??? for notreq@???
@@ -258,7 +258,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    4
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbK-0005vi-00@??? for noverify_getticket@???
@@ -269,7 +269,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke--AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke--AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbM-0005vi-00@??? for noverify_resume@???
@@ -281,7 +281,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbO-0005vi-00@??? for getticket@???
@@ -292,7 +292,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-PSK-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbR-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-PSK-AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbQ-0005vi-00@??? for resume@??? xyz@???
@@ -304,7 +304,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbS-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbQ-0005vi-00@??? for abcd@???
@@ -315,7 +315,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-PSK-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbU-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-PSK-AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbT-0005vi-00@??? for renewal@???
@@ -326,7 +326,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    0
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-PSK-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbW-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-PSK-AES256-SHAnnn:xxx* CV=no S=sss id=E10HmbV-0005vi-00@??? for postrenewal@???
@@ -337,7 +337,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmbY-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbX-0005vi-00@??? for timeout@???
@@ -348,7 +348,7 @@
 1999-03-02 09:44:33 peer cert subject    
 1999-03-02 09:44:33 peer cert verified    0
 1999-03-02 09:44:33 peer dn    
-1999-03-02 09:44:33 ocsp    2
+1999-03-02 09:44:33 ocsp    1
 1999-03-02 09:44:33 cipher    TLS1.x:ke-RSA-AES256-SHAnnn:xxx
 1999-03-02 09:44:33 bits    256
 1999-03-02 09:44:33 10HmcA-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbZ-0005vi-00@??? for notreq@???
diff --git a/test/scripts/5650-OCSP-GnuTLS/5650 b/test/scripts/5650-OCSP-GnuTLS/5650
index 78c0afd..99aaa0b 100644
--- a/test/scripts/5650-OCSP-GnuTLS/5650
+++ b/test/scripts/5650-OCSP-GnuTLS/5650
@@ -38,8 +38,6 @@ exim -z '2: Server does not staple an outdated response'
 exim -bd -oX PORT_D -DSERVER=server \
  -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.
 client-gnutls -ocsp aux-fixed/exim-ca/expired1.example.com/CA.pem HOSTIPV4 PORT_D aux-fixed/cert2 aux-fixed/cert2
 ??? 220
 ehlo rhu.barb
@@ -50,7 +48,7 @@ ehlo rhu.barb
 ??? 250-
 ??? 250
 starttls
-??? 220
+??? 454
 ****
 killdaemon
 #
@@ -76,7 +74,7 @@ ehlo rhu.barb
 ??? 250-
 ??? 250
 starttls
-??? 220
+??? 454
 ****
 killdaemon
 #
diff --git a/test/scripts/5650-OCSP-GnuTLS/5652 b/test/scripts/5650-OCSP-GnuTLS/5652
index 4a33ea8..9130f65 100644
--- a/test/scripts/5650-OCSP-GnuTLS/5652
+++ b/test/scripts/5650-OCSP-GnuTLS/5652
@@ -1,4 +1,4 @@
-# OCSP stapling, server, multiple certs
+# OCSP stapling, server, multiple leaf certs
 #
 #
 #
diff --git a/test/scripts/5650-OCSP-GnuTLS/5653 b/test/scripts/5650-OCSP-GnuTLS/5653
new file mode 100644
index 0000000..55cea8b
--- /dev/null
+++ b/test/scripts/5650-OCSP-GnuTLS/5653
@@ -0,0 +1,23 @@
+# OCSP stapling, server, multiple chain-element OCSP
+#
+#
+#
+exim -z '1: Server sends good staple on request, to client requiring RSA auth'
+****
+#
+exim -d+all -bd -oX PORT_D -DSERVER=server
+****
+exim -odf \
+  -DOPT=NONE:+SIGN-RSA-SHA256:+VERS-TLS-ALL:+ECDHE-RSA:+DHE-RSA:+RSA:+CIPHER-ALL:+MAC-ALL:+COMP-NULL:+CURVE-ALL:+CTYPE-X509 \
+  -DCERT=DIR/aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem \
+  rsa.auth@???
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+#
+#
+no_msglog_check
diff --git a/test/stdout/5650 b/test/stdout/5650
index 7b5628c..8a72c0f 100644
--- a/test/stdout/5650
+++ b/test/stdout/5650
@@ -49,10 +49,9 @@ Key file = aux-fixed/cert2
 ??? 250
 <<< 250 HELP

>>> starttls

-??? 220
-<<< 220 TLS go ahead
-Attempting to start TLS
-Bad certificate
+??? 454
+<<< 454 TLS currently unavailable
+Abandoning TLS start attempt
End of script
Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
Certificate file = aux-fixed/cert2
@@ -73,10 +72,9 @@ Key file = aux-fixed/cert2
??? 250
<<< 250 HELP
>>> starttls

-??? 220
-<<< 220 TLS go ahead
-Attempting to start TLS
-Bad certificate
+??? 454
+<<< 454 TLS currently unavailable
+Abandoning TLS start attempt
End of script
Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
Certificate file = aux-fixed/cert2