From: Thomas Roessler Date: Tue, 29 Jan 2002 21:08:10 +0000 (+0000) Subject: Improved certificate handling. Suggested by Oliver Ehli, X-Git-Tag: mutt-1-5-1-rel~109 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ae248a367371e35ca7fa62d1f71ffe16f661cf78;p=mutt Improved certificate handling. Suggested by Oliver Ehli, implemented by Mike Schiraldi. --- diff --git a/smime.c b/smime.c index 93380e5a..fcfa7013 100644 --- a/smime.c +++ b/smime.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2001 Oliver Ehli - * Copyright (C) 2002 Mike Schiraldi * * 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;