diff options
author | Daniel Fiala <daniel@openssl.org> | 2022-05-29 20:11:24 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2022-06-20 12:44:40 +0200 |
commit | ce60b13707add7e6b54c5817376234c4043506ed (patch) | |
tree | 7ef4382aa6900f3b16ff7300eb03017c6add5e87 /tools | |
parent | providers/implementations/exchange/kdf_exch.c: fix unavailable SIZE_MAX (diff) | |
download | openssl-ce60b13707add7e6b54c5817376234c4043506ed.tar.xz openssl-ce60b13707add7e6b54c5817376234c4043506ed.zip |
Fix file operations in c_rehash.
CVE-2022-2068
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/c_rehash.in | 106 |
1 files changed, 52 insertions, 54 deletions
diff --git a/tools/c_rehash.in b/tools/c_rehash.in index 081b34aec8..2f735d68c9 100644 --- a/tools/c_rehash.in +++ b/tools/c_rehash.in @@ -104,18 +104,41 @@ foreach (@dirlist) { } exit($errorcount); +sub copy_file { + my ($src_fname, $dst_fname) = @_; + + if (open(my $in, "<", $src_fname)) { + if (open(my $out, ">", $dst_fname)) { + print $out $_ while (<$in>); + close $out; + } else { + warn "Cannot open $dst_fname for write, $!"; + } + close $in; + } else { + warn "Cannot open $src_fname for read, $!"; + } +} + sub hash_dir { + my $dir = shift; my %hashlist; - print "Doing $_[0]\n"; - chdir $_[0]; - opendir(DIR, "."); + + print "Doing $dir\n"; + + if (!chdir $dir) { + print STDERR "WARNING: Cannot chdir to '$dir', $!\n"; + return; + } + + opendir(DIR, ".") || print STDERR "WARNING: Cannot opendir '.', $!\n"; my @flist = sort readdir(DIR); closedir DIR; if ( $removelinks ) { # Delete any existing symbolic links foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { if (-l $_) { - print "unlink $_" if $verbose; + print "unlink $_\n" if $verbose; unlink $_ || warn "Can't unlink $_, $!\n"; } } @@ -130,13 +153,16 @@ sub hash_dir { link_hash_cert($fname) if ($cert); link_hash_crl($fname) if ($crl); } + + chdir $pwd; } sub check_file { my ($is_cert, $is_crl) = (0,0); my $fname = $_[0]; - open IN, $fname; - while(<IN>) { + + open(my $in, "<", $fname); + while(<$in>) { if (/^-----BEGIN (.*)-----/) { my $hdr = $1; if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { @@ -148,7 +174,7 @@ sub check_file { } } } - close IN; + close $in; return ($is_cert, $is_crl); } @@ -177,51 +203,22 @@ sub compute_hash { # certificate fingerprints sub link_hash_cert { - my $fname = $_[0]; - my ($hash, $fprint) = compute_hash($openssl, "x509", $x509hash, - "-fingerprint", "-noout", - "-in", $fname); - chomp $hash; - chomp $fprint; - return if !$hash; - $fprint =~ s/^.*=//; - $fprint =~ tr/://d; - my $suffix = 0; - # Search for an unused hash filename - while(exists $hashlist{"$hash.$suffix"}) { - # Hash matches: if fingerprint matches its a duplicate cert - if ($hashlist{"$hash.$suffix"} eq $fprint) { - print STDERR "WARNING: Skipping duplicate certificate $fname\n"; - return; - } - $suffix++; - } - $hash .= ".$suffix"; - if ($symlink_exists) { - print "link $fname -> $hash\n" if $verbose; - symlink $fname, $hash || warn "Can't symlink, $!"; - } else { - print "copy $fname -> $hash\n" if $verbose; - if (open($in, "<", $fname)) { - if (open($out,">", $hash)) { - print $out $_ while (<$in>); - close $out; - } else { - warn "can't open $hash for write, $!"; - } - close $in; - } else { - warn "can't open $fname for read, $!"; - } - } - $hashlist{$hash} = $fprint; + link_hash($_[0], 'cert'); } # Same as above except for a CRL. CRL links are of the form <hash>.r<n> sub link_hash_crl { - my $fname = $_[0]; - my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash, + link_hash($_[0], 'crl'); +} + +sub link_hash { + my ($fname, $type) = @_; + my $is_cert = $type eq 'cert'; + + my ($hash, $fprint) = compute_hash($openssl, + $is_cert ? "x509" : "crl", + $is_cert ? $x509hash : $crlhash, "-fingerprint", "-noout", "-in", $fname); chomp $hash; @@ -231,22 +228,23 @@ sub link_hash_crl { $fprint =~ tr/://d; my $suffix = 0; # Search for an unused hash filename - while(exists $hashlist{"$hash.r$suffix"}) { + my $crlmark = $is_cert ? "" : "r"; + while(exists $hashlist{"$hash.$crlmark$suffix"}) { # Hash matches: if fingerprint matches its a duplicate cert - if ($hashlist{"$hash.r$suffix"} eq $fprint) { - print STDERR "WARNING: Skipping duplicate CRL $fname\n"; + if ($hashlist{"$hash.$crlmark$suffix"} eq $fprint) { + my $what = $is_cert ? 'certificate' : 'CRL'; + print STDERR "WARNING: Skipping duplicate $what $fname\n"; return; } $suffix++; } - $hash .= ".r$suffix"; + $hash .= ".$crlmark$suffix"; if ($symlink_exists) { print "link $fname -> $hash\n" if $verbose; symlink $fname, $hash || warn "Can't symlink, $!"; } else { - print "cp $fname -> $hash\n" if $verbose; - system ("cp", $fname, $hash); - warn "Can't copy, $!" if ($? >> 8) != 0; + print "copy $fname -> $hash\n" if $verbose; + copy_file($fname, $hash); } $hashlist{$hash} = $fprint; } |