Add accessor method for clearsigned message for a packet
authorJacob Bachmeyer <jcb@gnu.org>
Sat, 1 Jul 2023 22:20:53 +0000 (17:20 -0500)
committerJacob Bachmeyer <jcb@gnu.org>
Sat, 1 Jul 2023 22:35:26 +0000 (17:35 -0500)
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

index 48d81565783a009684820b5c7feb1a4791da5732..009fd1a27a412db0aa86dc4ec4d5715edff5b25d 100755 (executable)
@@ -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) {