From 8103f1d987e1c3e970b7fc492c60757fe80d3133 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Fri, 15 Sep 2023 19:11:22 -0500 Subject: [PATCH] Reorganize and document internal Local::Packet class --- gatekeeper.pl | 244 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 215 insertions(+), 29 deletions(-) diff --git a/gatekeeper.pl b/gatekeeper.pl index abdaf9b..ea47302 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -1907,9 +1907,12 @@ BEGIN { =head2 Packet model classes -=over +=head3 Local::Packet -=item TODO +C is an abstract base class for all packets. This class +defines the interface used, with forward declarations for methods that must +be implemented by derived classes. While this class provides the +constructor, actually instantiating an object of this type is an error. =cut @@ -1918,6 +1921,24 @@ BEGIN { use main qw(:err); +=pod + +Constructor: + +=over + +=item $packet = CLASS->collect($filesref) + +=item $packet = CLASS->collect(@files) + +Collect a set of files into a packet object. This constructor is inherited +by packet type classes and must only be called as an inherited class method. + +The argument is either a list of files directly or exactly one arrayref +containing a list of files. + +=cut + # can be given an arrayref or a file list sub collect { my $class = shift; @@ -1938,43 +1959,72 @@ BEGIN { notices => [], installation_successful => 0 }, $class } +=back + +Methods on all packets: + +=over + +=item $packet->add_notice(@messages) + +=item @messages = $packet->notices + +Store (using C) messages to be included in the final report +email for this packet. Retrieve (using C) all such messages +stored during processing. + +=cut + # store additional messages that should appear in the report sub add_notice { my $self = shift; push @{$self->{notices}}, @_ } # return list of messages stored for the report sub notices { return @{(shift)->{notices}} } - sub report_message; - # internal base class helper method for report_message - sub _report_message { - my $self = shift; - my @messages = @_; # collect final messages +=back - # add notices stored in the packet object... - unshift @messages, $self->notices, ''; - # ...and remove any leading blank lines... - shift @messages while $messages[0] eq ''; - # ...before returning the report message text - return join "\n", @messages; - } +Packet processing steps: - # has this packet been installed into the managed tree? - sub successful { (shift)->{installation_successful} } +=over - # scaffolding for now... - sub files { @{(shift)->{files}} } - sub file_name_stem { (shift)->{stem} } +=item $packet->parse - sub has_uploaded_file { return 0 } - sub allow_overwrite { return 0 } +Parse PACKET by reading the clearsigned control message. This populates +most of the internal fields and enables further processing. This step is +distinct from construction to save memory during processing. - sub auth_clearsigned_message; +=item $packet->auth_check - sub target_package; - sub target_directory; +Authenticate PACKET using the keyrings in the configuration tree. This +step verifies all signatures on the files in PACKET. - sub auth_keyrings; - sub auth_signature_fingerprints; - sub auth_signature_timestamp; +=item $packet->upload_check + +Perform additional validation on uploaded files. This is done after the +uploaded files have been authenticated and authorization for the target +directory verified. This step is distinct from authentication because it +verifies the contents of an uploaded file. + +For file uploads, this step ensures that vulnerabilities introduced by +certain (now ancient) versions of GNU Automake are not present. For +autosign uploads, this step ensures that the digests in the autosign file +actually match the files on the server to avoid embarassment and/or +possibly detect some types of attacks. + +=item $packet->install_check + +Perform final validation on proposed operation list. This step exists to +reduce the risk of partially executing an upload directive by ensuring that +all data-dependent verifications are performed before any changes are made. +This step is distinct because it also examines the managed file tree and +other state information on the server, while previous steps examine only +the file(s) uploaded for PACKET. + +=item $packet->install + +Actually install PACKET into the managed file tree by applying the changes +PACKET directs. + +=cut sub parse; sub auth_check; @@ -2003,8 +2053,146 @@ BEGIN { $self->{installation_successful} = 1; } + +=back + +Accessors valid immediately after packet object construction: + +=over + +=item @files = $packet->files + +Return the list of files used to construct PACKET. + +=item $stem = $packet->file_name_stem + +Return the common name prefix of all files in PACKET. + +=cut + + sub files { @{(shift)->{files}} } + sub file_name_stem { (shift)->{stem} } + +=item $boolean = $packet->successful + +Indicate if PACKET has been fully and successfully processed. + +=cut + + # has this packet been installed into the managed tree? + sub successful { (shift)->{installation_successful} } + +=back + +Accessors valid only after the packet has been parsed: + +=over + +=item $boolean = $packet->has_uploaded_file + +Indicate if PACKET carries an uploaded file separate from the clearsigned +message. + +=item $boolean = $packet->allow_overwrite + +Indicate if PACKET directs an operation that is permitted to replace an +existing file. This is irrelevant unless C<< $packet->has_uploaded_file >> +is true. + +=cut + + sub has_uploaded_file { return 0 } + sub allow_overwrite { return 0 } + +=item $text = $packet->auth_clearsigned_message + +Return the full text of the clearsigned control message for PACKET. For +packets using a directive file, this is the contents of the directive. + +This is currently used for error reporting, since this text contains the +signature that can be matched against other known keys if authorization +checks fail. + +=cut + + sub auth_clearsigned_message; + +=item $package_name = $packet->target_package + +Return the name of the package whose files PACKET seeks to change. + +=item $directory = $packet->target_directory + +Return the name of the directory (as a directory name object) that PACKET +seeks to change. An uploaded file will be placed in this directory, while +other commands may refer to files in a subtree rooted at this directory. + +=cut + + sub target_package; + sub target_directory; + +=item @keyring_filenames = $packet->auth_keyrings + +Return a set of keyring filenames containing keys that are authorized for +validating PACKET. All of the returned filenames name existing files. + +=back + +Accessors valid only after the packet has been authenticated: + +=over + +=item @fingerprints = $packet->auth_signature_fingerprints + +Return a set of fingerprints for all keys that produced a signature on +PACKET. For packets carrying file uploads, this includes the detached +signature on the uploaded file. + +=item $timestamp = $packet->auth_signature_timestamp + +Return the signature creation timestamp for the clearsigned control message +for PACKET. For packets using a directive file, this is the timestamp of +the directive signature. + +=cut + + sub auth_keyrings; + sub auth_signature_fingerprints; + sub auth_signature_timestamp; + +=back + +Accessor valid only after the packet has been sucessfully installed: + +=over + +=item $message_text = $packet->report_message + +Return the complete body text for the email reporting successful processing +of PACKET. The returned text includes any messages added using the +C method. + +=cut + + sub report_message; + # internal base class helper method for report_message + sub _report_message { + my $self = shift; + my @messages = @_; # collect final messages + + # add notices stored in the packet object... + unshift @messages, $self->notices, ''; + # ...and remove any leading blank lines... + shift @messages while $messages[0] eq ''; + # ...before returning the report message text + return join "\n", @messages; + } + } +=back + { package Local::Packet::Directive; {our @ISA = qw(Local::Packet)} @@ -2202,8 +2390,6 @@ BEGIN { -=back - =head2 [SC] Scan Inbox =over -- 2.25.1