[exim-cvs] GSASL channel-binding: TLS resumption checks

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] GSASL channel-binding: TLS resumption checks
Gitweb: https://git.exim.org/exim.git/commitdiff/1c519e07b908a314ce7bdfceb6baa9e18e302dfc
Commit:     1c519e07b908a314ce7bdfceb6baa9e18e302dfc
Parent:     9540bcf2addf37f08505454247f5687b68d340c7
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sat Dec 28 17:00:30 2019 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sat Dec 28 17:04:18 2019 +0000


    GSASL channel-binding: TLS resumption checks
---
 doc/doc-docbook/spec.xfpt  |  2 +-
 src/src/auths/gsasl_exim.c | 43 ++++++++++++++++++++++++++++++++-----------
 src/src/auths/gsasl_exim.h |  2 +-
 src/src/globals.h          |  1 +
 src/src/tls-gnu.c          |  6 ++++++
 src/src/tls-openssl.c      |  2 ++
 6 files changed, 43 insertions(+), 13 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 9043685..1d4c39c 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -27447,7 +27447,7 @@ without code changes in Exim.
.option client_authz gsasl string&!! unset
This option can be used to supply an &'authorization id'&
which is different to the &'authentication_id'& provided
-by $%client_username%& option.
+by &%client_username%& option.
If unset or (after expansion) empty it is not used,
which is the common case.

diff --git a/src/src/auths/gsasl_exim.c b/src/src/auths/gsasl_exim.c
index db14a40..f527e13 100644
--- a/src/src/auths/gsasl_exim.c
+++ b/src/src/auths/gsasl_exim.c
@@ -96,7 +96,7 @@ auth_gsasl_options_block auth_gsasl_option_defaults = {
/* Dummy values */
void auth_gsasl_init(auth_instance *ablock) {}
int auth_gsasl_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_gsasl_client(auth_instance *ablock, smtp_inblock * sx,
+int auth_gsasl_client(auth_instance *ablock, void * sx,
int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_gsasl_version_report(FILE *f) {}

@@ -301,14 +301,24 @@ HDEBUG(D_auth)
       ablock->name, ob->server_mech);


 #ifndef DISABLE_TLS
+if (tls_in.channelbinding && ob->server_channelbinding)
+  {
+# ifdef EXPERIMENTAL_TLS_RESUME
+  if (!tls_in.ext_master_secret && tls_in.resumption == RESUME_USED)
+    {        /* per RFC 7677 section 4 */
+    HDEBUG(D_auth) debug_printf(
+      "channel binding not usable on resumed TLS without extended-master-secret");
+    return FAIL;
+    }
+# endif
 # ifdef CHANNELBIND_HACK
 /* This is a gross hack to get around the library a) requiring that
 c-b was already set, at the _start() call, and b) caching a b64'd
 version of the binding then which it never updates. */


-if (tls_in.channelbinding && ob->server_channelbinding)
gsasl_callback_hook_set(gsasl_ctx, tls_in.channelbinding);
# endif
+ }
#endif

 if ((rc = gsasl_server_start(gsasl_ctx, CCS ob->server_mech, &sctx)) != GSASL_OK)
@@ -362,7 +372,7 @@ if (tls_in.channelbinding)
     {
     HDEBUG(D_auth) debug_printf("Auth %s: Enabling channel-binding\n",
     ablock->name);
-# ifdef CHANNELBIND_HACK
+# ifndef CHANNELBIND_HACK
     gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_in.channelbinding);
 # endif
     }
@@ -720,7 +730,7 @@ return TRUE;
 int
 auth_gsasl_client(
   auth_instance *ablock,        /* authenticator block */
-  smtp_inblock * sx,            /* connection */
+  void * sx,                /* connection */
   int timeout,                /* command timeout */
   uschar *buffer,            /* buffer for reading response */
   int buffsize)                /* size of buffer */
@@ -740,13 +750,24 @@ HDEBUG(D_auth)
 *buffer = 0;


 #ifndef DISABLE_TLS
-/* This is a gross hack to get around the library a) requiring that
-c-b was already set, at the _start() call, and b) caching a b64'd
-version of the binding then which it never updates. */
+if (tls_out.channelbinding && ob->client_channelbinding)
+  {
+# ifdef EXPERIMENTAL_TLS_RESUME
+  if (!tls_out.ext_master_secret && tls_out.resumption == RESUME_USED)
+    {        /* per RFC 7677 section 4 */
+    string_format(buffer, buffsize, "%s",
+      "channel binding not usable on resumed TLS without extended-master-secret");
+    return FAIL;
+    }
+# endif
+# ifdef CHANNELBIND_HACK
+  /* This is a gross hack to get around the library a) requiring that
+  c-b was already set, at the _start() call, and b) caching a b64'd
+  version of the binding then which it never updates. */


-if (tls_out.channelbinding)
-  if (ob->client_channelbinding)
-    gsasl_callback_hook_set(gsasl_ctx, tls_out.channelbinding);
+  gsasl_callback_hook_set(gsasl_ctx, tls_out.channelbinding);
+# endif
+  }
 #endif


 if ((rc = gsasl_client_start(gsasl_ctx, CCS ob->server_mech, &sctx)) != GSASL_OK)
@@ -780,7 +801,7 @@ if (tls_out.channelbinding)
     {
     HDEBUG(D_auth) debug_printf("Auth %s: Enabling channel-binding\n",
     ablock->name);
-# ifdef CHANNELBIND_HACK
+# ifndef CHANNELBIND_HACK
     gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE, CCS tls_out.channelbinding);
 # endif
     }
diff --git a/src/src/auths/gsasl_exim.h b/src/src/auths/gsasl_exim.h
index 93d2078..7afec70 100644
--- a/src/src/auths/gsasl_exim.h
+++ b/src/src/auths/gsasl_exim.h
@@ -42,7 +42,7 @@ extern auth_gsasl_options_block auth_gsasl_option_defaults;


 extern void auth_gsasl_init(auth_instance *);
 extern int auth_gsasl_server(auth_instance *, uschar *);
-extern int auth_gsasl_client(auth_instance *, smtp_inblock *,
+extern int auth_gsasl_client(auth_instance *, void *,
                 int, uschar *, int);
 extern void auth_gsasl_version_report(FILE *f);


diff --git a/src/src/globals.h b/src/src/globals.h
index 03a56f0..bb66cb2 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -111,6 +111,7 @@ typedef struct {
   BOOL      ticket_received:1;
 #endif
   BOOL      verify_override:1;    /* certificate_verified only due to tls_try_verify_hosts */
+  BOOL      ext_master_secret:1;    /* extended-master-secret was used */
 } tls_support;
 extern tls_support tls_in;
 extern tls_support tls_out;
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 837b991..69a8bd6 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -2529,6 +2529,9 @@ if (rc != GNUTLS_E_SUCCESS)
   return FAIL;
   }


+if (gnutls_session_get_flags(state->session) & GNUTLS_SFLAGS_EXT_MASTER_SECRET)
+ tls_in.ext_master_secret = TRUE;
+
#ifdef EXPERIMENTAL_TLS_RESUME
tls_server_resume_posthandshake(state);
#endif
@@ -2998,6 +3001,9 @@ if (!verify_certificate(state, errstr))
return FALSE;
}

+if (gnutls_session_get_flags(state->session) & GNUTLS_SFLAGS_EXT_MASTER_SECRET)
+ tlsp->ext_master_secret = TRUE;
+
#ifndef DISABLE_OCSP
if (request_ocsp)
{
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index bee5a42..d16479e 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -2784,6 +2784,7 @@ if (SSL_session_reused(server_ssl))
/* TLS has been set up. Record data for the connection,
adjust the input functions to read via TLS, and initialize things. */

+tls_in.ext_master_secret = SSL_get_extms_support(server_ssl) == 1;
peer_cert(server_ssl, &tls_in, peerdn, sizeof(peerdn));

tls_in.ver = tlsver_name(server_ssl);
@@ -3384,6 +3385,7 @@ DEBUG(D_tls)
tls_client_resume_posthandshake(exim_client_ctx, tlsp);
#endif

+tlsp->ext_master_secret = SSL_get_extms_support(exim_client_ctx->ssl) == 1;
peer_cert(exim_client_ctx->ssl, tlsp, peerdn, sizeof(peerdn));

tlsp->ver = tlsver_name(exim_client_ctx->ssl);