diff options
Diffstat (limited to 'crypto/openssl/tools/c_rehash.in')
-rw-r--r-- | crypto/openssl/tools/c_rehash.in | 209 |
1 files changed, 148 insertions, 61 deletions
diff --git a/crypto/openssl/tools/c_rehash.in b/crypto/openssl/tools/c_rehash.in index cc3b658..baec7c1 100644 --- a/crypto/openssl/tools/c_rehash.in +++ b/crypto/openssl/tools/c_rehash.in @@ -1,61 +1,148 @@ -#!/bin/sh -# -# redo the hashes for the certificates in your cert path or the ones passed -# on the command line. -# - -if [ "$OPENSSL"x = "x" -o ! -x "$OPENSSL" ]; then - OPENSSL='openssl' - export OPENSSL -fi -DIR=/usr/local/ssl -PATH=$DIR/bin:$PATH - -if [ ! -f "$OPENSSL" ]; then - found=0 - for dir in . `echo $PATH | sed -e 's/:/ /g'`; do - if [ -f "$dir/$OPENSSL" ]; then - found=1 - break - fi - done - if [ $found = 0 ]; then - echo "c_rehash: rehashing skipped ('openssl' program not available)" 1>&2 - exit 0 - fi -fi - -SSL_DIR=$DIR/certs - -if [ "$*" = "" ]; then - CERTS=${*:-${SSL_CERT_DIR:-$SSL_DIR}} -else - CERTS=$* -fi - -IFS=': ' -for i in $CERTS -do - ( - IFS=' ' - if [ -d $i -a -w $i ]; then - cd $i - echo "Doing $i" - for i in *.pem - do - if [ $i != '*.pem' ]; then - h=`$OPENSSL x509 -hash -noout -in $i` - if [ "x$h" = "x" ]; then - echo $i does not contain a certificate - else - if [ -f $h.0 ]; then - /bin/rm -f $h.0 - fi - echo "$i => $h.0" - ln -s $i $h.0 - fi - fi - done - fi - ) -done +#!/usr/local/bin/perl + + +# Perl c_rehash script, scan all files in a directory +# and add symbolic links to their hash values. + +my $openssl; + +my $dir; + +if(defined $ENV{OPENSSL}) { + $openssl = $ENV{OPENSSL}; +} else { + $openssl = "openssl"; + $ENV{OPENSSL} = $openssl; +} + +$ENV{PATH} .= ":$dir/bin"; + +if(! -f $openssl) { + my $found = 0; + foreach (split /:/, $ENV{PATH}) { + if(-f "$_/$openssl") { + $found = 1; + last; + } + } + if($found == 0) { + print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n"; + exit 0; + } +} + +if(@ARGV) { + @dirlist = @ARGV; +} elsif($ENV{SSL_CERT_DIR}) { + @dirlist = split /:/, $ENV{SSL_CERT_DIR}; +} else { + $dirlist[0] = "$dir/certs"; +} + + +foreach (@dirlist) { + if(-d $_ and -w $_) { + hash_dir($_); + } +} + +sub hash_dir { + my %hashlist; + print "Doing $_[0]\n"; + chdir $_[0]; + opendir(DIR, "."); + my @flist = readdir(DIR); + # Delete any existing symbolic links + foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { + if(-l $_) { + unlink $_; + } + } + closedir DIR; + FILE: foreach $fname (grep {/\.pem$/} @flist) { + # Check to see if certificates and/or CRLs present. + my ($cert, $crl) = check_file($fname); + if(!$cert && !$crl) { + print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; + next; + } + link_hash_cert($fname) if($cert); + link_hash_crl($fname) if($crl); + } +} + +sub check_file { + my ($is_cert, $is_crl) = (0,0); + my $fname = $_[0]; + open IN, $fname; + while(<IN>) { + if(/^-----BEGIN (.*)-----/) { + my $hdr = $1; + if($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { + $is_cert = 1; + last if($is_crl); + } elsif($hdr eq "X509 CRL") { + $is_crl = 1; + last if($is_cert); + } + } + } + close IN; + return ($is_cert, $is_crl); +} + + +# Link a certificate to its subject name hash value, each hash is of +# the form <hash>.<n> where n is an integer. If the hash value already exists +# then we need to up the value of n, unless its a duplicate in which +# case we skip the link. We check for duplicates by comparing the +# certificate fingerprints + +sub link_hash_cert { + my $fname = $_[0]; + my ($hash, $fprint) = `$openssl x509 -hash -fingerprint -noout -in $fname`; + chomp $hash; + chomp $fprint; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; + # Search for an unused hash filename + while(exists $hashlist{"$hash.$suffix"}) { + # Hash matches: if fingerprint matches its a duplicate cert + if($hashlist{"$hash.$suffix"} eq $fprint) { + print STDERR "WARNING: Skipping duplicate certificate $fname\n"; + return; + } + $suffix++; + } + $hash .= ".$suffix"; + print "$fname => $hash\n"; + symlink $fname, $hash; + $hashlist{$hash} = $fprint; +} + +# Same as above except for a CRL. CRL links are of the form <hash>.r<n> + +sub link_hash_crl { + my $fname = $_[0]; + my ($hash, $fprint) = `$openssl crl -hash -fingerprint -noout -in $fname`; + chomp $hash; + chomp $fprint; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; + # Search for an unused hash filename + while(exists $hashlist{"$hash.r$suffix"}) { + # Hash matches: if fingerprint matches its a duplicate cert + if($hashlist{"$hash.r$suffix"} eq $fprint) { + print STDERR "WARNING: Skipping duplicate CRL $fname\n"; + return; + } + $suffix++; + } + $hash .= ".r$suffix"; + print "$fname => $hash\n"; + symlink $fname, $hash; + $hashlist{$hash} = $fprint; +} + |