From e408c31e4b43bbf8ed9194dc03e1572c93da9509 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Sat, 1 Jul 2023 17:20:53 -0500 Subject: [PATCH] Add accessor method for clearsigned message for a packet For directive-based packets, this returns the full text of the directive, including its enclosing OpenPGP signature. This commit trades a small amount of efficiency for encapsulation: one avoidable gpgv run will occur when the directive is signed with a known key, but not a key authorized for the target directory. --- gatekeeper.pl | 78 +++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/gatekeeper.pl b/gatekeeper.pl index 48d8156..009fd1a 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -1634,6 +1634,8 @@ sub read_directive_from_string { sub has_uploaded_file { return 0 } sub allow_overwrite { return 0 } + sub auth_clearsigned_message; + sub target_package; sub target_directory; @@ -1736,6 +1738,8 @@ sub read_directive_from_string { ::validate_directive($self, $self->{oplist}); } + sub auth_clearsigned_message { (shift)->{directive_text} } + sub allow_overwrite { (shift)->{oplist}->[0][1]->{options}{replace} } sub target_directory { (shift)->{oplist}->[0][1]->{directory} } sub target_package { (shift)->{oplist}->[0][1]->{package} } @@ -3358,24 +3362,15 @@ my @packets; } foreach my $packet (@packets) { - # variables preserved for the report if an exception is thrown - my $directive_text; # full text of directive - my $dsig_info; # directive signature information my $complete = 0; # direct flag to indicate successful processing eval { # trap exceptions encountered while processing a packet local $Phase = 'PS'; $packet->parse; - # scaffolding to be cleaned up later - $directive_text = $packet->{directive_text}; - $Phase = 'AA'; $packet->auth_check; - # scaffolding to be cleaned up later - $dsig_info = $packet->{auth_directive_signature_info}; - $Phase = 'VL'; $packet->upload_check; @@ -3394,7 +3389,7 @@ foreach my $packet (@packets) { # Phone home. E-mail the contents of the directive file to the public # archive list. - report_upload_to_archive($directive_text, + report_upload_to_archive($packet->auth_clearsigned_message, defined $packet->target_package ? $packet->target_package : ''); @@ -3444,62 +3439,53 @@ foreach my $packet (@packets) { # Otherwise, we do not have a target directory at all, which probably # has something to do with the exception we are handling... - my $have_any_directive_signature = 0; - { my @fprs; # scratchpad for key fingerprints of valid signatures - - # scaffolding to be removed later - $directive_text = $packet->{directive_text} unless $directive_text; + my $have_any_known_directive_signature = 0; + if ($packet->auth_clearsigned_message) { # skip if no signature at all + my @fprs = $packet->auth_signature_fingerprints; - last unless $directive_text; # skip if no signature at all + unless (@fprs) { + my $key_id; - my $key_id; - - if (defined $dsig_info) { - if ($dsig_info->{key_fingerprint}) { - # This signature was successfully matched to a known key. - push @fprs, $dsig_info->{key_fingerprint} - if $dsig_info->{exitcode} == 0 && !defined $dsig_info->{TILT}; - } else { - # Only a key ID is available. - $key_id = $dsig_info->{key_longid}; + { + my $sig_info = verify_clearsigned_message + ($packet->auth_clearsigned_message, File::Spec->devnull); + # Verification with no keyrings at all will of course fail, but + # will extract a key ID from the signature, which we need here. + $key_id = $sig_info->{key_longid}; } - } else { - my $sig_info = verify_clearsigned_message($directive_text, - File::Spec->devnull); - # Verification with no keyrings at all will of course fail, but - # will extract a key ID from the signature, which we need here. - $key_id = $sig_info->{key_longid}; - } - if (defined $key_id) { - # We have a key ID; find candidate keys and try them. - my @keyrings = keyidx_locate keyidx_resolve $key_id; - my $sig = verify_clearsigned_message($directive_text, @keyrings); + if (defined $key_id) { + # We have a key ID; find candidate keys and try them. + my @keyrings = keyidx_locate keyidx_resolve $key_id; + my $sig = verify_clearsigned_message + ($packet->auth_clearsigned_message, @keyrings); - if ($sig->{exitcode} == 0 && !defined $sig->{TILT}) { - # The signature is indeed valid, but the key that produced it - # lacks permission for the requested directory. - push @fprs, $sig->{key_fingerprint}; + if ($sig->{exitcode} == 0 && !defined $sig->{TILT}) { + # The signature is indeed valid, but the key that produced it + # lacks permission for the requested directory. + push @fprs, $sig->{key_fingerprint}; + } } } if (@fprs) { - $have_any_directive_signature = 1; + $have_any_known_directive_signature = 1; push @email_addresses, keyidx_email @fprs; } } - if ($have_any_directive_signature) { + if ($have_any_known_directive_signature) { # The directive was signed with a known key. # Send it to the public archive list. - report_upload_to_archive($directive_text, + report_upload_to_archive($packet->auth_clearsigned_message, defined $packet->target_package ? $packet->target_package : ''); } else { # The directive was not signed with any known key. To reduce abuse, # send it only to the internal inbox. - mail $directive_text, subject => 'debug: directive file contents' - if $directive_text && DEBUG; + mail $packet->auth_clearsigned_message, + subject => 'debug: directive file contents' + if $packet->auth_clearsigned_message && DEBUG; } if (ref $E) { -- 2.25.1