]> granicus.if.org Git - mutt/commitdiff
Improved certificate handling. Suggested by Oliver Ehli,
authorThomas Roessler <roessler@does-not-exist.org>
Tue, 29 Jan 2002 21:08:10 +0000 (21:08 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Tue, 29 Jan 2002 21:08:10 +0000 (21:08 +0000)
implemented by Mike Schiraldi.

smime.c

diff --git a/smime.c b/smime.c
index 93380e5acd3e78b73ecbed582b15fd7eda4aff04..fcfa7013c982bb936df380b74892d6c5d7b4ed76 100644 (file)
--- a/smime.c
+++ b/smime.c
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2001 Oliver Ehli <elmy@acm.org>
- * Copyright (C) 2002 Mike Schiraldi <raldi@research.netsol.com>
  *
  *     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
@@ -820,11 +819,15 @@ char *smime_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
 
 
 
-/* Check one single certificate for an email address */
-static int smime_check_cert_email (char *certificate, char *email)
+
+
+
+static int smime_check_cert_email (char *certificate, char *mailbox)
 {
   FILE *fpout = NULL, *fperr = NULL;
   char tmpfname[_POSIX_PATH_MAX];
+  char email[STRING];
+  int ret = 0;
   pid_t thepid;
 
   mutt_mktemp (tmpfname);
@@ -844,7 +847,7 @@ static int smime_check_cert_email (char *certificate, char *email)
   }
   mutt_unlink (tmpfname);
 
-  if ((thepid = smime_invoke (NULL, NULL, NULL,
+  if ((thepid =  smime_invoke (NULL, NULL, NULL,
                               -1, fileno (fpout), fileno (fperr),
                               certificate, NULL, NULL, NULL, NULL, NULL,
                               SmimeGetCertEmailCommand))== -1)
@@ -862,257 +865,36 @@ static int smime_check_cert_email (char *certificate, char *email)
   rewind (fperr);
   fflush (fperr);
 
-  if (!(fgets (email, STRING, fpout)))
+
+  if (!(fgets (email, sizeof (email), fpout)))
   {
     mutt_copy_stream (fperr, stdout);
     fclose (fpout);
     fclose (fperr);
     mutt_endwin(NULL);
-    return 2;
-  }
-  *(email+mutt_strlen(email)-1) = '\0';
-
-  return 0;
-}
-
-/* Loop through the list of certs, trying to find an email address.
- * Stop as soon as one is found 
- */
-static int smime_check_certs_email (char *certificates, char *mailbox)
-{
-  FILE *fpcerts = NULL;
-  char email[STRING];
-  int ret = 0;
-  
-  if ((fpcerts = fopen(certificates, "r")) == NULL)
-  {
-    mutt_perror (certificates);
+    printf ("Alert: No mailbox specified in certificate.\n");
     return 1;
   }
-  
-  /* For each certificate, copy it into a temp file and call 
-   * smime_check_cert_email() on it */
-  do 
-  {
-    char *line = NULL;
-    int lineno = 0;
-    size_t linelen;
+  *(email+mutt_strlen(email)-1) = '\0';
 
-    FILE *fptmp = NULL;
-    char tmpfname[_POSIX_PATH_MAX];
-    
-    if (feof (fpcerts))
-    {
-      mutt_error (_("Error: Unable to extract email address from certificate"));
-      return 1;
-    }
-    
-    mutt_mktemp (tmpfname);
-    if ((fptmp = safe_fopen (tmpfname, "w+")) == NULL)
-    {
-      mutt_perror (tmpfname);
-      return 1;
-    }
-    
-    /* Copy up until the next blank line */
-    while(1) 
-    {
-      line = mutt_read_line (line, &linelen, fpcerts, &lineno);
 
-      /* EOF */
-      if (line == NULL)
-        break;
-      
-      /* Blank line */
-      if (line[0] == 0)
-        {
-          safe_free ((void **) &line);
-          break;
-        }
-      
-      fprintf (fptmp, "%s\n", line);  
-      safe_free ((void **) &line);
-    }
-    
-    fclose (fptmp);
-    
-    ret = smime_check_cert_email (tmpfname, email);
-    
-    mutt_unlink (tmpfname);
-    
-    if (ret == 1)
-      return 1;
-  } while (ret != 0);
-  
-  if (mutt_strncasecmp (email, mailbox, mutt_strlen (mailbox)))
+  if(mutt_strncasecmp (email, mailbox, mutt_strlen (mailbox)))
   {
     mutt_endwin(NULL);
-    mutt_error (_("Alert: Certificate belongs to \"%s\".\n"
-                  "       But sender was \"%s\".\n"), email, mailbox);
+    printf ("Alert: Certificate belongs to \"%s\".\n"
+           "       But sender was \"%s\".\n", email, mailbox);
     ret = 1;
   }
 
-  return ret;
-}
-
-
-/* Add a certificate and update index file. */
-
-static void smime_add_certificate (char *certificate, char *mailbox, short public)
-{
-  FILE *fpin = NULL, *fpout = NULL, *fperr = NULL;
-  char tmpfname[_POSIX_PATH_MAX], dest[_POSIX_PATH_MAX];
-  char buf[LONG_STRING], hashval[STRING], *tmpKey;
-  struct stat info;
-  int i = 0;
-  pid_t thepid;
-
-
-  if (smime_check_certs_email (certificate, mailbox))
-  {
-    mutt_message _("Certificate *NOT* added.");
-    return;
-  }
-
-  mutt_mktemp (tmpfname);
-  if ((fperr = safe_fopen (tmpfname, "w+")) == NULL)
-  {
-    mutt_perror (tmpfname);
-    return;
-  }
-  mutt_unlink (tmpfname);
-
-  mutt_mktemp (tmpfname);
-  if ((fpout = safe_fopen (tmpfname, "w+")) == NULL)
-  {
-    fclose (fperr);
-    mutt_perror (tmpfname);
-    return;
-  }
-  mutt_unlink (tmpfname);
-
-  /* 
-     OpenSSl can create a hash value of the certificate's subject.
-     This and a concatenated integer make up the certificat's
-     'unique id' and also its filename.
-  */
-
-  mutt_endwin (NULL);
-  
-  if ((thepid =  smime_invoke (NULL, NULL, NULL,
-                              -1, fileno (fpout), fileno (fperr),
-                              certificate, NULL, NULL, NULL, NULL, NULL,
-                              SmimeHashCertCommand))== -1)
-  {
-    mutt_message (_("Error: unable to create OpenSSL subprocess!"));
-    fclose (fperr);
-    fclose (fpout);
-    return;
-  }
-
-  mutt_wait_filter (thepid);
-  
-  fflush (fpout);
-  rewind (fpout);
-  rewind (fperr);
-  fflush (fperr);
-
-  if (!(fgets (hashval, sizeof (hashval), fpout)))
-  {
-    mutt_copy_stream (fperr, stdout);
-    fclose (fpout);
-    fclose (fperr);
-    return;
-  }
   fclose (fpout);
   fclose (fperr);
 
-  *(hashval+mutt_strlen(hashval)-1) = '\0';
-
-  while (1)
-  {
-    snprintf (dest, sizeof (dest), _("%s/%s.%d"), NONULL(SmimeCertificates),
-             hashval, i);
-
-    if (stat (dest, &info))
-      break;
-    else
-      i++;
-  }
-    
-  if ((fpout = safe_fopen (dest, "w+")) == NULL)
-  {
-    mutt_perror (dest);
-    return;
-  }
-
-  if ((fpin = safe_fopen (certificate, "r")) == NULL)
-  {
-    mutt_perror (certificate);
-    fclose (fpout);
-    mutt_unlink (dest);
-    return;
-  }
-    
-  mutt_copy_stream (fpin, fpout);
-  fclose (fpout);
-  fclose (fpin);
-
-
-  /*
-    Now check if the mailbox is already found with the certificate's
-    hash value.
-
-    openssl uses md5 fingerprints to check wether two keys are identical.
-    I have to add that.
-    
-  */
-  
-  tmpKey = smime_get_field_from_db (mailbox, NULL, public, 0);
-
-  /* check if hash values are identical => same certificate ? */
-  /* perhaps we should ask for permission to overwrite ? */
-  /* what about revoked certificates anyway ? */
-
-  /* reminder: openssl checks md5 - fingerprint for equality. add this. */
-
-  if (tmpKey && !mutt_strncmp (tmpKey, hashval, mutt_strlen (hashval)))
-  {
-    mutt_message (_("Certificate \"%s\" exists for \"%s\"."), hashval, mailbox);
-    mutt_unlink (dest);
-    return;
-  }
-    
-  /* append to index. */
-  snprintf (tmpfname, sizeof (tmpfname), _("%s/.index"),
-           (public ? NONULL(SmimeCertificates) : NONULL(SmimeKeys)));
-  
-  if (!stat (tmpfname, &info))
-  {
-    if ((fpout = safe_fopen (tmpfname, "a")) == NULL)
-    {
-      mutt_perror (tmpfname);
-      mutt_unlink (dest);
-      return;
-    }
-    /*
-       ? = unknown issuer, - = unassigned label,
-       u = undefined trust settings.
-    */
-    snprintf (buf, sizeof (buf), _("%s %s.%d - ? u\n"), mailbox, hashval, i);
-    fputs (buf, fpout);
-    fclose (fpout);
-    
-    mutt_message (_("Successfully added certificate \"%s\" for \"%s\". "), hashval, mailbox);
-  }
-
-  return;
+  return ret;
 }
 
 
 
-
-static char *smime_extract_certificate (char *infile, int split)
+static char *smime_extract_certificate (char *infile)
 {
   FILE *fpout = NULL, *fperr = NULL;
   char pk7out[_POSIX_PATH_MAX], certfile[_POSIX_PATH_MAX];
@@ -1221,10 +1003,7 @@ static char *smime_extract_certificate (char *infile, int split)
   return safe_strdup (certfile);
 }
 
-
-
-
-static char *smime_extract_signer_certificate (char *infile, int split)
+static char *smime_extract_signer_certificate (char *infile)
 {
   FILE *fpout = NULL, *fperr = NULL;
   char pk7out[_POSIX_PATH_MAX], certfile[_POSIX_PATH_MAX];
@@ -1279,7 +1058,6 @@ static char *smime_extract_signer_certificate (char *infile, int split)
     fclose (fperr);
     mutt_unlink (certfile);
     return NULL;
-    
   }
 
   fclose (fpout);
@@ -1289,13 +1067,177 @@ static char *smime_extract_signer_certificate (char *infile, int split)
 }
 
 
+/* Add a certificate and update index file. */
+
+static void smime_add_certificate (char *certificate, char *mailbox, short public)
+{
+  FILE *fpin = NULL, *fpout = NULL, *fperr = NULL;
+  char tmpfname[_POSIX_PATH_MAX], dest[_POSIX_PATH_MAX];
+  char buf[LONG_STRING], hashval[STRING], *tmpKey;
+  struct stat info;
+  int i = 0;
+  pid_t thepid;
+
+  mutt_mktemp (tmpfname);
+  if ((fperr = safe_fopen (tmpfname, "w+")) == NULL)
+  {
+    mutt_perror (tmpfname);
+    return;
+  }
+  mutt_unlink (tmpfname);
+
+  mutt_mktemp (tmpfname);
+  if ((fpout = safe_fopen (tmpfname, "w+")) == NULL)
+  {
+    fclose (fperr);
+    mutt_perror (tmpfname);
+    return;
+  }
+  mutt_unlink (tmpfname);
+
+  /* 
+     OpenSSl can create a hash value of the certificate's subject.
+     This and a concatenated integer make up the certificat's
+     'unique id' and also its filename.
+  */
+
+  mutt_endwin (NULL);
+  
+  if ((thepid =  smime_invoke (NULL, NULL, NULL,
+                              -1, fileno (fpout), fileno (fperr),
+                              certificate, NULL, NULL, NULL, NULL, NULL,
+                              SmimeHashCertCommand))== -1)
+  {
+    mutt_message (_("Error: unable to create OpenSSL subprocess!"));
+    fclose (fperr);
+    fclose (fpout);
+    return;
+  }
+
+  mutt_wait_filter (thepid);
+  
+  fflush (fpout);
+  rewind (fpout);
+  rewind (fperr);
+  fflush (fperr);
+
+  if (!(fgets (hashval, sizeof (hashval), fpout)))
+  {
+    mutt_copy_stream (fperr, stdout);
+    fclose (fpout);
+    fclose (fperr);
+    return;
+  }
+  fclose (fpout);
+  fclose (fperr);
+
+  *(hashval+mutt_strlen(hashval)-1) = '\0';
+
+  while (1)
+  {
+    snprintf (dest, sizeof (dest), _("%s/%s.%d"), NONULL(SmimeCertificates),
+             hashval, i);
+
+    if (stat (dest, &info))
+      break;
+    else
+      i++;
+  }
+    
+  if ((fpout = safe_fopen (dest, "w+")) == NULL)
+  {
+    mutt_perror (dest);
+    return;
+  }
+
+  if ((fpin = safe_fopen (certificate, "r")) == NULL)
+  {
+    mutt_perror (certificate);
+    fclose (fpout);
+    mutt_unlink (dest);
+    return;
+  }
+    
+  mutt_copy_stream (fpin, fpout);
+  fclose (fpout);
+  fclose (fpin);
+
+
+  /*
+    Now check if the mailbox is already found with the certificate's
+    hash value.
+
+    openssl uses md5 fingerprints to check wether two keys are identical.
+    I have to add that.
+    
+  */
+  
+  tmpKey = smime_get_field_from_db (mailbox, NULL, public, 0);
+
+  /* check if hash values are identical => same certificate ? */
+  /* perhaps we should ask for permission to overwrite ? */
+  /* what about revoked certificates anyway ? */
+
+  /* reminder: openssl checks md5 - fingerprint for equality. add this. */
+
+  if (tmpKey && !mutt_strncmp (tmpKey, hashval, mutt_strlen (hashval)))
+  {
+    mutt_message (_("Certificate \"%s\" exists for \"%s\"."), hashval, mailbox);
+    mutt_unlink (dest);
+    return;
+  }
+    
+  /* append to index. */
+  snprintf (tmpfname, sizeof (tmpfname), _("%s/.index"),
+           (public ? NONULL(SmimeCertificates) : NONULL(SmimeKeys)));
+  
+  if (!stat (tmpfname, &info))
+  {
+    if ((fpout = safe_fopen (tmpfname, "a")) == NULL)
+    {
+      mutt_perror (tmpfname);
+      mutt_unlink (dest);
+      return;
+    }
+    /*
+       ? = unknown issuer, - = unassigned label,
+       u = undefined trust settings.
+    */
+    snprintf (buf, sizeof (buf), _("%s %s.%d - ? u\n"), mailbox, hashval, i);
+    fputs (buf, fpout);
+    fclose (fpout);
+    
+    mutt_message (_("Successfully added certificate \"%s\" for \"%s\". "), hashval, mailbox);
+  }
+
+  return;
+}
+
 
 
 void smime_invoke_import (char *infile, char *mailbox)
 {
   char *certfile = NULL;
+  int i;
+  certfile = smime_extract_signer_certificate(infile);
+  
+  if (certfile == NULL)
+  { 
+    mutt_message _("Certificate *NOT* added.");
+    return;
+  }  
+  
+  i = smime_check_cert_email (certfile, mailbox);
+  
+  mutt_unlink(certfile);
+  
+  if (i)
+  {
+    mutt_message _("Certificate *NOT* added.");
+    return;
+  }
 
-  if ((certfile = smime_extract_certificate(infile, FALSE)))
+  if ((certfile = smime_extract_certificate(infile)))
   {
     smime_add_certificate (certfile, mailbox, 1);
     mutt_unlink (certfile);
@@ -1343,10 +1285,10 @@ int smime_verify_sender(HEADER *h)
 
   if (mbox)
   {
-    if ((certfile = smime_extract_signer_certificate(tempfname,TRUE)))
+    if ((certfile = smime_extract_signer_certificate(tempfname)))
     {
       mutt_unlink(tempfname);
-      if (smime_check_certs_email (certfile, mbox))
+      if (smime_check_cert_email (certfile, mbox))
        mutt_any_key_to_continue(NULL);
       else
        retval = 0;