[Rt-commit] rt branch, 5.0/support-gpg-2.2, created. rt-5.0.0alpha1-465-g549b998207

? sunnavy sunnavy at bestpractical.com
Fri May 15 16:53:37 EDT 2020


The branch, 5.0/support-gpg-2.2 has been created
        at  549b99820767151c3f1dda1f9bc6750d7d3c8c99 (commit)

- Log -----------------------------------------------------------------
commit 734bc6972fd8250718b00344907ff2aa280c9101
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Mon May 4 14:17:13 2020 +0100

    Fix uninitialized warnings of $latest_user_main_key for gpg 2.2
    
    $latest_user_main_key is set by USERID_HINT line, which is absent in gpg
    2.2 output.

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index c78a870b65..7fe0164db1 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1542,10 +1542,12 @@ sub ParseStatus {
                 Class          => $props[3],
                 Timestamp      => $props[4],
                 KeyFingerprint => $props[5],
-                User           => $user_hint{ $latest_user_main_key },
+                ( defined $latest_user_main_key ? ( User => $user_hint{$latest_user_main_key} ) : () )
             };
-            $res[-1]->{Message} .= ' by '. $user_hint{ $latest_user_main_key }->{'EmailAddress'}
-                if $user_hint{ $latest_user_main_key };
+            if ($latest_user_main_key) {
+                $res[-1]->{Message} .= ' by '. $user_hint{ $latest_user_main_key }->{'EmailAddress'}
+                    if $user_hint{ $latest_user_main_key };
+            }
         }
         elsif ( $keyword eq 'INV_RECP' ) {
             my ($rcode, $recipient) = split /\s+/, $args, 2;

commit 4cc1b76b74dee34c42364d24e2e6ac0ba08ef9cf
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Fri May 1 21:26:01 2020 +0100

    Handle FAILURE keyword for gpg 2.2

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index 7fe0164db1..e0311b27a5 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1344,7 +1344,7 @@ my %parse_keyword = map { $_ => 1 } qw(
     DECRYPTION_FAILED DECRYPTION_OKAY
     BAD_PASSPHRASE GOOD_PASSPHRASE
     NO_SECKEY NO_PUBKEY
-    NO_RECP INV_RECP NODATA UNEXPECTED
+    NO_RECP INV_RECP NODATA UNEXPECTED FAILURE
 );
 
 # keywords we ignore without any messages as we parse them using other
@@ -1572,8 +1572,20 @@ sub ParseStatus {
                 Reason     => $reason,
             };
         }
+        elsif ( $keyword eq 'FAILURE' ) {
+            # FAILURE encrypt 167772218
+            my ($op, $rcode) = split /\s+/, $args;
+            my $reason = ReasonCodeToText( $keyword, $rcode );
+            push @res, {
+                Operation  => ucfirst($op),
+                Status     => 'ERROR',
+                Message    => "Failed to $op",
+                ReasonCode => $rcode,
+                Reason     => $reason,
+            };
+        }
         else {
-            $RT::Logger->warning("Keyword $keyword is unknown");
+            $RT::Logger->warning("Keyword $keyword is unknown : status line is $line");
             next;
         }
         $res[-1]{'Keyword'} = $keyword if @res && !$res[-1]{'Keyword'};

commit ee9a2a7bcf0f26376aca19e9fdb5e4568a1728be
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Wed May 6 17:00:50 2020 +0100

    Add extra ignored keywords for gnupg 2.2.x

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index e0311b27a5..93ee2d56ec 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1354,7 +1354,8 @@ my %ignore_keyword = map { $_ => 1 } qw(
     BEGIN_ENCRYPTION SIG_ID VALIDSIG
     ENC_TO BEGIN_DECRYPTION END_DECRYPTION GOODMDC
     TRUST_UNDEFINED TRUST_NEVER TRUST_MARGINAL TRUST_FULLY TRUST_ULTIMATE
-    DECRYPTION_INFO
+    DECRYPTION_INFO KEY_CONSIDERED DECRYPTION_KEY NEWSIG PINENTRY_LAUNCHED
+    IMPORT_OK DECRYPTION_COMPLIANCE_MODE PROGRESS INV_SGNR
 );
 
 sub ParseStatus {

commit 37eb1901a631db493f33ffe7dcaa5db543ce4bf3
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri May 15 15:32:00 2020 +0800

    Default cert-digest-algo from SHA1 to SHA256
    
    Since 2.2.18, SHA1 is not allowed any more, the error message is:
    
        third-party key signatures using the SHA1 algorithm are rejected

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index 93ee2d56ec..f0c9a6d12f 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -330,6 +330,7 @@ sub CallGnuPG {
     my %GnuPGOptions = RT->Config->Get('GnuPGOptions');
     my %opt = (
         'digest-algo' => 'SHA1',
+        'cert-digest-algo' => 'SHA256',
         %GnuPGOptions,
         %{ $args{Options} || {} },
     );

commit 58580e05691da2f53834ffd9969bd6392e95db0f
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat May 16 00:37:00 2020 +0800

    Add gpg.conf for gpg 2.2 so we can specify passphrase in command line
    
    The option "pinentry-mode loopback" is invalid in gpg 1.4, so we need to
    delete the conf file accordingly.

diff --git a/lib/RT/Test/GnuPG.pm b/lib/RT/Test/GnuPG.pm
index 414097e810..358645d8c2 100644
--- a/lib/RT/Test/GnuPG.pm
+++ b/lib/RT/Test/GnuPG.pm
@@ -96,6 +96,17 @@ sub bootstrap_more_config {
     );
     $gnupg_options{homedir} ||= scalar tempdir( CLEANUP => 1 );
 
+    my ($gnupg_version) = split /\./, GnuPG::Interface->new->version;
+    my $conf = File::Spec->catfile( $gnupg_options{homedir}, 'gpg.conf' );
+    if ( $gnupg_version >= 2 ) {
+        open my $fh, '>', $conf or die $!;
+        print $fh "pinentry-mode loopback\n";
+        close $fh;
+    }
+    else {
+        unlink $conf if -e $conf;
+    }
+
     use Data::Dumper;
     local $Data::Dumper::Terse = 1; # "{...}" instead of "$VAR1 = {...};"
     my $dumped_gnupg_options = Dumper(\%gnupg_options);

commit 09201a7592069892f81c0a8c5fa0c39adcec9ccb
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri May 15 20:16:10 2020 +0800

    Update warning message tests for gpg 2.2

diff --git a/t/crypt/no-signer-address.t b/t/crypt/no-signer-address.t
index 31ba5ebc2a..4c459c06a8 100644
--- a/t/crypt/no-signer-address.t
+++ b/t/crypt/no-signer-address.t
@@ -36,7 +36,6 @@ my ($status, undef, $msg) = $ticket->Create(
 ok( $status, "created ticket" ) or diag "error: $msg";
 
 is( scalar @warnings, 1, "Got a warning" );
-like( $warnings[0], qr{signing failed: secret key not available},
-    "Found warning of no secret key");
+like( $warnings[0], qr{signing failed: (?:secret key not available|No secret key)}, "Found warning of no secret key" );
 
 done_testing;
diff --git a/t/mail/gnupg-reverification.t b/t/mail/gnupg-reverification.t
index e5dcf09bb4..1ec9aa19e8 100644
--- a/t/mail/gnupg-reverification.t
+++ b/t/mail/gnupg-reverification.t
@@ -60,11 +60,11 @@ foreach my $file ( @files ) {
     );
     $m->content_like(qr/This is .*ID:$eid/ims, "$eid: content is there and message is decrypted");
 
-    $m->next_warning_like(qr/public key not found/);
+    $m->next_warning_like(qr/public key not found|No public key/);
 
     # some mails contain multiple signatures
     if ($eid == 5 || $eid == 17 || $eid == 18) {
-        $m->next_warning_like(qr/public key not found/);
+        $m->next_warning_like(qr/public key not found|No public key/);
     }
 
     $m->no_leftover_warnings_ok;
diff --git a/t/security/CVE-2012-4735-incoming-encryption-header.t b/t/security/CVE-2012-4735-incoming-encryption-header.t
index 6c15632979..bd89e67566 100644
--- a/t/security/CVE-2012-4735-incoming-encryption-header.t
+++ b/t/security/CVE-2012-4735-incoming-encryption-header.t
@@ -57,7 +57,7 @@ EOF
     warnings_like {
         ($status, $id) = RT::Test->send_via_mailgate($mail);
         ok $id, "created a ticket";
-    } [qr/keyring .* created/,
+    } [qr/(?:keyring|keybox) .* created/,
        qr/Failure during GnuPG data: No data has been found\. The reason is 'Invalid packet found'/,
        qr/Failure during GnuPG data: No data has been found\. The reason is 'No armored data'/,
    ];
diff --git a/t/web/crypt-gnupg.t b/t/web/crypt-gnupg.t
index fed621ce46..827d06d2c6 100644
--- a/t/web/crypt-gnupg.t
+++ b/t/web/crypt-gnupg.t
@@ -355,7 +355,7 @@ warning_like {
     $tick->Create(Subject => 'owner lacks pubkey', Queue => 'general',
                   Owner => $nokey);
 } [
-    qr/nokey\@example.com: skipped: public key not found/,
+    qr/nokey\@example.com: skipped: public key not found|error retrieving 'nokey\@example.com' via WKD: No data/,
     qr/Recipient 'nokey\@example.com' is unusable/,
 ];
 ok(my $id = $tick->id, 'created ticket for owner-without-pubkey');
@@ -377,7 +377,7 @@ my $status;
 warning_like {
     ($status, $id) = RT::Test->send_via_mailgate($mail);
 } [
-    qr/nokey\@example.com: skipped: public key not found/,
+    qr/nokey\@example.com: skipped: public key not found|error retrieving 'nokey\@example.com' via WKD: No data/,
     qr/Recipient 'nokey\@example.com' is unusable/,
 ];
 
@@ -458,8 +458,8 @@ like($content, qr/KR-<recipient\@example\.com>-K/,
 like($content, qr/KR-nokey \(no pubkey!\)-K/,
      "KeyRequestors DOES issue no-pubkey warning for nokey\@example.com");
 
-$m->next_warning_like(qr/public key not found/);
-$m->next_warning_like(qr/public key not found/);
+$m->next_warning_like(qr/public key not found|No public key/);
+$m->next_warning_like(qr/public key not found|No public key/);
 $m->no_leftover_warnings_ok;
 
 done_testing;
diff --git a/t/web/gnupg-select-keys-on-create.t b/t/web/gnupg-select-keys-on-create.t
index 64d6c6e46d..78e1fbba02 100644
--- a/t/web/gnupg-select-keys-on-create.t
+++ b/t/web/gnupg-select-keys-on-create.t
@@ -28,7 +28,7 @@ diag "check that signing doesn't work if there is no key";
         'unable to sign outgoing email messages',
         'problems with passphrase'
     );
-    $m->warning_like(qr/signing failed: secret key not available/);
+    $m->warning_like(qr/signing failed: (?:secret key not available|No secret key)/);
 
     my @mail = RT::Test->fetch_caught_mails;
     ok !@mail, 'there are no outgoing emails';
@@ -66,7 +66,7 @@ diag "check that things don't work if there is no key";
     my @mail = RT::Test->fetch_caught_mails;
     ok !@mail, 'there are no outgoing emails';
 
-    $m->next_warning_like(qr/public key not found/) for 1 .. 2;
+    $m->next_warning_like(qr/public key not found|No public key/) for 1 .. 2;
     $m->no_leftover_warnings_ok;
 }
 

commit 0547b8ff05c93f0dbcd952ca4b8c4cd7bdc3406f
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat May 16 03:35:09 2020 +0800

    Don't override fingerprint if it exsits already
    
    With gpg 2.2, subkey fingerprints also show up(after mainkeys), thus we
    need to prevent them from wrongly overridding ones of mainkeys.

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index f0c9a6d12f..4ece75390a 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -1755,7 +1755,7 @@ sub ParseKeysInfo {
             push @{ $res[-1]{'User'} ||= [] }, \%info;
         }
         elsif ( $tag eq 'fpr' ) {
-            $res[-1]{'Fingerprint'} = (split /:/, $line, 10)[8];
+            $res[-1]{'Fingerprint'} ||= (split /:/, $line, 10)[8];
         }
     }
     return @res;

commit 113fab11d62f33a96ab18ad3e9030e30d3beaaa9
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri May 15 23:20:56 2020 +0800

    Make t/mail/crypt-gnupg.t happy with gpg 2.2
    
    Besides the differences of returned info from gpg 1.4 and 2.2, the
    missing passphrase tests are skipped because otherwise the test would
    hang(probably waiting for passphrase input)

diff --git a/t/mail/crypt-gnupg.t b/t/mail/crypt-gnupg.t
index 567573e934..f55a1fe252 100644
--- a/t/mail/crypt-gnupg.t
+++ b/t/mail/crypt-gnupg.t
@@ -10,9 +10,11 @@ BEGIN {
         qw/data gnupg keyrings/ );
 }
 
-use RT::Test::GnuPG tests => 100, gnupg_options => { homedir => $homedir };
+use RT::Test::GnuPG tests => undef, gnupg_options => { homedir => $homedir, quiet => 1 };
 use Test::Warn;
 
+my ($gnupg_version) = split /\./, GnuPG::Interface->new->version;
+
 use_ok('RT::Crypt');
 use_ok('MIME::Entity');
 
@@ -29,12 +31,22 @@ diag 'only signing. correct passphrase';
     my @status = RT::Crypt->ParseStatus(
         Protocol => $res{'Protocol'}, Status => $res{'status'}
     );
-    is( scalar @status, 2, 'two records: passphrase, signing');
-    is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
-    is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
-    is( $status[1]->{'Operation'}, 'Sign', 'operation is correct');
-    is( $status[1]->{'Status'}, 'DONE', 'done');
-    is( $status[1]->{'User'}->{'EmailAddress'}, 'rt at example.com', 'correct email');
+
+    if ( $gnupg_version < 2 ) {
+        is( scalar @status,                         2,                 'two records: passphrase, signing' );
+        is( $status[0]->{'Operation'},              'PassphraseCheck', 'operation is correct' );
+        is( $status[0]->{'Status'},                 'DONE',            'good passphrase' );
+        is( $status[1]->{'Operation'},              'Sign',            'operation is correct' );
+        is( $status[1]->{'Status'},                 'DONE',            'done' );
+        is( $status[1]->{'User'}->{'EmailAddress'}, 'rt at example.com',  'correct email' );
+    }
+    else {
+        is( scalar @status,                 1,                                          'one record: signing' );
+        is( $status[0]->{'Operation'},      'Sign',                                     'operation is correct' );
+        is( $status[0]->{'Status'},         'DONE',                                     'done' );
+        is( $status[0]->{'Message'},        'Signed message',                           'message is correct' );
+        is( $status[0]->{'KeyFingerprint'}, 'F23574193C1BA40ACB8DC6A4B5A462194345F7A5', 'signing key is correct' );
+    }
 
     ok( $entity->is_multipart, 'signed message is multipart' );
     is( $entity->parts, 2, 'two parts' );
@@ -56,8 +68,12 @@ diag 'only signing. correct passphrase';
     is( $status[0]->{'Trust'}, 'ULTIMATE', 'have trust value');
 }
 
+# To forget passphrase
+system( 'gpg-connect-agent', "--homedir", $homedir, 'reloadagent', '/bye' );
+
 diag 'only signing. missing passphrase';
-{
+SKIP: {
+    skip "gpg-agent caches passphrase", 6 unless $gnupg_version < 2;
     my $entity = MIME::Entity->build(
         From    => 'rt at example.com',
         Subject => 'test',
@@ -97,7 +113,7 @@ diag 'only signing. wrong passphrase';
             Encrypt    => 0,
             Passphrase => 'wrong',
         );
-    } qr/bad passphrase/;
+    } qr/bad passphrase/i;
 
     ok( $res{'exit_code'}, "couldn't sign with bad passphrase");
     ok( $res{'error'} || $res{'logger'}, "error is here" );
@@ -106,8 +122,8 @@ diag 'only signing. wrong passphrase';
         Protocol => $res{'Protocol'}, Status => $res{'status'}
     );
     is( scalar @status, 1, 'one record');
-    is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
-    is( $status[0]->{'Status'}, 'BAD', 'wrong passphrase');
+    like( $status[0]->{'Operation'}, qr/PassphraseCheck|Sign/, 'operation is correct');
+    like( $status[0]->{'Status'}, qr/BAD|ERROR/, 'wrong passphrase');
 }
 
 diag 'encryption only';
@@ -153,7 +169,7 @@ diag 'encryption only, bad recipient';
             Entity => $entity,
             Sign   => 0,
         );
-    } qr/public key not found/;
+    } qr/public key not found|error retrieving 'keyless\@example.com' via WKD: No data/;
 
     ok( $res{'exit_code'}, 'no way to encrypt without keys of recipients');
     ok( $res{'logger'}, "errors are in logger" );
@@ -161,8 +177,15 @@ diag 'encryption only, bad recipient';
     my @status = RT::Crypt->ParseStatus(
         Protocol => $res{'Protocol'}, Status => $res{'status'}
     );
-    is( scalar @status, 1, 'one record');
-    is( $status[0]->{'Keyword'}, 'INV_RECP', 'invalid recipient');
+    if ( $gnupg_version < 2 ) {
+        is( scalar @status,          1,          'one record' );
+        is( $status[0]->{'Keyword'}, 'INV_RECP', 'invalid recipient' );
+    }
+    else {
+        is( scalar @status,          2,          '2 records' );
+        is( $status[0]->{'Keyword'}, 'INV_RECP', 'invalid recipient' );
+        is( $status[1]->{'Keyword'}, 'FAILURE',  'failure' );
+    }
 }
 
 diag 'encryption and signing with combined method';
@@ -175,18 +198,27 @@ diag 'encryption and signing with combined method';
     );
     my %res = RT::Crypt->SignEncrypt( Entity => $entity, Passphrase => 'test' );
     ok( !$res{'exit_code'}, "successful encryption with signing" );
-    ok( !$res{'logger'}, "no records in logger" );
+    ok( !$res{'logger'}, "log is here as well" ) or diag $res{'logger'};
 
     my @status = RT::Crypt->ParseStatus(
         Protocol => $res{'Protocol'}, Status => $res{'status'}
     );
-    is( scalar @status, 3, 'three records: passphrase, sign and encrypt');
-    is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
-    is( $status[0]->{'Status'}, 'DONE', 'done');
-    is( $status[1]->{'Operation'}, 'Sign', 'operation is correct');
-    is( $status[1]->{'Status'}, 'DONE', 'done');
-    is( $status[2]->{'Operation'}, 'Encrypt', 'operation is correct');
-    is( $status[2]->{'Status'}, 'DONE', 'done');
+    if ($gnupg_version < 2) {
+        is( scalar @status, 3, 'three records: passphrase, sign and encrypt');
+        is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
+        is( $status[0]->{'Status'}, 'DONE', 'done');
+        is( $status[1]->{'Operation'}, 'Sign', 'operation is correct');
+        is( $status[1]->{'Status'}, 'DONE', 'done');
+        is( $status[2]->{'Operation'}, 'Encrypt', 'operation is correct');
+        is( $status[2]->{'Status'}, 'DONE', 'done');
+    }
+    else {
+        is( scalar @status, 2, 'two records: sign and encrypt');
+        is( $status[0]->{'Operation'}, 'Sign', 'operation is correct');
+        is( $status[0]->{'Status'}, 'DONE', 'done');
+        is( $status[1]->{'Operation'}, 'Encrypt', 'operation is correct');
+        is( $status[1]->{'Status'}, 'DONE', 'done');
+    }
 
     ok($entity, 'get an encrypted and signed part');
 
@@ -353,3 +385,4 @@ diag 'verify inline and in attachment signatures';
     $parser->filer->purge();
 }
 
+done_testing;

commit 549b99820767151c3f1dda1f9bc6750d7d3c8c99
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat May 16 04:46:45 2020 +0800

    Bump GnuPG::Interface to 1.00 to support gpg 2.2

diff --git a/etc/cpanfile b/etc/cpanfile
index 995dd9730e..a4f903c1e9 100644
--- a/etc/cpanfile
+++ b/etc/cpanfile
@@ -182,7 +182,7 @@ feature 'sqlite' => sub {
 # Optional features
 feature 'gpg' => sub {
     requires 'File::Which';
-    requires 'GnuPG::Interface';
+    requires 'GnuPG::Interface', '>= 1.00';
     requires 'PerlIO::eol';
 };
 

-----------------------------------------------------------------------


More information about the rt-commit mailing list