diff options
author | Rob Austein <sra@hactrn.net> | 2006-08-29 23:37:35 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2006-08-29 23:37:35 +0000 |
commit | 26192428936c7e2c5c9daa2c68e64513bf2f7b1a (patch) | |
tree | 16efc21dbd2e9194d1933faaaaf0cc332f884e0e | |
parent | ff9c60fc05e315455cfb3a5da15606ef1bbf84f5 (diff) |
Apparently we need to fetch the CRL in order to verify the cert in
which we found the CRL's URI. Ick. Have asked on list, deferring
work briefly in the hope that someone will tell me that I'm wrong
about this.
svn path=/scripts/rcynic-prototype.pl; revision=243
-rw-r--r-- | scripts/rcynic-prototype.pl | 135 |
1 files changed, 85 insertions, 50 deletions
diff --git a/scripts/rcynic-prototype.pl b/scripts/rcynic-prototype.pl index 4570e3e1..94fe4aca 100644 --- a/scripts/rcynic-prototype.pl +++ b/scripts/rcynic-prototype.pl @@ -21,44 +21,58 @@ my $authenticated_tree = "$root/authenticated"; my $temporary_tree = "$root/temporary"; my $cafile = "$root/CAfile.pem"; - my @anchors; my @preaggregated; my %certs; -sub mkdir_maybe { - my $dir = shift; - $dir =~ s=[^/]+$==; - !system("mkdir", "-p", $dir) - or die("Couldn't make $dir") - unless (-d $dir); -} +my $verbose = 1; -sub rsync { - !system("rsync", "-rtiLk", @_) - or print("rsync @_ returned failure\n"); +sub run { + print(join(" ", "Running", @_), "\n") + if ($verbose); + system(@_); + print("$_[0] returned $?\n") + if ($? != 0); } -sub openssl { - !system($openssl, @_) - or die("Couldn't openssl @_"); -} - -sub openssl_pipe { +sub run_pipe { + print(join(" ", "Running", @_), "\n") + if ($verbose); my $pid = open(F, "-|"); if ($pid) { my @result = <F>; close(F); chomp(@result); + print("$_[0] returned $?\n") + if ($? != 0); return @result; } else { open(STDERR, ">&STDOUT") or die("Couldn't dup() STDOUT: $!"); - exec($openssl, @_) - or die("Couldn't exec() openssl @_: $!"); + exec(@_) + or die("Couldn't exec() ", join(" ", @_), ": $!"); } } +sub mkdir_maybe { + my $dir = shift; + $dir =~ s=[^/]+$==; + run("mkdir", "-p", $dir) + unless (-d $dir); +} + +sub rsync { + run("rsync", "-rtiLk", @_); +} + +sub openssl { + run($openssl, @_); +} + +sub openssl_pipe { + run_pipe($openssl, @_); +} + sub uri_to_filename { local $_ = shift; if ($_) { @@ -160,59 +174,70 @@ sub verify_cert { my @result = openssl_pipe(qw(verify -verbose -crl_check_all -policy_check -explicit_policy -policy 1.3.6.1.5.5.7.14.2 -x509_strict -CAfile), $cafile, "$temporary_tree/$cert"); local $_; - my $ok; for (@result) { - $ok = 1 if (/OK$/); + return 1 if (/OK$/); } - return $ok; + print("Verification failure:\n"); + print(" Inputs:\n"); + print(" $_\n") + foreach (($cert, @_)); + print(" Result:\n"); + print(" $_\n") + foreach (@result); + return 0; } sub check_cert { - my $cert = shift; # -verified- cert we're examining (we start from trust anchors) + my $c = shift; # parsed verified cert we're examining my @chain = @_; # ancestors and crls - print("Starting check of $cert\n"); + die("check_cert() called without a certificate to check") + unless ($c); - my $u = parse_cert($cert); - die("Couldn't parse certificate: $cert") - unless ($u); + print("Starting check of $c->{uri}\n"); + + print("URI: $c->{uri}\n"); + print("AIA: $c->{aia}\n") if ($c->{aia}); + print("SIA: $c->{sia}\n") if ($c->{sai}); + print("CDP: $c->{cdp}\n") if ($c->{cdp}); + print("CA: ", ($c->{ca} ? "Yes" : "No"), "\n"); my $crl; - if ($u->{cdp}) { - $crl = uri_to_filename($u->{cdp}); - die ("Problem with CRL signature: $u->{cdp}") - unless (check_crl($u->{cdp}, $crl, $u->{file}, @chain)); + if ($c->{cdp}) { + $crl = uri_to_filename($c->{cdp}); + die ("Problem with CRL signature: $c->{cdp}") + unless (check_crl($c->{cdp}, $crl, $c->{file}, @chain)); copy_crl($crl); } else { - print("CDP missing for cert: $cert\n"); + print("CDP missing for cert: $c->{uri}\n"); } - if (@chain && !$u->{aia}) { - print("Non-trust-anchor certificate missing AIA extension: $cert\n"); - } elsif (@chain && $chain[0] ne $u->{aia}) { - print("AIA does not match parent URI:\n\t$cert\n\t$u->{aia}\n"); + if (@chain && !$c->{aia}) { + print("Non-trust-anchor certificate missing AIA extension: $c->{uri}\n"); + } elsif (@chain && $chain[0] ne uri_to_filename($c->{aia})) { + print("AIA does not match parent URI:\n\trsync://$chain[0]\n\t$c->{aia}\n"); } unshift(@chain, $crl) if ($crl); - unshift(@chain, $u->{file}); + unshift(@chain, $c->{file}); - if ($u->{ca}) { - print("CA certificate without SIA extension: $cert\n") - unless ($u->{sia}); + if ($c->{ca}) { + print("CA certificate without SIA extension: $c->{uri}\n") + unless ($c->{sia}); } else { - print("EE certificate shouldn't have SIA extension: $cert\n") - if ($u->{sia}); + print("EE certificate shouldn't have SIA extension: $c->{uri}\n") + if ($c->{sia}); } - if ($u->{sia}) { - my $sia = uri_to_filename($u->{sia}); + if ($c->{sia}) { + my $sia = uri_to_filename($c->{sia}); # # Suppress this rsync when we've already done an ancestor? # Almost certainly. Deal with it later. # mkdir_maybe("$unauthenticated_tree/$sia"); - rsync($u->{sia}, "$unauthenticated_tree/$sia"); + rsync($c->{sia}, "$unauthenticated_tree/$sia"); for my $file (glob("$unauthenticated_tree/${sia}*.cer")) { $file =~ s=^$unauthenticated_tree/==; my $uri = "rsync://" . $file; @@ -222,17 +247,27 @@ sub check_cert { next; } copy_cert($file); - if (!verify_cert($file, @chain)) { + my $x = parse_cert($uri, $temporary_tree); + if (!$x) { + print("Parse failure for $uri, skipping\n"); + next; + } + # + # This is questionable -- CRL may not have been checked yet. + # One would hope that verification checks CRL signatures, + # but the CRL may not be in our verified repository yet. + # + if (!verify_cert($file, uri_to_filename($x->{cdp}), @chain)) { print("Verification failure for $uri, skipping\n"); unlink("$temporary_tree/$file"); next; } install_cert($file); - check_cert($uri, @chain); + check_cert($x, @chain); } } - print("Finished check of $cert\n"); + print("Finished check of $c->{uri}\n"); } ### @@ -265,7 +300,7 @@ if (1) { # Initial cleanup. -system("rm", "-rf", $temporary_tree, "${authenticated_tree}.old"); +run("rm", "-rf", $temporary_tree, "${authenticated_tree}.old"); rename($authenticated_tree, "${authenticated_tree}.old"); # Create any missing directories. @@ -300,7 +335,7 @@ for my $anchor (@anchors) { # Now start walking the tree, starting with our trust anchors. for my $anchor (@anchors) { - check_cert($anchor); + check_cert(parse_cert($anchor)); } |