From: Jacob Bachmeyer Date: Thu, 20 Oct 2022 04:24:16 +0000 (-0500) Subject: Factor timestamp ratchet out of read_directive_file X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=5038c81307ae8befaf015e71bc237429cb2f1d3f;p=gatekeeper.git Factor timestamp ratchet out of read_directive_file --- diff --git a/gatekeeper.pl b/gatekeeper.pl index 6e6348a..d1969c9 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -1460,6 +1460,70 @@ sub interpret_directive { return \@ops; } +=item $epoch = advance_timestamp_ratchet ( $full_filename, $epoch, ) + +Locate the stored timestamp for FULL_FILENAME, which is relative to the +root of the managed tree, verify that the given EPOCH is newer, and update +the stored timestamp to EPOCH. Return the previous stored timestamp. + +An exception is thrown if the given EPOCH timestamp is not newer than the +stored value. An undefined value is returned if FULL_FILENAME did not have +a stored timestamp. + +=cut + +sub advance_timestamp_ratchet { + my $full_filename = shift; + my $new_epoch = shift; + + # Now we need to flock the our 'serials' file; + # verify the epoch value there/update it, etc. + my %serials = (); + my @serials = (); + + if (!-e $serials_path) { + open(SERIALS,">$serials_path"); + flock(SERIALS,2); # Take exclusive lock + } else { + open(SERIALS,"+<$serials_path"); + flock(SERIALS,2); # Take exclusive lock + @serials = ; + foreach (@serials) { + my ($tmp1,$tmp2) = /(.*?):(.*?)\n/; + $tmp1 =~ s/\s+//g; + $tmp2 =~ s/\s+//g; + $serials{$tmp1} = $tmp2; + } + } + seek(SERIALS,0,0); + + my $old_epoch = $serials{$full_filename}; + + # Verify that this is really a new version of the file! + if (exists($serials{$full_filename}) + && ($serials{$full_filename} >= $new_epoch)) { + flock(SERIALS,4); # Release lock + fatal("Gpg signed upload older than/same timestamp as existing version " + ."- not allowed. In other words, the filenames for the triplet " + ."you have uploaded are an exact match for a triplet that has " + ."been uploaded in the past, and the directive file that you " + ."just uploaded has been signed before or at the same time as " + ."the directive file for the triplet that was uploaded earlier. " + ."Most likely, you are re-uploading an old triplet.",1); + } + + $serials{$full_filename} = $new_epoch; + + foreach my $key (keys %serials) { + print SERIALS "$key:$serials{$key}\n"; + } + + flock(SERIALS,4); # Release lock + close(SERIALS); + + return $old_epoch; +} + sub read_directive_file { my $directive_file = shift; my $uploaded_file = shift; @@ -1621,50 +1685,10 @@ sub read_directive_file { ."change the filename for your triplet.",1); } - # Now we need to flock the our 'serials' file; - # verify the epoch value there/update it, etc. - my %serials = (); - my @serials = (); - - if (!-e $serials_path) { - open(SERIALS,">$serials_path"); - flock(SERIALS,2); # Take exclusive lock - } else { - open(SERIALS,"+<$serials_path"); - flock(SERIALS,2); # Take exclusive lock - @serials = ; - foreach (@serials) { - my ($tmp1,$tmp2) = /(.*?):(.*?)\n/; - $tmp1 =~ s/\s+//g; - $tmp2 =~ s/\s+//g; - $serials{$tmp1} = $tmp2; - } - } - seek(SERIALS,0,0); my $full_filename = $info{"directory"} . '/' . $uploaded_file; $full_filename =~ s/\/\//\//g; # Just in case... - # Verify that this is really a new version of the file! - if (exists($serials{$full_filename}) - && ($serials{$full_filename} >= $epoch)) { - flock(SERIALS,4); # Release lock - fatal("Gpg signed upload older than/same timestamp as existing version " - ."- not allowed. In other words, the filenames for the triplet " - ."you have uploaded are an exact match for a triplet that has " - ."been uploaded in the past, and the directive file that you " - ."just uploaded has been signed before or at the same time as " - ."the directive file for the triplet that was uploaded earlier. " - ."Most likely, you are re-uploading an old triplet.",1); - } - - $serials{$full_filename} = $epoch; - - foreach my $key (keys %serials) { - print SERIALS "$key:$serials{$key}\n"; - } - - flock(SERIALS,4); # Release lock - close(SERIALS); + advance_timestamp_ratchet($full_filename, $epoch); } elsif ($filename_required) { fatal("gpg verification problem: could not extract timestamp",1); }