Rocco Rutte:
[apps/madmutt.git] / mutt_ssl_gnutls.c
index d1b26e1..7b6cb09 100644 (file)
@@ -1,48 +1,49 @@
-/* Copyright (C) 2001 Marco d'Itri <md@linux.it>
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 2001 Marco d'Itri <md@linux.it>
  * Copyright (C) 2001-2004 Andrew McDonald <andrew@mcdonald.org.uk>
  *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
  */
 
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
+#ifdef HAVE_GNUTLS_OPENSSL_H
+#include <gnutls/openssl.h>
+#endif
 
 #include "mutt.h"
 #include "mutt_socket.h"
 #include "mutt_curses.h"
 #include "mutt_menu.h"
 #include "mutt_ssl.h"
-#include "mutt_regex.h"
 
-typedef struct _tlssockdata
-{
+#include "lib/mem.h"
+#include "lib/str.h"
+#include "lib/intl.h"
+#include "lib/rx.h"
+
+typedef struct _tlssockdata {
   gnutls_session state;
   gnutls_certificate_credentials xcred;
-}
-tlssockdata;
+} tlssockdata;
 
 /* local prototypes */
-static int tls_socket_read (CONNECTION* conn, char* buf, size_t len);
-static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len);
-static int tls_socket_open (CONNECTION* conn);
-static int tls_socket_close (CONNECTION* conn);
-static int tls_starttls_close (CONNECTION* conn);
+static int tls_socket_read (CONNECTION * conn, char *buf, size_t len);
+static int tls_socket_write (CONNECTION * conn, const char *buf, size_t len);
+static int tls_socket_open (CONNECTION * conn);
+static int tls_socket_close (CONNECTION * conn);
+static int tls_starttls_close (CONNECTION * conn);
 
 static int tls_init (void);
-static int tls_negotiate (CONNECTION* conn);
-static int tls_check_certificate (CONNECTION* conn);
+static int tls_negotiate (CONNECTION * conn);
+static int tls_check_certificate (CONNECTION * conn);
 
 
 static int tls_init (void)
@@ -53,10 +54,9 @@ static int tls_init (void)
   if (init_complete)
     return 0;
 
-  err = gnutls_global_init();
-  if (err < 0)
-  {
-    mutt_error ("gnutls_global_init: %s", gnutls_strerror(err));
+  err = gnutls_global_init ();
+  if (err < 0) {
+    mutt_error ("gnutls_global_init: %s", gnutls_strerror (err));
     mutt_sleep (2);
     return -1;
   }
@@ -65,34 +65,32 @@ static int tls_init (void)
   return 0;
 }
 
-int mutt_gnutls_socket_setup (CONNECTION* conn)
+int mutt_gnutls_socket_setup (CONNECTION * conn)
 {
-  if (tls_init() < 0)
+  if (tls_init () < 0)
     return -1;
 
-  conn->open   = tls_socket_open;
-  conn->read   = tls_socket_read;
-  conn->write  = tls_socket_write;
-  conn->close  = tls_socket_close;
+  conn->conn_open = tls_socket_open;
+  conn->conn_read = tls_socket_read;
+  conn->conn_write = tls_socket_write;
+  conn->conn_close = tls_socket_close;
 
   return 0;
 }
 
-static int tls_socket_read (CONNECTION* conn, char* buf, size_t len)
+static int tls_socket_read (CONNECTION * conn, char *buf, size_t len)
 {
   tlssockdata *data = conn->sockdata;
   int ret;
 
-  if (!data)
-  {
+  if (!data) {
     mutt_error ("Error: no TLS socket open");
     mutt_sleep (2);
     return -1;
   }
 
   ret = gnutls_record_recv (data->state, buf, len);
-  if (gnutls_error_is_fatal(ret) == 1)
-  {
+  if (gnutls_error_is_fatal (ret) == 1) {
     mutt_error ("tls_socket_read (%s)", gnutls_strerror (ret));
     mutt_sleep (4);
     return -1;
@@ -100,21 +98,19 @@ static int tls_socket_read (CONNECTION* conn, char* buf, size_t len)
   return ret;
 }
 
-static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len)
+static int tls_socket_write (CONNECTION * conn, const char *buf, size_t len)
 {
   tlssockdata *data = conn->sockdata;
   int ret;
 
-  if (!data)
-  {
+  if (!data) {
     mutt_error ("Error: no TLS socket open");
     mutt_sleep (2);
     return -1;
   }
 
   ret = gnutls_record_send (data->state, buf, len);
-  if (gnutls_error_is_fatal(ret) == 1)
-  {
+  if (gnutls_error_is_fatal (ret) == 1) {
     mutt_error ("tls_socket_write (%s)", gnutls_strerror (ret));
     mutt_sleep (4);
     return -1;
@@ -122,13 +118,12 @@ static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len)
   return ret;
 }
 
-static int tls_socket_open (CONNECTION* conn)
+static int tls_socket_open (CONNECTION * conn)
 {
   if (raw_socket_open (conn) < 0)
     return -1;
 
-  if (tls_negotiate (conn) < 0)
-  {
+  if (tls_negotiate (conn) < 0) {
     tls_socket_close (conn);
     return -1;
   }
@@ -136,22 +131,22 @@ static int tls_socket_open (CONNECTION* conn)
   return 0;
 }
 
-int mutt_gnutls_starttls (CONNECTION* conn)
+int mutt_gnutls_starttls (CONNECTION * conn)
 {
-  if (tls_init() < 0)
+  if (tls_init () < 0)
     return -1;
 
   if (tls_negotiate (conn) < 0)
     return -1;
 
-  conn->read   = tls_socket_read;
-  conn->write  = tls_socket_write;
-  conn->close  = tls_starttls_close;
+  conn->conn_read = tls_socket_read;
+  conn->conn_write = tls_socket_write;
+  conn->conn_close = tls_starttls_close;
 
   return 0;
 }
 
-static int protocol_priority[] = {GNUTLS_TLS1, GNUTLS_SSL3, 0};
+static int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
 
 /* tls_negotiate: After TLS state has been initialised, attempt to negotiate
  *   TLS over the wire, including certificate checks. */
@@ -163,20 +158,19 @@ static int tls_negotiate (CONNECTION * conn)
   data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));
   conn->sockdata = data;
   err = gnutls_certificate_allocate_credentials (&data->xcred);
-  if (err < 0)
-  {
-    FREE(&conn->sockdata);
-    mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
+  if (err < 0) {
+    FREE (&conn->sockdata);
+    mutt_error ("gnutls_certificate_allocate_credentials: %s",
+                gnutls_strerror (err));
     mutt_sleep (2);
     return -1;
   }
 
   gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile,
-                                         GNUTLS_X509_FMT_PEM);
+                                          GNUTLS_X509_FMT_PEM);
   /* ignore errors, maybe file doesn't exist yet */
 
-  if (SslCACertFile)
-  {
+  if (SslCACertFile) {
     gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile,
                                             GNUTLS_X509_FMT_PEM);
   }
@@ -186,39 +180,35 @@ static int tls_negotiate (CONNECTION * conn)
   gnutls_set_x509_cert_callback (data->xcred, cert_callback);
 */
 
-  gnutls_init(&data->state, GNUTLS_CLIENT);
+  gnutls_init (&data->state, GNUTLS_CLIENT);
 
   /* set socket */
-  gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd);
+  gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr) conn->fd);
 
   /* disable TLS/SSL protocols as needed */
-  if (!option(OPTTLSV1) && !option(OPTSSLV3))
-  {
+  if (!option (OPTTLSV1) && !option (OPTSSLV3)) {
     mutt_error (_("All available protocols for TLS/SSL connection disabled"));
     goto fail;
   }
-  else if (!option(OPTTLSV1))
-  {
+  else if (!option (OPTTLSV1)) {
     protocol_priority[0] = GNUTLS_SSL3;
     protocol_priority[1] = 0;
   }
-  else if (!option(OPTSSLV3))
-  {
+  else if (!option (OPTSSLV3)) {
     protocol_priority[0] = GNUTLS_TLS1;
     protocol_priority[1] = 0;
   }
   /*
-  else
-    use the list set above
-  */
+     else
+     use the list set above
+   */
 
   /* We use default priorities (see gnutls documentation),
      except for protocol version */
   gnutls_set_default_priority (data->state);
   gnutls_protocol_set_priority (data->state, protocol_priority);
 
-  if (SslDHPrimeBits > 0)
-  {
+  if (SslDHPrimeBits > 0) {
     gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits);
   }
 
@@ -228,72 +218,71 @@ static int tls_negotiate (CONNECTION * conn)
 
   gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);
 
-  err = gnutls_handshake(data->state);
+  err = gnutls_handshake (data->state);
 
-  while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
-  {
-    err = gnutls_handshake(data->state);
+  while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED) {
+    err = gnutls_handshake (data->state);
   }
   if (err < 0) {
-    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
-    {
-      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
-                gnutls_alert_get_name(gnutls_alert_get(data->state)));
+    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) {
+      mutt_error ("gnutls_handshake: %s(%s)", gnutls_strerror (err),
+                  gnutls_alert_get_name (gnutls_alert_get (data->state)));
     }
-    else
-    {
-      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
+    else {
+      mutt_error ("gnutls_handshake: %s", gnutls_strerror (err));
     }
     mutt_sleep (2);
     goto fail;
   }
 
-  if (!tls_check_certificate(conn))
+  if (!tls_check_certificate (conn))
     goto fail;
 
   /* set Security Strength Factor (SSF) for SASL */
   /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
-  conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8;
+  conn->ssf =
+    gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8;
 
   mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"),
-               gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)),
-               gnutls_kx_get_name (gnutls_kx_get (data->state)),
-               gnutls_cipher_get_name (gnutls_cipher_get (data->state)),
-               gnutls_mac_get_name (gnutls_mac_get (data->state)));
+                gnutls_protocol_get_name (gnutls_protocol_get_version
+                                          (data->state)),
+                gnutls_kx_get_name (gnutls_kx_get (data->state)),
+                gnutls_cipher_get_name (gnutls_cipher_get (data->state)),
+                gnutls_mac_get_name (gnutls_mac_get (data->state)));
   mutt_sleep (0);
 
   return 0;
 
- fail:
+fail:
   gnutls_certificate_free_credentials (data->xcred);
   gnutls_deinit (data->state);
-  FREE(&conn->sockdata);
+  FREE (&conn->sockdata);
   return -1;
 }
 
-static int tls_socket_close (CONNECTION* conn)
+static int tls_socket_close (CONNECTION * conn)
 {
   tlssockdata *data = conn->sockdata;
-  if (data)
-  {
+
+  if (data) {
     gnutls_bye (data->state, GNUTLS_SHUT_RDWR);
 
     gnutls_certificate_free_credentials (data->xcred);
     gnutls_deinit (data->state);
-    safe_free ((void **) &conn->sockdata);
+    FREE(&conn->sockdata);
   }
 
   return raw_socket_close (conn);
 }
 
-static int tls_starttls_close (CONNECTION* conn)
+static int tls_starttls_close (CONNECTION * conn)
 {
   int rc;
 
   rc = tls_socket_close (conn);
-  conn->read = raw_socket_read;
-  conn->write = raw_socket_write;
-  conn->close = raw_socket_close;
+  conn->conn_read = raw_socket_read;
+  conn->conn_write = raw_socket_write;
+  conn->conn_close = raw_socket_close;
 
   return rc;
 }
@@ -301,7 +290,7 @@ static int tls_starttls_close (CONNECTION* conn)
 #define CERT_SEP "-----BEGIN"
 
 /* this bit is based on read_ca_file() in gnutls */
-static int tls_compare_certificates (const gnutls_datum *peercert)
+static int tls_compare_certificates (const gnutls_datum * peercert)
 {
   gnutls_datum cert;
   unsigned char *ptr;
@@ -311,48 +300,45 @@ static int tls_compare_certificates (const gnutls_datum *peercert)
   unsigned char *b64_data_data;
   struct stat filestat;
 
-  if (stat(SslCertFile, &filestat) == -1)
+  if (stat (SslCertFile, &filestat) == -1)
     return 0;
 
-  b64_data.size = filestat.st_size+1;
+  b64_data.size = filestat.st_size + 1;
   b64_data_data = (unsigned char *) safe_calloc (1, b64_data.size);
-  b64_data_data[b64_data.size-1] = '\0';
+  b64_data_data[b64_data.size - 1] = '\0';
   b64_data.data = b64_data_data;
 
-  fd1 = fopen(SslCertFile, "r");
+  fd1 = fopen (SslCertFile, "r");
   if (fd1 == NULL) {
     return 0;
   }
 
-  b64_data.size = fread(b64_data.data, 1, b64_data.size, fd1);
-  fclose(fd1);
+  b64_data.size = fread (b64_data.data, 1, b64_data.size, fd1);
+  fclose (fd1);
 
   do {
-    ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
-    if (ret != 0)
-    {
+    ret = gnutls_pem_base64_decode_alloc (NULL, &b64_data, &cert);
+    if (ret != 0) {
       FREE (&b64_data_data);
       return 0;
     }
 
-    ptr = (unsigned char *)strstr(b64_data.data, CERT_SEP) + 1;
-    ptr = (unsigned char *)strstr(ptr, CERT_SEP);
+    ptr = (unsigned char *) strstr (b64_data.data, CERT_SEP) + 1;
+    ptr = (unsigned char *) strstr (ptr, CERT_SEP);
 
     b64_data.size = b64_data.size - (ptr - b64_data.data);
     b64_data.data = ptr;
 
-    if (cert.size == peercert->size)
-    {
-      if (memcmp (cert.data, peercert->data, cert.size) == 0)
-      {
-       /* match found */
-        gnutls_free(cert.data);
-       FREE (&b64_data_data);
-       return 1;
+    if (cert.size == peercert->size) {
+      if (memcmp (cert.data, peercert->data, cert.size) == 0) {
+        /* match found */
+        gnutls_free (cert.data);
+        FREE (&b64_data_data);
+        return 1;
       }
     }
 
-    gnutls_free(cert.data);
+    gnutls_free (cert.data);
   } while (ptr != NULL);
 
   /* no match found */
@@ -361,7 +347,7 @@ static int tls_compare_certificates (const gnutls_datum *peercert)
 }
 
 static void tls_fingerprint (gnutls_digest_algorithm algo,
-                             char* s, int l, const gnutls_datum* data)
+                             char *s, int l, const gnutls_datum * data)
 {
   unsigned char md[36];
   size_t n;
@@ -369,19 +355,17 @@ static void tls_fingerprint (gnutls_digest_algorithm algo,
 
   n = 36;
 
-  if (gnutls_fingerprint (algo, data, (char *)md, &n) < 0)
-  {
+  if (gnutls_fingerprint (algo, data, (char *) md, &n) < 0) {
     snprintf (s, l, _("[unable to calculate]"));
   }
-  else
-  {
-    for (j = 0; j < (int) n; j++)
-    {
+  else {
+    for (j = 0; j < (int) n; j++) {
       char ch[8];
+
       snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));
       strncat (s, ch, l);
     }
-    s[2*n+n/2-1] = '\0'; /* don't want trailing space */
+    s[2 * n + n / 2 - 1] = '\0';        /* don't want trailing space */
   }
 }
 
@@ -390,16 +374,16 @@ static char *tls_make_date (time_t t, char *s, size_t len)
   struct tm *l = gmtime (&t);
 
   if (l)
-    snprintf (s, len,  "%s, %d %s %d %02d:%02d:%02d UTC",
-             Weekdays[l->tm_wday], l->tm_mday, Months[l->tm_mon],
-             l->tm_year + 1900, l->tm_hour, l->tm_min, l->tm_sec);
+    snprintf (s, len, "%s, %d %s %d %02d:%02d:%02d UTC",
+              Weekdays[l->tm_wday], l->tm_mday, Months[l->tm_mon],
+              l->tm_year + 1900, l->tm_hour, l->tm_min, l->tm_sec);
   else
     strfcpy (s, _("[invalid date]"), len);
 
   return (s);
 }
 
-static int tls_check_stored_hostname (const gnutls_datum *cert,
+static int tls_check_stored_hostname (const gnutls_datum * cert,
                                       const char *hostname)
 {
   char buf[80];
@@ -411,45 +395,43 @@ static int tls_check_stored_hostname (const gnutls_datum *cert,
   regmatch_t pmatch[3];
 
   /* try checking against names stored in stored certs file */
-  if ((fp = fopen (SslCertFile, "r")))
-  {
-    if (regcomp(&preg, "^#H ([a-zA-Z0-9_\\.-]+) ([0-9A-F]{4}( [0-9A-F]{4}){7})[ \t]*$", REG_ICASE|REG_EXTENDED) != 0)
-    {
-       regfree(&preg);
-       return 0;
+  if ((fp = fopen (SslCertFile, "r"))) {
+    if (regcomp
+        (&preg,
+         "^#H ([a-zA-Z0-9_\\.-]+) ([0-9A-F]{4}( [0-9A-F]{4}){7})[ \t]*$",
+         REG_ICASE | REG_EXTENDED) != 0) {
+      regfree (&preg);
+      return 0;
     }
 
     buf[0] = '\0';
     tls_fingerprint (GNUTLS_DIG_MD5, buf, sizeof (buf), cert);
-    while ((linestr = mutt_read_line(linestr, &linestrsize, fp, &linenum)) != NULL)
-    {
-      if(linestr[0] == '#' && linestr[1] == 'H')
-      {
-        if (regexec(&preg, linestr, 3, pmatch, 0) == 0)
-        {
+    while ((linestr =
+            mutt_read_line (linestr, &linestrsize, fp, &linenum)) != NULL) {
+      if (linestr[0] == '#' && linestr[1] == 'H') {
+        if (regexec (&preg, linestr, 3, pmatch, 0) == 0) {
           linestr[pmatch[1].rm_eo] = '\0';
           linestr[pmatch[2].rm_eo] = '\0';
-          if (strcmp(linestr + pmatch[1].rm_so, hostname) == 0 &&
-              strcmp(linestr + pmatch[2].rm_so, buf) == 0)
-          {
-            regfree(&preg);
-            safe_free((void**)&linestr);
-            fclose(fp);
+          if (mutt_strcmp (linestr + pmatch[1].rm_so, hostname) == 0 &&
+              mutt_strcmp (linestr + pmatch[2].rm_so, buf) == 0) {
+            regfree (&preg);
+            FREE(&linestr);
+            fclose (fp);
             return 1;
           }
         }
       }
     }
 
-    regfree(&preg);
-    fclose(fp);
+    regfree (&preg);
+    fclose (fp);
   }
 
   /* not found a matching name */
   return 0;
 }
 
-static int tls_check_certificate (CONNECTION* conn)
+static int tls_check_certificate (CONNECTION * conn)
 {
   tlssockdata *data = conn->sockdata;
   gnutls_session state = data->state;
@@ -482,94 +464,81 @@ static int tls_check_certificate (CONNECTION* conn)
   int certerr_revoked = 0;
   int certerr_signernotca = 0;
 
-  if (gnutls_auth_get_type(state) != GNUTLS_CRD_CERTIFICATE)
-  {
+  if (gnutls_auth_get_type (state) != GNUTLS_CRD_CERTIFICATE) {
     mutt_error (_("Unable to get certificate from peer"));
     mutt_sleep (2);
     return 0;
   }
 
-  certstat = gnutls_certificate_verify_peers(state);
+  certstat = gnutls_certificate_verify_peers (state);
 
-  if (certstat == GNUTLS_E_NO_CERTIFICATE_FOUND)
-  {
+  if (certstat == GNUTLS_E_NO_CERTIFICATE_FOUND) {
     mutt_error (_("Unable to get certificate from peer"));
     mutt_sleep (2);
     return 0;
   }
-  if (certstat < 0)
-  {
-    mutt_error (_("Certificate verification error (%s)"), gnutls_strerror(certstat));
+  if (certstat < 0) {
+    mutt_error (_("Certificate verification error (%s)"),
+                gnutls_strerror (certstat));
     mutt_sleep (2);
     return 0;
   }
 
   /* We only support X.509 certificates (not OpenPGP) at the moment */
-  if (gnutls_certificate_type_get(state) != GNUTLS_CRT_X509)
-  {
+  if (gnutls_certificate_type_get (state) != GNUTLS_CRT_X509) {
     mutt_error (_("Error certificate is not X.509"));
     mutt_sleep (2);
     return 0;
   }
 
-  if (gnutls_x509_crt_init(&cert) < 0)
-  {
+  if (gnutls_x509_crt_init (&cert) < 0) {
     mutt_error (_("Error initialising gnutls certificate data"));
     mutt_sleep (2);
     return 0;
   }
 
-  cert_list = gnutls_certificate_get_peers(state, &cert_list_size);
-  if (!cert_list)
-  {
+  cert_list = gnutls_certificate_get_peers (state, &cert_list_size);
+  if (!cert_list) {
     mutt_error (_("Unable to get certificate from peer"));
     mutt_sleep (2);
     return 0;
   }
 
   /* FIXME: Currently only check first certificate in chain. */
-  if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
-  {
+  if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) {
     mutt_error (_("Error processing certificate data"));
     mutt_sleep (2);
     return 0;
   }
 
-  if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
-  {
+  if (gnutls_x509_crt_get_expiration_time (cert) < time (NULL)) {
     certerr_expired = 1;
   }
 
-  if (gnutls_x509_crt_get_activation_time(cert) > time(NULL))
-  {
+  if (gnutls_x509_crt_get_activation_time (cert) > time (NULL)) {
     certerr_notyetvalid = 1;
   }
 
-  if (!gnutls_x509_crt_check_hostname(cert, conn->account.host) &&
-      !tls_check_stored_hostname (&cert_list[0], conn->account.host))
-  {
+  if (!gnutls_x509_crt_check_hostname (cert, conn->account.host) &&
+      !tls_check_stored_hostname (&cert_list[0], conn->account.host)) {
     certerr_hostname = 1;
   }
 
   /* see whether certificate is in our cache (certificates file) */
-  if (tls_compare_certificates (&cert_list[0]))
-  {
-    if (certstat & GNUTLS_CERT_INVALID)
-    {
+  if (tls_compare_certificates (&cert_list[0])) {
+    if (certstat & GNUTLS_CERT_INVALID) {
       /* doesn't matter - have decided is valid because server
          certificate is in our trusted cache */
       certstat ^= GNUTLS_CERT_INVALID;
     }
 
-    if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND)
-    {
+    if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND) {
       /* doesn't matter that we haven't found the signer, since
          certificate is in our trusted cache */
       certstat ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
     }
 
-    if (certstat & GNUTLS_CERT_SIGNER_NOT_CA)
-    {
+    if (certstat & GNUTLS_CERT_SIGNER_NOT_CA) {
       /* Hmm. Not really sure how to handle this, but let's say
          that we don't care if the CA certificate hasn't got the
          correct X.509 basic constraints if server certificate is
@@ -579,27 +548,23 @@ static int tls_check_certificate (CONNECTION* conn)
 
   }
 
-  if (certstat & GNUTLS_CERT_REVOKED)
-  {
+  if (certstat & GNUTLS_CERT_REVOKED) {
     certerr_revoked = 1;
     certstat ^= GNUTLS_CERT_REVOKED;
   }
 
-  if (certstat & GNUTLS_CERT_INVALID)
-  {
+  if (certstat & GNUTLS_CERT_INVALID) {
     certerr_nottrusted = 1;
     certstat ^= GNUTLS_CERT_INVALID;
   }
 
-  if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND)
-  {
+  if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND) {
     /* NB: already cleared if cert in cache */
     certerr_nottrusted = 1;
     certstat ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
   }
 
-  if (certstat & GNUTLS_CERT_SIGNER_NOT_CA)
-  {
+  if (certstat & GNUTLS_CERT_SIGNER_NOT_CA) {
     /* NB: already cleared if cert in cache */
     certerr_signernotca = 1;
     certstat ^= GNUTLS_CERT_SIGNER_NOT_CA;
@@ -609,10 +574,9 @@ static int tls_check_certificate (CONNECTION* conn)
   /* we've been zeroing the interesting bits in certstat - 
      don't return OK if there are any unhandled bits we don't
      understand */
-  if (!(certerr_expired || certerr_notyetvalid || 
-       certerr_hostname || certerr_nottrusted) && certstat == 0)
-  {
-    gnutls_x509_crt_deinit(cert);
+  if (!(certerr_expired || certerr_notyetvalid ||
+        certerr_hostname || certerr_nottrusted) && certstat == 0) {
+    gnutls_x509_crt_deinit (cert);
     return 1;
   }
 
@@ -625,141 +589,157 @@ static int tls_check_certificate (CONNECTION* conn)
     menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));
 
   row = 0;
-  strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
+  strfcpy (menu->dialog[row], _("This certificate belongs to:"),
+           SHORT_STRING);
   row++;
 
-  buflen = sizeof(dn_common_name);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
-                                    dn_common_name, &buflen) != 0)
+  buflen = sizeof (dn_common_name);
+  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
+                                     dn_common_name, &buflen) != 0)
     dn_common_name[0] = '\0';
-  buflen = sizeof(dn_email);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
-                                    dn_email, &buflen) != 0)
+  buflen = sizeof (dn_email);
+  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
+                                     dn_email, &buflen) != 0)
     dn_email[0] = '\0';
-  buflen = sizeof(dn_organization);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
-                                    dn_organization, &buflen) != 0)
+  buflen = sizeof (dn_organization);
+  if (gnutls_x509_crt_get_dn_by_oid
+      (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, dn_organization,
+       &buflen) != 0)
     dn_organization[0] = '\0';
-  buflen = sizeof(dn_organizational_unit);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
-                                    dn_organizational_unit, &buflen) != 0)
+  buflen = sizeof (dn_organizational_unit);
+  if (gnutls_x509_crt_get_dn_by_oid
+      (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
+       dn_organizational_unit, &buflen) != 0)
     dn_organizational_unit[0] = '\0';
-  buflen = sizeof(dn_locality);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
-                                    dn_locality, &buflen) != 0)
+  buflen = sizeof (dn_locality);
+  if (gnutls_x509_crt_get_dn_by_oid
+      (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, dn_locality, &buflen) != 0)
     dn_locality[0] = '\0';
-  buflen = sizeof(dn_province);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
-                                    dn_province, &buflen) != 0)
+  buflen = sizeof (dn_province);
+  if (gnutls_x509_crt_get_dn_by_oid
+      (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, dn_province,
+       &buflen) != 0)
     dn_province[0] = '\0';
-  buflen = sizeof(dn_country);
-  if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
-                                    dn_country, &buflen) != 0)
+  buflen = sizeof (dn_country);
+  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
+                                     dn_country, &buflen) != 0)
     dn_country[0] = '\0';
 
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name,
+            dn_email);
   snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
-            dn_locality, dn_province, dn_country);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s",
+            dn_organizational_unit);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s", dn_locality,
+            dn_province, dn_country);
   row++;
-  
-  strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
+
+  strfcpy (menu->dialog[row], _("This certificate was issued by:"),
+           SHORT_STRING);
   row++;
 
-  buflen = sizeof(dn_common_name);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
-                                    dn_common_name, &buflen) != 0)
+  buflen = sizeof (dn_common_name);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, dn_common_name, &buflen) != 0)
     dn_common_name[0] = '\0';
-  buflen = sizeof(dn_email);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
-                                    dn_email, &buflen) != 0)
+  buflen = sizeof (dn_email);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0, dn_email, &buflen) != 0)
     dn_email[0] = '\0';
-  buflen = sizeof(dn_organization);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
-                                    dn_organization, &buflen) != 0)
+  buflen = sizeof (dn_organization);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, dn_organization,
+       &buflen) != 0)
     dn_organization[0] = '\0';
-  buflen = sizeof(dn_organizational_unit);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
-                                    dn_organizational_unit, &buflen) != 0)
+  buflen = sizeof (dn_organizational_unit);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
+       dn_organizational_unit, &buflen) != 0)
     dn_organizational_unit[0] = '\0';
-  buflen = sizeof(dn_locality);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
-                                    dn_locality, &buflen) != 0)
+  buflen = sizeof (dn_locality);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, dn_locality, &buflen) != 0)
     dn_locality[0] = '\0';
-  buflen = sizeof(dn_province);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
-                                    dn_province, &buflen) != 0)
+  buflen = sizeof (dn_province);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, dn_province,
+       &buflen) != 0)
     dn_province[0] = '\0';
-  buflen = sizeof(dn_country);
-  if (gnutls_x509_crt_get_issuer_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
-                                    dn_country, &buflen) != 0)
+  buflen = sizeof (dn_country);
+  if (gnutls_x509_crt_get_issuer_dn_by_oid
+      (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, dn_country, &buflen) != 0)
     dn_country[0] = '\0';
 
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name,
+            dn_email);
   snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
-  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
-            dn_locality, dn_province, dn_country);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s",
+            dn_organizational_unit);
+  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s", dn_locality,
+            dn_province, dn_country);
   row++;
 
-  snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));
+  snprintf (menu->dialog[row++], SHORT_STRING,
+            _("This certificate is valid"));
 
-  t = gnutls_x509_crt_get_activation_time(cert);
-  snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"), 
-           tls_make_date(t, datestr, 30));
+  t = gnutls_x509_crt_get_activation_time (cert);
+  snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
+            tls_make_date (t, datestr, 30));
 
-  t = gnutls_x509_crt_get_expiration_time(cert);
-  snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"), 
-           tls_make_date(t, datestr, 30));
+  t = gnutls_x509_crt_get_expiration_time (cert);
+  snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
+            tls_make_date (t, datestr, 30));
 
   fpbuf[0] = '\0';
   tls_fingerprint (GNUTLS_DIG_SHA, fpbuf, sizeof (fpbuf), &cert_list[0]);
-  snprintf (menu->dialog[row++], SHORT_STRING, _("SHA1 Fingerprint: %s"), fpbuf);
+  snprintf (menu->dialog[row++], SHORT_STRING, _("SHA1 Fingerprint: %s"),
+            fpbuf);
   fpbuf[0] = '\0';
   tls_fingerprint (GNUTLS_DIG_MD5, fpbuf, sizeof (fpbuf), &cert_list[0]);
-  snprintf (menu->dialog[row++], SHORT_STRING, _("MD5 Fingerprint: %s"), fpbuf);
+  snprintf (menu->dialog[row++], SHORT_STRING, _("MD5 Fingerprint: %s"),
+            fpbuf);
 
-  if (certerr_notyetvalid)
-  {
+  if (certerr_notyetvalid) {
     row++;
-    strfcpy (menu->dialog[row], _("WARNING: Server certificate is not yet valid"), SHORT_STRING);
+    strfcpy (menu->dialog[row],
+             _("WARNING: Server certificate is not yet valid"), SHORT_STRING);
   }
-  if (certerr_expired)
-  {
+  if (certerr_expired) {
     row++;
-    strfcpy (menu->dialog[row], _("WARNING: Server certificate has expired"), SHORT_STRING);
+    strfcpy (menu->dialog[row], _("WARNING: Server certificate has expired"),
+             SHORT_STRING);
   }
-  if (certerr_revoked)
-  {
+  if (certerr_revoked) {
     row++;
-    strfcpy (menu->dialog[row], _("WARNING: Server certificate has been revoked"), SHORT_STRING);
+    strfcpy (menu->dialog[row],
+             _("WARNING: Server certificate has been revoked"), SHORT_STRING);
   }
-  if (certerr_hostname)
-  {
+  if (certerr_hostname) {
     row++;
-    strfcpy (menu->dialog[row], _("WARNING: Server hostname does not match certificate"), SHORT_STRING);
+    strfcpy (menu->dialog[row],
+             _("WARNING: Server hostname does not match certificate"),
+             SHORT_STRING);
   }
-  if (certerr_signernotca)
-  {
+  if (certerr_signernotca) {
     row++;
-    strfcpy (menu->dialog[row], _("WARNING: Signer of server certificate is not a CA"), SHORT_STRING);
+    strfcpy (menu->dialog[row],
+             _("WARNING: Signer of server certificate is not a CA"),
+             SHORT_STRING);
   }
 
   menu->title = _("TLS/SSL Certificate check");
   /* certificates with bad dates, or that are revoked, must be
      accepted manually each and every time */
-  if (SslCertFile && !certerr_expired && !certerr_notyetvalid && !certerr_revoked)
-  {
+  if (SslCertFile && !certerr_expired && !certerr_notyetvalid
+      && !certerr_revoked) {
     menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
     menu->keys = _("roa");
   }
-  else
-  {
+  else {
     menu->prompt = _("(r)eject, accept (o)nce");
     menu->keys = _("ro");
   }
-  
+
   helpstr[0] = '\0';
   mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
   strncat (helpstr, buf, sizeof (helpstr));
@@ -768,58 +748,49 @@ static int tls_check_certificate (CONNECTION* conn)
   menu->help = helpstr;
 
   done = 0;
-  while (!done)
-  {
-    switch (mutt_menuLoop (menu))
-    {
-      case -1:                 /* abort */
-      case OP_MAX + 1:         /* reject */
-      case OP_EXIT:
-        done = 1;
-        break;
-      case OP_MAX + 3:         /* accept always */
-        done = 0;
-        if ((fp = fopen (SslCertFile, "a")))
-       {
-         /* save hostname if necessary */
-         if (certerr_hostname)
-         {
-           fprintf(fp, "#H %s %s\n", conn->account.host, fpbuf);
-           done = 1;
-         }
-         if (certerr_nottrusted)
-         {
-            done = 0;
-           ret = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &cert_list[0],
-                                                  &pemdata);
-           if (ret == 0)
-           {
-             if (fwrite(pemdata.data, pemdata.size, 1, fp) == 1)
-             {
-               done = 1;
-             }
-              gnutls_free(pemdata.data);
-           }
-         }
-         fclose (fp);
-       }
-       if (!done)
-        {
-         mutt_error (_("Warning: Couldn't save certificate"));
-         mutt_sleep (2);
-       }
-       else
-        {
-         mutt_message (_("Certificate saved"));
-         mutt_sleep (0);
-       }
-        /* fall through */
-      case OP_MAX + 2:         /* accept once */
-        done = 2;
-        break;
+  while (!done) {
+    switch (mutt_menuLoop (menu)) {
+    case -1:                   /* abort */
+    case OP_MAX + 1:           /* reject */
+    case OP_EXIT:
+      done = 1;
+      break;
+    case OP_MAX + 3:           /* accept always */
+      done = 0;
+      if ((fp = fopen (SslCertFile, "a"))) {
+        /* save hostname if necessary */
+        if (certerr_hostname) {
+          fprintf (fp, "#H %s %s\n", conn->account.host, fpbuf);
+          done = 1;
+        }
+        if (certerr_nottrusted) {
+          done = 0;
+          ret = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &cert_list[0],
+                                                &pemdata);
+          if (ret == 0) {
+            if (fwrite (pemdata.data, pemdata.size, 1, fp) == 1) {
+              done = 1;
+            }
+            gnutls_free (pemdata.data);
+          }
+        }
+        fclose (fp);
+      }
+      if (!done) {
+        mutt_error (_("Warning: Couldn't save certificate"));
+        mutt_sleep (2);
+      }
+      else {
+        mutt_message (_("Certificate saved"));
+        mutt_sleep (0);
+      }
+      /* fall through */
+    case OP_MAX + 2:           /* accept once */
+      done = 2;
+      break;
     }
   }
   mutt_menuDestroy (&menu);
-  gnutls_x509_crt_deinit(cert);
+  gnutls_x509_crt_deinit (cert);
   return (done == 2);
 }