diff options
Diffstat (limited to 'SBO-Lib/lib/SBO/Lib/Cryptography.pm')
-rw-r--r-- | SBO-Lib/lib/SBO/Lib/Cryptography.pm | 114 |
1 files changed, 84 insertions, 30 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); } |