From: Jacob Bachmeyer Date: Wed, 26 Oct 2022 03:24:59 +0000 (-0500) Subject: Replace clearsigned message verification X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=fc58d8e82444d9f949f2ac5cbbed928ad6b12c30;p=gatekeeper.git Replace clearsigned message verification This removes the use of the shell to run gpgv when verifying directives. This also improves the handling the of gpgv generally, since the use of the --status-fd option is the recommended mechanism for automatic usage. --- diff --git a/gatekeeper.pl b/gatekeeper.pl index 1616677..31622b5 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -1596,59 +1596,6 @@ sub verify_clearsigned_message { return \%ret; } -# -# Verify that the signature used for the directive file is valid for -# this package's keyring. We go through all keyring files, starting at the -# sub-most directory, until we find one that matches (or not!) -# -sub verify_keyring { - my $directive_file = shift; - my $directive_file_contents = shift; - my @keyrings = @_; - - my $directive_file_size = -s $directive_file; - ftp_syslog('debug', "DEBUG: " - ."$directive_file size is $directive_file_size") if DEBUG; - - foreach (@keyrings) { - # We need what gpgv writes to STDERR to determine the timestamp - # Hence the silly trick with storing the return code of gpgv in - # the command output - my @verify_args = (GPGV_BIN, "--keyring", $_, - $directive_file,"2>&1",";echo \$?"); - - my $verify_str = join(' ',@verify_args); - - ($verify_str) = $verify_str =~ /^(.*)$/; - - ftp_syslog('debug',"DEBUG: gpgv command line: $verify_str\n") - if (DEBUG > 0); - my $retval = ''; - open (GPGV, "$verify_str|") - or fatal("failed to run command: $verify_str",1); - while (defined (my $line = )) { - $retval .= $line; - } - close (GPGV) or ftp_warn("gpgv exited $?"); - - if (!defined($retval)) { - # This is bad - we couldn't even execute the gpgv command properly - guess_uploader_email($directive_file_contents); - fatal("gpg verify of directive file failed (error executing gpgv): $!", - 0,'',2); - } elsif ($retval =~ /\n0\n$/s) { - # We store the return value of gpgv on the last line of the output - ftp_syslog('info', "verified against $_\n"); - return $retval; # We got return value 0 from gpgv -> key verified! - } else { - # gpgv returned an error - most likely just key not found. Ignore, - # since we are testing all keyrings. - } - } - guess_uploader_email($directive_file_contents); - fatal("gpg verify of directive file failed",1,'',2); -} - # # - [PV] Parsing and Validation @@ -1868,19 +1815,27 @@ sub read_directive_file { # 'directory:' line is messed up or not there, we'd still like to let the # uploader know something went wrong. So let's see if we can match the # directive file signature against one of our public keyrings. - my @tmp_keyrings; - open(TMP,"/usr/bin/find $package_config_base -name pubring.gpg|"); - while() { - chomp; - m,^(/?${RE_filename_relative})$, or next; - push @tmp_keyrings, $1; - } - close(TMP); + { + my @tmp_keyrings; + open(TMP,"/usr/bin/find $package_config_base -name pubring.gpg|"); + while() { + chomp; + m,^(/?${RE_filename_relative})$, or next; + push @tmp_keyrings, $1; + } + close(TMP); - my $tmp_retval = verify_keyring($directive_file,$directive_file_contents, - @tmp_keyrings); - push(@{$info{email}},$1) - if ($tmp_retval =~ /Good signature from .*?<(.*?)>/); + my $tmp_result = verify_clearsigned_message + ($directive_file_contents, @tmp_keyrings); + + if ($tmp_result->{exitcode} != 0 || defined $tmp_result->{TILT}) { + guess_uploader_email($directive_file_contents); + fatal("gpg verify of directive file failed",1,'',2); + } + + push(@{$info{email}},$1) + if ($tmp_result->{raw_log} =~ /Good signature from .*?<(.*?)>/); + } my $ops = interpret_directive($directive, $directive_file_contents); my $op_header = $ops->[0][1]; @@ -1951,14 +1906,19 @@ sub read_directive_file { unless $stem eq $op_header->{filename}; } - my $retval = verify_keyring($directive_file,$directive_file_contents, - @keyrings); + my $result = verify_clearsigned_message($directive_file_contents, @keyrings); + + if ($result->{exitcode} != 0 || defined $result->{TILT}) { + guess_uploader_email($directive_file_contents); + fatal("gpg verify of directive file failed",1,'',2); + } # Now check that the timestamp of signing for the directive is not older # than the one for the last file that was uploaded # This is only relevant when a 'filename' directive is present, hence the # test of the $filename_required variable. - if (($retval =~ /Signature made (.*)/) && (exists($info{filename}))) { + if (($result->{raw_log} =~ /Signature made (.*)/) + && (exists($info{filename}))) { my $timestr = $1; ftp_syslog('debug', "DEBUG: Signature made $1") if DEBUG;