[exim-cvs] Fix bug verifying certs on dual-tls.

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Fix bug verifying certs on dual-tls.
Gitweb: http://git.exim.org/exim.git/commitdiff/a2ff477a5d13000485dff61867b0001a7fb8e39f
Commit:     a2ff477a5d13000485dff61867b0001a7fb8e39f
Parent:     4ed8d31a9ccdfc4a948703fd8ac3f7cb6b8fdf8e
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Tue May 15 22:39:27 2012 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Mon Jun 4 14:57:03 2012 +0100


    Fix bug verifying certs on dual-tls.
---
 src/src/tls-openssl.c          |   74 ++++++++++++++++++++++++++++-----------
 test/scripts/2100-OpenSSL/2112 |    2 +-
 2 files changed, 54 insertions(+), 22 deletions(-)


diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 3140560..bbf6855 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -42,7 +42,8 @@ typedef struct randstuff {

/* Local static variables */

-static BOOL verify_callback_called = FALSE;
+static BOOL client_verify_callback_called = FALSE;
+static BOOL server_verify_callback_called = FALSE;
static const uschar *sid_ctx = US"exim";

static SSL_CTX *client_ctx = NULL;
@@ -57,7 +58,8 @@ static SSL_CTX *server_sni = NULL;
static char ssl_errstring[256];

static int ssl_session_timeout = 200;
-static BOOL verify_optional = FALSE;
+static BOOL client_verify_optional = FALSE;
+static BOOL server_verify_optional = FALSE;

 static BOOL    reexpand_tls_files_for_sni = FALSE;


@@ -84,7 +86,7 @@ tls_ext_ctx_cb *client_static_cbinfo = NULL;
tls_ext_ctx_cb *server_static_cbinfo = NULL;

static int
-setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host, BOOL optional);
+setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host, BOOL optional, BOOL client);

 /* Callbacks */
 #ifdef EXIM_HAVE_OPENSSL_TLSEXT
@@ -200,14 +202,31 @@ setting SSL_VERIFY_FAIL_IF_NO_PEER_CERT in the non-optional case.
 Arguments:
   state      current yes/no state as 1/0
   x509ctx    certificate information.
+  client     TRUE for client startup, FALSE for server startup


 Returns:     1 if verified, 0 if not
 */


static int
-verify_callback(int state, X509_STORE_CTX *x509ctx)
+verify_callback(int state, X509_STORE_CTX *x509ctx, BOOL client)
{
static uschar txt[256];
+tls_support * tlsp;
+BOOL * calledp;
+BOOL * optionalp;
+
+if (client)
+ {
+ tlsp= &tls_out;
+ calledp= &client_verify_callback_called;
+ optionalp= &client_verify_optional;
+ }
+else
+ {
+ tlsp= &tls_in;
+ calledp= &server_verify_callback_called;
+ optionalp= &server_verify_optional;
+ }

 X509_NAME_oneline(X509_get_subject_name(x509ctx->current_cert),
   CS txt, sizeof(txt));
@@ -218,9 +237,9 @@ if (state == 0)
     x509ctx->error_depth,
     X509_verify_cert_error_string(x509ctx->error),
     txt);
-  tls_in.certificate_verified = FALSE;
-  verify_callback_called = TRUE;
-  if (!verify_optional) return 0;    /* reject */
+  tlsp->certificate_verified = FALSE;
+  *calledp = TRUE;
+  if (!*optionalp) return 0;    /* reject */
   DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
     "tls_try_verify_hosts)\n");
   return 1;                          /* accept */
@@ -234,16 +253,28 @@ if (x509ctx->error_depth != 0)
 else
   {
   DEBUG(D_tls) debug_printf("SSL%s peer: %s\n",
-    verify_callback_called? "" : " authenticated", txt);
-  tls_in.peerdn = txt;
+    *calledp ? "" : " authenticated", txt);
+  tlsp->peerdn = txt;
   }


-if (!verify_callback_called) tls_in.certificate_verified = TRUE;
-verify_callback_called = TRUE;
+if (!*calledp) tlsp->certificate_verified = TRUE;
+*calledp = TRUE;

return 1; /* accept */
}

+static int
+verify_callback_client(int state, X509_STORE_CTX *x509ctx)
+{
+return verify_callback(state, x509ctx, TRUE);
+}
+
+static int
+verify_callback_server(int state, X509_STORE_CTX *x509ctx)
+{
+return verify_callback(state, x509ctx, FALSE);
+}
+


/*************************************************
@@ -644,7 +675,7 @@ if (cbinfo->ocsp_file)
}
#endif

-rc = setup_certs(server_sni, tls_verify_certificates, tls_crl, NULL, FALSE);
+rc = setup_certs(server_sni, tls_verify_certificates, tls_crl, NULL, FALSE, FALSE);
if (rc != OK) return SSL_TLSEXT_ERR_NOACK;

 /* do this after setup_certs, because this can require the certs for verifying
@@ -948,12 +979,13 @@ Arguments:
   host          NULL in a server; the remote host in a client
   optional      TRUE if called from a server for a host in tls_try_verify_hosts;
                 otherwise passed as FALSE
+  client        TRUE if called for client startup, FALSE for server startup


 Returns:        OK/DEFER/FAIL
 */


static int
-setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host, BOOL optional)
+setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host, BOOL optional, BOOL client)
{
uschar *expcerts, *expcrl;

@@ -1052,7 +1084,7 @@ if (expcerts != NULL)

   SSL_CTX_set_verify(sctx,
     SSL_VERIFY_PEER | (optional? 0 : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
-    verify_callback);
+    client ? verify_callback_client : verify_callback_server);
   }


return OK;
@@ -1127,19 +1159,19 @@ if (expciphers != NULL)
optional, set up appropriately. */

tls_in.certificate_verified = FALSE;
-verify_callback_called = FALSE;
+server_verify_callback_called = FALSE;

if (verify_check_host(&tls_verify_hosts) == OK)
{
- rc = setup_certs(server_ctx, tls_verify_certificates, tls_crl, NULL, FALSE);
+ rc = setup_certs(server_ctx, tls_verify_certificates, tls_crl, NULL, FALSE, FALSE);
if (rc != OK) return rc;
- verify_optional = FALSE;
+ server_verify_optional = FALSE;
}
else if (verify_check_host(&tls_try_verify_hosts) == OK)
{
- rc = setup_certs(server_ctx, tls_verify_certificates, tls_crl, NULL, TRUE);
+ rc = setup_certs(server_ctx, tls_verify_certificates, tls_crl, NULL, TRUE, FALSE);
if (rc != OK) return rc;
- verify_optional = TRUE;
+ server_verify_optional = TRUE;
}

/* Prepare for new connection */
@@ -1280,7 +1312,7 @@ rc = tls_init(&client_ctx, host, dhparam, certificate, privatekey,
if (rc != OK) return rc;

tls_out.certificate_verified = FALSE;
-verify_callback_called = FALSE;
+client_verify_callback_called = FALSE;

 if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
   return FAIL;
@@ -1298,7 +1330,7 @@ if (expciphers != NULL)
     return tls_error(US"SSL_CTX_set_cipher_list", host, NULL);
   }


-rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE);
+rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, TRUE);
if (rc != OK) return rc;

if ((client_ssl = SSL_new(client_ctx)) == NULL) return tls_error(US"SSL_new", host, NULL);
diff --git a/test/scripts/2100-OpenSSL/2112 b/test/scripts/2100-OpenSSL/2112
index 1a39b4e..4793929 100644
--- a/test/scripts/2100-OpenSSL/2112
+++ b/test/scripts/2100-OpenSSL/2112
@@ -1,5 +1,5 @@
# TLS client: verify certificate from server - fails
-exim -DSERVER=server -d+all -bd -oX PORT_D
+exim -DSERVER=server -bd -oX PORT_D
****
exim userx@???
Testing