c_rehash.cmake 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. # Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
  2. #
  3. # Licensed under the OpenSSL license (the "License"). You may not use
  4. # this file except in compliance with the License. You can obtain a copy
  5. # in the file LICENSE in the source distribution or at
  6. # https://www.openssl.org/source/license.html
  7. # Perl c_rehash script, scan all files in a directory
  8. # and add symbolic links to their hash values.
  9. my $dir = "@OPENSSLDIR@";
  10. my $prefix = "@CMAKE_INSTALL_PREFIX@";
  11. my $errorcount = 0;
  12. my $openssl = $ENV{OPENSSL} || "openssl";
  13. my $pwd;
  14. my $x509hash = "-subject_hash";
  15. my $crlhash = "-hash";
  16. my $verbose = 0;
  17. my $symlink_exists=eval {symlink("",""); 1};
  18. my $removelinks = 1;
  19. ## Parse flags.
  20. while ( $ARGV[0] =~ /^-/ ) {
  21. my $flag = shift @ARGV;
  22. last if ( $flag eq '--');
  23. if ( $flag eq '-old') {
  24. $x509hash = "-subject_hash_old";
  25. $crlhash = "-hash_old";
  26. } elsif ( $flag eq '-h' || $flag eq '-help' ) {
  27. help();
  28. } elsif ( $flag eq '-n' ) {
  29. $removelinks = 0;
  30. } elsif ( $flag eq '-v' ) {
  31. $verbose++;
  32. }
  33. else {
  34. print STDERR "Usage error; try -h.\n";
  35. exit 1;
  36. }
  37. }
  38. sub help {
  39. print "Usage: c_rehash [-old] [-h] [-help] [-v] [dirs...]\n";
  40. print " -old use old-style digest\n";
  41. print " -h or -help print this help text\n";
  42. print " -v print files removed and linked\n";
  43. exit 0;
  44. }
  45. eval "require Cwd";
  46. if (defined(&Cwd::getcwd)) {
  47. $pwd=Cwd::getcwd();
  48. } else {
  49. $pwd=`pwd`;
  50. chomp($pwd);
  51. }
  52. # DOS/Win32 or Unix delimiter? Prefix our installdir, then search.
  53. my $path_delim = ($pwd =~ /^[a-z]\:/i) ? ';' : ':';
  54. $ENV{PATH} = "$prefix/bin" . ($ENV{PATH} ? $path_delim . $ENV{PATH} : "");
  55. if (! -x $openssl) {
  56. my $found = 0;
  57. foreach (split /$path_delim/, $ENV{PATH}) {
  58. if (-x "$_/$openssl") {
  59. $found = 1;
  60. $openssl = "$_/$openssl";
  61. last;
  62. }
  63. }
  64. if ($found == 0) {
  65. print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n";
  66. exit 0;
  67. }
  68. }
  69. if (@ARGV) {
  70. @dirlist = @ARGV;
  71. } elsif ($ENV{SSL_CERT_DIR}) {
  72. @dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR};
  73. } else {
  74. $dirlist[0] = "$dir/certs";
  75. }
  76. if (-d $dirlist[0]) {
  77. chdir $dirlist[0];
  78. $openssl="$pwd/$openssl" if (!-x $openssl);
  79. chdir $pwd;
  80. }
  81. foreach (@dirlist) {
  82. if (-d $_ ) {
  83. if ( -w $_) {
  84. hash_dir($_);
  85. } else {
  86. print "Skipping $_, can't write\n";
  87. $errorcount++;
  88. }
  89. }
  90. }
  91. exit($errorcount);
  92. sub hash_dir {
  93. my %hashlist;
  94. print "Doing $_[0]\n";
  95. chdir $_[0];
  96. opendir(DIR, ".");
  97. my @flist = sort readdir(DIR);
  98. closedir DIR;
  99. if ( $removelinks ) {
  100. # Delete any existing symbolic links
  101. foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
  102. if (-l $_) {
  103. print "unlink $_" if $verbose;
  104. unlink $_ || warn "Can't unlink $_, $!\n";
  105. }
  106. }
  107. }
  108. FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) {
  109. # Check to see if certificates and/or CRLs present.
  110. my ($cert, $crl) = check_file($fname);
  111. if (!$cert && !$crl) {
  112. print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
  113. next;
  114. }
  115. link_hash_cert($fname) if ($cert);
  116. link_hash_crl($fname) if ($crl);
  117. }
  118. }
  119. sub check_file {
  120. my ($is_cert, $is_crl) = (0,0);
  121. my $fname = $_[0];
  122. open IN, $fname;
  123. while(<IN>) {
  124. if (/^-----BEGIN (.*)-----/) {
  125. my $hdr = $1;
  126. if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
  127. $is_cert = 1;
  128. last if ($is_crl);
  129. } elsif ($hdr eq "X509 CRL") {
  130. $is_crl = 1;
  131. last if ($is_cert);
  132. }
  133. }
  134. }
  135. close IN;
  136. return ($is_cert, $is_crl);
  137. }
  138. # Link a certificate to its subject name hash value, each hash is of
  139. # the form <hash>.<n> where n is an integer. If the hash value already exists
  140. # then we need to up the value of n, unless its a duplicate in which
  141. # case we skip the link. We check for duplicates by comparing the
  142. # certificate fingerprints
  143. sub link_hash_cert {
  144. my $fname = $_[0];
  145. $fname =~ s/'/'\\''/g;
  146. my ($hash, $fprint) = `"$openssl" x509 $x509hash -fingerprint -noout -in "$fname"`;
  147. chomp $hash;
  148. chomp $fprint;
  149. $fprint =~ s/^.*=//;
  150. $fprint =~ tr/://d;
  151. my $suffix = 0;
  152. # Search for an unused hash filename
  153. while(exists $hashlist{"$hash.$suffix"}) {
  154. # Hash matches: if fingerprint matches its a duplicate cert
  155. if ($hashlist{"$hash.$suffix"} eq $fprint) {
  156. print STDERR "WARNING: Skipping duplicate certificate $fname\n";
  157. return;
  158. }
  159. $suffix++;
  160. }
  161. $hash .= ".$suffix";
  162. if ($symlink_exists) {
  163. print "link $fname -> $hash\n" if $verbose;
  164. symlink $fname, $hash || warn "Can't symlink, $!";
  165. } else {
  166. print "copy $fname -> $hash\n" if $verbose;
  167. if (open($in, "<", $fname)) {
  168. if (open($out,">", $hash)) {
  169. print $out $_ while (<$in>);
  170. close $out;
  171. } else {
  172. warn "can't open $hash for write, $!";
  173. }
  174. close $in;
  175. } else {
  176. warn "can't open $fname for read, $!";
  177. }
  178. }
  179. $hashlist{$hash} = $fprint;
  180. }
  181. # Same as above except for a CRL. CRL links are of the form <hash>.r<n>
  182. sub link_hash_crl {
  183. my $fname = $_[0];
  184. $fname =~ s/'/'\\''/g;
  185. my ($hash, $fprint) = `"$openssl" crl $crlhash -fingerprint -noout -in '$fname'`;
  186. chomp $hash;
  187. chomp $fprint;
  188. $fprint =~ s/^.*=//;
  189. $fprint =~ tr/://d;
  190. my $suffix = 0;
  191. # Search for an unused hash filename
  192. while(exists $hashlist{"$hash.r$suffix"}) {
  193. # Hash matches: if fingerprint matches its a duplicate cert
  194. if ($hashlist{"$hash.r$suffix"} eq $fprint) {
  195. print STDERR "WARNING: Skipping duplicate CRL $fname\n";
  196. return;
  197. }
  198. $suffix++;
  199. }
  200. $hash .= ".r$suffix";
  201. if ($symlink_exists) {
  202. print "link $fname -> $hash\n" if $verbose;
  203. symlink $fname, $hash || warn "Can't symlink, $!";
  204. } else {
  205. print "cp $fname -> $hash\n" if $verbose;
  206. system ("cp", $fname, $hash);
  207. warn "Can't copy, $!" if ($? >> 8) != 0;
  208. }
  209. $hashlist{$hash} = $fprint;
  210. }