Skip to content

Commit 2c9c358

Browse files
faramir-devmattcaswell
authored andcommitted
Fix file operations in c_rehash.
CVE-2022-2068 Reviewed-by: Richard Levitte <levitte@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org>
1 parent abebcec commit 2c9c358

File tree

1 file changed

+52
-54
lines changed

1 file changed

+52
-54
lines changed

Diff for: tools/c_rehash.in

+52-54
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,41 @@ foreach (@dirlist) {
104104
}
105105
exit($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+
107123
sub hash_dir {
124+
my $dir = shift;
108125
my %hashlist;
109-
print "Doing $_[0]\n";
110-
chdir $_[0];
111-
opendir(DIR, ".");
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";
112135
my @flist = sort readdir(DIR);
113136
closedir DIR;
114137
if ( $removelinks ) {
115138
# Delete any existing symbolic links
116139
foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
117140
if (-l $_) {
118-
print "unlink $_" if $verbose;
141+
print "unlink $_\n" if $verbose;
119142
unlink $_ || warn "Can't unlink $_, $!\n";
120143
}
121144
}
@@ -130,13 +153,16 @@ sub hash_dir {
130153
link_hash_cert($fname) if ($cert);
131154
link_hash_crl($fname) if ($crl);
132155
}
156+
157+
chdir $pwd;
133158
}
134159

135160
sub check_file {
136161
my ($is_cert, $is_crl) = (0,0);
137162
my $fname = $_[0];
138-
open IN, $fname;
139-
while(<IN>) {
163+
164+
open(my $in, "<", $fname);
165+
while(<$in>) {
140166
if (/^-----BEGIN (.*)-----/) {
141167
my $hdr = $1;
142168
if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
@@ -148,7 +174,7 @@ sub check_file {
148174
}
149175
}
150176
}
151-
close IN;
177+
close $in;
152178
return ($is_cert, $is_crl);
153179
}
154180

@@ -177,51 +203,22 @@ sub compute_hash {
177203
# certificate fingerprints
178204

179205
sub 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

222211
sub link_hash_crl {
223-
my $fname = $_[0];
224-
my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash,
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,
225222
"-fingerprint", "-noout",
226223
"-in", $fname);
227224
chomp $hash;
@@ -231,22 +228,23 @@ sub link_hash_crl {
231228
$fprint =~ tr/://d;
232229
my $suffix = 0;
233230
# Search for an unused hash filename
234-
while(exists $hashlist{"$hash.r$suffix"}) {
231+
my $crlmark = $is_cert ? "" : "r";
232+
while(exists $hashlist{"$hash.$crlmark$suffix"}) {
235233
# 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";
234+
if ($hashlist{"$hash.$crlmark$suffix"} eq $fprint) {
235+
my $what = $is_cert ? 'certificate' : 'CRL';
236+
print STDERR "WARNING: Skipping duplicate $what $fname\n";
238237
return;
239238
}
240239
$suffix++;
241240
}
242-
$hash .= ".r$suffix";
241+
$hash .= ".$crlmark$suffix";
243242
if ($symlink_exists) {
244243
print "link $fname -> $hash\n" if $verbose;
245244
symlink $fname, $hash || warn "Can't symlink, $!";
246245
} else {
247-
print "cp $fname -> $hash\n" if $verbose;
248-
system ("cp", $fname, $hash);
249-
warn "Can't copy, $!" if ($? >> 8) != 0;
246+
print "copy $fname -> $hash\n" if $verbose;
247+
copy_file($fname, $hash);
250248
}
251249
$hashlist{$hash} = $fprint;
252250
}

0 commit comments

Comments
 (0)