xref: /minix3/crypto/external/bsd/openssl/dist/tools/c_rehash.in (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc#!/usr/local/bin/perl
2*ebfedea0SLionel Sambuc
3*ebfedea0SLionel Sambuc
4*ebfedea0SLionel Sambuc# Perl c_rehash script, scan all files in a directory
5*ebfedea0SLionel Sambuc# and add symbolic links to their hash values.
6*ebfedea0SLionel Sambuc
7*ebfedea0SLionel Sambucmy $openssl;
8*ebfedea0SLionel Sambuc
9*ebfedea0SLionel Sambucmy $dir;
10*ebfedea0SLionel Sambucmy $prefix;
11*ebfedea0SLionel Sambuc
12*ebfedea0SLionel Sambucif(defined $ENV{OPENSSL}) {
13*ebfedea0SLionel Sambuc	$openssl = $ENV{OPENSSL};
14*ebfedea0SLionel Sambuc} else {
15*ebfedea0SLionel Sambuc	$openssl = "openssl";
16*ebfedea0SLionel Sambuc	$ENV{OPENSSL} = $openssl;
17*ebfedea0SLionel Sambuc}
18*ebfedea0SLionel Sambuc
19*ebfedea0SLionel Sambucmy $pwd;
20*ebfedea0SLionel Sambuceval "require Cwd";
21*ebfedea0SLionel Sambucif (defined(&Cwd::getcwd)) {
22*ebfedea0SLionel Sambuc	$pwd=Cwd::getcwd();
23*ebfedea0SLionel Sambuc} else {
24*ebfedea0SLionel Sambuc	$pwd=`pwd`; chomp($pwd);
25*ebfedea0SLionel Sambuc}
26*ebfedea0SLionel Sambucmy $path_delim = ($pwd =~ /^[a-z]\:/i) ? ';' : ':'; # DOS/Win32 or Unix delimiter?
27*ebfedea0SLionel Sambuc
28*ebfedea0SLionel Sambuc$ENV{PATH} = "$prefix/bin" . ($ENV{PATH} ? $path_delim . $ENV{PATH} : ""); # prefix our path
29*ebfedea0SLionel Sambuc
30*ebfedea0SLionel Sambucif(! -x $openssl) {
31*ebfedea0SLionel Sambuc	my $found = 0;
32*ebfedea0SLionel Sambuc	foreach (split /$path_delim/, $ENV{PATH}) {
33*ebfedea0SLionel Sambuc		if(-x "$_/$openssl") {
34*ebfedea0SLionel Sambuc			$found = 1;
35*ebfedea0SLionel Sambuc			$openssl = "$_/$openssl";
36*ebfedea0SLionel Sambuc			last;
37*ebfedea0SLionel Sambuc		}
38*ebfedea0SLionel Sambuc	}
39*ebfedea0SLionel Sambuc	if($found == 0) {
40*ebfedea0SLionel Sambuc		print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n";
41*ebfedea0SLionel Sambuc		exit 0;
42*ebfedea0SLionel Sambuc	}
43*ebfedea0SLionel Sambuc}
44*ebfedea0SLionel Sambuc
45*ebfedea0SLionel Sambucif(@ARGV) {
46*ebfedea0SLionel Sambuc	@dirlist = @ARGV;
47*ebfedea0SLionel Sambuc} elsif($ENV{SSL_CERT_DIR}) {
48*ebfedea0SLionel Sambuc	@dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR};
49*ebfedea0SLionel Sambuc} else {
50*ebfedea0SLionel Sambuc	$dirlist[0] = "$dir/certs";
51*ebfedea0SLionel Sambuc}
52*ebfedea0SLionel Sambuc
53*ebfedea0SLionel Sambucif (-d $dirlist[0]) {
54*ebfedea0SLionel Sambuc	chdir $dirlist[0];
55*ebfedea0SLionel Sambuc	$openssl="$pwd/$openssl" if (!-x $openssl);
56*ebfedea0SLionel Sambuc	chdir $pwd;
57*ebfedea0SLionel Sambuc}
58*ebfedea0SLionel Sambuc
59*ebfedea0SLionel Sambucforeach (@dirlist) {
60*ebfedea0SLionel Sambuc	if(-d $_ and -w $_) {
61*ebfedea0SLionel Sambuc		hash_dir($_);
62*ebfedea0SLionel Sambuc	}
63*ebfedea0SLionel Sambuc}
64*ebfedea0SLionel Sambuc
65*ebfedea0SLionel Sambucsub hash_dir {
66*ebfedea0SLionel Sambuc	my %hashlist;
67*ebfedea0SLionel Sambuc	print "Doing $_[0]\n";
68*ebfedea0SLionel Sambuc	chdir $_[0];
69*ebfedea0SLionel Sambuc	opendir(DIR, ".");
70*ebfedea0SLionel Sambuc	my @flist = readdir(DIR);
71*ebfedea0SLionel Sambuc	# Delete any existing symbolic links
72*ebfedea0SLionel Sambuc	foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
73*ebfedea0SLionel Sambuc		if(-l $_) {
74*ebfedea0SLionel Sambuc			unlink $_;
75*ebfedea0SLionel Sambuc		}
76*ebfedea0SLionel Sambuc	}
77*ebfedea0SLionel Sambuc	closedir DIR;
78*ebfedea0SLionel Sambuc	FILE: foreach $fname (grep {/\.pem$/} @flist) {
79*ebfedea0SLionel Sambuc		# Check to see if certificates and/or CRLs present.
80*ebfedea0SLionel Sambuc		my ($cert, $crl) = check_file($fname);
81*ebfedea0SLionel Sambuc		if(!$cert && !$crl) {
82*ebfedea0SLionel Sambuc			print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
83*ebfedea0SLionel Sambuc			next;
84*ebfedea0SLionel Sambuc		}
85*ebfedea0SLionel Sambuc		link_hash_cert($fname) if($cert);
86*ebfedea0SLionel Sambuc		link_hash_crl($fname) if($crl);
87*ebfedea0SLionel Sambuc	}
88*ebfedea0SLionel Sambuc}
89*ebfedea0SLionel Sambuc
90*ebfedea0SLionel Sambucsub check_file {
91*ebfedea0SLionel Sambuc	my ($is_cert, $is_crl) = (0,0);
92*ebfedea0SLionel Sambuc	my $fname = $_[0];
93*ebfedea0SLionel Sambuc	open IN, $fname;
94*ebfedea0SLionel Sambuc	while(<IN>) {
95*ebfedea0SLionel Sambuc		if(/^-----BEGIN (.*)-----/) {
96*ebfedea0SLionel Sambuc			my $hdr = $1;
97*ebfedea0SLionel Sambuc			if($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
98*ebfedea0SLionel Sambuc				$is_cert = 1;
99*ebfedea0SLionel Sambuc				last if($is_crl);
100*ebfedea0SLionel Sambuc			} elsif($hdr eq "X509 CRL") {
101*ebfedea0SLionel Sambuc				$is_crl = 1;
102*ebfedea0SLionel Sambuc				last if($is_cert);
103*ebfedea0SLionel Sambuc			}
104*ebfedea0SLionel Sambuc		}
105*ebfedea0SLionel Sambuc	}
106*ebfedea0SLionel Sambuc	close IN;
107*ebfedea0SLionel Sambuc	return ($is_cert, $is_crl);
108*ebfedea0SLionel Sambuc}
109*ebfedea0SLionel Sambuc
110*ebfedea0SLionel Sambuc
111*ebfedea0SLionel Sambuc# Link a certificate to its subject name hash value, each hash is of
112*ebfedea0SLionel Sambuc# the form <hash>.<n> where n is an integer. If the hash value already exists
113*ebfedea0SLionel Sambuc# then we need to up the value of n, unless its a duplicate in which
114*ebfedea0SLionel Sambuc# case we skip the link. We check for duplicates by comparing the
115*ebfedea0SLionel Sambuc# certificate fingerprints
116*ebfedea0SLionel Sambuc
117*ebfedea0SLionel Sambucsub link_hash_cert {
118*ebfedea0SLionel Sambuc		my $fname = $_[0];
119*ebfedea0SLionel Sambuc		$fname =~ s/'/'\\''/g;
120*ebfedea0SLionel Sambuc		my ($hash, $fprint) = `"$openssl" x509 -hash -fingerprint -noout -in "$fname"`;
121*ebfedea0SLionel Sambuc		chomp $hash;
122*ebfedea0SLionel Sambuc		chomp $fprint;
123*ebfedea0SLionel Sambuc		$fprint =~ s/^.*=//;
124*ebfedea0SLionel Sambuc		$fprint =~ tr/://d;
125*ebfedea0SLionel Sambuc		my $suffix = 0;
126*ebfedea0SLionel Sambuc		# Search for an unused hash filename
127*ebfedea0SLionel Sambuc		while(exists $hashlist{"$hash.$suffix"}) {
128*ebfedea0SLionel Sambuc			# Hash matches: if fingerprint matches its a duplicate cert
129*ebfedea0SLionel Sambuc			if($hashlist{"$hash.$suffix"} eq $fprint) {
130*ebfedea0SLionel Sambuc				print STDERR "WARNING: Skipping duplicate certificate $fname\n";
131*ebfedea0SLionel Sambuc				return;
132*ebfedea0SLionel Sambuc			}
133*ebfedea0SLionel Sambuc			$suffix++;
134*ebfedea0SLionel Sambuc		}
135*ebfedea0SLionel Sambuc		$hash .= ".$suffix";
136*ebfedea0SLionel Sambuc		print "$fname => $hash\n";
137*ebfedea0SLionel Sambuc		$symlink_exists=eval {symlink("",""); 1};
138*ebfedea0SLionel Sambuc		if ($symlink_exists) {
139*ebfedea0SLionel Sambuc			symlink $fname, $hash;
140*ebfedea0SLionel Sambuc		} else {
141*ebfedea0SLionel Sambuc			open IN,"<$fname" or die "can't open $fname for read";
142*ebfedea0SLionel Sambuc			open OUT,">$hash" or die "can't open $hash for write";
143*ebfedea0SLionel Sambuc			print OUT <IN>;	# does the job for small text files
144*ebfedea0SLionel Sambuc			close OUT;
145*ebfedea0SLionel Sambuc			close IN;
146*ebfedea0SLionel Sambuc		}
147*ebfedea0SLionel Sambuc		$hashlist{$hash} = $fprint;
148*ebfedea0SLionel Sambuc}
149*ebfedea0SLionel Sambuc
150*ebfedea0SLionel Sambuc# Same as above except for a CRL. CRL links are of the form <hash>.r<n>
151*ebfedea0SLionel Sambuc
152*ebfedea0SLionel Sambucsub link_hash_crl {
153*ebfedea0SLionel Sambuc		my $fname = $_[0];
154*ebfedea0SLionel Sambuc		$fname =~ s/'/'\\''/g;
155*ebfedea0SLionel Sambuc		my ($hash, $fprint) = `"$openssl" crl -hash -fingerprint -noout -in '$fname'`;
156*ebfedea0SLionel Sambuc		chomp $hash;
157*ebfedea0SLionel Sambuc		chomp $fprint;
158*ebfedea0SLionel Sambuc		$fprint =~ s/^.*=//;
159*ebfedea0SLionel Sambuc		$fprint =~ tr/://d;
160*ebfedea0SLionel Sambuc		my $suffix = 0;
161*ebfedea0SLionel Sambuc		# Search for an unused hash filename
162*ebfedea0SLionel Sambuc		while(exists $hashlist{"$hash.r$suffix"}) {
163*ebfedea0SLionel Sambuc			# Hash matches: if fingerprint matches its a duplicate cert
164*ebfedea0SLionel Sambuc			if($hashlist{"$hash.r$suffix"} eq $fprint) {
165*ebfedea0SLionel Sambuc				print STDERR "WARNING: Skipping duplicate CRL $fname\n";
166*ebfedea0SLionel Sambuc				return;
167*ebfedea0SLionel Sambuc			}
168*ebfedea0SLionel Sambuc			$suffix++;
169*ebfedea0SLionel Sambuc		}
170*ebfedea0SLionel Sambuc		$hash .= ".r$suffix";
171*ebfedea0SLionel Sambuc		print "$fname => $hash\n";
172*ebfedea0SLionel Sambuc		$symlink_exists=eval {symlink("",""); 1};
173*ebfedea0SLionel Sambuc		if ($symlink_exists) {
174*ebfedea0SLionel Sambuc			symlink $fname, $hash;
175*ebfedea0SLionel Sambuc		} else {
176*ebfedea0SLionel Sambuc			system ("cp", $fname, $hash);
177*ebfedea0SLionel Sambuc		}
178*ebfedea0SLionel Sambuc		$hashlist{$hash} = $fprint;
179*ebfedea0SLionel Sambuc}
180*ebfedea0SLionel Sambuc
181