Jacob Bachmeyer [Sun, 30 Oct 2022 03:26:24 +0000 (22:26 -0500)]
Factor SMTP client out of mail and debug
Jacob Bachmeyer [Sun, 30 Oct 2022 02:04:48 +0000 (21:04 -0500)]
Fix bug in find_directory
Contrary to documentation, the return value was tainted.
Jacob Bachmeyer [Sat, 29 Oct 2022 04:28:14 +0000 (23:28 -0500)]
Remove useless check of operation list
The interpret_directive function either returns an operation list or
throws an exception, so testing the returned value is silly. This code
had been carried over from previous refactoring when the return value of
read_directive_file was changed to an operation list; it had been a flag
nominally, but was actually a constant in read_directive_file.
Jacob Bachmeyer [Sat, 29 Oct 2022 04:22:55 +0000 (23:22 -0500)]
Revise main code to prepare for future improvements
Jacob Bachmeyer [Sat, 29 Oct 2022 03:08:16 +0000 (22:08 -0500)]
Use File::Spec in validate_commands
Jacob Bachmeyer [Sat, 29 Oct 2022 03:06:24 +0000 (22:06 -0500)]
Remove temporary scaffolding
Jacob Bachmeyer [Sat, 29 Oct 2022 03:04:16 +0000 (22:04 -0500)]
Split read_directive_file into smaller functions
The overall logic was pulled up to top-level, while most of the code is now
in new functions without side-effects.
Jacob Bachmeyer [Sat, 29 Oct 2022 01:52:52 +0000 (20:52 -0500)]
Remove old model in interpret_directive
This removes most of the keys stored in the quasi-global %info hash, but
the current package and collection of email addresses remain to resolve.
Jacob Bachmeyer [Fri, 28 Oct 2022 23:46:23 +0000 (18:46 -0500)]
Revise directory_email_addresses
Addresses are now collected in an array; repeated addresses are accepted at
this stage, and filtered out in the mail function.
Jacob Bachmeyer [Fri, 28 Oct 2022 23:38:46 +0000 (18:38 -0500)]
Add central email address non-repetition filter
Jacob Bachmeyer [Fri, 28 Oct 2022 23:37:48 +0000 (18:37 -0500)]
Revise exclude_mail_blacklist
Jacob Bachmeyer [Fri, 28 Oct 2022 22:44:44 +0000 (17:44 -0500)]
Add tests for email address handling
Jacob Bachmeyer [Fri, 28 Oct 2022 22:43:15 +0000 (17:43 -0500)]
Add testsuite infrastructure for detecting repeated email addresses
Jacob Bachmeyer [Fri, 28 Oct 2022 22:42:45 +0000 (17:42 -0500)]
Fix emission of repeated email addresses
This bug was discovered when support for checking for repeated email
addresses was developed for the testsuite.
Jacob Bachmeyer [Fri, 28 Oct 2022 21:48:16 +0000 (16:48 -0500)]
Reject blatantly invalid email addresses
This was added after discovering that, while the maintainers file and
regular email lists were screened for validity, the addresses reported
by GPG were not. Tests for this will soon be added to the testsuite.
Jacob Bachmeyer [Fri, 28 Oct 2022 04:13:55 +0000 (23:13 -0500)]
Revise email_addresses and rename it to directory_email_addresses
This also adds a new feature: email addresses can be registered only for
certain subdirectories belonging to a package if desired, by listing them
in an "email" file at the corresponding location in the configuration tree.
This uses the same code as is used to locate authorized keyrings.
The use of pattern matching to extract email addresses is a precaution,
although observant readers may notice that the patterns are very lax.
Perl taint mode checks do not require this, since the email addresses will
be written to a socket rather than passed as command arguments, and hash
keys, used here for efficient de-duplication, do not carry taintedness.
Jacob Bachmeyer [Fri, 28 Oct 2022 04:05:45 +0000 (23:05 -0500)]
Change example to mention only packages that actually exist
Mentioning a package that does not exist in a message reporting an attempt
to upload a file for a package that does not exist is certainly a clever
joke, but might be confusing to the recipient.
Jacob Bachmeyer [Fri, 28 Oct 2022 03:59:19 +0000 (22:59 -0500)]
Factor scanning loop out of directory_keyrings
This allows the same loop to be used to support other per-directory items.
Jacob Bachmeyer [Fri, 28 Oct 2022 02:09:42 +0000 (21:09 -0500)]
Revise and rename keyring_file to directory_keyrings
This fixes a long-standing bug, due to keyring_file never actually
returning an empty list, even if the "root" keyring does not actually
exist in the filesystem. The testsuite is adjusted accordingly.
This also introduces another minor issue, in that processing for a
misconfigured package is now abandoned earlier, before email addresses
are gathered. This will be corrected in later improvements.
This also eliminates the special handling for a "root" keyring, although
the feature remains available as part of the general case: "pubring.gpg"
at the root of the package configuration tree applies to all directories
in all packages. Be very careful with the keys on such a ring, as they
would be of immense value to an attacker.
Jacob Bachmeyer [Thu, 27 Oct 2022 05:02:46 +0000 (00:02 -0500)]
Remove parse_directory_line and guess_uploader_email
The former has been merged into interpret_directive, and the latter is
no longer useful. Both are now removed.
Jacob Bachmeyer [Thu, 27 Oct 2022 05:01:10 +0000 (00:01 -0500)]
Remove other call to guess_uploader_email in read_directive_file
The directive has already been parsed and this call is useless here.
Jacob Bachmeyer [Thu, 27 Oct 2022 04:59:32 +0000 (23:59 -0500)]
Accept failure to verify signature during speculative check
Previously, the tool would stop before examining the directive file if the
signature did not match a keyring somewhere. Plans to replace this check
with a single check against the collected master keyring ran afoul of plans
to eliminate the collected master keyring. Current future plans are to use
an index mapping long key IDs to email addresses to replace this, since GPG
will report the long key ID used to produce a signature even if the key is
not in the available keyrings.
This changed the email sent in two cases in the testsuite, which has been
adjusted accordingly in this commit. Concerns about unauthorized parties
abusing the mechanism to spam ftp-upload-report are not relevant here,
since a reuse of a valid directive with a bogus file would be sufficient
to cause mail to be sent to that box. In short, that is a separate issue.
Jacob Bachmeyer [Thu, 27 Oct 2022 04:31:40 +0000 (23:31 -0500)]
Factor email address collection out of directive-scanning loop
Jacob Bachmeyer [Thu, 27 Oct 2022 04:07:08 +0000 (23:07 -0500)]
Merge parse_directory_line into interpret_directive
The old code is still extant because it is also used elsewhere, but will
be cleaned up in future commits.
Jacob Bachmeyer [Thu, 27 Oct 2022 04:05:20 +0000 (23:05 -0500)]
Also avoid further processing after other errors in directive files
Jacob Bachmeyer [Thu, 27 Oct 2022 03:46:47 +0000 (22:46 -0500)]
Avoid processing invalid directive elements
The old code simply abandoned the entire loop at the first error; this
meant that a "directory" element after an error would not be seen and was
fixed in commit
86b458910ddda2c227622cafa3c37b10682d0561. That commit
allowed the values of the capture variables from the last successful match
to be reused if a later line did not match its filter pattern.
No exploit was possible, since an error was recorded and an exception would
be thrown instead of returning the corrupted operation list, but this had
side effects that caused failures in the testsuite that were traced to this
issue, now fixed.
Jacob Bachmeyer [Thu, 27 Oct 2022 03:40:32 +0000 (22:40 -0500)]
Adjust pattern in testsuite
An empty "directory" element is considered invalid, but results in the
message "invalid directory" with no following text. This was hidden by
another issue with the main code, where a failure in parse_directory_line
would add the complete contents of the directive to the message.
Jacob Bachmeyer [Thu, 27 Oct 2022 00:30:22 +0000 (19:30 -0500)]
Add tests for tighter file name patterns in bad directory names
Also fixes a minor bug in the testsuite that prevented $BDIR from being
properly substituted in messages for these tests.
Jacob Bachmeyer [Thu, 27 Oct 2022 00:29:13 +0000 (19:29 -0500)]
Revise timestamp check to use new operation list
Jacob Bachmeyer [Thu, 27 Oct 2022 00:28:18 +0000 (19:28 -0500)]
Recognize that an inability to execute gpgv is a server error
This is an event that should never happen, therefore it now uses ftp_abort.
Jacob Bachmeyer [Thu, 27 Oct 2022 00:24:56 +0000 (19:24 -0500)]
Refactor directive validity checks
The check for the "replace" element appearing in a v1.1 directive is moved
to interpret_directive and directive processing no longer stops at the
first error, since the documentation states that the order of directive
elements is insignificant.
This also fixes a long-standing bug that resulted in the sending of email
to the registered maintainers for a package depending on the relative
location of the "directory" element; the testsuite is adjusted accordingly.
Jacob Bachmeyer [Wed, 26 Oct 2022 23:55:11 +0000 (18:55 -0500)]
Reorganize gatekeeper to collect generic GPG support functions
Prior to committing, this was validated with:
(DIFF='git diff --cached';
comm -3 <($DIFF | grep ^- | sed -e 's/^-//' | sort) \
<($DIFF | grep ^+ | sed -e 's/^+//' | sort) )
The output shows only blank lines, comments, and a diff header were
added, and only a diff header removed, after all lines are sorted
and paired for analysis. To replicate, change the "git diff" command
to compare this commit with its parent.
Jacob Bachmeyer [Wed, 26 Oct 2022 04:34:34 +0000 (23:34 -0500)]
Rename slurp_directive_file to slurp_clearsigned_message
Jacob Bachmeyer [Wed, 26 Oct 2022 04:26:57 +0000 (23:26 -0500)]
Use epoch timestamp from GPG instead of parsing the display timestamp
The --status-fd option reports timestamps in epoch time directly, although
the documentation indicates that ISO 8601 format is also possible. This
change eliminates several manipulations and removes the dependency on the
external Date::Manip module.
Jacob Bachmeyer [Wed, 26 Oct 2022 03:24:59 +0000 (22:24 -0500)]
Replace clearsigned message verification
This removes the use of the shell to run gpgv when verifying directives.
This also improves the handling the of gpgv generally, since the use of
the --status-fd option is the recommended mechanism for automatic usage.
Jacob Bachmeyer [Wed, 26 Oct 2022 02:13:41 +0000 (21:13 -0500)]
Fix bug in testing mock
If nonexistent files appear in the keyring list, grep will return an error
even if a later keyring contains a match; this will cause the mock tool to
incorrectly report not finding a key. This bug was hidden by the main
gatekeeper only using one keyring on each gpgv run.
Jacob Bachmeyer [Wed, 26 Oct 2022 01:33:40 +0000 (20:33 -0500)]
Complete initial implementation of new clearsigned message verification
Jacob Bachmeyer [Wed, 26 Oct 2022 01:28:51 +0000 (20:28 -0500)]
Avoid passing tainted keyrings to signature verification
Jacob Bachmeyer [Wed, 26 Oct 2022 01:27:55 +0000 (20:27 -0500)]
Use revised ftp_abort in verify_clearsigned_message
Jacob Bachmeyer [Wed, 26 Oct 2022 01:25:55 +0000 (20:25 -0500)]
Revise ftp_abort to be useful in a forked child process
This commit introduces global variables to control the destination of an
abort message and the default exit code. These variables are accessed
using lexical aliases and are only accessible in the code that uses them.
Jacob Bachmeyer [Tue, 25 Oct 2022 03:30:11 +0000 (22:30 -0500)]
Add option to pipe signed message to mock signature verification tool
Jacob Bachmeyer [Sun, 23 Oct 2022 03:55:33 +0000 (22:55 -0500)]
Begin to implement new gpgv clearsigned message verification
The new code allows presenting gpgv with exactly the directive that was parsed
and eliminates all risk of confusion by keeping the output, log, and status
channels separate. This also avoids using the shell to run gpgv.
The use of a dedicated pipe with --status-fd protects against CVE-2018-12020
and any similar future vulnerabilities.
Jacob Bachmeyer [Sat, 22 Oct 2022 04:28:38 +0000 (23:28 -0500)]
Revise execute_commands to use new model
Jacob Bachmeyer [Sat, 22 Oct 2022 04:23:23 +0000 (23:23 -0500)]
Revise install_files to use new model
Jacob Bachmeyer [Sat, 22 Oct 2022 03:37:30 +0000 (22:37 -0500)]
Revise use of system() in check_files
The indirect object form of system absolutely does not use the shell.
Jacob Bachmeyer [Sat, 22 Oct 2022 03:36:12 +0000 (22:36 -0500)]
Revise check_files to use new model
Jacob Bachmeyer [Sat, 22 Oct 2022 03:02:55 +0000 (22:02 -0500)]
Begin to revise check_files, install_files, execute_commands
This commit removes the local %info hashes in these functions.
Jacob Bachmeyer [Fri, 21 Oct 2022 04:29:39 +0000 (23:29 -0500)]
Add operation list header to calls to check_files and install_files
Jacob Bachmeyer [Fri, 21 Oct 2022 04:25:53 +0000 (23:25 -0500)]
Revise execute_commands to use new operation list
Jacob Bachmeyer [Fri, 21 Oct 2022 03:51:25 +0000 (22:51 -0500)]
Add operation list to execute_commands call
This also adds a simple consistency check in execute_commands.
Jacob Bachmeyer [Fri, 21 Oct 2022 03:50:31 +0000 (22:50 -0500)]
Change return value of read_directive_file to operation list
Previously, read_directive_file always returned zero or did not return.
We now return an operation list that will eventually replace the global
%info hash.
Jacob Bachmeyer [Fri, 21 Oct 2022 03:31:13 +0000 (22:31 -0500)]
Tidy check for known Automake CVEs
While it is very unlikely that anyone will still use such an old version
of Automake, the potential risk is significant, so we still check.
Jacob Bachmeyer [Fri, 21 Oct 2022 03:15:45 +0000 (22:15 -0500)]
Avoid using the shell to run /bin/tar to examine uploads
This new code uses the list-form pipe open introduced in Perl 5.8.0.
Jacob Bachmeyer [Fri, 21 Oct 2022 02:58:37 +0000 (21:58 -0500)]
Remove intermediate array and send vulnerability check messages to syslog
Jacob Bachmeyer [Fri, 21 Oct 2022 02:29:20 +0000 (21:29 -0500)]
Revise handling of "filename" directive element
All protocol versions so far imply an "install" command when a directive
is uploaded as part of a triplet. This commit also adds infrastructure
to support a possible future explicit "install" command, removes a useless
validation of the packet stem against the directive file name, and cleans
up a now-unneeded variable that had been left as scaffolding.
Jacob Bachmeyer [Fri, 21 Oct 2022 01:55:22 +0000 (20:55 -0500)]
Remove unneeded scratchpad array when reading serials file
Jacob Bachmeyer [Fri, 21 Oct 2022 01:48:56 +0000 (20:48 -0500)]
Add tests for timestamp ratchet
Jacob Bachmeyer [Thu, 20 Oct 2022 23:59:22 +0000 (18:59 -0500)]
Fix typo in error message
Jacob Bachmeyer [Thu, 20 Oct 2022 23:52:08 +0000 (18:52 -0500)]
Factor version check into separate block in interpret_directive
Produced messages are changed; the testsuite is adjusted accordingly.
Jacob Bachmeyer [Thu, 20 Oct 2022 23:17:20 +0000 (18:17 -0500)]
Add scaffolding for checking "filename" element in read_directive_file
Jacob Bachmeyer [Thu, 20 Oct 2022 04:32:00 +0000 (23:32 -0500)]
Convert "filename_required" flag in read_directive_file to scaffolding
Further refactoring will eventually remove it entirely.
Jacob Bachmeyer [Thu, 20 Oct 2022 04:24:16 +0000 (23:24 -0500)]
Factor timestamp ratchet out of read_directive_file
Jacob Bachmeyer [Thu, 20 Oct 2022 04:00:32 +0000 (23:00 -0500)]
Add tests verifying handling of directives lacking commands
Jacob Bachmeyer [Thu, 20 Oct 2022 03:49:36 +0000 (22:49 -0500)]
Revise checks for "filename" directive element in read_directive_file
The revised code uses the "filename" directive element as a command to
install an uploaded file. This change ensures that a legitimate loose
directive will be processed even if accompanied with a bogus file.
This is a definitive break from protocol version 1.0, which was disabled
in 2012 and recently removed.
Jacob Bachmeyer [Thu, 20 Oct 2022 03:47:46 +0000 (22:47 -0500)]
Revise interpretation of directives into operation lists
The operation list structure replaces the "order" subkey in elements in
the %info hash; as such, the "replace" option should not produce an entry
in the operation list, instead being a global flag stored in the header.
Jacob Bachmeyer [Wed, 19 Oct 2022 03:54:29 +0000 (22:54 -0500)]
Rearrange validation checks in read_directive_file
This also resolves a TODO item in the testsuite.
Jacob Bachmeyer [Wed, 19 Oct 2022 02:50:12 +0000 (21:50 -0500)]
Use operation list header instead of %info hash in read_directive_file
Jacob Bachmeyer [Wed, 19 Oct 2022 02:43:34 +0000 (21:43 -0500)]
Adjust testsuite to copy output to log
Jacob Bachmeyer [Wed, 19 Oct 2022 02:03:45 +0000 (21:03 -0500)]
Use new slurp_directive_file helper in read_directive_file
This also ensures that unsigned lines in directives are consistently
ignored. The testsuite is adjusted accordingly; this resolves an issue
with consistently detecting and rejecting unsigned directives.
Jacob Bachmeyer [Wed, 19 Oct 2022 01:58:28 +0000 (20:58 -0500)]
Tighten allowed file names
Jacob Bachmeyer [Tue, 18 Oct 2022 04:20:30 +0000 (23:20 -0500)]
Improve RFC4880 conformance
Jacob Bachmeyer [Tue, 18 Oct 2022 02:25:20 +0000 (21:25 -0500)]
Refactor directive parsing to only read file once
Jacob Bachmeyer [Tue, 18 Oct 2022 02:07:45 +0000 (21:07 -0500)]
Add POD block for interpret_directive
This was held out of the previous commit to improve diff readability.
Jacob Bachmeyer [Tue, 18 Oct 2022 02:06:20 +0000 (21:06 -0500)]
Factor element-processing loop out of read_directive_file
Jacob Bachmeyer [Sun, 16 Oct 2022 04:32:40 +0000 (23:32 -0500)]
Use new read_directive helper in read_directive_file
Jacob Bachmeyer [Sun, 16 Oct 2022 04:24:00 +0000 (23:24 -0500)]
Move declaration of counter in read_directive_file nearer to loop
Jacob Bachmeyer [Sun, 16 Oct 2022 04:15:45 +0000 (23:15 -0500)]
Replace file-reading loop with list operations
Jacob Bachmeyer [Sun, 16 Oct 2022 04:08:27 +0000 (23:08 -0500)]
Remove obsolete comment describing protocol v1.0
Jacob Bachmeyer [Sun, 16 Oct 2022 04:02:56 +0000 (23:02 -0500)]
Revise main packet processing loop to use new gather_packets result
Jacob Bachmeyer [Sun, 16 Oct 2022 03:41:29 +0000 (22:41 -0500)]
Remove testsuite handling of obsolete message
This message was removed from the gatekeeper along with the rest of the
legacy v1.0 support in commit
af0774b9c0ce4907bbdf95e57ffdb534366e19dc.
Jacob Bachmeyer [Sun, 16 Oct 2022 03:16:16 +0000 (22:16 -0500)]
Add helper procedures for directive handling in gatekeeper
Jacob Bachmeyer [Sun, 16 Oct 2022 02:39:40 +0000 (21:39 -0500)]
Rename ftp_die to ftp_abort in gatekeeper
Jacob Bachmeyer [Sun, 16 Oct 2022 01:10:20 +0000 (20:10 -0500)]
Use value from splitting directory line to obtain package name
Jacob Bachmeyer [Sun, 16 Oct 2022 01:07:24 +0000 (20:07 -0500)]
Use File::Spec::Unix to count directories in parse_directory_line
Jacob Bachmeyer [Sun, 16 Oct 2022 01:02:16 +0000 (20:02 -0500)]
Use symbolic constant for maximum directory depth
Jacob Bachmeyer [Sun, 16 Oct 2022 00:53:35 +0000 (19:53 -0500)]
Add report of number of files with bogus names discarded
Jacob Bachmeyer [Sun, 16 Oct 2022 00:47:51 +0000 (19:47 -0500)]
Finish refactoring of gather_packets/scan_incoming to use absolute names
This eliminates the need to change to the incoming directory and is a
step towards a goal of eliminating any dependency on the current directory
and presenting only absolute file names to the system.
Jacob Bachmeyer [Sun, 16 Oct 2022 00:39:40 +0000 (19:39 -0500)]
Refactor scan_incoming as helper for gather_packets
The old scan_incoming function was very long and performed two related
but distinct tasks: collecting a list of files eligible for processing
and collecting those files into packets. The new scan_incoming now only
produces a list of files; the second loop to collect files into packets
has been moved to a new gather_packets function.
Jacob Bachmeyer [Sun, 16 Oct 2022 00:28:40 +0000 (19:28 -0500)]
Improve comments
Jacob Bachmeyer [Sun, 16 Oct 2022 00:28:25 +0000 (19:28 -0500)]
Update testsuite for terminology change
The original concept of "triplets" is now generalized to "packets" that
can contain any number of files.
Jacob Bachmeyer [Sun, 16 Oct 2022 00:26:56 +0000 (19:26 -0500)]
Revise packet-gathering loop in scan_incoming
Since every packet must contain a directive, the process is now driven
based on the set of directives available. This change also avoids
considering every file and fixes a related minor bug in the old code:
comments indicated that all files from each triplet were supposed to be
removed from possible consideration, but the loop was actually iterating
over a temporary list containing the keys of the %possible hash as of the
start of the loop.
This change also introduces a new internal format for the result of the
scan_incoming function and some temporary scaffolding code to convert the
new format to the old format to keep the tool working during the change.
Jacob Bachmeyer [Sat, 15 Oct 2022 03:43:44 +0000 (22:43 -0500)]
Discard names of trash files immediately after unlink
Jacob Bachmeyer [Sat, 15 Oct 2022 03:33:34 +0000 (22:33 -0500)]
Add comment describing expected issue on modern GNU/Linux
Jacob Bachmeyer [Sat, 15 Oct 2022 03:29:55 +0000 (22:29 -0500)]
Improve comments in scan_incoming
Jacob Bachmeyer [Sat, 15 Oct 2022 03:24:04 +0000 (22:24 -0500)]
Revise check for open files in scan_incoming
The old code would incorrectly assume that no files are open if the
lsof program fails to run; this new code uses a list-form pipe open
introduced in Perl 5.8.0 instead of an implied fork.
Also use File::Spec to form the arguments to lsof.
Jacob Bachmeyer [Sat, 15 Oct 2022 03:19:29 +0000 (22:19 -0500)]
Check file sizes while scanning directory in scan_incoming
Excessively large directive and signature files are now detected while
scanning the incoming files directory and promptly removed afterward;
the testsuite is adjusted accordingly.
Jacob Bachmeyer [Sat, 15 Oct 2022 03:11:22 +0000 (22:11 -0500)]
Check timestamps while scanning directory in scan_incoming
Recent files are now filtered out very early, before checking if they
are open; the testsuite is adjusted accordingly.
Jacob Bachmeyer [Sat, 15 Oct 2022 03:05:01 +0000 (22:05 -0500)]
Revise directory scanning loop in scan_incoming
Files with unacceptable names are now removed immediately after scanning
the incoming files directory; the testsuite is adjusted accordingly.
Jacob Bachmeyer [Sat, 15 Oct 2022 02:54:32 +0000 (21:54 -0500)]
Use arguments instead of globals in scan_incoming
Also move the declaration of the return array.
Jacob Bachmeyer [Sat, 15 Oct 2022 02:40:57 +0000 (21:40 -0500)]
Use symbolic constants for limits in scan_incoming