From dd141d844a8bc4be085970657a3b44fbe73bdc75 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Fri, 7 Oct 2022 22:45:23 -0500 Subject: [PATCH] Add initial shared directive-reading functions --- gatekeeper.pl | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/gatekeeper.pl b/gatekeeper.pl index ae078e2..69e0081 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -731,6 +731,81 @@ sub fatal { ftp_die("(in $cwd) $msg",$exit_code); } + +# +# - Directive reader +# + +=item $directive = read_directive ( $handle ) + +Read a PGP-clearsigned directive from the provided handle, which must be +open for reading. The handle is assumed to be positioned at the start of +the file. This function will search for the PGP header and stop reading at +the signature. + +The return value is an arrayref of key/value arrayrefs representing the +directive elements in the first PGP-clearsigned message found while reading +from HANDLE. The values in the returned structure are tainted. + +=cut + +sub read_directive { + my $directive = shift; + + local *_; + my @records = (); + + # First, we find the PGP signature header. + while (<$directive>) { + chomp; s/\r+$//; # remove line ending, including DOS type + last if m/^-----BEGIN PGP SIGNED MESSAGE-----$/; + } + # We are now in the armor headers. + while (<$directive>) { + chomp; s/\r+$//; # remove line ending, including DOS type + # According to RFC4880, there must be exactly one empty line to + # separate the signed message from the armor headers. + last if m/^$/; + } + # We are now looking at the signed message text. + while (<$directive>) { + chomp; s/\r+$//; # remove line ending, including DOS type + s/^\s+//; s/\s+$//; # trim leading and trailing whitespace + + last if m/^-----BEGIN PGP SIGNATURE-----$/; + + unless (/^$/) { # ignore blank lines + push @records, [split /\s+/,$_,2]; + $records[-1][0] =~ s/\s*:$//; # trim trailing colon on key + } + } + # That is all: we have reached the signature and are done. + return \@records; +} + +=item $directive = read_directive_from_file ( $filename ) + +Read a PGP-clearsigned directive file and return an arrayref of key/value +pair arrayrefs representing the directive elements in the signed portion of +the file FILENAME. Any text in the file not within the first clearsigned +message is ignored. + +The values returned from this procedure are tainted. + +=cut + +sub read_directive_from_file { + my $filename = shift; + + open my $handle, '<', $filename + or die "open($filename) failed: $!"; + my $records = read_directive($handle); + close $handle + or die "close($filename) failed: $!"; + + return $records; +} + # # - [SC] Scan for incoming packets -- 2.25.1