1diff --git a/tools/c_rehash.in b/tools/c_rehash.in 2index cfd18f5da1..9d2a6f6db7 100644 3--- a/tools/c_rehash.in 4+++ b/tools/c_rehash.in 5@@ -104,52 +104,78 @@ foreach (@dirlist) { 6 } 7 exit($errorcount); 8 9+sub copy_file { 10+ my ($src_fname, $dst_fname) = @_; 11+ 12+ if (open(my $in, "<", $src_fname)) { 13+ if (open(my $out, ">", $dst_fname)) { 14+ print $out $_ while (<$in>); 15+ close $out; 16+ } else { 17+ warn "Cannot open $dst_fname for write, $!"; 18+ } 19+ close $in; 20+ } else { 21+ warn "Cannot open $src_fname for read, $!"; 22+ } 23+} 24+ 25 sub hash_dir { 26- my %hashlist; 27- print "Doing $_[0]\n"; 28- chdir $_[0]; 29- opendir(DIR, "."); 30- my @flist = sort readdir(DIR); 31- closedir DIR; 32- if ( $removelinks ) { 33- # Delete any existing symbolic links 34- foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { 35- if (-l $_) { 36- print "unlink $_" if $verbose; 37- unlink $_ || warn "Can't unlink $_, $!\n"; 38- } 39- } 40- } 41- FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) { 42- # Check to see if certificates and/or CRLs present. 43- my ($cert, $crl) = check_file($fname); 44- if (!$cert && !$crl) { 45- print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; 46- next; 47- } 48- link_hash_cert($fname) if ($cert); 49- link_hash_crl($fname) if ($crl); 50- } 51+ my $dir = shift; 52+ my %hashlist; 53+ 54+ print "Doing $dir\n"; 55+ 56+ if (!chdir $dir) { 57+ print STDERR "WARNING: Cannot chdir to '$dir', $!\n"; 58+ return; 59+ } 60+ 61+ opendir(DIR, ".") || print STDERR "WARNING: Cannot opendir '.', $!\n"; 62+ my @flist = sort readdir(DIR); 63+ closedir DIR; 64+ if ( $removelinks ) { 65+ # Delete any existing symbolic links 66+ foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { 67+ if (-l $_) { 68+ print "unlink $_\n" if $verbose; 69+ unlink $_ || warn "Can't unlink $_, $!\n"; 70+ } 71+ } 72+ } 73+ FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) { 74+ # Check to see if certificates and/or CRLs present. 75+ my ($cert, $crl) = check_file($fname); 76+ if (!$cert && !$crl) { 77+ print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; 78+ next; 79+ } 80+ link_hash_cert($fname) if ($cert); 81+ link_hash_crl($fname) if ($crl); 82+ } 83+ 84+ chdir $pwd; 85 } 86 87 sub check_file { 88- my ($is_cert, $is_crl) = (0,0); 89- my $fname = $_[0]; 90- open IN, $fname; 91- while(<IN>) { 92- if (/^-----BEGIN (.*)-----/) { 93- my $hdr = $1; 94- if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { 95- $is_cert = 1; 96- last if ($is_crl); 97- } elsif ($hdr eq "X509 CRL") { 98- $is_crl = 1; 99- last if ($is_cert); 100- } 101- } 102- } 103- close IN; 104- return ($is_cert, $is_crl); 105+ my ($is_cert, $is_crl) = (0,0); 106+ my $fname = $_[0]; 107+ 108+ open(my $in, "<", $fname); 109+ while(<$in>) { 110+ if (/^-----BEGIN (.*)-----/) { 111+ my $hdr = $1; 112+ if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { 113+ $is_cert = 1; 114+ last if ($is_crl); 115+ } elsif ($hdr eq "X509 CRL") { 116+ $is_crl = 1; 117+ last if ($is_cert); 118+ } 119+ } 120+ } 121+ close $in; 122+ return ($is_cert, $is_crl); 123 } 124 125 sub compute_hash { 126@@ -177,76 +203,48 @@ sub compute_hash { 127 # certificate fingerprints 128 129 sub link_hash_cert { 130- my $fname = $_[0]; 131- my ($hash, $fprint) = compute_hash($openssl, "x509", $x509hash, 132- "-fingerprint", "-noout", 133- "-in", $fname); 134- chomp $hash; 135- chomp $fprint; 136- return if !$hash; 137- $fprint =~ s/^.*=//; 138- $fprint =~ tr/://d; 139- my $suffix = 0; 140- # Search for an unused hash filename 141- while(exists $hashlist{"$hash.$suffix"}) { 142- # Hash matches: if fingerprint matches its a duplicate cert 143- if ($hashlist{"$hash.$suffix"} eq $fprint) { 144- print STDERR "WARNING: Skipping duplicate certificate $fname\n"; 145- return; 146- } 147- $suffix++; 148- } 149- $hash .= ".$suffix"; 150- if ($symlink_exists) { 151- print "link $fname -> $hash\n" if $verbose; 152- symlink $fname, $hash || warn "Can't symlink, $!"; 153- } else { 154- print "copy $fname -> $hash\n" if $verbose; 155- if (open($in, "<", $fname)) { 156- if (open($out,">", $hash)) { 157- print $out $_ while (<$in>); 158- close $out; 159- } else { 160- warn "can't open $hash for write, $!"; 161- } 162- close $in; 163- } else { 164- warn "can't open $fname for read, $!"; 165- } 166- } 167- $hashlist{$hash} = $fprint; 168+ link_hash($_[0], 'cert'); 169 } 170 171 # Same as above except for a CRL. CRL links are of the form <hash>.r<n> 172 173 sub link_hash_crl { 174- my $fname = $_[0]; 175- my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash, 176- "-fingerprint", "-noout", 177- "-in", $fname); 178- chomp $hash; 179- chomp $fprint; 180- return if !$hash; 181- $fprint =~ s/^.*=//; 182- $fprint =~ tr/://d; 183- my $suffix = 0; 184- # Search for an unused hash filename 185- while(exists $hashlist{"$hash.r$suffix"}) { 186- # Hash matches: if fingerprint matches its a duplicate cert 187- if ($hashlist{"$hash.r$suffix"} eq $fprint) { 188- print STDERR "WARNING: Skipping duplicate CRL $fname\n"; 189- return; 190- } 191- $suffix++; 192- } 193- $hash .= ".r$suffix"; 194- if ($symlink_exists) { 195- print "link $fname -> $hash\n" if $verbose; 196- symlink $fname, $hash || warn "Can't symlink, $!"; 197- } else { 198- print "cp $fname -> $hash\n" if $verbose; 199- system ("cp", $fname, $hash); 200- warn "Can't copy, $!" if ($? >> 8) != 0; 201- } 202- $hashlist{$hash} = $fprint; 203+ link_hash($_[0], 'crl'); 204+} 205+ 206+sub link_hash { 207+ my ($fname, $type) = @_; 208+ my $is_cert = $type eq 'cert'; 209+ 210+ my ($hash, $fprint) = compute_hash($openssl, 211+ $is_cert ? "x509" : "crl", 212+ $is_cert ? $x509hash : $crlhash, 213+ "-fingerprint", "-noout", 214+ "-in", $fname); 215+ chomp $hash; 216+ chomp $fprint; 217+ return if !$hash; 218+ $fprint =~ s/^.*=//; 219+ $fprint =~ tr/://d; 220+ my $suffix = 0; 221+ # Search for an unused hash filename 222+ my $crlmark = $is_cert ? "" : "r"; 223+ while(exists $hashlist{"$hash.$crlmark$suffix"}) { 224+ # Hash matches: if fingerprint matches its a duplicate cert 225+ if ($hashlist{"$hash.$crlmark$suffix"} eq $fprint) { 226+ my $what = $is_cert ? 'certificate' : 'CRL'; 227+ print STDERR "WARNING: Skipping duplicate $what $fname\n"; 228+ return; 229+ } 230+ $suffix++; 231+ } 232+ $hash .= ".$crlmark$suffix"; 233+ if ($symlink_exists) { 234+ print "link $fname -> $hash\n" if $verbose; 235+ symlink $fname, $hash || warn "Can't symlink, $!"; 236+ } else { 237+ print "copy $fname -> $hash\n" if $verbose; 238+ copy_file($fname, $hash); 239+ } 240+ $hashlist{$hash} = $fprint; 241 }