[Rt-commit] rt branch, 4.4/work-with-both-gnupgs, repushed

Brian Duggan brian at bestpractical.com
Thu May 3 12:34:18 EDT 2018


The branch 4.4/work-with-both-gnupgs was deleted and repushed:
       was 357e8e956da2f8bb6c1af2936a31dde69965a9ff
       now 350d0069b465ef8351d177102992e6888cb7e760

 2: 61f359f1c !  1: 288493ecf Add GnuPG 2.1+ specific test homedir and supporting test files
    @@ -1,80 +1,21 @@
     Author: Brian C. Duggan <brian at bestpractical.com>
     
    -    WIP Let more RT::Crypt::GnuPG tests pass
    +    Add GnuPG 2.1+ specific test homedir and supporting test files
         
    -    The important changes are in t/mail/crypt-gnupg.t. That test file
    -    demonstrates most of what needs to be done for other tests to let them
    -    pass. Most types of GnuPG tests pass under 2.1.
    +    GnuPG 2.1 requires some different settings in gpg.conf to function
    +    properly for tests. This change adds a new homedir with keyrings in
    +    2.1+ format and new config files.
         
    -    Previously, I thought one type of test will need some more changes in
    -    upstream libraries. The 'only signing, missing passphrase' tests hang
    -    when trying to pass an empty passphrase. Earlier, I thought this meant
    -    that the passphrase argument to RT::Crypt::GnuPG::SignEncrypt and
    -    sibling functions wasn't getting passed to the gpg binary. But now I see
    -    that it actually is - otherwise other tests in t/mail/crypt-gnupg.t
    -    would not pass. Also previously, I had been relying on a fake pinentry
    -    program that does not rely on printing the passphrase to the
    -    GnuPG::Interface passphrase filehandle. At some point, I changed that
    -    and never realized that passing by filehandle was actually working.
    +    GnuPG 2.1 emits some warnings when importing keys
    +    that were created by GnuPG 1.4 with preferred compression algorithms
    +    that are no longer supported. The warnings tell the user about those
    +    algorithms. These probably wouldn't cause any tests to fail. But this
    +    change adds new keys that were imported and then exported again by
    +    GnuPG 2.1. GnuPG 2.1 can import these keys without warnings.
         
    -    Now I see that the missing passphrase test is the only type of test
    -    that really might not work. That's probably not that big of a deal, but
    -    we should figure out how to bail if the passphrase is empty. Otherwise,
    -    RT could just hang if the user gives an empty passphrase.
    -
    -diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
    ---- a/lib/RT/Crypt/GnuPG.pm
    -+++ b/lib/RT/Crypt/GnuPG.pm
    -@@
    -         @_
    -     );
    - 
    -+
    -     my %handle = %{$args{Handles}};
    -     my ($handles, $handle_list) = _make_gpg_handles( %handle );
    -     $handles->options( $_ )->{'direct'} = 1
    -@@
    -     my $self = shift;
    - 
    -     my $format = lc RT->Config->Get('GnuPG')->{'OutgoingMessagesFormat'} || 'RFC';
    -+
    -     if ( $format eq 'inline' ) {
    -         return $self->SignEncryptInline( @_ );
    -     } else {
    -@@
    -         );
    -         $entity->parts(-1)->bodyhandle->{'_dirty_hack_to_save_a_ref_tmp_fh'} = $tmp_fh;
    -     }
    -+
    -     return %res;
    - }
    - 
    -@@
    - # keywords as starting point or just ignore as they are useless for us
    - my %ignore_keyword = map { $_ => 1 } qw(
    -     NEED_PASSPHRASE MISSING_PASSPHRASE BEGIN_SIGNING PLAINTEXT PLAINTEXT_LENGTH
    --    BEGIN_ENCRYPTION SIG_ID VALIDSIG
    -+    BEGIN_ENCRYPTION SIG_ID VALIDSIG NEWSIG
    -     ENC_TO BEGIN_DECRYPTION END_DECRYPTION GOODMDC
    -     TRUST_UNDEFINED TRUST_NEVER TRUST_MARGINAL TRUST_FULLY TRUST_ULTIMATE
    --    DECRYPTION_INFO
    -+    DECRYPTION_INFO KEY_CONSIDERED PINENTRY_LAUNCHED FAILURE
    - );
    - 
    - sub ParseStatus {
    -@@
    -                 Class          => $props[3],
    -                 Timestamp      => $props[4],
    -                 KeyFingerprint => $props[5],
    --                User           => $user_hint{ $latest_user_main_key },
    -+                User           => $latest_user_main_key ? $user_hint{ $latest_user_main_key } : undef,
    -             };
    -             $res[-1]->{Message} .= ' by '. $user_hint{ $latest_user_main_key }->{'EmailAddress'}
    --                if $user_hint{ $latest_user_main_key };
    -+                if $latest_user_main_key && $user_hint{ $latest_user_main_key };
    -         }
    -         elsif ( $keyword eq 'INV_RECP' ) {
    -             my ($rcode, $recipient) = split /\s+/, $args, 2;
    +    Some other files included in this commit are probably unnecessary with
    +    some test re-design. But they are a safe base for updating
    +    GnuPG-related tests to work with 2.1+.
     
     diff --git a/t/data/gnupg2/bin/fake-pinentry.pl b/t/data/gnupg2/bin/fake-pinentry.pl
     new file mode 100755
    @@ -2055,286 +1996,3 @@
     +=jFJl
     +-----END PGP PRIVATE KEY BLOCK-----
     
    -diff --git a/t/mail/crypt-gnupg.t b/t/mail/crypt-gnupg.t
    ---- a/t/mail/crypt-gnupg.t
    -+++ b/t/mail/crypt-gnupg.t
    -@@
    - use strict;
    - use warnings;
    - 
    -+my $gnupg;
    -+my @gnupg_versions;
    - my $homedir;
    - BEGIN {
    -     require RT::Test;
    --    $homedir =
    --      RT::Test::get_abs_relocatable_dir( File::Spec->updir(),
    --        qw/data gnupg keyrings/ );
    -+    require GnuPG::Interface;
    -+    
    -+    $gnupg = GnuPG::Interface->new;
    -+    @gnupg_versions = split /\./, $gnupg->version;
    -+
    -+    if ($gnupg_versions[0] < 2) {
    -+        $homedir =
    -+            RT::Test::get_abs_relocatable_dir( File::Spec->updir(),
    -+                                               qw/data gnupg keyrings/ );
    -+    } else {
    -+        $homedir =
    -+            RT::Test::get_abs_relocatable_dir( File::Spec->updir(),
    -+                                               qw/data gnupg2 keyrings/ );
    -+        $ENV{'GNUPGHOME'} = $homedir;
    -+        system('gpgconf', '--quiet', '--kill', 'gpg-agent');
    -+    }
    - }
    - 
    --use RT::Test::GnuPG tests => 100, gnupg_options => { homedir => $homedir };
    -+END {
    -+    if ($gnupg_versions[0] >= 2 && $gnupg_versions[1] >= 1) {
    -+        system('gpgconf', '--quiet', '--kill', 'gpg-agent');
    -+        delete $ENV{'GNUPGHOME'};
    -+    }
    -+}
    -+
    -+use RT::Test::GnuPG gnupg_options => { homedir => $homedir };
    - use Test::Warn;
    - 
    - use_ok('RT::Crypt');
    -@@
    -         Data    => ['test'],
    -     );
    -     my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
    -+
    -     ok( $entity, 'signed entity');
    -     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, 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_versions[0] < 2) {
    -+        is( scalar @status, 2, 'two records: passphrase, signing');
    -+    }
    -+    else {
    -+        is( scalar @status, 1, 'one record: signing');
    -+    }
    -+
    -+    if ($gnupg_versions[0] < 2) {
    -+        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( $status[0]->{'Operation'}, 'Sign', 'operation is correct');
    -+        is( $status[0]->{'Status'}, 'DONE', 'done');
    -+        is( $status[0]->{'KeyFingerprint'}, 'F23574193C1BA40ACB8DC6A4B5A462194345F7A5', 'signing key is correct');
    -+    }
    -+    
    -     ok( $entity->is_multipart, 'signed message is multipart' );
    -     is( $entity->parts, 2, 'two parts' );
    --
    -+    
    -     my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
    -     is( scalar @parts, 1, 'one protected part' );
    -     is( $parts[0]->{'Type'}, 'signed', "have signed part" );
    -     is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
    -     is( $parts[0]->{'Top'}, $entity, "it's the same entity" );
    --
    -+    
    -     my @res = RT::Crypt->VerifyDecrypt( Entity => $entity );
    -     is scalar @res, 1, 'one operation';
    -+
    -     @status = RT::Crypt->ParseStatus(
    -         Protocol => $res[0]{'Protocol'}, Status => $res[0]{'status'}
    --    );
    -+        );
    -+
    -     is( scalar @status, 1, 'one record');
    -     is( $status[0]->{'Operation'}, 'Verify', 'operation is correct');
    -     is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
    -     is( $status[0]->{'Trust'}, 'ULTIMATE', 'have trust value');
    - }
    - 
    --diag 'only signing. missing passphrase';
    --{
    --    my $entity = MIME::Entity->build(
    --        From    => 'rt at example.com',
    --        Subject => 'test',
    --        Data    => ['test'],
    --    );
    --    my %res;
    --    warning_like {
    --        %res = RT::Crypt->SignEncrypt(
    --            Entity     => $entity,
    --            Encrypt    => 0,
    --            Passphrase => ''
    --        );
    --    } qr/can't query passphrase in batch mode/;
    --    ok( $res{'exit_code'}, "couldn't sign without passphrase");
    --    ok( $res{'error'} || $res{'logger'}, "error is here" );
    --
    --    my @status = RT::Crypt->ParseStatus(
    --        Protocol => $res{'Protocol'}, Status => $res{'status'}
    --    );
    --    is( scalar @status, 1, 'one record');
    --    is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
    --    is( $status[0]->{'Status'}, 'MISSING', 'missing passphrase');
    --}
    --
    --diag 'only signing. wrong passphrase';
    --{
    --    my $entity = MIME::Entity->build(
    --        From    => 'rt at example.com',
    --        Subject => 'test',
    --        Data    => ['test'],
    --    );
    --
    --    my %res;
    --    warning_like {
    --        %res = RT::Crypt->SignEncrypt(
    --            Entity     => $entity,
    --            Encrypt    => 0,
    --            Passphrase => 'wrong',
    --        );
    --    } qr/bad passphrase/;
    --
    --    ok( $res{'exit_code'}, "couldn't sign with bad passphrase");
    --    ok( $res{'error'} || $res{'logger'}, "error is here" );
    --
    --    my @status = RT::Crypt->ParseStatus(
    --        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');
    --}
    -+#diag 'only signing. missing passphrase';
    -+#{
    -+#    if ($gnupg_versions[0] >= 2 && $gnupg_versions[1] >= 1) {
    -+#       system('gpgconf', '--quiet', '--kill', 'gpg-agent');
    -+#    }
    -+#    
    -+#    my $entity = MIME::Entity->build(
    -+#        From    => 'rt at example.com',
    -+#        Subject => 'test',
    -+#        Data    => ['test'],
    -+#    );
    -+#    my %res;
    -+#    warning_like {
    -+#        %res = RT::Crypt->SignEncrypt(
    -+#            Entity     => $entity,
    -+#            Encrypt    => 0,
    -+#            Passphrase => ''
    -+#        );
    -+#    } qr/can't query passphrase in batch mode/;
    -+#    ok( $res{'exit_code'}, "couldn't sign without passphrase");
    -+#    ok( $res{'error'} || $res{'logger'}, "error is here" );
    -+#
    -+#    my @status = RT::Crypt->ParseStatus(
    -+#        Protocol => $res{'Protocol'}, Status => $res{'status'}
    -+#    );
    -+#
    -+#    is( scalar @status, 1, 'one record');
    -+#    is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
    -+#    is( $status[0]->{'Status'}, 'MISSING', 'missing passphrase');
    -+#}
    -+#
    -+#diag 'only signing. wrong passphrase';
    -+#{
    -+#    if ($gnupg_versions[0] >= 2 && $gnupg_versions[1] >= 1) {
    -+#       system('gpgconf', '--quiet', '--kill', 'gpg-agent');
    -+#    }
    -+#    
    -+#    my $entity = MIME::Entity->build(
    -+#        From    => 'rt at example.com',
    -+#        Subject => 'test',
    -+#        Data    => ['test'],
    -+#    );
    -+#
    -+#    my %res;
    -+#    warning_like {
    -+#        %res = RT::Crypt->SignEncrypt(
    -+#            Entity     => $entity,
    -+#            Encrypt    => 0,
    -+#            Passphrase => 'wrong',
    -+#        );
    -+#    } qr/bad passphrase/;
    -+#
    -+#    ok( $res{'exit_code'}, "couldn't sign with bad passphrase");
    -+#    ok( $res{'error'} || $res{'logger'}, "error is here" );
    -+#
    -+#    my @status = RT::Crypt->ParseStatus(
    -+#        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');
    -+#}
    - 
    - diag 'encryption only';
    - {
    -@@
    -             Entity => $entity,
    -             Sign   => 0,
    -         );
    --    } qr/public key not found/;
    -+    } qr/(public key not found|No public key)/;
    - 
    -     ok( $res{'exit_code'}, 'no way to encrypt without keys of recipients');
    -     ok( $res{'logger'}, "errors are in logger" );
    -@@
    -     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');
    - }
    -@@
    -     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_versions[0] < 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');
    - 
    -@@
    -     my @status = RT::Crypt->ParseStatus(
    -         Protocol => $res[0]{'Protocol'}, Status => $res[0]{'status'}
    -     );
    -+
    -     is( scalar @status, 1, 'one record');
    -     is( $status[0]->{'Operation'}, 'Verify', 'operation is correct');
    -     is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
    -
 1: 294af5fb3 =  2: 5c5ac9a37 Test modern gpg signing failure warnings
--:  ------- >  3: 710a6118a Ignore GnuPG 2.1-specific statuses
--:  ------- >  4: 0e6fe3cf6 Allow empty user main key fields in GnuPG status messages
--:  ------- >  5: 88468e7e7 Use latest configs for GnuPG 2.1
--:  ------- >  6: 915d9df3a Handle new GnuPG 2.1 status messages
 3: ccb278027 =  7: 6ec7fe28a Parse GnuPG subkeys for 2.x
 4: 682a93d0e =  8: 4974d2d37 Ignore DECRYPTION_KEY GnuPG status message
 5: 2bc9f5abd =  9: b39240348 Use GnuPG 2.1 homedir for t/mail/gnupg-bad.t
 6: 4848a1061 = 10: 0bd6c1d00 Use GnuPG 2.1 homedir for t/mail/gnupg-incoming.t
 7: cae2234ee = 11: b6898bc6b Use GnuPG 2.1 homedir for t/mail/gnupg-outgoing-signed-plaintext.t
 8: 357e8e956 = 12: 350d0069b Allow GnuPG 2.1 warning, keybox instead of keyring



More information about the rt-commit mailing list