Commit ee217d50 authored by Thomas Roessler's avatar Thomas Roessler

S/MIME fixes from Oliver Ehli:

- smime_keys.pl:

  support for multiple email adrresses in cert: will add one entry
  to {keys, cetrificates}/.index now (for each mailbox)

  support for certificates without intermediate certs (e.g. for
  people who are their own CA: use root as intermediate, for it
  probably wouldn't be known to anyone...)

  bugfix in handle_pem: the checks if some type of cert is present;
  die() could never be reached, as the variables checked wouldn't
  have been set in that case, so it would break because of undefined
  value or some such thing.... (so it has to check $iter instead)

- smime.c (init.h, ....)

  support for importing certificates issued for multiple addresses.

  introduced smime_fingerprint_cert_command, so finally certs can
  get compared ... (so the above works..)

  cleaned up some error messages, that would mess up the terminal.

  fixed typos (init.h)
parent 8134072a
......@@ -45,6 +45,10 @@ set smime_get_signer_cert_command="openssl smime -verify -in %f -noverify -signe
# above directory
set smime_hash_cert_command="openssl x509 -in %f -noout -hash"
# This is used to get a md5-fingerprint of a certificate for purpose
# of comparism
set smime_fingerprint_cert_command="openssl x509 -in %f -noout -fingerprint"
# This is used to get the email address the certificate was issued to.
set smime_get_cert_email_command="openssl x509 -in %f -noout -email"
......
......@@ -1485,11 +1485,11 @@ struct option_t MuttVars[] = {
/*
** .pp
** Since there is no pubring/secring as with PGP, mutt has to handle
** storage ad retrieval of keys by itself. This is very basic right now,
** storage ad retrieval of keys/certs by itself. This is very basic right now,
** and stores keys and certificates in two different directories, both
** named as the hash-value retrieved from OpenSSl. There is an index file
** which contains mailbox-address keyid pai, and which can be manually
** edited.
** named as the hash-value retrieved from OpenSSL. There is an index file
** which contains mailbox-address keyid pair, and which can be manually
** edited. This one points to the location of the private keys.
*/
{ "smime_ca_location", DT_PATH, R_NONE, UL &SmimeCALocation, 0 },
/*
......@@ -1505,12 +1505,12 @@ struct option_t MuttVars[] = {
** and stores keys and certificates in two different directories, both
** named as the hash-value retrieved from OpenSSl. There is an index file
** which contains mailbox-address keyid pai, and which can be manually
** edited.
** edited. This one points to the location of the certificates.
*/
{ "smime_decrypt_command", DT_STR, R_NONE, UL &SmimeDecryptCommand, 0},
/*
** .pp
** This format strings specifies a command which is used to decrypt
** This format string specifies a command which is used to decrypt
** application/x-pkcs7-mime attachments.
** .pp
** The OpenSSL command formats have their own set of printf-like sequences
......@@ -1528,7 +1528,7 @@ struct option_t MuttVars[] = {
** . "-CApath $$smime_ca_location" or "-CAfile $$smime_ca_location".
** .de
** .pp
** For examples on how to configure these formats, see the smime.rc
** For examples on how to configure these formats, see the smime.rc in
** the samples/ subdirectory which has been installed on your system
** alongside the documentation.
*/
......@@ -1565,7 +1565,7 @@ struct option_t MuttVars[] = {
/*
** .pp
** This command is used to extract PKCS7 structures of S/MIME signatures,
** in Order to extract the public X509 certificate(s).
** in order to extract the public X509 certificate(s).
*/
{ "smime_get_cert_command", DT_STR, R_NONE, UL &SmimeGetCertCommand, 0},
/*
......@@ -1575,28 +1575,34 @@ struct option_t MuttVars[] = {
{ "smime_get_signer_cert_command", DT_STR, R_NONE, UL &SmimeGetSignerCertCommand, 0},
/*
** .pp
** This command is used to extract only the signers X509 certificate from a S/MIME signature,
** so that the certificate's owner may get compared to the email's from field.
** This command is used to extract only the signers X509 certificate from a S/MIME
** signature, so that the certificate's owner may get compared to the email's
** 'From'-field.
*/
{ "smime_hash_cert_command", DT_STR, R_NONE, UL &SmimeHashCertCommand, 0},
/*
** .pp
** This command is used to calculate a hash value used for storing
** X509 certificates.
** X509 certificates. (The value is derived from the cert's subject field)
*/
{ "smime_fingerprint_cert_command", DT_STR, R_NONE, UL &SmimeFingerprintCertCommand, 0},
/*
** .pp
** This command returns a md5-fingerprint of the certificate.
** That way, certificates with an identical subject field can get compared.
*/
{ "smime_get_cert_email_command", DT_STR, R_NONE, UL &SmimeGetCertEmailCommand, 0},
/*
** .pp
** This command is used to extract the mail address used for storing
** X509 certificates, abd for verification purposes (to see if the
** certifacate was issued for the sender's mailbox.
** This command is used to extract the mail address(es) used for storing
** X509 certificates, and for verification purposes (to check, wether the
** certifacate was issued for the sender's mailbox).
*/
{ "smime_sign_as", DT_STR, R_NONE, UL &SmimeSignAs, 0 },
/*
** .pp
** This is the default key-pair to use vor signing. This must be set to the
** keyid (the hash-value, OpenSSL generates) to work properly (key handling
** is very limited right now.)
** keyid (the hash-value that OpenSSL generates) to work properly
*/
#endif /* HAVE_SMIME */
......
This diff is collapsed.
......@@ -43,6 +43,7 @@ WHERE char *SmimeGetSignerCertCommand;
WHERE char *SmimePk7outCommand;
WHERE char *SmimeGetCertCommand;
WHERE char *SmimeHashCertCommand;
WHERE char *SmimeFingerprintCertCommand;
WHERE char *SmimeGetCertEmailCommand;
......
#! /usr/bin/perl -w
# Copyright (C) 2001 Oliver Ehli <[email protected]>
# Copyright (C) 2001,2002 Oliver Ehli <[email protected]>
# Copyright (C) 2001 Mike Schiraldi <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
......@@ -107,8 +107,10 @@ elsif( @ARGV == 2 and $ARGV[0] eq "add_p12") {
handle_pem(@pem);
}
elsif(@ARGV == 4 and $ARGV[0] eq "add_chain") {
my $mailbox;
my $cmd = "openssl x509 -noout -hash -in $ARGV[2]";
my $cert_hash = `$cmd`;
$? and die "'$cmd' returned $?";
$cmd = "openssl x509 -noout -hash -in $ARGV[3]";
......@@ -121,9 +123,12 @@ elsif(@ARGV == 4 and $ARGV[0] eq "add_chain") {
my $label = query_label;
add_certificate($ARGV[3], \$issuer_hash, 0, $label);
my $mailbox = &add_certificate($ARGV[2], \$cert_hash, 1, $label, $issuer_hash);
my @mailbox = &add_certificate($ARGV[2], \$cert_hash, 1, $label, $issuer_hash);
add_key($ARGV[1], $cert_hash, $mailbox, $label);
foreach $mailbox (@mailbox) {
chomp($mailbox);
add_key($ARGV[1], $cert_hash, $mailbox, $label);
}
}
elsif((@ARGV == 2 or @ARGV == 3) and $ARGV[0] eq "verify") {
verify_cert($ARGV[1], $ARGV[2]);
......@@ -264,8 +269,8 @@ sub list_certs () {
print "$fields[1]: Issued for: $fields[0] \"$fields[2]\" $keyflags{$fields[4]}\n";
}
(my $subject_in, my $email_in, my $issuer_in, my $date1_in, my $date2_in) =
`openssl x509 -subject -email -issuer -dates -noout -in $certificates_path/$fields[1]`;
(my $subject_in, my $issuer_in, my $date1_in, my $date2_in) =
`openssl x509 -subject -issuer -dates -noout -in $certificates_path/$fields[1]`;
my @subject = split(/\//, $subject_in);
while(@subject) {
......@@ -379,6 +384,7 @@ sub add_certificate ($$$$;$) {
my $issuer_hash = shift;
my $iter = 0;
my @mailbox;
my $mailbox;
while(-e "$certificates_path/$$hashvalue.$iter") {
......@@ -404,20 +410,22 @@ sub add_certificate ($$$$;$) {
if ($add_to_index) {
my $cmd = "openssl x509 -in $filename -email -noout";
$mailbox = `$cmd`;
@mailbox = `$cmd`;
$? and die "'$cmd' returned $?";
chomp($mailbox);
add_entry($mailbox, $$hashvalue, 1, $label, $issuer_hash);
foreach $mailbox (@mailbox) {
chomp($mailbox);
add_entry($mailbox, $$hashvalue, 1, $label, $issuer_hash);
print "added certificate: $certificates_path/$$hashvalue for $mailbox.\n";
print "added certificate: $certificates_path/$$hashvalue for $mailbox.\n";
}
}
else {
print "added certificate: $certificates_path/$$hashvalue.\n";
}
}
return $mailbox;
return @mailbox;
}
......@@ -430,10 +438,11 @@ sub add_key ($$$$) {
unless (-e "$private_keys_path/$hashvalue") {
my $cmd = "cp $file $private_keys_path/$hashvalue";
system $cmd and die "$cmd returned $!";
print "added private key: " .
"$private_keys_path/$hashvalue for $mailbox\n";
add_entry($mailbox, $hashvalue, 0, $label, "");
}
add_entry($mailbox, $hashvalue, 0, $label, "");
print "added private key: " .
"$private_keys_path/$hashvalue for $mailbox\n";
}
......@@ -514,6 +523,8 @@ sub handle_pem (@) {
my $root_cert;
my $key;
my $certificate;
my $intermediate;
my @mailbox;
my $mailbox;
@pem_contents = &parse_pem(@_);
......@@ -526,7 +537,7 @@ sub handle_pem (@) {
}
$iter++;
}
($key > $#pem_contents>>2) and die("Couldn't find private key!");
($iter > $#pem_contents>>2) and die("Couldn't find private key!");
$pem_contents[($key<<2)+1] or die("Attribute 'localKeyID' wasn't set.");
......@@ -539,7 +550,7 @@ sub handle_pem (@) {
}
$iter++;
}
($certificate > $#pem_contents>>2) and die("Couldn't find matching certificate!");
($iter > $#pem_contents>>2) and die("Couldn't find matching certificate!");
my $cmd = "cp cert_tmp.$key tmp_key";
system $cmd and die "'$cmd' returned $?";
......@@ -562,13 +573,15 @@ sub handle_pem (@) {
}
$iter++;
}
($root_cert > $#pem_contents>>2) and die("Couldn't identify root certificate!");
($iter > $#pem_contents>>2) and die("Couldn't identify root certificate!");
# what's left are intermediate certificates.
$iter = 0;
unlink "tmp_issuer_cert";
# needs to be set, so we can check it later
$intermediate = $root_cert;
while($iter <= $#pem_contents>>2) {
if ($iter == $key or $iter == $certificate or $iter == $root_cert) {
$iter++;
......@@ -578,9 +591,17 @@ sub handle_pem (@) {
my $cmd = "cat cert_tmp.$iter >> tmp_issuer_cert";
system $cmd and die "'$cmd' returned $?";
# although there may be many, just need to know if there was any
$intermediate = $iter;
$iter++;
}
# no intermediate certificates ? use root-cert instead
if($intermediate == $root_cert) {
$cmd = "cp cert_tmp.$root_cert tmp_issuer_cert";
}
my $label = query_label;
$cmd = "openssl x509 -noout -hash -in tmp_certificate";
......@@ -596,8 +617,11 @@ sub handle_pem (@) {
# Note: $cert_hash will be changed to reflect the correct filename
# within add_cert() ONLY, so these _have_ to get called first..
add_certificate("tmp_issuer_cert", \$issuer_hash, 0, $label);
$mailbox = &add_certificate("tmp_certificate", \$cert_hash, 1, $label, $issuer_hash);
add_key("tmp_key", $cert_hash, $mailbox, $label);
@mailbox = &add_certificate("tmp_certificate", \$cert_hash, 1, $label, $issuer_hash);
foreach $mailbox (@mailbox) {
chomp($mailbox);
add_key("tmp_key", $cert_hash, $mailbox, $label);
}
unlink <cert_tmp.*>;
unlink <tmp_*>;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment