]> granicus.if.org Git - neomutt/commitdiff
Don't allow storing duplicate certs for OpenSSL interactive prompt. (closes #3914)
authorKevin McCarthy <kevin@8t8.us>
Wed, 8 Mar 2017 02:26:07 +0000 (18:26 -0800)
committerKevin McCarthy <kevin@8t8.us>
Wed, 8 Mar 2017 02:26:07 +0000 (18:26 -0800)
Check to make sure the certificate is not already in the
$certificate_file before offering the (a)ccept always option.

To allow a cert with a new validity timespan to be added to the file,
check the expiration dates when comparing certificates in the
certficate file.

mutt_ssl.c

index 82a237670e444ec5422ddcb3adf5af66d9237349..2ca21dda36b05f93658c3ab561760e814c4129b8 100644 (file)
@@ -795,33 +795,46 @@ static int check_certificate_cache (X509 *peercert)
   return 0;
 }
 
-static int check_certificate_by_digest (X509 *peercert)
+static int check_certificate_expiration (X509 *peercert, int silent)
 {
-  unsigned char peermd[EVP_MAX_MD_SIZE];
-  unsigned int peermdlen;
-  X509 *cert = NULL;
-  int pass = 0;
-  FILE *fp;
-
-  /* expiration check */
   if (option (OPTSSLVERIFYDATES) != MUTT_NO)
   {
     if (X509_cmp_current_time (X509_get_notBefore (peercert)) >= 0)
     {
-      dprint (2, (debugfile, "Server certificate is not yet valid\n"));
-      mutt_error (_("Server certificate is not yet valid"));
-      mutt_sleep (2);
+      if (!silent)
+      {
+        dprint (2, (debugfile, "Server certificate is not yet valid\n"));
+        mutt_error (_("Server certificate is not yet valid"));
+        mutt_sleep (2);
+      }
       return 0;
     }
     if (X509_cmp_current_time (X509_get_notAfter (peercert)) <= 0)
     {
-      dprint (2, (debugfile, "Server certificate has expired\n"));
-      mutt_error (_("Server certificate has expired"));
-      mutt_sleep (2);
+      if (!silent)
+      {
+        dprint (2, (debugfile, "Server certificate has expired\n"));
+        mutt_error (_("Server certificate has expired"));
+        mutt_sleep (2);
+      }
       return 0;
     }
   }
 
+  return 1;
+}
+
+static int check_certificate_file (X509 *peercert)
+{
+  unsigned char peermd[EVP_MAX_MD_SIZE];
+  unsigned int peermdlen;
+  X509 *cert = NULL;
+  int pass = 0;
+  FILE *fp;
+
+  if (!SslCertFile)
+    return 0;
+
   if ((fp = fopen (SslCertFile, "rt")) == NULL)
     return 0;
 
@@ -833,10 +846,12 @@ static int check_certificate_by_digest (X509 *peercert)
 
   while (PEM_read_X509 (fp, &cert, NULL, NULL) != NULL)
   {
-    pass = compare_certificates (cert, peercert, peermd, peermdlen) ? 0 : 1;
-
-    if (pass)
+    if ((compare_certificates (cert, peercert, peermd, peermdlen) == 0) &&
+        check_certificate_expiration (cert, 1))
+    {
+      pass = 1;
       break;
+    }
   }
   /* PEM_read_X509 sets an error on eof */
   if (!pass)
@@ -847,6 +862,12 @@ static int check_certificate_by_digest (X509 *peercert)
   return pass;
 }
 
+static int check_certificate_by_digest (X509 *peercert)
+{
+  return check_certificate_expiration (peercert, 0) &&
+    check_certificate_file (peercert);
+}
+
 /* port to mutt from msmtp's tls.c */
 static int hostname_match (const char *hostname, const char *certname)
 {
@@ -1161,10 +1182,9 @@ static int interactive_check_cert (X509 *cert, int idx, int len, SSL *ssl)
    * an OpenSSL connection.
    */
   menu->keys = _("roas");
-  if (SslCertFile
-      && (option (OPTSSLVERIFYDATES) == MUTT_NO
-         || (X509_cmp_current_time (X509_get_notAfter (cert)) >= 0
-             && X509_cmp_current_time (X509_get_notBefore (cert)) < 0)))
+  if (SslCertFile &&
+      check_certificate_expiration (cert, 1) &&
+      !check_certificate_file (cert))
   {
     allow_always = 1;
     if (allow_skip)