[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