[exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog exim…

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Tony Finch
Datum:  
To: exim-cvs
Betreff: [exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog exim/exim-src/src tls-gnu.c tls-openssl.c
fanf2 2008/09/03 19:53:29 BST

  Modified files:
    exim-doc/doc-txt     ChangeLog 
    exim-src/src         tls-gnu.c tls-openssl.c 
  Log:
  TLS error reporting now respects the incoming_interface and
  incoming_port log selectors.


  Revision  Changes    Path
  1.552     +3 -0      exim/exim-doc/doc-txt/ChangeLog
  1.20      +59 -81    exim/exim-src/src/tls-gnu.c
  1.13      +37 -56    exim/exim-src/src/tls-openssl.c


  Index: ChangeLog
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
  retrieving revision 1.551
  retrieving revision 1.552
  diff -u -r1.551 -r1.552
  --- ChangeLog    7 Aug 2008 11:05:03 -0000    1.551
  +++ ChangeLog    3 Sep 2008 18:53:29 -0000    1.552
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.551 2008/08/07 11:05:03 fanf2 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.552 2008/09/03 18:53:29 fanf2 Exp $


Change log file for Exim from version 4.21
-------------------------------------------
@@ -62,6 +62,9 @@

TF/07 Fix the way ${extract is skipped in the untaken branch of a conditional.

  +TF/08 TLS error reporting now respects the incoming_interface and
  +      incoming_port log selectors.
  +


Exim version 4.69
-----------------

  Index: tls-gnu.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-gnu.c,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- tls-gnu.c    13 Apr 2007 15:13:47 -0000    1.19
  +++ tls-gnu.c    3 Sep 2008 18:53:29 -0000    1.20
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-gnu.c,v 1.19 2007/04/13 15:13:47 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-gnu.c,v 1.20 2008/09/03 18:53:29 fanf2 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -26,14 +26,12 @@
   #define PARAM_SIZE 2*1024



-/* Values for verify_requirment and initialized */
+/* Values for verify_requirment */

enum { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED };
-enum { INITIALIZED_NOT, INITIALIZED_SERVER, INITIALIZED_CLIENT };

/* Local static variables for GNUTLS */

-static BOOL initialized = INITIALIZED_NOT;
static host_item *client_host;

   static gnutls_dh_params dh_params = NULL;
  @@ -164,27 +162,28 @@
     prefix    text to include in the logged error
     host      NULL if setting up a server;
               the connected host if setting up a client
  -  err       a GnuTLS error number, or 0 if local error
  +  msg       additional error string (may be NULL)
  +            usually obtained from gnutls_strerror()


   Returns:    OK/DEFER/FAIL
   */


   static int
  -tls_error(uschar *prefix, host_item *host, int err)
  +tls_error(uschar *prefix, host_item *host, const char *msg)
   {
  -uschar *errtext = US"";
  -if (err != 0) errtext = string_sprintf(": %s", gnutls_strerror(err));
   if (host == NULL)
     {
  -  log_write(0, LOG_MAIN, "TLS error on connection from %s (%s)%s",
  -    (sender_fullhost != NULL)? sender_fullhost : US "local process",
  -    prefix, errtext);
  +  uschar *conn_info = smtp_get_connection_info();
  +  if (strncmp(conn_info, "SMTP ", 5) == 0)
  +    conn_info += 5;
  +  log_write(0, LOG_MAIN, "TLS error on %s (%s)%s%s",
  +    conn_info, prefix, msg ? ": " : "", msg ? msg : "");
     return DEFER;
     }
   else
     {
  -  log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s)%s",
  -    host->name, host->address, prefix, errtext);
  +  log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s)%s%s",
  +    host->name, host->address, prefix, msg ? ": " : "", msg ? msg : "");
     return FAIL;
     }
   }
  @@ -206,7 +205,7 @@
   */


   static BOOL
  -verify_certificate(gnutls_session session, uschar **error)
  +verify_certificate(gnutls_session session, const char **error)
   {
   int verify;
   uschar *dn_string = US"";
  @@ -241,7 +240,7 @@
     {
     DEBUG(D_tls) debug_printf("no peer certificate supplied\n");
     verify = GNUTLS_CERT_INVALID;
  -  *error = US"not supplied";
  +  *error = "not supplied";
     }


   /* Handle the result of verification. INVALID seems to be set as well
  @@ -251,7 +250,7 @@
     {
     tls_certificate_verified = FALSE;
     if (*error == NULL) *error = ((verify & GNUTLS_CERT_REVOKED) != 0)?
  -    US"revoked" : US"invalid";
  +    "revoked" : "invalid";
     if (verify_requirement == VERIFY_REQUIRED)
       {
       DEBUG(D_tls) debug_printf("TLS certificate verification failed (%s): "
  @@ -306,13 +305,13 @@
   /* Initialize the data structures for holding the parameters */


ret = gnutls_dh_params_init(&dh_params);
-if (ret < 0) return tls_error(US"init dh_params", host, ret);
+if (ret < 0) return tls_error(US"init dh_params", host, gnutls_strerror(ret));

/* Set up the name of the cache file */

   if (!string_format(filename, sizeof(filename), "%s/gnutls-params",
         spool_directory))
  -  return tls_error(US"overlong filename", host, 0);
  +  return tls_error(US"overlong filename", host, NULL);


   /* Open the cache file for reading and if successful, read it and set up the
   parameters. */
  @@ -324,19 +323,21 @@
     if (fstat(fd, &statbuf) < 0)
       {
       (void)close(fd);
  -    return tls_error(US"TLS cache stat failed", host, 0);
  +    return tls_error(US"TLS cache stat failed", host, strerror(errno));
       }


     m.size = statbuf.st_size;
     m.data = malloc(m.size);
     if (m.data == NULL)
  -    return tls_error(US"memory allocation failed", host, 0);
  +    return tls_error(US"memory allocation failed", host, strerror(errno));
  +  errno = 0;
     if (read(fd, m.data, m.size) != m.size)
  -    return tls_error(US"TLS cache read failed", host, 0);
  +    return tls_error(US"TLS cache read failed", host, strerror(errno));
     (void)close(fd);


     ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
  -  if (ret < 0) return tls_error(US"DH params import", host, ret);
  +  if (ret < 0)
  +    return tls_error(US"DH params import", host, gnutls_strerror(ret));
     DEBUG(D_tls) debug_printf("read D-H parameters from file\n");


     free(m.data);
  @@ -353,7 +354,7 @@
     }
   else
     return tls_error(string_open_failed(errno, "%s for reading", filename),
  -    host, 0);
  +    host, NULL);


   /* If ret < 0, either the cache file does not exist, or the data it contains
   is not useful. One particular case of this is when upgrading from an older
  @@ -368,7 +369,7 @@
     DEBUG(D_tls) debug_printf("generating %d bit Diffie-Hellman key...\n",
       DH_BITS);
     ret = gnutls_dh_params_generate2(dh_params, DH_BITS);
  -  if (ret < 0) return tls_error(US"D-H key generation", host, ret);
  +  if (ret < 0) return tls_error(US"D-H key generation", host, gnutls_strerror(ret));


     /* Write the parameters to a file in the spool directory so that we
     can use them from other Exim processes. */
  @@ -377,7 +378,7 @@
     fd = Uopen(tempfilename, O_WRONLY|O_CREAT, 0400);
     if (fd < 0)
       return tls_error(string_open_failed(errno, "%s for writing", filename),
  -      host, 0);
  +      host, NULL);
     (void)fchown(fd, exim_uid, exim_gid);   /* Probably not necessary */


     /* export the parameters in a format that can be generated using GNUTLS'
  @@ -390,23 +391,25 @@
     m.size = PARAM_SIZE;
     m.data = malloc(m.size);
     if (m.data == NULL)
  -    return tls_error(US"memory allocation failed", host, 0);
  +    return tls_error(US"memory allocation failed", host, strerror(errno));


     m.size = PARAM_SIZE;
     ret = gnutls_dh_params_export_pkcs3(dh_params, GNUTLS_X509_FMT_PEM, m.data,
       &m.size);
  -  if (ret < 0) return tls_error(US"DH params export", host, ret);
  +  if (ret < 0)
  +    return tls_error(US"DH params export", host, gnutls_strerror(ret));


     m.size = Ustrlen(m.data);
  +  errno = 0;
     if (write(fd, m.data, m.size) != m.size || write(fd, "\n", 1) != 1)
  -    return tls_error(US"TLS cache write failed", host, 0);
  +    return tls_error(US"TLS cache write failed", host, strerror(errno));


     free(m.data);
     (void)close(fd);


     if (rename(CS tempfilename, CS filename) < 0)
  -    return tls_error(string_sprintf("failed to rename %s as %s: %s",
  -      tempfilename, filename, strerror(errno)), host, 0);
  +    return tls_error(string_sprintf("failed to rename %s as %s",
  +      tempfilename, filename), host, strerror(errno));


     DEBUG(D_tls) debug_printf("wrote D-H parameters to file %s\n", filename);
     }
  @@ -442,10 +445,10 @@
   int rc;
   uschar *cert_expanded, *key_expanded, *cas_expanded, *crl_expanded;


-initialized = (host == NULL)? INITIALIZED_SERVER : INITIALIZED_CLIENT;
+client_host = host;

rc = gnutls_global_init();
-if (rc < 0) return tls_error(US"tls-init", host, rc);
+if (rc < 0) return tls_error(US"tls-init", host, gnutls_strerror(rc));

/* Create D-H parameters, or read them from the cache file. This function does
its own SMTP error messaging. */
@@ -456,7 +459,9 @@
/* Create the credentials structure */

   rc = gnutls_certificate_allocate_credentials(&x509_cred);
  -if (rc < 0) return tls_error(US"certificate_allocate_credentials", host, rc);
  +if (rc < 0)
  +  return tls_error(US"certificate_allocate_credentials",
  +    host, gnutls_strerror(rc));


   /* This stuff must be done for each session, because different certificates
   may be required for different sessions. */
  @@ -490,7 +495,7 @@
       {
       uschar *msg = string_sprintf("cert/key setup: cert=%s key=%s",
         cert_expanded, key_expanded);
  -    return tls_error(msg, host, rc);
  +    return tls_error(msg, host, gnutls_strerror(rc));
       }
     }


  @@ -499,7 +504,7 @@
   else
     {
     if (host == NULL)
  -    return tls_error(US"no TLS server certificate is specified", host, 0);
  +    return tls_error(US"no TLS server certificate is specified", NULL, NULL);
     DEBUG(D_tls) debug_printf("no TLS client certificate is specified\n");
     }


  @@ -532,7 +537,7 @@
       {
       rc = gnutls_certificate_set_x509_trust_file(x509_cred, CS cas_expanded,
         GNUTLS_X509_FMT_PEM);
  -    if (rc < 0) return tls_error(US"setup_certs", host, rc);
  +    if (rc < 0) return tls_error(US"setup_certs", host, gnutls_strerror(rc));


       if (crl != NULL && *crl != 0)
         {
  @@ -541,7 +546,7 @@
         DEBUG(D_tls) debug_printf("loading CRL file = %s\n", crl_expanded);
         rc = gnutls_certificate_set_x509_crl_file(x509_cred, CS crl_expanded,
           GNUTLS_X509_FMT_PEM);
  -      if (rc < 0) return tls_error(US"CRL setup", host, rc);
  +      if (rc < 0) return tls_error(US"CRL setup", host, gnutls_strerror(rc));
         }
       }
     }
  @@ -855,7 +860,7 @@
     uschar *require_kx, uschar *require_proto)
   {
   int rc;
  -uschar *error;
  +const char *error;
   uschar *expciphers = NULL;
   uschar *expmac = NULL;
   uschar *expkx = NULL;
  @@ -865,9 +870,7 @@


   if (tls_active >= 0)
     {
  -  log_write(0, LOG_MAIN, "STARTTLS received in already encrypted "
  -    "connection from %s",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process");
  +  tls_error("STARTTLS received after TLS started", NULL, "");
     smtp_printf("554 Already in TLS\r\n");
     return FAIL;
     }
  @@ -903,7 +906,8 @@
   tls_session = tls_session_init(GNUTLS_SERVER, expciphers, expmac, expkx,
     expproto);
   if (tls_session == NULL)
  -  return tls_error(US"tls_session_init", NULL, GNUTLS_E_MEMORY_ERROR);
  +  return tls_error(US"tls_session_init", NULL,
  +    gnutls_strerror(GNUTLS_E_MEMORY_ERROR));


/* Set context and tell client to go ahead, except in the case of TLS startup
on connection, where outputting anything now upsets the clients and tends to
@@ -930,14 +934,8 @@

   if (rc < 0)
     {
  -  if (sigalrm_seen)
  -    Ustrcpy(ssl_errstring, "timed out");
  -  else
  -    Ustrcpy(ssl_errstring, gnutls_strerror(rc));
  -  log_write(0, LOG_MAIN,
  -    "TLS error on connection from %s (gnutls_handshake): %s",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process",
  -    ssl_errstring);
  +  tls_error(US"gnutls_handshake", NULL,
  +    sigalrm_seen ? "timed out" : gnutls_strerror(rc));


     /* It seems that, except in the case of a timeout, we have to close the
     connection right here; otherwise if the other end is running OpenSSL it hangs
  @@ -957,9 +955,7 @@
   if (verify_requirement != VERIFY_NONE &&
        !verify_certificate(tls_session, &error))
     {
  -  log_write(0, LOG_MAIN,
  -    "TLS error on connection from %s: certificate verification failed (%s)",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process", error);
  +  tls_error(US"certificate verification failed", NULL, error);
     return FAIL;
     }


@@ -1022,13 +1018,12 @@
uschar *expmac = NULL;
uschar *expkx = NULL;
uschar *expproto = NULL;
-uschar *error;
+const char *error;
unsigned int server_certs_size;
int rc;

DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");

  -client_host = host;
   verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
   rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
   if (rc != OK) return rc;
  @@ -1043,7 +1038,8 @@
     expproto);


   if (tls_session == NULL)
  -  return tls_error(US "tls_session_init", host, GNUTLS_E_MEMORY_ERROR);
  +  return tls_error(US "tls_session_init", host,
  +    gnutls_strerror(GNUTLS_E_MEMORY_ERROR));


gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);

@@ -1055,15 +1051,8 @@
alarm(0);

   if (rc < 0)
  -  {
  -  if (sigalrm_seen)
  -    {
  -    log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
  -      "gnutls_handshake timed out", host->name, host->address);
  -    return FAIL;
  -    }
  -  else return tls_error(US "gnutls_handshake", host, rc);
  -  }
  +  return tls_error(US "gnutls_handshake", host,
  +    sigalrm_seen ? "timed out" : gnutls_strerror(rc));


server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);

@@ -1087,12 +1076,7 @@

   if (verify_requirement != VERIFY_NONE &&
         !verify_certificate(tls_session, &error))
  -  {
  -  log_write(0, LOG_MAIN,
  -    "TLS error on connection to %s [%s]: certificate verification failed (%s)",
  -    host->name, host->address, error);
  -  return FAIL;
  -  }
  +  return tls_error(US"certificate verification failed", host, error);


   construct_cipher_name(tls_session);    /* Sets tls_cipher */
   tls_active = fd;
  @@ -1118,21 +1102,15 @@
   static void
   record_io_error(int ec, uschar *when, uschar *text)
   {
  -uschar *additional = US"";
  +const char *msg;


   if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
  -  additional = string_sprintf(": %s",
  +  msg = string_sprintf("%s: %s", gnutls_strerror(ec),
       gnutls_alert_get_name(gnutls_alert_get(tls_session)));
  -
  -if (initialized == INITIALIZED_SERVER)
  -  log_write(0, LOG_MAIN, "TLS %s error on connection from %s: %s%s", when,
  -    (sender_fullhost != NULL)? sender_fullhost : US "local process",
  -    (ec == 0)? text : US gnutls_strerror(ec), additional);
  -
   else
  -  log_write(0, LOG_MAIN, "TLS %s error on connection to %s [%s]: %s%s", when,
  -    client_host->name, client_host->address,
  -    (ec == 0)? text : US gnutls_strerror(ec), additional);
  +  msg = gnutls_strerror(ec);
  +
  +tls_error(when, client_host, msg);
   }




  Index: tls-openssl.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-openssl.c,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- tls-openssl.c    13 Apr 2007 15:13:47 -0000    1.12
  +++ tls-openssl.c    3 Sep 2008 18:53:29 -0000    1.13
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.12 2007/04/13 15:13:47 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.13 2008/09/03 18:53:29 fanf2 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -62,25 +62,33 @@
     prefix    text to include in the logged error
     host      NULL if setting up a server;
               the connected host if setting up a client
  +  msg       error message or NULL if we should ask OpenSSL


   Returns:    OK/DEFER/FAIL
   */


   static int
  -tls_error(uschar *prefix, host_item *host)
  +tls_error(uschar *prefix, host_item *host, uschar *msg)
   {
  -ERR_error_string(ERR_get_error(), ssl_errstring);
  +if (msg == NULL)
  +  {
  +  ERR_error_string(ERR_get_error(), ssl_errstring);
  +  msg = ssl_errstring;
  +  }
  +
   if (host == NULL)
     {
  -  log_write(0, LOG_MAIN, "TLS error on connection from %s (%s): %s",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process",
  -    prefix, ssl_errstring);
  +  uschar *conn_info = smtp_get_connection_info();
  +  if (strncmp(conn_info, "SMTP ", 5) == 0)
  +    conn_info += 5;
  +  log_write(0, LOG_MAIN, "TLS error on %s (%s): %s",
  +    conn_info, prefix, msg);
     return DEFER;
     }
   else
     {
     log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s): %s",
  -    host->name, host->address, prefix, ssl_errstring);
  +    host->name, host->address, prefix, msg);
     return FAIL;
     }
   }
  @@ -224,12 +232,13 @@


   Arguments:
     dhparam   DH parameter file
  +  host      connected host, if client; NULL if server


   Returns:    TRUE if OK (nothing to set up, or setup worked)
   */


static BOOL
-init_dh(uschar *dhparam)
+init_dh(uschar *dhparam, host_item *host)
{
BOOL yield = TRUE;
BIO *bio;
@@ -243,16 +252,16 @@

   if ((bio = BIO_new_file(CS dhexpanded, "r")) == NULL)
     {
  -  log_write(0, LOG_MAIN, "DH: could not read %s: %s", dhexpanded,
  -    strerror(errno));
  +  tls_error(string_sprintf("could not read dhparams file %s", dhexpanded),
  +    host, strerror(errno));
     yield = FALSE;
     }
   else
     {
     if ((dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL)
       {
  -    log_write(0, LOG_MAIN, "DH: could not load params from %s",
  -      dhexpanded);
  +    tls_error(string_sprintf("could not read dhparams file %s", dhexpanded),
  +      host, NULL);
       yield = FALSE;
       }
     else
  @@ -301,7 +310,7 @@
   ctx = SSL_CTX_new((host == NULL)?
     SSLv23_server_method() : SSLv23_client_method());


-if (ctx == NULL) return tls_error(US"SSL_CTX_new", host);
+if (ctx == NULL) return tls_error(US"SSL_CTX_new", host, NULL);

   /* It turns out that we need to seed the random number generator this early in
   order to get the full complement of ciphers to work. It took me roughly a day
  @@ -322,22 +331,8 @@
     if (addr != NULL) RAND_seed((uschar *)addr, sizeof(addr));


     if (!RAND_status())
  -    {
  -    if (host == NULL)
  -      {
  -      log_write(0, LOG_MAIN, "TLS error on connection from %s: "
  -        "unable to seed random number generator",
  -        (sender_fullhost != NULL)? sender_fullhost : US"local process");
  -      return DEFER;
  -      }
  -    else
  -      {
  -      log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
  -        "unable to seed random number generator",
  -        host->name, host->address);
  -      return FAIL;
  -      }
  -    }
  +    return tls_error(US"RAND_status", host,
  +      "unable to seed random number generator");
     }


/* Set up the information callback, which outputs if debugging is at a suitable
@@ -358,12 +353,12 @@
/* XXX (Silently?) ignore failure here? XXX*/

if (!(SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)))
- return tls_error(US"SSL_CTX_set_option", host);
+ return tls_error(US"SSL_CTX_set_option", host, NULL);
#endif

/* Initialize with DH parameters if supplied */

-if (!init_dh(dhparam)) return DEFER;
+if (!init_dh(dhparam, host)) return DEFER;

/* Set up certificate and key */

  @@ -378,7 +373,7 @@
       DEBUG(D_tls) debug_printf("tls_certificate file %s\n", expanded);
       if (!SSL_CTX_use_certificate_chain_file(ctx, CS expanded))
         return tls_error(string_sprintf(
  -        "SSL_CTX_use_certificate_chain_file file=%s", expanded), host);
  +        "SSL_CTX_use_certificate_chain_file file=%s", expanded), host, NULL);
       }


     if (privatekey != NULL &&
  @@ -394,7 +389,7 @@
       DEBUG(D_tls) debug_printf("tls_privatekey file %s\n", expanded);
       if (!SSL_CTX_use_PrivateKey_file(ctx, CS expanded, SSL_FILETYPE_PEM))
         return tls_error(string_sprintf(
  -        "SSL_CTX_use_PrivateKey_file file=%s", expanded), host);
  +        "SSL_CTX_use_PrivateKey_file file=%s", expanded), host, NULL);
       }
     }


  @@ -491,7 +486,7 @@
     {
     struct stat statbuf;
     if (!SSL_CTX_set_default_verify_paths(ctx))
  -    return tls_error(US"SSL_CTX_set_default_verify_paths", host);
  +    return tls_error(US"SSL_CTX_set_default_verify_paths", host, NULL);


     if (Ustat(expcerts, &statbuf) < 0)
       {
  @@ -514,7 +509,7 @@


       if ((file == NULL || statbuf.st_size > 0) &&
             !SSL_CTX_load_verify_locations(ctx, CS file, CS dir))
  -      return tls_error(US"SSL_CTX_load_verify_locations", host);
  +      return tls_error(US"SSL_CTX_load_verify_locations", host, NULL);


       if (file != NULL)
         {
  @@ -564,7 +559,7 @@
           DEBUG(D_tls) debug_printf("SSL CRL value is a file %s\n", file);
           }
         if (X509_STORE_load_locations(cvstore, CS file, CS dir) == 0)
  -        return tls_error(US"X509_STORE_load_locations", host);
  +        return tls_error(US"X509_STORE_load_locations", host, NULL);


         /* setting the flags to check against the complete crl chain */


@@ -620,9 +615,7 @@

   if (tls_active >= 0)
     {
  -  log_write(0, LOG_MAIN, "STARTTLS received in already encrypted "
  -    "connection from %s",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process");
  +  tls_error("STARTTLS received after TLS started", NULL, "");
     smtp_printf("554 Already in TLS\r\n");
     return FAIL;
     }
  @@ -646,7 +639,7 @@
     while (*s != 0) { if (*s == '_') *s = '-'; s++; }
     DEBUG(D_tls) debug_printf("required ciphers: %s\n", expciphers);
     if (!SSL_CTX_set_cipher_list(ctx, CS expciphers))
  -    return tls_error(US"SSL_CTX_set_cipher_list", NULL);
  +    return tls_error(US"SSL_CTX_set_cipher_list", NULL, NULL);
     }


/* If this is a host for which certificate verification is mandatory or
@@ -670,7 +663,7 @@

/* Prepare for new connection */

-if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", NULL);
+if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", NULL, NULL);
SSL_clear(ssl);

/* Set context and tell client to go ahead, except in the case of TLS startup
@@ -702,11 +695,7 @@

   if (rc <= 0)
     {
  -  if (sigalrm_seen) Ustrcpy(ssl_errstring, "timed out");
  -    else ERR_error_string(ERR_get_error(), ssl_errstring);
  -  log_write(0, LOG_MAIN, "TLS error on connection from %s (SSL_accept): %s",
  -    (sender_fullhost != NULL)? sender_fullhost : US"local process",
  -    ssl_errstring);
  +  tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL);
     return FAIL;
     }


  @@ -801,13 +790,13 @@
     while (*s != 0) { if (*s == '_') *s = '-'; s++; }
     DEBUG(D_tls) debug_printf("required ciphers: %s\n", expciphers);
     if (!SSL_CTX_set_cipher_list(ctx, CS expciphers))
  -    return tls_error(US"SSL_CTX_set_cipher_list", host);
  +    return tls_error(US"SSL_CTX_set_cipher_list", host, NULL);
     }


rc = setup_certs(verify_certs, crl, host, FALSE);
if (rc != OK) return rc;

-if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", host);
+if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", host, NULL);
SSL_set_session_id_context(ssl, sid_ctx, Ustrlen(sid_ctx));
SSL_set_fd(ssl, fd);
SSL_set_connect_state(ssl);
@@ -821,15 +810,7 @@
alarm(0);

   if (rc <= 0)
  -  {
  -  if (sigalrm_seen)
  -    {
  -    log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
  -      "SSL_connect timed out", host->name, host->address);
  -    return FAIL;
  -    }
  -  else return tls_error(US"SSL_connect", host);
  -  }
  +  return tls_error(US"SSL_connect", host, sigalrm_seen ? US"timed out" : NULL);


DEBUG(D_tls) debug_printf("SSL_connect succeeded\n");