@@ -104,52 +104,78 @@ foreach (@dirlist) {
104104}
105105exit($errorcount);
106106
107+ sub copy_file {
108+ my ($src_fname, $dst_fname) = @_;
109+
110+ if (open(my $in, "<", $src_fname)) {
111+ if (open(my $out, ">", $dst_fname)) {
112+ print $out $_ while (<$in>);
113+ close $out;
114+ } else {
115+ warn "Cannot open $dst_fname for write, $!";
116+ }
117+ close $in;
118+ } else {
119+ warn "Cannot open $src_fname for read, $!";
120+ }
121+ }
122+
107123sub hash_dir {
108- my %hashlist;
109- print "Doing $_[0]\n";
110- chdir $_[0];
111- opendir(DIR, ".");
112- my @flist = sort readdir(DIR);
113- closedir DIR;
114- if ( $removelinks ) {
115- # Delete any existing symbolic links
116- foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
117- if (-l $_) {
118- print "unlink $_" if $verbose;
119- unlink $_ || warn "Can't unlink $_, $!\n";
120- }
121- }
122- }
123- FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) {
124- # Check to see if certificates and/or CRLs present.
125- my ($cert, $crl) = check_file($fname);
126- if (!$cert && !$crl) {
127- print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
128- next;
129- }
130- link_hash_cert($fname) if ($cert);
131- link_hash_crl($fname) if ($crl);
132- }
124+ my $dir = shift;
125+ my %hashlist;
126+
127+ print "Doing $dir\n";
128+
129+ if (!chdir $dir) {
130+ print STDERR "WARNING: Cannot chdir to '$dir', $!\n";
131+ return;
132+ }
133+
134+ opendir(DIR, ".") || print STDERR "WARNING: Cannot opendir '.', $!\n";
135+ my @flist = sort readdir(DIR);
136+ closedir DIR;
137+ if ( $removelinks ) {
138+ # Delete any existing symbolic links
139+ foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
140+ if (-l $_) {
141+ print "unlink $_\n" if $verbose;
142+ unlink $_ || warn "Can't unlink $_, $!\n";
143+ }
144+ }
145+ }
146+ FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) {
147+ # Check to see if certificates and/or CRLs present.
148+ my ($cert, $crl) = check_file($fname);
149+ if (!$cert && !$crl) {
150+ print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
151+ next;
152+ }
153+ link_hash_cert($fname) if ($cert);
154+ link_hash_crl($fname) if ($crl);
155+ }
156+
157+ chdir $pwd;
133158}
134159
135160sub check_file {
136- my ($is_cert, $is_crl) = (0,0);
137- my $fname = $_[0];
138- open IN, $fname;
139- while(<IN>) {
140- if (/^-----BEGIN (.*)-----/) {
141- my $hdr = $1;
142- if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
143- $is_cert = 1;
144- last if ($is_crl);
145- } elsif ($hdr eq "X509 CRL") {
146- $is_crl = 1;
147- last if ($is_cert);
148- }
149- }
150- }
151- close IN;
152- return ($is_cert, $is_crl);
161+ my ($is_cert, $is_crl) = (0,0);
162+ my $fname = $_[0];
163+
164+ open(my $in, "<", $fname);
165+ while(<$in>) {
166+ if (/^-----BEGIN (.*)-----/) {
167+ my $hdr = $1;
168+ if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
169+ $is_cert = 1;
170+ last if ($is_crl);
171+ } elsif ($hdr eq "X509 CRL") {
172+ $is_crl = 1;
173+ last if ($is_cert);
174+ }
175+ }
176+ }
177+ close $in;
178+ return ($is_cert, $is_crl);
153179}
154180
155181sub compute_hash {
@@ -177,76 +203,48 @@ sub compute_hash {
177203# certificate fingerprints
178204
179205sub link_hash_cert {
180- my $fname = $_[0];
181- my ($hash, $fprint) = compute_hash($openssl, "x509", $x509hash,
182- "-fingerprint", "-noout",
183- "-in", $fname);
184- chomp $hash;
185- chomp $fprint;
186- return if !$hash;
187- $fprint =~ s/^.*=//;
188- $fprint =~ tr/://d;
189- my $suffix = 0;
190- # Search for an unused hash filename
191- while(exists $hashlist{"$hash.$suffix"}) {
192- # Hash matches: if fingerprint matches its a duplicate cert
193- if ($hashlist{"$hash.$suffix"} eq $fprint) {
194- print STDERR "WARNING: Skipping duplicate certificate $fname\n";
195- return;
196- }
197- $suffix++;
198- }
199- $hash .= ".$suffix";
200- if ($symlink_exists) {
201- print "link $fname -> $hash\n" if $verbose;
202- symlink $fname, $hash || warn "Can't symlink, $!";
203- } else {
204- print "copy $fname -> $hash\n" if $verbose;
205- if (open($in, "<", $fname)) {
206- if (open($out,">", $hash)) {
207- print $out $_ while (<$in>);
208- close $out;
209- } else {
210- warn "can't open $hash for write, $!";
211- }
212- close $in;
213- } else {
214- warn "can't open $fname for read, $!";
215- }
216- }
217- $hashlist{$hash} = $fprint;
206+ link_hash($_[0], 'cert');
218207}
219208
220209# Same as above except for a CRL. CRL links are of the form <hash>.r<n>
221210
222211sub link_hash_crl {
223- my $fname = $_[0];
224- my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash,
225- "-fingerprint", "-noout",
226- "-in", $fname);
227- chomp $hash;
228- chomp $fprint;
229- return if !$hash;
230- $fprint =~ s/^.*=//;
231- $fprint =~ tr/://d;
232- my $suffix = 0;
233- # Search for an unused hash filename
234- while(exists $hashlist{"$hash.r$suffix"}) {
235- # Hash matches: if fingerprint matches its a duplicate cert
236- if ($hashlist{"$hash.r$suffix"} eq $fprint) {
237- print STDERR "WARNING: Skipping duplicate CRL $fname\n";
238- return;
239- }
240- $suffix++;
241- }
242- $hash .= ".r$suffix";
243- if ($symlink_exists) {
244- print "link $fname -> $hash\n" if $verbose;
245- symlink $fname, $hash || warn "Can't symlink, $!";
246- } else {
247- print "cp $fname -> $hash\n" if $verbose;
248- system ("cp", $fname, $hash);
249- warn "Can't copy, $!" if ($? >> 8) != 0;
250- }
251- $hashlist{$hash} = $fprint;
212+ link_hash($_[0], 'crl');
213+ }
214+
215+ sub link_hash {
216+ my ($fname, $type) = @_;
217+ my $is_cert = $type eq 'cert';
218+
219+ my ($hash, $fprint) = compute_hash($openssl,
220+ $is_cert ? "x509" : "crl",
221+ $is_cert ? $x509hash : $crlhash,
222+ "-fingerprint", "-noout",
223+ "-in", $fname);
224+ chomp $hash;
225+ chomp $fprint;
226+ return if !$hash;
227+ $fprint =~ s/^.*=//;
228+ $fprint =~ tr/://d;
229+ my $suffix = 0;
230+ # Search for an unused hash filename
231+ my $crlmark = $is_cert ? "" : "r";
232+ while(exists $hashlist{"$hash.$crlmark$suffix"}) {
233+ # Hash matches: if fingerprint matches its a duplicate cert
234+ if ($hashlist{"$hash.$crlmark$suffix"} eq $fprint) {
235+ my $what = $is_cert ? 'certificate' : 'CRL';
236+ print STDERR "WARNING: Skipping duplicate $what $fname\n";
237+ return;
238+ }
239+ $suffix++;
240+ }
241+ $hash .= ".$crlmark$suffix";
242+ if ($symlink_exists) {
243+ print "link $fname -> $hash\n" if $verbose;
244+ symlink $fname, $hash || warn "Can't symlink, $!";
245+ } else {
246+ print "copy $fname -> $hash\n" if $verbose;
247+ copy_file($fname, $hash);
248+ }
249+ $hashlist{$hash} = $fprint;
252250}
0 commit comments