3 # Copyright (C) 2001,2002 Oliver Ehli <elmy@acm.org>
4 # Copyright (C) 2001 Mike Schiraldi <raldi@research.netsol.com>
5 # Copyright (C) 2003 Bjoern Jacke <bjoern@j3e.de>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 use File::Glob ':glob';
34 # directory setup routines
35 sub mkdir_recursive ($ );
38 # key/certificate management methods
41 sub add_entry ($$$$$ );
42 sub add_certificate ($$$$;$ );
44 sub add_root_cert ($ );
47 sub modify_entry ($$$;$ );
49 sub change_label ($ );
53 # Get the directories mutt uses for certificate/key storage.
55 my $mutt = $ENV{MUTT_CMDLINE} || 'mutt';
56 my $opensslbin = "/usr/bin/openssl";
58 my @cert_tmp_file = ();
61 my $private_keys_path = mutt_Q 'smime_keys';
62 die "smime_keys is not set in mutt's configuration file"
63 if length $private_keys_path == 0;
65 my $certificates_path = mutt_Q 'smime_certificates';
66 die "smime_certificates is not set in mutt's configuration file"
67 if length $certificates_path == 0;
68 my $root_certs_path = mutt_Q 'smime_ca_location';
69 die "smime_ca_location is not set in mutt's configuration file"
70 if length $root_certs_path == 0;
72 my $root_certs_switch;
73 if ( -d $root_certs_path) {
74 $root_certs_switch = -CApath;
76 $root_certs_switch = -CAfile;
84 if(@ARGV == 1 and $ARGV[0] eq "init") {
87 elsif(@ARGV == 1 and $ARGV[0] eq "list") {
90 elsif(@ARGV == 2 and $ARGV[0] eq "label") {
91 change_label($ARGV[1]);
93 elsif(@ARGV == 2 and $ARGV[0] eq "add_cert") {
94 my $format = -B $ARGV[1] ? 'DER' : 'PEM';
95 my $cmd = "$opensslbin x509 -noout -hash -in $ARGV[1] -inform $format";
96 my $cert_hash = `$cmd`;
97 $? and die "'$cmd' returned $?";
99 my $label = query_label;
100 &add_certificate($ARGV[1], \$cert_hash, 1, $label, '?');
102 elsif(@ARGV == 2 and $ARGV[0] eq "add_pem") {
103 -e $ARGV[1] and -s $ARGV[1] or die("$ARGV[1] is nonexistent or empty.");
104 open(PEM_FILE, "<$ARGV[1]") or die("Can't open $ARGV[1]: $!");
105 my @pem = <PEM_FILE>;
109 elsif( @ARGV == 2 and $ARGV[0] eq "add_p12") {
110 -e $ARGV[1] and -s $ARGV[1] or die("$ARGV[1] is nonexistent or empty.");
112 print "\nNOTE: This will ask you for two passphrases:\n";
113 print " 1. The passphrase you used for exporting\n";
114 print " 2. The passphrase you wish to secure your private key with.\n\n";
116 my $pem_file = "$ARGV[1].pem";
118 my $cmd = "$opensslbin pkcs12 -in $ARGV[1] -out $pem_file";
119 system $cmd and die "'$cmd' returned $?";
121 -e $pem_file and -s $pem_file or die("Conversion of $ARGV[1] failed.");
122 open(PEM_FILE, $pem_file) or die("Can't open $pem_file: $!");
123 my @pem = <PEM_FILE>;
128 elsif(@ARGV == 4 and $ARGV[0] eq "add_chain") {
130 my $format = -B $ARGV[2] ? 'DER' : 'PEM';
131 my $cmd = "$opensslbin x509 -noout -hash -in $ARGV[2] -inform $format";
132 my $cert_hash = `$cmd`;
134 $? and die "'$cmd' returned $?";
136 $format = -B $ARGV[3] ? 'DER' : 'PEM';
138 $cmd = "$opensslbin x509 -noout -hash -in $ARGV[3] -inform $format";
139 my $issuer_hash = `$cmd`;
140 $? and die "'$cmd' returned $?";
145 my $label = query_label;
147 add_certificate($ARGV[3], \$issuer_hash, 0, $label);
148 my @mailbox = &add_certificate($ARGV[2], \$cert_hash, 1, $label, $issuer_hash);
150 foreach $mailbox (@mailbox) {
152 add_key($ARGV[1], $cert_hash, $mailbox, $label);
155 elsif((@ARGV == 2 or @ARGV == 3) and $ARGV[0] eq "verify") {
156 verify_cert($ARGV[1], $ARGV[2]);
158 elsif(@ARGV == 2 and $ARGV[0] eq "remove") {
159 remove_pair($ARGV[1]);
161 elsif(@ARGV == 2 and $ARGV[0] eq "add_root") {
162 add_root_cert($ARGV[1]);
175 ############## sub-routines ########################
180 Usage: smime_keys <operation> [file(s) | keyID [file(s)]]
182 with operation being one of:
184 init : no files needed, inits directory structure.
186 list : lists the certificates stored in database.
187 label : keyID required. changes/removes/adds label.
188 remove : keyID required.
189 verify : 1=keyID and optionally 2=CRL
190 Verifies the certificate chain, and optionally wether
191 this certificate is included in supplied CRL (PEM format).
192 Note: to verify all certificates at the same time,
193 replace keyID with "all"
195 add_cert : certificate required.
196 add_chain : three files reqd: 1=Key, 2=certificate
197 plus 3=intermediate certificate(s).
198 add_p12 : one file reqd. Adds keypair to database.
199 file is PKCS12 (e.g. export from netscape).
200 add_pem : one file reqd. Adds keypair to database.
201 (file was converted from e.g. PKCS12).
203 add_root : one file reqd. Adds PEM root certificate to the location
204 specified within muttrc (smime_verify_* command)
210 my $var = shift or die;
212 my $cmd = "$mutt -v >/dev/null 2>/dev/null";
215 Couldn't launch mutt. I attempted to do so by running the command "$mutt".
216 If that's not the right command, you can override it by setting the
217 environment variable \$MUTT_CMDLINE
220 $cmd = "$mutt -Q $var 2>/dev/null";
224 Couldn't look up the value of the mutt variable "$var".
225 You must set this in your mutt config file. See contrib/smime.rc for an example.
229 $answer =~ /\"(.*?)\"/ and return bsd_glob($1, GLOB_TILDE | GLOB_NOCHECK);
231 $answer =~ /^Mutt (.*?) / and die<<EOF;
232 This script requires mutt 1.5.0 or later. You are using mutt $1.
235 die "Value of $var is weird\n";
239 my $source = shift or die;
240 my $dest = shift or die;
242 copy $source, $dest or die "Problem copying $source to $dest: $!\n";
246 # directory setup routines
250 sub mkdir_recursive ($) {
251 my $path = shift or die;
254 for my $dir (split /\//, $path) {
255 $tmp_path .= "$dir/";
258 or mkdir $tmp_path, 0700
259 or die "Can't mkdir $tmp_path: $!";
264 mkdir_recursive($certificates_path);
265 mkdir_recursive($private_keys_path);
269 $file = $certificates_path . "/.index";
270 -f $file or open(TMP_FILE, ">$file") and close(TMP_FILE)
271 or die "Can't touch $file: $!";
273 $file = $private_keys_path . "/.index";
274 -f $file or open(TMP_FILE, ">$file") and close(TMP_FILE)
275 or die "Can't touch $file: $!";
281 # certificate management methods
285 my %keyflags = ( 'i', '(Invalid)', 'r', '(Revoked)', 'e', '(Expired)',
286 'u', '(Unverified)', 'v', '(Valid)', 't', '(Trusted)');
288 open(INDEX, "<$certificates_path/.index") or
289 die "Couldn't open $certificates_path/.index: $!";
298 if($fields[2] eq '-') {
299 print "$fields[1]: Issued for: $fields[0] $keyflags{$fields[4]}\n";
301 print "$fields[1]: Issued for: $fields[0] \"$fields[2]\" $keyflags{$fields[4]}\n";
304 my $certfile = "$certificates_path/$fields[1]";
308 die "Couldn't open $certfile: $!";
319 my $format = -B $certfile ? 'DER' : 'PEM';
320 my $cmd = "$opensslbin x509 -subject -issuer -dates -noout -in $certfile -inform $format";
321 ($subject_in, $issuer_in, $date1_in, $date2_in) = `$cmd`;
322 $? and print "ERROR: '$cmd' returned $?\n\n" and next;
325 my @subject = split(/\//, $subject_in);
327 $tmp = shift @subject;
328 ($tmp =~ /^CN\=/) and last;
331 defined $tmp and @tmp = split (/\=/, $tmp) and
332 print $tab."Subject: $tmp[1]\n";
334 my @issuer = split(/\//, $issuer_in);
336 $tmp = shift @issuer;
337 ($tmp =~ /^CN\=/) and last;
340 defined $tmp and @tmp = split (/\=/, $tmp) and
341 print $tab."Issued by: $tmp[1]";
343 if ( defined $date1_in and defined $date2_in ) {
344 @tmp = split (/\=/, $date1_in);
346 @tmp = split (/\=/, $date2_in);
347 print $tab."Certificate is not valid before $tmp".
348 $tab." or after ".$tmp[1];
351 -e "$private_keys_path/$fields[1]" and
352 print "$tab - Matching private key installed -\n";
354 $format = -B "$certificates_path/$fields[1]" ? 'DER' : 'PEM';
355 $cmd = "$opensslbin x509 -purpose -noout -in $certfile -inform $format";
356 my $purpose_in = `$cmd`;
357 $? and die "'$cmd' returned $?";
359 my @purpose = split (/\n/, $purpose_in);
360 print "$tab$purpose[0] (displays S/MIME options only)\n";
362 $tmp = shift @purpose;
363 ($tmp =~ /^S\/MIME/ and $tmp =~ /Yes/) or next;
364 my @tmptmp = split (/:/, $tmp);
365 print "$tab $tmptmp[0]\n";
380 print "\nYou may assign a label to this key, so you don't have to remember\n";
381 print "the key ID. This has to be _one_ word (no whitespaces).\n\n";
383 print "Enter label: ";
384 chomp($input = <STDIN>);
386 my ($label, $junk) = split(/\s/, $input, 2);
389 and print "\nUsing '$label' as label; ignoring '$junk'\n";
391 defined $label || ($label = "-");
398 sub add_entry ($$$$$) {
399 my $mailbox = shift or die;
400 my $hashvalue = shift or die;
401 my $use_cert = shift;
402 my $label = shift or die;
403 my $issuer_hash = shift;
408 open(INDEX, "+<$certificates_path/.index") or
409 die "Couldn't open $certificates_path/.index: $!";
412 open(INDEX, "+<$private_keys_path/.index") or
413 die "Couldn't open $private_keys_path/.index: $!";
418 return if ($fields[0] eq $mailbox && $fields[1] eq $hashvalue);
422 print INDEX "$mailbox $hashvalue $label $issuer_hash u\n";
425 print INDEX "$mailbox $hashvalue $label \n";
432 sub add_certificate ($$$$;$) {
433 my $filename = shift or die;
434 my $hashvalue = shift or die;
435 my $add_to_index = shift;
436 my $label = shift or die;
437 my $issuer_hash = shift;
443 while(-e "$certificates_path/$$hashvalue.$iter") {
445 my $format = -B $filename ? 'DER' : 'PEM';
446 my $cmd = "$opensslbin x509 -in $filename -inform $format -fingerprint -noout";
448 $? and die "'$cmd' returned $?";
450 $format = -B "$certificates_path/$$hashvalue.$iter" ? 'DER' : 'PEM';
451 $cmd = "$opensslbin x509 -in $certificates_path/$$hashvalue.$iter -inform $format -fingerprint -noout";
453 $? and die "'$cmd' returned $?";
459 $$hashvalue .= ".$iter";
461 if (-e "$certificates_path/$$hashvalue") {
462 print "\nCertificate: $certificates_path/$$hashvalue already installed.\n";
465 mycopy $filename, "$certificates_path/$$hashvalue";
468 my $format = -B $filename ? 'DER' : 'PEM';
469 my $cmd = "$opensslbin x509 -in $filename -inform $format -email -noout";
471 $? and die "'$cmd' returned $?";
473 foreach $mailbox (@mailbox) {
475 add_entry($mailbox, $$hashvalue, 1, $label, $issuer_hash);
477 print "\ncertificate $$hashvalue ($label) for $mailbox added.\n";
479 verify_cert($$hashvalue, undef);
482 print "added certificate: $certificates_path/$$hashvalue.\n";
491 my $file = shift or die;
492 my $hashvalue = shift or die;
493 my $mailbox = shift or die;
494 my $label = shift or die;
496 unless (-e "$private_keys_path/$hashvalue") {
497 mycopy $file, "$private_keys_path/$hashvalue";
500 add_entry($mailbox, $hashvalue, 0, $label, "");
501 print "added private key: " .
502 "$private_keys_path/$hashvalue for $mailbox\n";
516 $cert_tmp_file[$cert_iter] = newfile("cert_tmp.$cert_iter","temp");
517 my $cert_tmp_iter = $cert_tmp_file[$cert_iter];
518 open(CERT_FILE, ">$cert_tmp_iter")
519 or die "Couldn't open $cert_tmp_iter: $!";
521 while($_ = shift(@_)) {
522 if(/^Bag Attributes/) {
524 $state == 0 or die("PEM-parse error at: $.");
526 $bag_attribs[$cert_iter*4+1] = "";
527 $bag_attribs[$cert_iter*4+2] = "";
528 $bag_attribs[$cert_iter*4+3] = "";
531 ($state == 1) and /localKeyID:\s*(.*)/
532 and ($bag_attribs[$cert_iter*4+1] = $1);
534 ($state == 1) and /subject=\s*(.*)/
535 and ($bag_attribs[$cert_iter*4+2] = $1);
537 ($state == 1) and /issuer=\s*(.*)/
538 and ($bag_attribs[$cert_iter*4+3] = $1);
546 $bag_attribs[$cert_iter*4] = "K";
550 $bag_attribs[$cert_iter*4] = "C";
553 die("What's this: $_");
560 $cert_tmp_file[$cert_iter] = newfile("cert_tmp.$cert_iter","temp");
561 $cert_tmp_iter = $cert_tmp_file[$cert_iter];
562 open(CERT_FILE, ">$cert_tmp_iter")
563 or die "Couldn't open $cert_tmp_iter: $!";
571 # I'll add support for unbagged cetificates, in case this is needed.
572 $numBags == $cert_iter or
573 die("Not all contents were bagged. can't continue.");
579 # This requires the Bag Attributes to be set
591 @pem_contents = &parse_pem(@_);
593 # private key and certificate use the same 'localKeyID'
594 while($iter <= $#pem_contents / 4) {
595 if($pem_contents[$iter * 4] eq "K") {
601 ($iter > $#pem_contents / 2) and die("Couldn't find private key!");
603 $pem_contents[($key * 4)+1] or die("Attribute 'localKeyID' wasn't set.");
606 while($iter <= $#pem_contents / 4) {
607 $iter == $key and ($iter++) and next;
608 if($pem_contents[($iter * 4)+1] eq $pem_contents[($key * 4)+1]) {
609 $certificate = $iter;
614 ($iter > $#pem_contents / 4) and die("Couldn't find matching certificate!");
616 my $tmp_key = newfile("tmp_key","temp");
617 mycopy $cert_tmp_file[$key], $tmp_key;
618 my $tmp_certificate = newfile("tmp_certificate","temp");
619 mycopy $cert_tmp_file[$certificate], $tmp_certificate;
621 # root certificate is self signed
624 while($iter <= $#pem_contents / 4) {
625 if ($iter == $key or $iter == $certificate) {
630 if($pem_contents[($iter * 4)+2] eq $pem_contents[($iter * 4)+3]) {
636 if ($iter > $#pem_contents / 4) {
637 print "Couldn't identify root certificate!\n";
641 # what's left are intermediate certificates.
644 # needs to be set, so we can check it later
645 $intermediate = $root_cert;
646 my $tmp_issuer_cert = newfile("tmp_issuer_cert","temp");
647 while($iter <= $#pem_contents / 4) {
648 if ($iter == $key or $iter == $certificate or $iter == $root_cert) {
653 open (IC, ">> $tmp_issuer_cert") or die "can't open $tmp_issuer_cert: $?";
654 my $cert_tmp_iter = $cert_tmp_file[$iter];
655 open (CERT, "< $cert_tmp_iter") or die "can't open $cert_tmp_iter: $?";
656 print IC while (<CERT>);
660 # although there may be many, just need to know if there was any
661 $intermediate = $iter;
666 # no intermediate certificates ? use root-cert instead (if that was found...)
667 if($intermediate == $root_cert) {
668 if ($root_cert == -1) {
669 die("No root and no intermediate certificates. Can't continue.");
671 mycopy $cert_tmp_file[$root_cert], $tmp_issuer_cert;
674 my $label = query_label;
676 my $format = -B $tmp_certificate ? 'DER' : 'PEM';
677 my $cmd = "$opensslbin x509 -noout -hash -in $tmp_certificate -inform $format";
678 my $cert_hash = `$cmd`;
679 $? and die "'$cmd' returned $?";
681 $format = -B $tmp_issuer_cert ? 'DER' : 'PEM';
682 $cmd = "$opensslbin x509 -noout -hash -in $tmp_issuer_cert -inform $format";
683 my $issuer_hash = `$cmd`;
684 $? and die "'$cmd' returned $?";
686 chomp($cert_hash); chomp($issuer_hash);
688 # Note: $cert_hash will be changed to reflect the correct filename
689 # within add_cert() ONLY, so these _have_ to get called first..
690 add_certificate($tmp_issuer_cert, \$issuer_hash, 0, $label);
691 @mailbox = &add_certificate("$tmp_certificate", \$cert_hash, 1, $label, $issuer_hash);
692 foreach $mailbox (@mailbox) {
694 add_key($tmp_key, $cert_hash, $mailbox, $label);
703 sub modify_entry ($$$;$ ) {
704 my $op = shift or die;
705 my $hashvalue = shift or die;
706 my $use_cert = shift;
712 $op eq 'L' and ($label = shift or die);
713 $op eq 'V' and ($crl = shift);
717 $path = $certificates_path;
720 $path = $private_keys_path;
723 open(INDEX, "<$path/.index") or
724 die "Couldn't open $path/.index: $!";
725 my $newindex = newfile("$path/.index.tmp");
726 open(NEW_INDEX, ">$newindex") or
727 die "Couldn't create $newindex: $!";
731 if($fields[1] eq $hashvalue or $hashvalue eq 'all') {
733 print NEW_INDEX "$fields[0] $fields[1]";
736 print NEW_INDEX " $label $fields[3] $fields[4]";
739 print NEW_INDEX " $label";
743 print "\n==> about to verify certificate of $fields[0]\n";
744 my $flag = &do_verify($fields[1], $fields[3], $crl);
745 print NEW_INDEX " $fields[2] $fields[3] $flag";
747 print NEW_INDEX "\n";
755 rename $newindex, "$path/.index"
756 or die "Couldn't rename $newindex to $path/.index: $!\n";
764 sub remove_pair ($ ) {
765 my $keyid = shift or die;
767 if (-e "$certificates_path/$keyid") {
768 unlink "$certificates_path/$keyid";
769 modify_entry('R', $keyid, 1);
770 print "Removed certificate $keyid.\n";
773 die "No such certificate: $keyid";
776 if (-e "$private_keys_path/$keyid") {
777 unlink "$private_keys_path/$keyid";
778 modify_entry('R', $keyid, 0);
779 print "Removed private key $keyid.\n";
785 sub change_label ($ ) {
786 my $keyid = shift or die;
788 my $label = query_label;
790 if (-e "$certificates_path/$keyid") {
791 modify_entry('L', $keyid, 1, $label);
792 print "Changed label for certificate $keyid.\n";
795 die "No such certificate: $keyid";
798 if (-e "$private_keys_path/$keyid") {
799 modify_entry('L', $keyid, 0, $label);
800 print "Changed label for private key $keyid.\n";
808 sub verify_cert ($$) {
809 my $keyid = shift or die;
812 -e "$certificates_path/$keyid" or $keyid eq 'all'
813 or die "No such certificate: $keyid";
814 modify_entry('V', $keyid, 1, $crl);
822 my $cert = shift or die;
823 my $issuerid = shift or die;
829 my $cert_path = "$certificates_path/$cert";
831 if($issuerid eq '?') {
832 $issuer_path = "$certificates_path/$cert";
834 $issuer_path = "$certificates_path/$issuerid";
837 my $cmd = "$opensslbin verify $root_certs_switch $root_certs_path -purpose smimesign -purpose smimeencrypt -untrusted $issuer_path $cert_path";
839 $? and die "'$cmd' returned $?";
843 ($output =~ /OK/) and ($result = 'v');
845 $result eq 'i' and return $result;
847 my $format = -B $cert_path ? 'DER' : 'PEM';
848 $cmd = "$opensslbin x509 -dates -serial -noout -in $cert_path -inform $format";
849 (my $date1_in, my $date2_in, my $serial_in) = `$cmd`;
850 $? and die "'$cmd' returned $?";
852 if ( defined $date1_in and defined $date2_in ) {
853 my @tmp = split (/\=/, $date1_in);
855 @tmp = split (/\=/, $date2_in);
856 my %months = ('Jan', '00', 'Feb', '01', 'Mar', '02', 'Apr', '03',
857 'May', '04', 'Jun', '05', 'Jul', '06', 'Aug', '07',
858 'Sep', '08', 'Oct', '09', 'Nov', '10', 'Dec', '11');
861 $tmp =~ /(\w+)\s*(\d+)\s*(\d+):(\d+):(\d+)\s*(\d+)\s*GMT/;
863 $#fields != 5 and print "Expiration Date: Parse Error : $tmp\n\n" or
864 timegm($fields[4], $fields[3], $fields[2], $fields[1],
865 $months{$fields[0]}, $fields[5]) > time and $result = 'e';
866 $result eq 'e' and print "Certificate is not yet valid.\n" and return $result;
869 $tmp[1] =~ /(\w+)\s*(\d+)\s*(\d+):(\d+):(\d+)\s*(\d+)\s*GMT/;
871 $#fields != 5 and print "Expiration Date: Parse Error : $tmp[1]\n\n" or
872 timegm($fields[4], $fields[3], $fields[2], $fields[1],
873 $months{$fields[0]}, $fields[5]) < time and $result = 'e';
874 $result eq 'e' and print "Certificate has expired.\n" and return $result;
878 if ( defined $crl ) {
879 my @serial = split (/\=/, $serial_in);
880 my $cmd = "$opensslbin crl -text -noout -in $crl | grep -A1 $serial[1]";
881 (my $l1, my $l2) = `$cmd`;
882 $? and die "'$cmd' returned $?";
885 my @revoke_date = split (/:\s/, $l2);
886 print "FAILURE: Certificate $cert has been revoked on $revoke_date[1]\n";
892 if ($result eq 'v') {
901 sub add_root_cert ($) {
902 my $root_cert = shift or die;
904 my $format = -B $root_cert ? 'DER' : 'PEM';
906 my $cmd = "$opensslbin x509 -noout -hash -in $root_cert -inform $format";
907 my $root_hash = `$cmd`;
908 $? and die "'$cmd' returned $?";
910 if (-d $root_certs_path) {
911 -e "$root_certs_path/$root_hash" or
912 mycopy $root_cert, "$root_certs_path/$root_hash";
915 open(ROOT_CERTS, ">>$root_certs_path") or
916 die ("Couldn't open $root_certs_path for writing");
918 $cmd = "$opensslbin x509 -in $root_cert -inform $format -fingerprint -noout";
919 $? and die "'$cmd' returned $?";
920 chomp(my $md5fp = `$cmd`);
922 $cmd = "$opensslbin x509 -in $root_cert -inform $format -text -noout";
923 $? and die "'$cmd' returned $?";
924 my @cert_text = `$cmd`;
926 print "Enter a label, name or description for this certificate: ";
929 my $line = "=======================================\n";
930 print ROOT_CERTS "\n$input$line$md5fp\nPEM-Data:\n";
932 $cmd = "$opensslbin x509 -in $root_cert -inform $format";
934 $? and die "'$cmd' returned $?";
935 print ROOT_CERTS $cert;
936 print ROOT_CERTS @cert_text;
943 # returns a file name which does not exist for tmp file creation
944 my $filename = shift;
946 $option = "notemp" if (not defined($option));
947 if (! $tmpdir and $option eq "temp") {
948 $tmpdir = mutt_Q 'tmpdir';
949 $tmpdir = newfile("$tmpdir/smime");
950 mkdir $tmpdir, 0700 || die "Can't create $tmpdir: $!\n";
952 $filename = "$tmpdir/$filename" if ($option eq "temp");
953 my $newfilename = $filename;
955 while (-e $newfilename) {
956 $newfilename = "$filename.$count";
959 unshift(@tempfiles,$newfilename);
965 # remove all our temporary files in the end: