diff options
Diffstat (limited to 'SBO-Lib/lib/SBO')
-rw-r--r-- | SBO-Lib/lib/SBO/Lib/Cryptography.pm | 114 | ||||
-rw-r--r-- | SBO-Lib/lib/SBO/Lib/Repo.pm | 30 |
2 files changed, 106 insertions, 38 deletions
diff --git a/SBO-Lib/lib/SBO/Lib/Cryptography.pm b/SBO-Lib/lib/SBO/Lib/Cryptography.pm index 4fca277..0022b8f 100644 --- a/SBO-Lib/lib/SBO/Lib/Cryptography.pm +++ b/SBO-Lib/lib/SBO/Lib/Cryptography.pm @@ -10,22 +10,36 @@ use Cwd; use File::Temp "tempdir"; use IPC::Open3; +use Exporter 'import'; + +# Minimal definitions of some GPG raw output messages. use constant { - BAD_SIGNATURE => 'bad signature', - EXPIRED_KEY => 'expired key', - VALID_SIGNATURE => 'good signature', + BADSIG => 'bad signature', + EXPSIG => 'signature expired', + EXPKEYSIG => 'signed by expired key', + ERRSIG => 'signature verification not possible', + GOODSIG => 'good signature', + REVKEYSIG => 'good signature by revoked public key', + NO_PUBKEY => 'public key unavailable', + VALIDSIG => 'valid signature', + # An unknown message type. + UNKNOWN => 'unknown', }; -use Exporter 'import'; - our @EXPORT_OK = qw{ - has_valid_gpg_signature import_gpg_key + parse_gpg_output verify_gpg_signed_file - BAD_SIGNATURE - EXPIRED_KEY - VALID_SIGNATURE + BADSIG + EXPSIG + EXPKEYSIG + ERRSIG + GOODSIG + REVKEYSIG + NO_PUBKEY + VALIDSIG + UNKNOWN }; our %EXPORT_TAGS = ( @@ -36,38 +50,80 @@ our %EXPORT_TAGS = ( =encoding UTF-8 -=head2 +=cut - has_valid_gpg_signature(@output, $key_id); +# Messages on Signature status which should only turn up once. +our %is_signature_status = ( + &BADSIG => 1, + &ERRSIG => 1, + &EXPSIG => 1, + &EXPKEYSIG => 1, + &GOODSIG => 1, + &REVKEYSIG => 1, +); + +=head2 -C<has_valid_gpg_siganture()> validates whether the captured gpg status output -contains a good signature for the given GPG key. + parse_gpg_output(@output, $key_id); =cut -sub has_valid_gpg_signature { +sub parse_gpg_output { my $output = shift; my $key_id = shift; - # VALIDSIG contains the hex key ID, GOODSIG is required for certainty. More - # information can be found in 'DETAILS' in the gnupg2 documentation folder. - my $is_good_sig = 0; - my $is_valid_sig = 0; my $line; + my $status = ''; + foreach $line (@$output) { - if ($line =~ /^\[GNUPG\:] VALIDSIG $key_id/) { - $is_valid_sig = 1; - } elsif ($line =~ /^\[GNUPG\:] GOODSIG /) { - $is_good_sig = 1; + my $msg = parse_gpg_line($line, $key_id); + + if (exists($is_signature_status{$msg})) { + # Only one signature expected. + if ($status ne '') { + return UNKNOWN; + } + + $status = $msg; } - if ($is_good_sig && $is_valid_sig) { - return 1; + if ($msg eq NO_PUBKEY) { + return NO_PUBKEY; + } elsif ($msg eq VALIDSIG) { + # VALIDSIG contains the full hex key ID to be certain it is signed by the + # right key. information can be found in 'DETAILS' in the gnupg2 + # documentation folder. + return $status; } } - return 0; + return UNKNOWN; +} + +sub parse_gpg_line { + my $line = shift; + my $key_id = shift; + + if ($line =~ /^\[GNUPG\:] BADSIG/) { + return BADSIG; + } elsif ($line =~ /^\[GNUPG\:] EXPSIG/) { + return EXPSIG; + } elsif ($line =~ /^\[GNUPG\:] EXPKEYSIG/) { + return EXPKEYSIG; + } elsif ($line =~ /^\[GNUPG\:] ERRSIG/) { + return ERRSIG; + } elsif ($line =~ /^\[GNUPG\:] GOODSIG/) { + return GOODSIG; + } elsif ($line =~ /^\[GNUPG\:] REVKEYSIG/) { + return REVKEYSIG; + } elsif ($line =~ /^\[GNUPG\:] NO_PUBKEY/) { + return NO_PUBKEY; + } elsif ($line =~ /^\[GNUPG\:] VALIDSIG $key_id/) { + return VALIDSIG; + } else { + return UNKNOWN; + } } =head2 import_gpg_key @@ -127,6 +183,8 @@ sub import_gpg_key { close($gpg_export); close($gpg_import); + sleep(1); + print("key imported\n"); } @@ -151,9 +209,5 @@ sub verify_gpg_signed_file { } close($std_out); - if (! has_valid_gpg_signature(\@output, $key_id)) { - return BAD_SIGNATURE; - } - - return VALID_SIGNATURE; + return parse_gpg_output(\@output, $key_id); } diff --git a/SBO-Lib/lib/SBO/Lib/Repo.pm b/SBO-Lib/lib/SBO/Lib/Repo.pm index 5337ea8..eaf1f2f 100644 --- a/SBO-Lib/lib/SBO/Lib/Repo.pm +++ b/SBO-Lib/lib/SBO/Lib/Repo.pm @@ -7,7 +7,7 @@ use warnings; our $VERSION = '2.7.2'; use SBO::Lib::Util qw/ %config prompt usage_error get_slack_version get_slack_version_key get_slack_version_url script_error open_fh open_read in _ERR_DOWNLOAD /; -use SBO::Lib::Cryptography qw/ has_valid_gpg_signature verify_gpg_signed_file VALID_SIGNATURE /; +use SBO::Lib::Cryptography qw/ GOODSIG NO_PUBKEY parse_gpg_output verify_gpg_signed_file /; use Cwd; use File::Copy; @@ -280,15 +280,22 @@ sub git_sbo_tree { if ($key_id) { my @output; - print("Verifying $git_ref...\n"); + print("Verifying $git_ref..."); open3(undef, undef, my $std_err = gensym, "git", $verify_cmd, "--raw", "$git_ref"); while (my $line = <$std_err>) { push(@output, $line); } close($std_err); - if (! has_valid_gpg_signature(\@output, $key_id)) { - print(STDERR "Repository GPG verification failed.\n"); + my $res = parse_gpg_output(\@output, $key_id); + if ($res eq GOODSIG) { + print("OK\n"); + } else { + print(STDERR "Repository GPG verification failed: $res."); + if ($res == NO_PUBKEY) { + print(STDERR " Did you import the GPG key?"); + } + print(STDERR "\n"); chdir $cwd; return 0; @@ -407,10 +414,16 @@ sub rsync_sbo_tree { print("GPG verification is not present for 14.0 and earlier. You should consider disabling GPG verification.") } - print("Verifying CHECKSUMS.md5...\n"); + print("Verifying CHECKSUMS.md5..."); my $res = verify_gpg_signed_file('CHECKSUMS.md5.asc', $key_id); - if ($res ne VALID_SIGNATURE) { - print(STDERR "Respository CHECKSUMS.md5 GPG verification failed.\n"); + if ($res eq GOODSIG) { + print("OK\n"); + } else { + print(STDERR "Respository CHECKSUMS.md5 GPG verification failed: $res."); + if ($res eq NO_PUBKEY) { + print(STDERR " Did you import the GPG key?"); + } + print(STDERR "\n"); chdir($cwd); return 0; @@ -418,11 +431,12 @@ sub rsync_sbo_tree { } if ( -e "CHECKSUMS.md5" ) { - print("Verifying file integrity using CHECKSUMS.md5...\n"); + print("Verifying file integrity using CHECKSUMS.md5..."); if (system('tail +13 CHECKSUMS.md5 | md5sum -c --quiet -')) { chdir($cwd); return 0; } + print("OK\n"); } return chdir($cwd); |