From: Jacob Bachmeyer Date: Fri, 21 Oct 2022 02:29:20 +0000 (-0500) Subject: Revise handling of "filename" directive element X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=e77dfc7773d28c7ac45e282234f240f2caa075d9;p=gatekeeper.git Revise handling of "filename" directive element All protocol versions so far imply an "install" command when a directive is uploaded as part of a triplet. This commit also adds infrastructure to support a possible future explicit "install" command, removes a useless validation of the packet stem against the directive file name, and cleans up a now-unneeded variable that had been left as scaffolding. --- diff --git a/gatekeeper.pl b/gatekeeper.pl index 3ac5586..97e4b8e 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -1373,10 +1373,12 @@ sub interpret_directive { my %options = ( replace => undef ); my %header = ( version => undef, options => \%options, - package => undef, directory => undef ); + package => undef, directory => undef, filename => undef ); my @ops = ([header => \%header]); - my $have_install = 0; # can only install one file per directive - my $filename; + my $install = undef; # can only install one file per directive + # The 'install' op carries the name of the file to install, while the + # 'filename' element binds the directive signature to its intended + # upload. These are assumed to be the same in protocol 1.2 and earlier. my $cnt = 0; # TODO: remove this { # Extract version first, since directive elements may be in any order. @@ -1417,9 +1419,9 @@ sub interpret_directive { # Only let them specify one filename directive. fatal("Only one filename directive is allowed per directive file. " ."Error at filename directive: $val.",1,$directive_file_contents) - if exists $info{"filename"}; + if defined $header{filename}; - $filename = $val; + $header{filename} = $val; $info{"filename"} = {"value" => $val, "order" => $cnt++}; # ok. } elsif ($tainted_cmd eq 'version') { # already handled above @@ -1460,8 +1462,9 @@ sub interpret_directive { 1,$directive_file_contents); } - if (!$have_install && $filename && defined $header{directory}) - { push @ops, [install => $filename]; $have_install = 1 } + if (!defined($install) + && defined $header{filename} && defined $header{directory}) + { push @ops, ($install = [install => $header{filename}]) } } return \@ops; @@ -1619,12 +1622,8 @@ sub read_directive_file { } } - # The above check that the directive contains at least one command - # ensures that we either have a filename or do not need one before we - # reach this point. This is temporarily kept as scaffolding. - my $filename_required = exists($info{filename}); - - if ($filename_required) { + # Check if this directive carries a file/validate stem if needed + if (defined $op_header->{filename}) { # Ben Pfaff wrote: # First, "gpg -b" doesn't verify that the filename of the signed # data is correct. This means that I can rename gcc-1.2.3.tar.gz @@ -1632,20 +1631,15 @@ sub read_directive_file { # correctly. This opens up the possibility for confusion, but in # itself it's not a huge deal. # - # To fix this, we require a 'filename:' line in the directive file - # that needs to match the name of the uploaded file. - - # Filename has to match the name of the uploaded file + # To fix this, we require a 'filename:' line in the directive file that + # needs to match the name of the uploaded file and serves to bind the + # directive signature and the uploaded packet. We already know that + # the name of the uploaded file must match the stem of the directive + # file name; this is how it was recognized as part of the packet. fatal("The filename directive does not match name of the uploaded file." - ."\n\n Filename directive: $info{filename}{value}" - ."\n Uploaded file: $uploaded_file\n",1) - if ($uploaded_file ne $info{filename}{value}); - - # Filename has to match the name of this directive file (a bit - # paranoid, but hey...) - fatal("filename $info{filename}{value} does not match name of directive " - ."file $directive_file",1) - if ($directive_file ne "$info{filename}{value}.directive.asc"); + ."\n\n Filename directive: $op_header->{filename}" + ."\n Uploaded file: $stem\n",1) + unless $stem eq $op_header->{filename}; } my $retval = verify_keyring($directive_file,$directive_file_contents, @@ -1655,7 +1649,7 @@ sub read_directive_file { # 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 (.*)/) && ($filename_required)) { + if (($retval =~ /Signature made (.*)/) && (exists($info{filename}))) { my $timestr = $1; ftp_syslog('debug', "DEBUG: Signature made $1") if DEBUG; @@ -1692,7 +1686,7 @@ sub read_directive_file { $full_filename =~ s/\/\//\//g; # Just in case... advance_timestamp_ratchet($full_filename, $epoch); - } elsif ($filename_required) { + } elsif (exists($info{filename})) { fatal("gpg verification problem: could not extract timestamp",1); }