[Exim] [patch] various TLS issues

Góra strony
Delete this message
Reply to this message
Autor: Steve Haslam
Data:  
Dla: exim-users
Temat: [Exim] [patch] various TLS issues
--
Hi,

As intimated, I've been poking around in the TLS code. I've made a big patch
that I'll quickly run through to give y'all an overview. Some of the
features you might not find worthwhile.

** Support for getting entropy from EGD/PRNGD

New config option: tls_prngd_pool <string>, pathname of EGD/PRNGD socket.

EGD (Entropy Gathering Daemon) gathers entropy and makes it available to
clients via a UNIX socket. This can be used to abstract away the problem of
where to get entropy on machines that don't have /dev/random, or where
/dev/random is not a good source.

PRNGD is interface-compatible with EGD, but contains a PRNG so that it can
always give data to a client-- i.e. it works like /dev/urnadom rather than
/dev/random.

** TLS certificate verification: verify hostname

New SMTP transport option: tls_verify_hostname

This allows to verify that the remote cerficiate matches the hostname that
we tried to connect to. So if we connected to outmail.example.com and get
the certificate for CN=interloper.example.com, ... then treat the
certificate as unverified. Hostname can be specified either in the CN of the
subject, or as a dNSNAME in the subjectAltName (although I've yet to be
convinced that OpenSSL's implementation of this actually matches anyone
else's implementation). Doesn't currently handle wilcard matching or IP
address matching.

** TLS certificate verification: make peer CN available

New expansion variable: tls_peercn

This just makes the CN part of the subject of the peer certificate available
as ${tls_peercn}. This can be easier to work with than the full tls_peerdn
in conditions, lookups etc.

** TLS certificate verification: make more debuggin information available

Lots more information avilable during verification when -d+tls is given. So
otherwise "mysterious" errors like "invalid certificate purpose" can be dug
out.

..

still to do:

Passing the verification result around is messy. probably change it to use
SSL_get_verify_result() instead.

If a server has tls_verify_certificates etc set up, but the client does not
have the server's CA certificate, the error is #19 (self-signed certificate
in chain) not "certificate issue not found" as you might expect. OpenSSL is
sending the root CA certificate as part of the SSL certificate chain, and I
don't think it should. (At least, the error messages suggest that it
shouldn't, and I remember that some web browsers just drop an SSL connection
if they find a self-signed certificate in the presented chain). If this is
indeed a bug, then it's an OpenSSL bug (in sslv3_send_certificate_chain()).
Will investigate. (Hmm, perhaps I should try and write a test client with
GNU TLS).

..

WHile I'm poking around in all the TLS stuff, are there any other things
that people have in mind for TLS? (that isn't on the main exim wishlist)

SRH
--
Steve Haslam      Reading, UK                           araqnid@???
Debian GNU/Linux Maintainer                               araqnid@???
                               maybe the human race deserves to be wiped out
--
Only in exim-4.10: build-Linux-i386
Only in exim-4.10: build-Linux-i386-light
Only in exim-4.10: debian
Only in exim-4.10/Local: eximon.conf
Only in exim-4.10/Local: Makefile
diff -x daemon.c -ru vanilla/exim-4.10/src/expand.c exim-4.10/src/expand.c
--- vanilla/exim-4.10/src/expand.c    2002-07-22 09:59:48.000000000 +0100
+++ exim-4.10/src/expand.c    2002-09-10 21:49:52.000000000 +0100
@@ -247,6 +247,7 @@
   { "thisaddress",         vtype_stringptr,   &filter_thisaddress },
 #ifdef SUPPORT_TLS
   { "tls_cipher",          vtype_stringptr,   &tls_cipher },
+  { "tls_peercn",          vtype_stringptr,   &tls_peercn },
   { "tls_peerdn",          vtype_stringptr,   &tls_peerdn },
 #endif
   { "tod_bsdinbox",        vtype_todbsdin,    NULL },
Only in exim-4.10/src: expand.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/functions.h exim-4.10/src/functions.h
--- vanilla/exim-4.10/src/functions.h    2002-07-22 09:59:48.000000000 +0100
+++ exim-4.10/src/functions.h    2002-09-11 00:29:38.000000000 +0100
@@ -22,7 +22,7 @@


 #ifdef SUPPORT_TLS
 extern BOOL    tls_client_start(int, host_item *, address_item *, uschar *,
-                 uschar *, uschar *, uschar *, uschar *, int);
+                 uschar *, uschar *, uschar *, uschar *, int, int);
 extern void    tls_close(BOOL);
 extern int     tls_feof(void);
 extern int     tls_ferror(void);
Only in exim-4.10/src: functions.h~
diff -x daemon.c -ru vanilla/exim-4.10/src/globals.c exim-4.10/src/globals.c
--- vanilla/exim-4.10/src/globals.c    2002-07-22 09:59:48.000000000 +0100
+++ exim-4.10/src/globals.c    2002-09-10 23:55:24.000000000 +0100
@@ -94,7 +94,9 @@
 BOOL    tls_offered            = FALSE;
 BOOL    tls_on_connect         = FALSE;
 uschar *tls_peerdn             = NULL;
+uschar *tls_peercn             = NULL;
 uschar *tls_privatekey         = NULL;
+uschar *tls_prngd_pool         = NULL;
 uschar *tls_try_verify_hosts   = NULL;
 uschar *tls_verify_certificates= NULL;
 uschar *tls_verify_hosts       = NULL;
Only in exim-4.10/src: globals.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/globals.h exim-4.10/src/globals.h
--- vanilla/exim-4.10/src/globals.h    2002-07-22 09:59:49.000000000 +0100
+++ exim-4.10/src/globals.h    2002-09-10 23:55:04.000000000 +0100
@@ -59,7 +59,9 @@
 extern BOOL    tls_offered;            /* Server offered TLS */
 extern BOOL    tls_on_connect;         /* For older MTAs that don't STARTTLS */
 extern uschar *tls_peerdn;             /* DN from peer */
+extern uschar *tls_peercn;             /* Just the commonName part of the peer DN */
 extern uschar *tls_privatekey;         /* Private key file */
+extern uschar *tls_prngd_pool;         /* PRNGD/EGD socket path */
 extern uschar *tls_try_verify_hosts;   /* Optional client verification */
 extern uschar *tls_verify_certificates;/* Path for certificates to check */
 extern uschar *tls_verify_hosts;       /* Mandatory client verification */
Only in exim-4.10/src: globals.h~
diff -x daemon.c -ru vanilla/exim-4.10/src/readconf.c exim-4.10/src/readconf.c
--- vanilla/exim-4.10/src/readconf.c    2002-07-22 09:59:50.000000000 +0100
+++ exim-4.10/src/readconf.c    2002-09-10 23:54:45.000000000 +0100
@@ -199,6 +199,7 @@
   { "tls_certificate",          opt_stringptr,   &tls_certificate },
   { "tls_dhparam",              opt_stringptr,   &tls_dhparam },
   { "tls_privatekey",           opt_stringptr,   &tls_privatekey },
+  { "tls_prngd_pool",           opt_stringptr,   &tls_prngd_pool },
   { "tls_try_verify_hosts",     opt_stringptr,   &tls_try_verify_hosts },
   { "tls_verify_certificates",  opt_stringptr,   &tls_verify_certificates },
   { "tls_verify_hosts",         opt_stringptr,   &tls_verify_hosts },
Only in exim-4.10/src: readconf.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/spool_in.c exim-4.10/src/spool_in.c
--- vanilla/exim-4.10/src/spool_in.c    2002-07-22 09:59:51.000000000 +0100
+++ exim-4.10/src/spool_in.c    2002-09-10 21:22:05.000000000 +0100
@@ -366,6 +366,8 @@
       tls_cipher = string_copy(big_buffer + 12);
     else if (Ustrncmp(big_buffer, "-tls_peerdn", 11) == 0)
       tls_peerdn = string_copy(big_buffer + 12);
+    else if (Ustrncmp(big_buffer, "-tls_peercn", 11) == 0)
+      tls_peerdn = string_copy(big_buffer + 12);
     #endif


     /* We now record the port number after the address, separated by a
Only in exim-4.10/src: spool_in.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/spool_out.c exim-4.10/src/spool_out.c
--- vanilla/exim-4.10/src/spool_out.c    2002-07-22 09:59:51.000000000 +0100
+++ exim-4.10/src/spool_out.c    2002-09-10 21:23:16.000000000 +0100
@@ -206,6 +206,7 @@
 #ifdef SUPPORT_TLS
 if (tls_cipher != NULL) fprintf(f, "-tls_cipher %s\n", tls_cipher);
 if (tls_peerdn != NULL) fprintf(f, "-tls_peerdn %s\n", tls_peerdn);
+if (tls_peercn != NULL) fprintf(f, "-tls_peercn %s\n", tls_peercn);
 #endif


 /* To complete the envelope, write out the tree of non-recipients, followed by
Only in exim-4.10/src: spool_out.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/tls.c exim-4.10/src/tls.c
--- vanilla/exim-4.10/src/tls.c    2002-07-22 09:59:51.000000000 +0100
+++ exim-4.10/src/tls.c    2002-09-11 01:25:38.000000000 +0100
@@ -29,6 +29,7 @@
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
+#include <openssl/x509v3.h>


/* Structure for collecting random data for seeding. */

@@ -43,7 +44,7 @@

static int session_timeout = 200;
static BOOL verify_optional = FALSE;
-static BOOL verify_callback_called = FALSE;
+static const char *verify_check_hostname = NULL;

static const uschar *sid_ctx = US"exim";
static uschar *ssl_xfer_buffer = NULL;
@@ -58,7 +59,24 @@



+/*************************************************
+*               Format ASN.1 time value          *
+*************************************************/
+
+/* May be called when debugging and displaying times as embedded in
+   certificates */
+
+static uschar *ASN1_TIME_to_string(ASN1_TIME *a, uschar *buf, size_t buflen)
+{
+  BIO *bio = BIO_new(BIO_s_mem());
+
+  ASN1_TIME_print(bio, a);
+  BIO_gets(bio, buf, buflen);
+
+  BIO_free(bio);


+ return buf;
+}

 /*************************************************
 *               Handle TLS error                 *
@@ -166,40 +184,186 @@
 static int
 verify_callback(int state, X509_STORE_CTX *x509ctx)
 {
-static uschar txt[256];
+  uschar subject[512];
+  X509 *err_cert;
+  int err,depth;
+
+  err_cert = X509_STORE_CTX_get_current_cert(x509ctx);
+  err      = X509_STORE_CTX_get_error(x509ctx);
+  depth    = X509_STORE_CTX_get_error_depth(x509ctx);
+
+  X509_NAME_oneline(X509_get_subject_name(err_cert), CS subject, sizeof(subject));
+
+  if (state == 0) {
+    /* there was a verification problem with this certificate */
+    if (verify_optional) {
+      DEBUG(D_tls) debug_printf("X.509 VERIFY %2d IGN \"%s\" [Err#%d: %s] (overridden)\n", depth, subject, err, X509_verify_cert_error_string(err));
+      log_write(0, LOG_MAIN, "SSL verify error: "
+        " (overridden)"
+        "depth=%d error=%s cert=%s",
+        depth,
+        X509_verify_cert_error_string(err),
+        subject);
+      state = 1;
+    }
+    else {
+      DEBUG(D_tls) debug_printf("X.509 VERIFY %2d ERR \"%s\" [Err#%d: %s]\n", depth, subject, err, X509_verify_cert_error_string(err));
+      log_write(0, LOG_MAIN, "SSL verify error: "
+        "depth=%d error=%s cert=%s",
+        depth,
+        X509_verify_cert_error_string(err),
+        subject);
+    }
+
+    /* Show some extra information about the certificate when debugging */
+    DEBUG(D_tls) {
+      uschar issuer[512];
+      uschar timebuf[256];
+
+      switch (err) {
+      case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+    X509_NAME_oneline(X509_get_subject_name(err_cert), CS issuer, sizeof(issuer));
+    debug_printf(" Issuer: %s\n", issuer);
+    break;
+
+      case X509_V_ERR_CERT_NOT_YET_VALID:
+      case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+    debug_printf(" notBefore=%s\n", ASN1_TIME_to_string(X509_get_notBefore(err_cert), timebuf, sizeof(timebuf)));
+    break;
+
+      case X509_V_ERR_CERT_HAS_EXPIRED:
+      case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+    debug_printf(" notAfter=%s\n", ASN1_TIME_to_string(X509_get_notAfter(err_cert), timebuf, sizeof(timebuf)));
+    break;
+
+      case X509_V_ERR_INVALID_PURPOSE:
+    if (err_cert->ex_flags & EXFLAG_NSCERT) {
+      debug_printf(" nsCertType: ");
+
+      if (err_cert->ex_nscert & NS_SSL_CLIENT)
+        debug_printf("sslClient ");
+      if (err_cert->ex_nscert & NS_SSL_SERVER)
+        debug_printf("sslServer ");
+
+      if (err_cert->ex_nscert & ~(NS_SSL_SERVER|NS_SSL_CLIENT))
+        debug_printf("...");
+
+      debug_printf("\n");
+    }
+
+    if (err_cert->ex_flags & EXFLAG_KUSAGE) {
+      debug_printf(" keyUsage: ");
+
+      if (err_cert->ex_kusage & KU_DIGITAL_SIGNATURE)
+        debug_printf("digitalSignature ");
+      if (err_cert->ex_kusage & KU_KEY_ENCIPHERMENT)
+        debug_printf("keyEncipherment ");
+
+      if (err_cert->ex_kusage & ~(KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE))
+        debug_printf("...");
+
+      debug_printf("\n");
+    }
+
+    if (err_cert->ex_flags & EXFLAG_XKUSAGE) {
+      debug_printf(" extendedKeyUsage: ");
+
+      if (err_cert->ex_xkusage & XKU_SSL_SERVER)
+        debug_printf("sslServer ");
+      if (err_cert->ex_xkusage & XKU_SSL_CLIENT)
+        debug_printf("sslClient ");


-X509_NAME_oneline(X509_get_subject_name(x509ctx->current_cert),
-  CS txt, sizeof(txt));
+      if (err_cert->ex_xkusage & ~(XKU_SSL_SERVER|XKU_SSL_CLIENT))
+        debug_printf("...");


-if (state == 0)
-  {
-  log_write(0, LOG_MAIN, "SSL verify error: depth=%d error=%s cert=%s",
-    x509ctx->error_depth,
-    X509_verify_cert_error_string(x509ctx->error),
-    txt);
-  verify_callback_called = TRUE;
-  if (!verify_optional) return 0;    /* reject */
-  DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
-    "tls_try_verify_hosts)\n");
-  return 1;                          /* accept */
-  }
+      debug_printf("\n");
+    }


-if (x509ctx->error_depth != 0)
-  {
-  DEBUG(D_tls) debug_printf("SSL verify ok: depth=%d cert=%s\n",
-     x509ctx->error_depth, txt);
-  }
-else
-  {
-  DEBUG(D_tls) debug_printf("SSL%s peer: %s\n",
-    verify_callback_called? "" : " authenticated", txt);
-  tls_peerdn = txt;
+        break;
+      }
+    }
   }
+  else {
+    DEBUG(D_tls) debug_printf("X.509 VERIFY %2d OK  \"%s\"\n", depth, subject);
+    if (depth == 0)
+      tls_certificate_verified = TRUE;
+  }
+
+  if (state == 1 && depth == 0 && verify_check_hostname) {
+    char peer_CN[256];
+    X509_NAME_get_text_by_NID(X509_get_subject_name(err_cert),
+                  NID_commonName, peer_CN, sizeof(peer_CN));
+
+    DEBUG(D_tls) debug_printf("Authenticating server hostname \"%s\"\n", verify_check_hostname);
+    if (strcasecmp(peer_CN, verify_check_hostname) == 0) {
+      DEBUG(D_tls) debug_printf("Verified server certificate using common name\n");
+    }
+    else {
+      int n = 0;
+      int found_altname = 0;
+
+      while ((n = X509_get_ext_by_NID(err_cert, NID_subject_alt_name, n)) > 0) {
+    X509_EXTENSION *ex;
+    X509V3_EXT_METHOD *method;
+    char *ext_str = NULL;
+    unsigned char *p;
+    ex = X509_get_ext(err_cert, n);
+    method = X509V3_EXT_get(ex);
+
+    DEBUG(D_tls) debug_printf("Found subjectAltName extension, critical=%d\n", ex->critical);
+    if (!method->i2v)
+      continue; /* subjectAltName not multi-valued? */
+
+    p = ex->value->data;
+    ext_str = method->d2i(NULL, &p, ex->value->length);
+    if (ext_str) {
+      STACK_OF(CONF_VALUE) *nval;
+      nval = method->i2v(method, ext_str, NULL);
+      if (nval) {
+        int i;
+        DEBUG(D_tls) debug_printf(" multi-valued num=%d\n", sk_CONF_VALUE_num(nval));
+        for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+          CONF_VALUE *innervalue = sk_CONF_VALUE_value(nval, i);
+          DEBUG(D_tls) {
+        debug_printf(" %2d: ", i);
+        if (innervalue->section) {
+          debug_printf("section=\"%s\" ", innervalue->section);
+        }
+        if (innervalue->name) {
+          debug_printf("name=\"%s\" ", innervalue->name);
+        }
+        if (innervalue->value) {
+          debug_printf("value=\"%s\" ", innervalue->value);
+        }
+        debug_printf("\n");
+          }
+          if (strcmp(innervalue->name, "DNS") == 0){
+        if (strcmp(innervalue->value, verify_check_hostname) == 0) {
+          found_altname = 1;
+        }
+        /* else { wildcard matches... } */
+          }
+          /* else { IP address matches... } */
+        }
+        sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+      }
+      method->ext_free(ext_str);
+    }
+      }


-if (!verify_callback_called) tls_certificate_verified = TRUE;
-verify_callback_called = TRUE;
+      if (found_altname) {
+    DEBUG(D_tls) debug_printf("Authenticated host name using subject alternate name\n");
+      }
+      else {
+    log_write(0, LOG_MAIN, "TLS authentication error: "
+          "Certificate common name (\"%s\") does not match hostname",
+          peer_CN);
+    state = 0;
+      }
+    }
+  }


-return 1; /* accept */
+ return state; /* 1 = accept; 0 = raise error */
}


@@ -367,8 +531,31 @@
there. Otherwise, we have to make something up as best we can. Double check
afterwards. */

+ if (tls_prngd_pool) {
+   if (RAND_egd_bytes(tls_prngd_pool, 255) < 255) {
+     if (host == NULL) {
+       log_write(0, LOG_MAIN, "TLS error on connection from %s: "
+         "unable to get entropy from egd/prngd: %s",
+         sender_fullhost ? sender_fullhost : US"local process",
+         strerror(errno)
+         );
+       smtp_printf("454 TLS currently unavailable\r\n");
+     }
+     else {
+       log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
+         "unable to get entropy from egd/prngd: %s",
+         host->name, host->address,
+         strerror(errno)
+         );
+     }
+     return FALSE;
+   }
+ }
+
 if (!RAND_status())
   {
+    /* SRH: make people use /dev/urandom or EGD/PRNGD instead of this */
+#if 0
   randstuff r;
   r.t = time(NULL);
   r.p = getpid();
@@ -379,6 +566,7 @@


   if (!RAND_status())
     {
+#endif
     if (host == NULL)
       {
       log_write(0, LOG_MAIN, "TLS error on connection from %s: "
@@ -394,7 +582,9 @@
       }
     return FALSE;
     }
+#if 0
   }
+#endif


 /* Set up the information callback, which outputs if debugging is at a suitable
 level. */
@@ -550,6 +740,11 @@
     SSL_VERIFY_PEER | (optional? 0 : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
     verify_callback);
   }
+ else {
+   /* Do basic verification of the peer certificate even if we aren't
+      checking against a CA */
+   SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+ }


return TRUE;
}
@@ -577,6 +772,7 @@
tls_server_start(void)
{
int rc;
+X509 *peer_cert;

/* Check for previous activation */

@@ -599,7 +795,6 @@
optional, set up appropriately. */

tls_certificate_verified = FALSE;
-verify_callback_called = FALSE;

if (verify_check_host(&tls_verify_hosts) == OK)
{
@@ -611,6 +806,7 @@
if (!setup_certs(tls_verify_certificates, NULL, TRUE)) return FALSE;
verify_optional = TRUE;
}
+verify_check_hostname = NULL;

/* Prepare for new connection */

@@ -665,6 +861,30 @@

construct_cipher_name(ssl);

+ peer_cert = SSL_get_peer_certificate(ssl);
+ if (peer_cert) {
+   static uschar subject[512];
+   static uschar peer_CN[256];
+
+   /* Get the peer cert's subject into tls_peerdn */
+   X509_NAME_oneline(X509_get_subject_name(peer_cert),
+             CS subject, sizeof(subject));
+   tls_peerdn = CS subject;
+   DEBUG(D_tls) debug_printf("Client certificate = %s\n", tls_peerdn);
+
+   /* Get the CN part of the subject */
+   /* Administrator may want to verify the CN matches the hostname
+      (leave this to be configured in an ACL?) */
+   X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
+                 NID_commonName, peer_CN, sizeof(peer_CN));
+   DEBUG(D_tls) debug_printf(" commonName = \"%s\"\n", peer_CN);
+   tls_peercn = CS peer_CN;
+ }
+ else {
+   tls_peerdn = tls_peercn = NULL;
+   DEBUG(D_tls) debug_printf("Client did not present a certificate\n");
+ }
+
 DEBUG(D_tls)
   {
   uschar buf[2048];
@@ -711,9 +931,8 @@
 BOOL
 tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
   uschar *certificate, uschar *privatekey, uschar *verify_certs,
-  uschar *require_ciphers, int timeout)
+  uschar *require_ciphers, int verify_hostname, int timeout)
 {
-static uschar txt[256];
 uschar *expciphers;
 X509* server_cert;
 int rc;
@@ -730,6 +949,7 @@
   }


if (!setup_certs(verify_certs, host, FALSE)) return FALSE;
+verify_check_hostname = verify_hostname ? host->name : NULL;

if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", host);
SSL_set_session_id_context(ssl, sid_ctx, Ustrlen(sid_ctx));
@@ -756,10 +976,19 @@
else return tls_error(US"SSL_connect", host);
}

-server_cert = SSL_get_peer_certificate (ssl);
-tls_peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert),
-  CS txt, sizeof(txt));
-tls_peerdn = txt;
+ if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
+   static uschar subject[256];
+   uschar peer_CN[256];
+
+   X509_NAME_oneline(X509_get_subject_name(server_cert),
+             CS subject, sizeof(subject));
+   tls_peerdn = subject;
+   DEBUG(D_tls) debug_printf("Server certificate = %s\n", tls_peerdn);
+ }
+ else {
+   /* This really shouldn't happen */
+   tls_peerdn = tls_peercn = NULL;
+ }


construct_cipher_name(ssl); /* Sets tls_cipher */

Only in exim-4.10/src: tls.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/transports/smtp.c exim-4.10/src/transports/smtp.c
--- vanilla/exim-4.10/src/transports/smtp.c    2002-07-22 09:59:51.000000000 +0100
+++ exim-4.10/src/transports/smtp.c    2002-09-11 00:56:14.000000000 +0100
@@ -95,7 +95,9 @@
   { "tls_tempfail_tryclear", opt_bool,
       (void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) },
   { "tls_verify_certificates", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }
+      (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) },
+  { "tls_verify_hostname",   opt_bool,
+      (void *)offsetof(smtp_transport_options_block, tls_verify_hostname) }
   #endif
 };


@@ -142,7 +144,8 @@
   NULL,                /* tls_privatekey */
   NULL,                /* tls_require_ciphers */
   NULL,                /* tls_verify_certificates */
-  TRUE                 /* tls_tempfail_tryclear */
+  TRUE,                /* tls_tempfail_tryclear */
+  FALSE /*??-SRH*/     /* tls_verify_hostname */
   #endif
 };


@@ -865,6 +868,7 @@
       ob->tls_privatekey,
       ob->tls_verify_certificates,
       ob->tls_require_ciphers,
+      ob->tls_verify_hostname,
       ob->command_timeout);


     /* TLS negotiation failed; give an error. From outside, this function may
Only in exim-4.10/src/transports: smtp.c~
diff -x daemon.c -ru vanilla/exim-4.10/src/transports/smtp.h exim-4.10/src/transports/smtp.h
--- vanilla/exim-4.10/src/transports/smtp.h    2002-07-22 09:59:51.000000000 +0100
+++ exim-4.10/src/transports/smtp.h    2002-09-11 00:24:08.000000000 +0100
@@ -43,6 +43,7 @@
   uschar *tls_require_ciphers;
   uschar *tls_verify_certificates;
   BOOL    tls_tempfail_tryclear;
+  BOOL    tls_verify_hostname;
   #endif
 } smtp_transport_options_block;


Only in exim-4.10/src/transports: smtp.h~
--