[Rt-commit] rt branch, 4.4/per-queue-outgoing-encryption-protocol, created. rt-4.4.4-175-g216f0a6649

? sunnavy sunnavy at bestpractical.com
Thu Nov 19 09:30:49 EST 2020


The branch, 4.4/per-queue-outgoing-encryption-protocol has been created
        at  216f0a66497deb317b0c2bbd7b2970aa491479c0 (commit)

- Log -----------------------------------------------------------------
commit 5275ed4237146550cf721d4bb546b2ac7e6bda44
Author: Dianne Skoll <dianne at bestpractical.com>
Date:   Fri Nov 6 11:22:57 2020 -0500

    Merge RT::Test::GnuPG and RT::Test::SMIME into a single package RT::Test::Crypt
    
    Supply at least one of GnuPG => 1 or SMIME => 1 when you use
    RT::Test::Crypt to enable tests for that encryption protocol.

diff --git a/lib/RT/Test/GnuPG.pm b/lib/RT/Test/Crypt.pm
similarity index 75%
rename from lib/RT/Test/GnuPG.pm
rename to lib/RT/Test/Crypt.pm
index 7720a5c10e..19517a6225 100644
--- a/lib/RT/Test/GnuPG.pm
+++ b/lib/RT/Test/Crypt.pm
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2019 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2020 Best Practical Solutions, LLC
 #                                          <sales at bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
@@ -46,10 +46,11 @@
 #
 # END BPS TAGGED BLOCK }}}
 
-package RT::Test::GnuPG;
+package RT::Test::Crypt;
 use strict;
 use warnings;
 use Test::More;
+use RT::Crypt;
 use base qw(RT::Test);
 use File::Temp qw(tempdir);
 use IPC::Run3 'run3';
@@ -62,18 +63,26 @@ our @EXPORT =
           create_and_test_outgoing_emails
           );
 
+our $UsingGnuPG = 0;
 sub import {
     my $class = shift;
     my %args  = @_;
     my $t     = $class->builder;
 
-    RT::Test::plan( skip_all => 'ENV SKIP_GPG_TESTS is set to true.' )
-      if $ENV{'SKIP_GPG_TESTS'};
-    RT::Test::plan( skip_all => 'GnuPG required.' )
-      unless GnuPG::Interface->require;
-    RT::Test::plan( skip_all => 'gpg executable is required.' )
-      unless RT::Test->find_executable('gpg');
+    if ($args{GnuPG}) {
+        $UsingGnuPG = 1;
+        RT::Test::plan( skip_all => 'ENV SKIP_GPG_TESTS is set to true.' )
+            if $ENV{'SKIP_GPG_TESTS'};
+        RT::Test::plan( skip_all => 'GnuPG required.' )
+            unless GnuPG::Interface->require;
+        RT::Test::plan( skip_all => 'gpg executable is required.' )
+            unless RT::Test->find_executable('gpg');
+    }
 
+    if ($args{SMIME}) {
+        RT::Test::plan( skip_all => 'openssl executable is required.' )
+            unless RT::Test->find_executable('openssl');
+    }
     $class->SUPER::import(%args);
     return $class->export_to_level(1)
         if $^C;
@@ -95,34 +104,114 @@ sub bootstrap_more_config {
 
     $self->SUPER::bootstrap_more_config($handle, $args, @_);
 
-    my %gnupg_options = (
-        'no-permission-warning' => undef,
-        $args->{gnupg_options} ? %{ $args->{gnupg_options} } : (),
-    );
-    $gnupg_options{homedir} ||= new_homedir();
+    if ($args->{GnuPG}) {
+        my %gnupg_options = (
+            'no-permission-warning' => undef,
+            $args->{gnupg_options} ? %{ $args->{gnupg_options} } : (),
+            );
+        $gnupg_options{homedir} ||= new_homedir();
 
-    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;
-    }
+        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);
+        use Data::Dumper;
+        local $Data::Dumper::Terse = 1; # "{...}" instead of "$VAR1 = {...};"
+        my $dumped_gnupg_options = Dumper(\%gnupg_options);
 
-    print $handle qq{
-Set(\%GnuPG, (
+        print $handle qq{
+        Set(\%GnuPG, (
     Enable                 => 1,
     OutgoingMessagesFormat => 'RFC',
-));
-Set(\%GnuPGOptions => \%{ $dumped_gnupg_options });
-};
+            ));
+        Set(\%GnuPGOptions => \%{ $dumped_gnupg_options });
+        };
+    }
 
+    if ($args->{SMIME}) {
+        my $openssl = $self->find_executable('openssl');
+
+        my $keyring = $self->smime_keyring_path;
+        mkdir($keyring);
+
+        my $ca = $self->smime_key_path("demoCA", "cacert.pem");
+
+        if (!$args->{GnuPG}) {
+            print $handle qq{ Set(\%GnuPG, Enable => 0); };
+        }
+        print $handle qq{
+        Set(\%SMIME =>
+            Enable => 1,
+            Passphrase => {
+        'root\@example.com' => '123456',
+            'sender\@example.com' => '123456',
+        },
+            OpenSSL => q{$openssl},
+            Keyring => q{$keyring},
+            CAPath  => q{$ca},
+            );
+        };
+
+    }
+}
+
+sub smime_keyring_path {
+    return File::Spec->catfile( RT::Test->temp_directory, "smime" );
+}
+
+sub smime_key_path {
+    my $self = shift;
+    my $keys = RT::Test::find_relocatable_path(
+        qw(data smime keys),
+    );
+    return File::Spec->catfile( $keys => @_ ),
+}
+
+sub smime_mail_set_path {
+    my $self = shift;
+    return RT::Test::find_relocatable_path(
+        qw(data smime mails),
+    );
+}
+
+sub smime_import_key {
+    my $self = shift;
+    my $key  = shift;
+    my $user = shift;
+
+    my $path = RT::Test::find_relocatable_path( 'data', 'smime', 'keys' );
+    die "can't find the dir where smime keys are stored"
+        unless $path;
+
+    my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
+    die "SMIME keyring '$keyring' doesn't exist"
+        unless $keyring && -e $keyring;
+
+    $key .= ".pem" unless $key =~ /\.(pem|crt|key)$/;
+
+    my $content = RT::Test->file_content( [ $path, $key ] );
+
+    if ( $user ) {
+        my ($status, $msg) = $user->SetSMIMECertificate( $content );
+        die "Couldn't set CF: $msg" unless $status;
+    } else {
+        my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
+        die "SMIME keyring '$keyring' doesn't exist"
+            unless $keyring && -e $keyring;
+
+        open my $fh, '>:raw', File::Spec->catfile($keyring, $key)
+            or die "can't open file: $!";
+        print $fh $content;
+        close $fh;
+    }
+
+    return;
 }
 
 sub create_a_ticket {
@@ -405,9 +494,11 @@ sub new_homedir {
 }
 
 END {
-    if ( gnupg_version() >= 2 ) {
-        system( 'gpgconf', '--homedir', RT->Config->Get('GnuPGOptions')->{homedir}, '--quiet', '--kill', 'gpg-agent' )
-            && warn $!;
+    if ($UsingGnuPG) {
+        if ( gnupg_version() >= 2 ) {
+            system( 'gpgconf', '--homedir', RT->Config->Get('GnuPGOptions')->{homedir}, '--quiet', '--kill', 'gpg-agent' )
+                && warn $!;
+        }
     }
 }
 
diff --git a/lib/RT/Test/SMIME.pm b/lib/RT/Test/SMIME.pm
deleted file mode 100644
index 25b3a43a2f..0000000000
--- a/lib/RT/Test/SMIME.pm
+++ /dev/null
@@ -1,163 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2019 Best Practical Solutions, LLC
-#                                          <sales at bestpractical.com>
-#
-# (Except where explicitly superseded by other copyright notices)
-#
-#
-# LICENSE:
-#
-# This work is made available to you under the terms of Version 2 of
-# the GNU General Public License. A copy of that license should have
-# been provided with this software, but in any event can be snarfed
-# from www.gnu.org.
-#
-# This work is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301 or visit their web page on the internet at
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-#
-#
-# CONTRIBUTION SUBMISSION POLICY:
-#
-# (The following paragraph is not intended to limit the rights granted
-# to you to modify and distribute this software under the terms of
-# the GNU General Public License and is only of importance to you if
-# you choose to contribute your changes and enhancements to the
-# community by submitting them to Best Practical Solutions, LLC.)
-#
-# By intentionally submitting any modifications, corrections or
-# derivatives to this work, or any other work intended for use with
-# Request Tracker, to Best Practical Solutions, LLC, you confirm that
-# you are the copyright holder for those contributions and you grant
-# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
-# royalty-free, perpetual, license to use, copy, create derivative
-# works based on those contributions, and sublicense and distribute
-# those contributions and any derivatives thereof.
-#
-# END BPS TAGGED BLOCK }}}
-
-use strict;
-use warnings;
-use 5.010;
-
-package RT::Test::SMIME;
-
-use Test::More;
-use base qw(RT::Test);
-use File::Temp qw(tempdir);
-
-sub import {
-    my $class = shift;
-    my %args  = @_;
-    my $t     = $class->builder;
-
-    RT::Test::plan( skip_all => 'openssl executable is required.' )
-        unless RT::Test->find_executable('openssl');
-
-    require RT::Crypt;
-    $class->SUPER::import(%args);
-
-    $class->set_rights(
-        Principal => 'Everyone',
-        Right => ['CreateTicket', 'ShowTicket', 'SeeQueue', 'ReplyToTicket', 'ModifyTicket'],
-    );
-
-    $class->export_to_level(1);
-}
-
-sub bootstrap_more_config {
-    my $self = shift;
-    my $handle = shift;
-    my $args = shift;
-
-    $self->SUPER::bootstrap_more_config($handle, $args, @_);
-
-    my $openssl = $self->find_executable('openssl');
-
-    my $keyring = $self->keyring_path;
-    mkdir($keyring);
-
-    my $ca = $self->key_path("demoCA", "cacert.pem");
-
-    print $handle qq{
-        Set(\%GnuPG, Enable => 0);
-        Set(\%SMIME =>
-            Enable => 1,
-            Passphrase => {
-                'root\@example.com' => '123456',
-                'sender\@example.com' => '123456',
-            },
-            OpenSSL => q{$openssl},
-            Keyring => q{$keyring},
-            CAPath  => q{$ca},
-        );
-    };
-
-}
-
-sub keyring_path {
-    return File::Spec->catfile( RT::Test->temp_directory, "smime" );
-}
-
-sub key_path {
-    my $self = shift;
-    my $keys = RT::Test::get_abs_relocatable_dir(
-        (File::Spec->updir()) x 2,
-        qw(data smime keys),
-    );
-    return File::Spec->catfile( $keys => @_ ),
-}
-
-sub mail_set_path {
-    my $self = shift;
-    return RT::Test::get_abs_relocatable_dir(
-        (File::Spec->updir()) x 2,
-        qw(data smime mails),
-    );
-}
-
-sub import_key {
-    my $self = shift;
-    my $key  = shift;
-    my $user = shift;
-
-    my $path = RT::Test::find_relocatable_path( 'data', 'smime', 'keys' );
-    die "can't find the dir where smime keys are stored"
-        unless $path;
-
-    my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
-    die "SMIME keyring '$keyring' doesn't exist"
-        unless $keyring && -e $keyring;
-
-    $key .= ".pem" unless $key =~ /\.(pem|crt|key)$/;
-
-    my $content = RT::Test->file_content( [ $path, $key ] );
-
-    if ( $user ) {
-        my ($status, $msg) = $user->SetSMIMECertificate( $content );
-        die "Couldn't set CF: $msg" unless $status;
-    } else {
-        my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
-        die "SMIME keyring '$keyring' doesn't exist"
-            unless $keyring && -e $keyring;
-
-        open my $fh, '>:raw', File::Spec->catfile($keyring, $key)
-            or die "can't open file: $!";
-        print $fh $content;
-        close $fh;
-    }
-
-    return;
-}
-
-1;
diff --git a/t/crypt/gnupg/attachments-in-db.t b/t/crypt/gnupg/attachments-in-db.t
index 1a377c341a..90caa32fbb 100644
--- a/t/crypt/gnupg/attachments-in-db.t
+++ b/t/crypt/gnupg/attachments-in-db.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+    GnuPG         => 1,
     tests         => 12,
     gnupg_options => {
         passphrase    => 'recipient',
diff --git a/t/crypt/no-signer-address.t b/t/crypt/no-signer-address.t
index 4c459c06a8..489b5e280f 100644
--- a/t/crypt/no-signer-address.t
+++ b/t/crypt/no-signer-address.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/crypt/smime/attachments-in-db.t b/t/crypt/smime/attachments-in-db.t
index 5230938ccd..94ecf868f1 100644
--- a/t/crypt/smime/attachments-in-db.t
+++ b/t/crypt/smime/attachments-in-db.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
+use RT::Test::Crypt SMIME => 1, tests => undef;
 
 use IPC::Run3 'run3';
 use String::ShellQuote 'shell_quote';
@@ -9,7 +9,7 @@ use RT::Tickets;
 
 RT->Config->Get('Crypt')->{'AllowEncryptDataInDB'} = 1;
 
-RT::Test::SMIME->import_key('sender at example.com');
+RT::Test::Crypt->smime_import_key('sender at example.com');
 my $queue = RT::Test->load_or_create_queue(
     Name              => 'General',
     CorrespondAddress => 'sender at example.com',
diff --git a/t/crypt/smime/bad-recipients.t b/t/crypt/smime/bad-recipients.t
index 1dc097adec..ca2461c33a 100644
--- a/t/crypt/smime/bad-recipients.t
+++ b/t/crypt/smime/bad-recipients.t
@@ -1,11 +1,11 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
+use RT::Test::Crypt SMIME => 1, tests => undef;
 
 use RT::Tickets;
 
-RT::Test::SMIME->import_key('sender at example.com');
+RT::Test::Crypt->smime_import_key('sender at example.com');
 my $queue = RT::Test->load_or_create_queue(
     Name              => 'General',
     CorrespondAddress => 'sender at example.com',
@@ -25,7 +25,7 @@ my $root;
     ok($root->Load('root'), "Loaded user 'root'");
     is($root->EmailAddress, 'root at localhost');
 
-    RT::Test::SMIME->import_key( 'root at example.com.crt' => $root );
+    RT::Test::Crypt->smime_import_key( 'root at example.com.crt' => $root );
 }
 
 my $bad_user;
diff --git a/t/crypt/smime/extract-email-address.t b/t/crypt/smime/extract-email-address.t
index ab709c58c7..20e58c0e15 100644
--- a/t/crypt/smime/extract-email-address.t
+++ b/t/crypt/smime/extract-email-address.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
+use RT::Test::Crypt SMIME => 1, tests => undef;
 
 sub extract_email_address
 {
diff --git a/t/crypt/smime/other-certs.t b/t/crypt/smime/other-certs.t
index ee067192d1..818c5e6f93 100644
--- a/t/crypt/smime/other-certs.t
+++ b/t/crypt/smime/other-certs.t
@@ -1,10 +1,10 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
+use RT::Test::Crypt SMIME => 1, tests => undef;
 use IPC::Run3 'run3';
 
-RT::Test::SMIME->import_key( 'sender at example.com' );
+RT::Test::Crypt->smime_import_key( 'sender at example.com' );
 
 diag "No OtherCertificatesToSend";
 
@@ -26,7 +26,7 @@ ok( $cert, 'got cert' );
 ok( !$err, 'no errors' );
 
 chomp $cert;
-open my $fh, '<', RT::Test::SMIME->key_path( 'sender at example.com.crt' ) or die $!;
+open my $fh, '<', RT::Test::Crypt->smime_key_path( 'sender at example.com.crt' ) or die $!;
 my $sender_cert = do { local $/; <$fh> };
 
 # Variations in how different versions of OpenSSL print certificates
@@ -39,7 +39,7 @@ is( $cert, $sender_cert, 'cert is the same one' );
 
 diag "Has OtherCertificatesToSend";
 
-RT->Config->Get( 'SMIME' )->{OtherCertificatesToSend} = RT::Test::SMIME->key_path( 'demoCA', 'cacert.pem' );
+RT->Config->Get( 'SMIME' )->{OtherCertificatesToSend} = RT::Test::Crypt->smime_key_path( 'demoCA', 'cacert.pem' );
 
 $mime = MIME::Entity->build(
     From => 'sender at example.com',
@@ -61,7 +61,7 @@ chomp $cert;
 my @certs = split /\n(?=Certificate:)/, $cert;
 is( scalar @certs, 2, 'found 2 certs' );
 
-open $fh, '<', RT::Test::SMIME->key_path( 'demoCA', 'cacert.pem' ) or die $!;
+open $fh, '<', RT::Test::Crypt->smime_key_path( 'demoCA', 'cacert.pem' ) or die $!;
 my $ca_cert = do { local $/; <$fh> };
 
 # Variations in how different versions of OpenSSL print certificates
diff --git a/t/mail/crypt-gnupg.t b/t/mail/crypt-gnupg.t
index 70c7447831..36d2ff1b44 100644
--- a/t/mail/crypt-gnupg.t
+++ b/t/mail/crypt-gnupg.t
@@ -4,15 +4,15 @@ use warnings;
 
 my $homedir;
 BEGIN {
-    require RT::Test::GnuPG;
-    $homedir = RT::Test::GnuPG::new_homedir(
+    require RT::Test::Crypt;
+    $homedir = RT::Test::Crypt::new_homedir(
         RT::Test::get_abs_relocatable_dir( File::Spec->updir(), qw/data gnupg keyrings/ ) );
 }
 
-use RT::Test::GnuPG tests => undef, gnupg_options => { homedir => $homedir, quiet => 1 };
+use RT::Test::Crypt GnuPG => 1, tests => undef, gnupg_options => { homedir => $homedir, quiet => 1 };
 use Test::Warn;
 
-my $gnupg_version = RT::Test::GnuPG::gnupg_version;
+my $gnupg_version = RT::Test::Crypt::gnupg_version;
 
 use_ok('RT::Crypt');
 use_ok('MIME::Entity');
@@ -24,7 +24,7 @@ diag 'only signing. correct passphrase';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test', Protocol => 'GnuPG' );
     ok( $entity, 'signed entity');
     ok( !$res{'logger'}, "log is here as well" ) or diag $res{'logger'};
     my @status = RT::Crypt->ParseStatus(
@@ -81,6 +81,7 @@ SKIP: {
     my %res;
     warning_like {
         %res = RT::Crypt->SignEncrypt(
+            Protocol   => 'GnuPG',
             Entity     => $entity,
             Encrypt    => 0,
             Passphrase => ''
@@ -108,6 +109,7 @@ diag 'only signing. wrong passphrase';
     my %res;
     warning_like {
         %res = RT::Crypt->SignEncrypt(
+            Protocol   => 'GnuPG',
             Entity     => $entity,
             Encrypt    => 0,
             Passphrase => 'wrong',
@@ -133,7 +135,7 @@ diag 'encryption only';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0, Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, "successful encryption" );
     ok( !$res{'logger'}, "no records in logger" );
 
@@ -165,6 +167,7 @@ diag 'encryption only, bad recipient';
     my %res;
     warning_like {
         %res = RT::Crypt->SignEncrypt(
+            Protocol   => 'GnuPG',
             Entity => $entity,
             Sign   => 0,
         );
@@ -195,7 +198,7 @@ diag 'encryption and signing with combined method';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Passphrase => 'test' );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Passphrase => 'test', Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, "successful encryption with signing" );
     ok( !$res{'logger'}, "log is here as well" ) or diag $res{'logger'};
 
@@ -236,10 +239,10 @@ diag 'encryption and signing with cascading, sign on encrypted';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0, Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, 'successful encryption' );
     ok( !$res{'logger'}, "no records in logger" );
-    %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+    %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test', Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, 'successful signing' );
     ok( !$res{'logger'}, "no records in logger" );
 
@@ -258,7 +261,7 @@ diag 'find signed/encrypted part deep inside';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0, Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, "success" );
     $entity->make_multipart( 'mixed', Force => 1 );
     $entity->attach(
@@ -283,6 +286,7 @@ diag 'wrong signed/encrypted parts: no protocol';
     );
 
     my %res = RT::Crypt->SignEncrypt(
+        Protocol   => 'GnuPG',
         Entity => $entity,
         Sign   => 0,
     );
@@ -309,6 +313,7 @@ diag 'wrong signed/encrypted parts: not enought parts';
     );
 
     my %res = RT::Crypt->SignEncrypt(
+        Protocol   => 'GnuPG',
         Entity => $entity,
         Sign   => 0,
     );
@@ -331,7 +336,7 @@ diag 'wrong signed/encrypted parts: wrong proto';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0, Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, 'success' );
     $entity->head->mime_attr( 'Content-Type.protocol' => 'application/bad-proto' );
 
@@ -347,7 +352,7 @@ diag 'wrong signed/encrypted parts: wrong proto';
         Subject => 'test',
         Data    => ['test'],
     );
-    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+    my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test', Protocol => 'GnuPG' );
     ok( !$res{'exit_code'}, 'success' );
     $entity->head->mime_attr( 'Content-Type.protocol' => 'application/bad-proto' );
 
diff --git a/t/mail/gnupg-bad.t b/t/mail/gnupg-bad.t
index 3ecbdb9bf0..ea90e3a4cd 100644
--- a/t/mail/gnupg-bad.t
+++ b/t/mail/gnupg-bad.t
@@ -1,11 +1,12 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => 7,
   gnupg_options => {
     passphrase => 'rt-test',
-    homedir => RT::Test::GnuPG::new_homedir(RT::Test::get_abs_relocatable_dir(
+    homedir => RT::Test::Crypt::new_homedir(RT::Test::get_abs_relocatable_dir(
         File::Spec->updir(), qw/data gnupg keyrings/
     )),
   };
diff --git a/t/mail/gnupg-incoming.t b/t/mail/gnupg-incoming.t
index 7b373e54bd..2a583adb99 100644
--- a/t/mail/gnupg-incoming.t
+++ b/t/mail/gnupg-incoming.t
@@ -3,12 +3,13 @@ use warnings;
 
 my $homedir;
 BEGIN {
-    require RT::Test::GnuPG;
-    $homedir = RT::Test::GnuPG::new_homedir(
+    require RT::Test::Crypt;
+    $homedir = RT::Test::Crypt::new_homedir(
         RT::Test::get_abs_relocatable_dir( File::Spec->updir(), qw/data gnupg keyrings/ ) ),
 }
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => 53,
   actual_server => 1,
   gnupg_options => {
diff --git a/t/mail/gnupg-outgoing-encrypted-plaintext.t b/t/mail/gnupg-outgoing-encrypted-plaintext.t
index 9507ff4767..1325ded56a 100644
--- a/t/mail/gnupg-outgoing-encrypted-plaintext.t
+++ b/t/mail/gnupg-outgoing-encrypted-plaintext.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG          => 1,
   tests          => undef,
   text_templates => 1,
   gnupg_options  => {
diff --git a/t/mail/gnupg-outgoing-encrypted.t b/t/mail/gnupg-outgoing-encrypted.t
index 802830fcd5..eab4ab8601 100644
--- a/t/mail/gnupg-outgoing-encrypted.t
+++ b/t/mail/gnupg-outgoing-encrypted.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/mail/gnupg-outgoing-plain-plaintext.t b/t/mail/gnupg-outgoing-plain-plaintext.t
index a9a68cee9d..8cad32acd0 100644
--- a/t/mail/gnupg-outgoing-plain-plaintext.t
+++ b/t/mail/gnupg-outgoing-plain-plaintext.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG          => 1,
   tests          => undef,
   text_templates => 1,
   gnupg_options  => {
diff --git a/t/mail/gnupg-outgoing-plain.t b/t/mail/gnupg-outgoing-plain.t
index d1cd301a71..d092e934b7 100644
--- a/t/mail/gnupg-outgoing-plain.t
+++ b/t/mail/gnupg-outgoing-plain.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/mail/gnupg-outgoing-signed-plaintext.t b/t/mail/gnupg-outgoing-signed-plaintext.t
index e51676243d..a9840117c8 100644
--- a/t/mail/gnupg-outgoing-signed-plaintext.t
+++ b/t/mail/gnupg-outgoing-signed-plaintext.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG          => 1,
   tests          => undef,
   text_templates => 1,
   gnupg_options  => {
diff --git a/t/mail/gnupg-outgoing-signed.t b/t/mail/gnupg-outgoing-signed.t
index b7119a176f..153f4a64cd 100644
--- a/t/mail/gnupg-outgoing-signed.t
+++ b/t/mail/gnupg-outgoing-signed.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t b/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t
index 946fa76a80..fc4173d9c1 100644
--- a/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t
+++ b/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG          => 1,
   tests          => undef,
   text_templates => 1,
   gnupg_options  => {
diff --git a/t/mail/gnupg-outgoing-signed_encrypted.t b/t/mail/gnupg-outgoing-signed_encrypted.t
index 61cf6b20f0..399f20f67c 100644
--- a/t/mail/gnupg-outgoing-signed_encrypted.t
+++ b/t/mail/gnupg-outgoing-signed_encrypted.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/mail/gnupg-realmail.t b/t/mail/gnupg-realmail.t
index 1609cffbba..eab0425187 100644
--- a/t/mail/gnupg-realmail.t
+++ b/t/mail/gnupg-realmail.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => 198, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => 198, gnupg_options => { passphrase => 'rt-test' };
 
 use Digest::MD5 qw(md5_hex);
 
diff --git a/t/mail/gnupg-reverification.t b/t/mail/gnupg-reverification.t
index 1ec9aa19e8..ec3b5a01fb 100644
--- a/t/mail/gnupg-reverification.t
+++ b/t/mail/gnupg-reverification.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => undef, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => undef, gnupg_options => { passphrase => 'rt-test' };
 
 diag "load Everyone group";
 my $everyone;
diff --git a/t/mail/gnupg-special.t b/t/mail/gnupg-special.t
index 15aad3489c..c95e5bfda5 100644
--- a/t/mail/gnupg-special.t
+++ b/t/mail/gnupg-special.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => 25, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => 25, gnupg_options => { passphrase => 'rt-test' };
 
 use Digest::MD5 qw(md5_hex);
 
diff --git a/t/mail/smime/incoming.t b/t/mail/smime/incoming.t
index 07897ee53d..4442c5744d 100644
--- a/t/mail/smime/incoming.t
+++ b/t/mail/smime/incoming.t
@@ -1,8 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef, actual_server => 1;
-my $test = 'RT::Test::SMIME';
+use RT::Test::Crypt SMIME => 1, tests => undef, actual_server => 1;
+my $test = 'RT::Test::Crypt';
 
 use IPC::Run3 'run3';
 use String::ShellQuote 'shell_quote';
@@ -13,7 +13,7 @@ my ($url, $m) = RT::Test->started_ok;
 ok $m->login, "logged in";
 
 # configure key for General queue
-RT::Test::SMIME->import_key('sender at example.com');
+$test->smime_import_key('sender at example.com');
 my $queue = RT::Test->load_or_create_queue(
     Name              => 'General',
     CorrespondAddress => 'sender at example.com',
@@ -25,7 +25,7 @@ my $user = RT::Test->load_or_create_user(
     Name => 'root at example.com',
     EmailAddress => 'root at example.com',
 );
-RT::Test::SMIME->import_key('root at example.com.crt', $user);
+$test->smime_import_key('root at example.com.crt', $user);
 RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
 
 my $mail = RT::Test->open_mailgate_ok($url);
@@ -63,7 +63,7 @@ RT::Test->close_mailgate_ok($mail);
             -from    => 'root at example.com',
             -to      => 'sender at example.com',
             -subject => "Encrypted message for queue",
-            $test->key_path('sender at example.com.crt'),
+            $test->smime_key_path('sender at example.com.crt'),
         ),
         \"Subject: test\n\norzzzzzz",
         \$buf,
@@ -103,8 +103,8 @@ RT::Test->close_mailgate_ok($mail);
             shell_quote(
                 RT->Config->Get('SMIME')->{'OpenSSL'},
                 qw( smime -sign -nodetach -passin pass:123456),
-                -signer => $test->key_path('root at example.com.crt'),
-                -inkey  => $test->key_path('root at example.com.key'),
+                -signer => $test->smime_key_path('root at example.com.crt'),
+                -inkey  => $test->smime_key_path('root at example.com.key'),
             ),
             '|',
             shell_quote(
@@ -112,7 +112,7 @@ RT::Test->close_mailgate_ok($mail);
                 -from    => 'root at example.com',
                 -to      => 'sender at example.com',
                 -subject => "Encrypted and signed message for queue",
-                $test->key_path('sender at example.com.crt'),
+                $test->smime_key_path('sender at example.com.crt'),
             )),
             \"Subject: test\n\norzzzzzz",
             \$buf,
@@ -144,8 +144,8 @@ RT::Test->close_mailgate_ok($mail);
         shell_quote(
             RT->Config->Get('SMIME')->{'OpenSSL'},
             qw( smime -sign -passin pass:123456),
-            -signer => $test->key_path('root at example.com.crt'),
-            -inkey  => $test->key_path('root at example.com.key'),
+            -signer => $test->smime_key_path('root at example.com.crt'),
+            -inkey  => $test->smime_key_path('root at example.com.key'),
         ),
         \"Content-type: text/plain\n\nThis is the body",
         \$buf,
diff --git a/t/mail/smime/other-signed.t b/t/mail/smime/other-signed.t
index 4e97e711f5..f4fc3d59d1 100644
--- a/t/mail/smime/other-signed.t
+++ b/t/mail/smime/other-signed.t
@@ -1,8 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
-my $test = 'RT::Test::SMIME';
+use RT::Test::Crypt SMIME=>1, tests => undef;
+my $test = 'RT::Test::Crypt';
 
 use IPC::Run3 'run3';
 use String::ShellQuote 'shell_quote';
@@ -10,7 +10,7 @@ use RT::Tickets;
 use Test::Warn;
 
 # configure key for General queue
-RT::Test::SMIME->import_key('sender at example.com');
+$test->smime_import_key('sender at example.com');
 my $queue = RT::Test->load_or_create_queue(
     Name              => 'General',
     CorrespondAddress => 'sender at example.com',
@@ -22,7 +22,7 @@ my $user = RT::Test->load_or_create_user(
     Name => 'root at example.com',
     EmailAddress => 'root at example.com',
 );
-RT::Test::SMIME->import_key('root at example.com.crt', $user);
+$test->smime_import_key('root at example.com.crt', $user);
 RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
 
 my $buf = '';
@@ -31,8 +31,8 @@ run3(
     shell_quote(
         RT->Config->Get('SMIME')->{'OpenSSL'},
         qw( smime -sign -passin pass:123456),
-        -signer => $test->key_path('root at example.com.crt'),
-        -inkey  => $test->key_path('root at example.com.key'),
+        -signer => $test->smime_key_path('root at example.com.crt'),
+        -inkey  => $test->smime_key_path('root at example.com.key'),
     ),
     \"Content-type: text/plain\n\nThis is the body",
     \$buf,
@@ -83,7 +83,7 @@ warning_like {
 
 # Test with the correct CA path; marked as signed, trusted
 {
-    my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/demoCA/cacert.pem" );
+    my ($msg, $status) = $send_mail->( CAPath => $test->smime_key_path . "/demoCA/cacert.pem" );
     is( $msg->GetHeader('X-RT-Incoming-Signature'),
         '"Enoch Root" <root at example.com>', "Message is signed" );
 
@@ -94,7 +94,7 @@ warning_like {
 
 # Test with the other CA
 warning_like {
-    my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/otherCA/cacert.pem" );
+    my ($msg, $status) = $send_mail->( CAPath => $test->smime_key_path . "/otherCA/cacert.pem" );
     is( $msg->GetHeader('X-RT-Incoming-Signature'),
         undef,
         "Message was not marked as signed"
@@ -108,7 +108,7 @@ warning_like {
 
 # Other CA, but allow all CAs
 {
-    my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/otherCA/cacert.pem", AcceptUntrustedCAs => 1 );
+    my ($msg, $status) = $send_mail->( CAPath => $test->smime_key_path . "/otherCA/cacert.pem", AcceptUntrustedCAs => 1 );
     is( $msg->GetHeader('X-RT-Incoming-Signature'),
         '"Enoch Root" <root at example.com>',
         "Message was marked as signed"
diff --git a/t/mail/smime/outgoing.t b/t/mail/smime/outgoing.t
index a90c4cb2bc..7e611756be 100644
--- a/t/mail/smime/outgoing.t
+++ b/t/mail/smime/outgoing.t
@@ -1,8 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
-my $test = 'RT::Test::SMIME';
+use RT::Test::Crypt SMIME => 1, tests => undef;
+my $test = 'RT::Test::Crypt';
 
 use IPC::Run3 'run3';
 use RT::Interface::Email;
@@ -30,7 +30,7 @@ my $user;
     ok($user->Load('root'), "Loaded user 'root'");
     is($user->EmailAddress, 'root at localhost');
 
-    RT::Test::SMIME->import_key( 'root at example.com.crt' => $user );
+    $test->smime_import_key( 'root at example.com.crt' => $user );
 }
 
 RT::Test->clean_caught_mails;
@@ -65,8 +65,8 @@ END
     ok(eval {
         run3([
             qw(openssl smime -decrypt -passin pass:123456),
-            '-inkey', $test->key_path('root at example.com.key'),
-            '-recip', $test->key_path('root at example.com.crt')
+            '-inkey', $test->smime_key_path('root at example.com.key'),
+            '-recip', $test->smime_key_path('root at example.com.crt')
         ], \$mails[0], \$buf, \$err )
         }, 'can decrypt'
     );
diff --git a/t/mail/smime/realmail.t b/t/mail/smime/realmail.t
index 13c9a51521..6676de5f2e 100644
--- a/t/mail/smime/realmail.t
+++ b/t/mail/smime/realmail.t
@@ -1,16 +1,16 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
+use RT::Test::Crypt SMIME => 1, tests => undef;
 use Digest::MD5 qw(md5_hex);
 
-my $test = 'RT::Test::SMIME';
-my $mails = $test->mail_set_path;
+my $test = 'RT::Test::Crypt';
+my $mails = $test->smime_mail_set_path;
 
 RT->Config->Get('SMIME')->{AcceptUntrustedCAs} = 1;
 
-RT::Test::SMIME->import_key('root at example.com');
-RT::Test::SMIME->import_key('sender at example.com');
+$test->smime_import_key('root at example.com');
+$test->smime_import_key('sender at example.com');
 
 my ($baseurl, $m) = RT::Test->started_ok;
 ok $m->login, 'we did log in';
diff --git a/t/mail/smime/reject_on_unencrypted.t b/t/mail/smime/reject_on_unencrypted.t
index 3d35e4f94e..0e853acb64 100644
--- a/t/mail/smime/reject_on_unencrypted.t
+++ b/t/mail/smime/reject_on_unencrypted.t
@@ -1,8 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef, actual_server => 1, config => 'Set( @MailPlugins, "Authz::RequireEncrypted" );';
-my $test = 'RT::Test::SMIME';
+use RT::Test::Crypt SMIME=>1, tests => undef, actual_server => 1, config => 'Set( @MailPlugins, "Authz::RequireEncrypted" );';
+my $test = 'RT::Test::Crypt';
 
 use IPC::Run3 'run3';
 use String::ShellQuote 'shell_quote';
@@ -12,7 +12,7 @@ my ($url, $m) = RT::Test->started_ok;
 ok $m->login, "logged in";
 
 # configure key for General queue
-RT::Test::SMIME->import_key('sender at example.com');
+$test->smime_import_key('sender at example.com');
 my $queue = RT::Test->load_or_create_queue(
     Name              => 'General',
     CorrespondAddress => 'sender at example.com',
@@ -24,7 +24,7 @@ my $user = RT::Test->load_or_create_user(
     Name => 'root at example.com',
     EmailAddress => 'root at example.com',
 );
-RT::Test::SMIME->import_key('root at example.com.crt', $user);
+$test->smime_import_key('root at example.com.crt', $user);
 RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
 
 my $mail = RT::Test->open_mailgate_ok($url);
@@ -59,7 +59,7 @@ RT::Test->close_mailgate_ok($mail);
             -from    => 'root at example.com',
             -to      => 'sender at example.com',
             -subject => "Encrypted message for queue",
-            $test->key_path('sender at example.com.crt' ),
+            $test->smime_key_path('sender at example.com.crt' ),
         ),
         \"Subject: test\n\norzzzzzz",
         \$buf,
@@ -99,8 +99,8 @@ RT::Test->close_mailgate_ok($mail);
             shell_quote(
                 RT->Config->Get('SMIME')->{'OpenSSL'},
                 qw( smime -sign -nodetach -passin pass:123456),
-                -signer => $test->key_path('root at example.com.crt' ),
-                -inkey  => $test->key_path('root at example.com.key' ),
+                -signer => $test->smime_key_path('root at example.com.crt' ),
+                -inkey  => $test->smime_key_path('root at example.com.key' ),
             ),
             '|',
             shell_quote(
@@ -108,7 +108,7 @@ RT::Test->close_mailgate_ok($mail);
                 -from    => 'root at example.com',
                 -to      => 'sender at example.com',
                 -subject => "Encrypted and signed message for queue",
-                $test->key_path('sender at example.com.crt' ),
+                $test->smime_key_path('sender at example.com.crt' ),
             )),
             \"Subject: test\n\norzzzzzz",
             \$buf,
diff --git a/t/security/CVE-2012-4735-incoming-encryption-header.t b/t/security/CVE-2012-4735-incoming-encryption-header.t
index bd89e67566..e067ff1136 100644
--- a/t/security/CVE-2012-4735-incoming-encryption-header.t
+++ b/t/security/CVE-2012-4735-incoming-encryption-header.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => undef;
+use RT::Test::Crypt GnuPG => 1, tests => undef;
 use Test::Warn;
 
 {
diff --git a/t/security/CVE-2012-4735-sign-any-key.t b/t/security/CVE-2012-4735-sign-any-key.t
index 248df9c55e..78e9d1bace 100644
--- a/t/security/CVE-2012-4735-sign-any-key.t
+++ b/t/security/CVE-2012-4735-sign-any-key.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
@@ -14,7 +15,7 @@ RT::Test->import_gnupg_key('general at example.com');
 # Determine the key IDs of the newly-loaded keys
 my %secret_keys;
 {
-    my %info = RT::Crypt->GetKeysInfo( Type => 'private', Force => 1 );
+    my %info = RT::Crypt->GetKeysInfo( Protocol => 'GnuPG', Type => 'private', Force => 1 );
     for my $key (@{$info{info}}) {
         my $user = $key->{User}[0]{String};
         $user = (Email::Address->parse( $user ))[0]->address;
diff --git a/t/security/CVE-2012-4735-sign-encrypt-header.t b/t/security/CVE-2012-4735-sign-encrypt-header.t
index 4cf8e00d70..de42d60668 100644
--- a/t/security/CVE-2012-4735-sign-encrypt-header.t
+++ b/t/security/CVE-2012-4735-sign-encrypt-header.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG => 1,
   tests => undef,
   gnupg_options => {
     passphrase    => 'rt-test',
diff --git a/t/web/admin_user.t b/t/web/admin_user.t
index 552543e6e7..2504bc8ff1 100644
--- a/t/web/admin_user.t
+++ b/t/web/admin_user.t
@@ -2,7 +2,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'recipient',
diff --git a/t/web/crypt-gnupg.t b/t/web/crypt-gnupg.t
index 119bd91350..550d52e11c 100644
--- a/t/web/crypt-gnupg.t
+++ b/t/web/crypt-gnupg.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => undef,
   gnupg_options => {
     passphrase    => 'recipient',
@@ -423,7 +424,7 @@ ok($user = RT::User->new(RT->SystemUser));
 ok($user->Load('root'), "Loaded user 'root'");
 is($user->PreferredKey, $key1, "preferred key is set correctly");
 $m->get("$baseurl/Prefs/Other.html");
-like($m->content, qr/Preferred key/, "preferred key option shows up in preference");
+like($m->content, qr/Preferred GnuPG key/, "preferred key option shows up in preference");
 
 # XXX: mech doesn't let us see the current value of the select, apparently
 like($m->content, qr/$key1/, "first key shows up in preferences");
@@ -439,7 +440,7 @@ ok($user->Load('root'), "Loaded user 'root'");
 is($user->PreferredKey, $key2, "preferred key is set correctly to the new value");
 
 $m->get("$baseurl/Prefs/Other.html");
-like($m->content, qr/Preferred key/, "preferred key option shows up in preference");
+like($m->content, qr/Preferred GnuPG key/, "preferred key option shows up in preference");
 
 # XXX: mech doesn't let us see the current value of the select, apparently
 like($m->content, qr/$key2/, "second key shows up in preferences");
diff --git a/t/web/gnupg-headers.t b/t/web/gnupg-headers.t
index 03e60901ea..d7155bd3f2 100644
--- a/t/web/gnupg-headers.t
+++ b/t/web/gnupg-headers.t
@@ -1,7 +1,8 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG
+use RT::Test::Crypt
+  GnuPG         => 1,
   tests         => 15,
   gnupg_options => {
     passphrase    => 'recipient',
diff --git a/t/web/gnupg-select-keys-on-create.t b/t/web/gnupg-select-keys-on-create.t
index ee8357d59f..6438c02be0 100644
--- a/t/web/gnupg-select-keys-on-create.t
+++ b/t/web/gnupg-select-keys-on-create.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => undef, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => undef, gnupg_options => { passphrase => 'rt-test' };
 use RT::Action::SendEmail;
 
 my $queue = RT::Test->load_or_create_queue(
@@ -37,7 +37,7 @@ diag "check that signing doesn't work if there is no key";
 {
     RT::Test->import_gnupg_key('rt-recipient at example.com');
     RT::Test->trust_gnupg_key('rt-recipient at example.com');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-recipient at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-recipient at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[0]{'TrustTerse'}, 'ultimate', 'ultimately trusted key';
 }
 
@@ -74,7 +74,7 @@ diag "import first key of rt-test\@example.com";
 my $fpr1 = '';
 {
     RT::Test->import_gnupg_key('rt-test at example.com', 'secret');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[0]{'TrustLevel'}, 0, 'is not trusted key';
     $fpr1 = $res{'info'}[0]{'Fingerprint'};
 }
@@ -123,7 +123,7 @@ diag "import a second key of rt-test\@example.com";
 my $fpr2 = '';
 {
     RT::Test->import_gnupg_key('rt-test at example.com.2', 'secret');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[1]{'TrustLevel'}, 0, 'is not trusted key';
     $fpr2 = $res{'info'}[2]{'Fingerprint'};
 }
@@ -170,7 +170,7 @@ diag "check that things still doesn't work if two keys are not trusted";
 
 {
     RT::Test->lsign_gnupg_key( $fpr1 );
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     ok $res{'info'}[0]{'TrustLevel'} > 0, 'trusted key';
     is $res{'info'}[1]{'TrustLevel'}, 0, 'is not trusted key';
 }
diff --git a/t/web/gnupg-select-keys-on-update.t b/t/web/gnupg-select-keys-on-update.t
index 2f31a0f0d2..5d8419b93a 100644
--- a/t/web/gnupg-select-keys-on-update.t
+++ b/t/web/gnupg-select-keys-on-update.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => undef, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => undef, gnupg_options => { passphrase => 'rt-test' };
 
 use RT::Action::SendEmail;
 
@@ -52,7 +52,7 @@ diag "check that signing doesn't work if there is no key";
 {
     RT::Test->import_gnupg_key('rt-recipient at example.com');
     RT::Test->trust_gnupg_key('rt-recipient at example.com');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-recipient at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-recipient at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[0]{'TrustTerse'}, 'ultimate', 'ultimately trusted key';
 }
 
@@ -91,7 +91,7 @@ diag "import first key of rt-test\@example.com";
 my $fpr1 = '';
 {
     RT::Test->import_gnupg_key('rt-test at example.com', 'secret');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[0]{'TrustLevel'}, 0, 'is not trusted key';
     $fpr1 = $res{'info'}[0]{'Fingerprint'};
 }
@@ -141,7 +141,7 @@ diag "import a second key of rt-test\@example.com";
 my $fpr2 = '';
 {
     RT::Test->import_gnupg_key('rt-test at example.com.2', 'secret');
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     is $res{'info'}[1]{'TrustLevel'}, 0, 'is not trusted key';
     $fpr2 = $res{'info'}[2]{'Fingerprint'};
 }
@@ -189,7 +189,7 @@ diag "check that things still doesn't work if two keys are not trusted";
 
 {
     RT::Test->lsign_gnupg_key( $fpr1 );
-    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com' );
+    my %res = RT::Crypt->GetKeysInfo( Key => 'rt-test at example.com', Protocol => 'GnuPG' );
     ok $res{'info'}[0]{'TrustLevel'} > 0, 'trusted key';
     is $res{'info'}[1]{'TrustLevel'}, 0, 'is not trusted key';
 }
diff --git a/t/web/gnupg-tickyboxes.t b/t/web/gnupg-tickyboxes.t
index eb4388a2c4..4629f8e459 100644
--- a/t/web/gnupg-tickyboxes.t
+++ b/t/web/gnupg-tickyboxes.t
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use RT::Test::GnuPG tests => 22, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::Crypt GnuPG => 1, tests => 22, gnupg_options => { passphrase => 'rt-test' };
 
 use RT::Action::SendEmail;
 
diff --git a/t/web/smime/outgoing.t b/t/web/smime/outgoing.t
index d85c2ca111..fd85917516 100644
--- a/t/web/smime/outgoing.t
+++ b/t/web/smime/outgoing.t
@@ -1,15 +1,15 @@
 use strict;
 use warnings;
 
-use RT::Test::SMIME tests => undef;
-my $test = 'RT::Test::SMIME';
+use RT::Test::Crypt SMIME=>1, tests => undef;
+my $test = 'RT::Test::Crypt';
 
 use RT::Action::SendEmail;
 use File::Temp qw(tempdir);
 
 use_ok('RT::Crypt::SMIME');
 
-RT::Test::SMIME->import_key('sender at example.com');
+$test->smime_import_key('sender at example.com');
 
 my $user_email = 'root at example.com';
 {
@@ -17,7 +17,7 @@ my $user_email = 'root at example.com';
         Name => $user_email, EmailAddress => $user_email
     );
     ok $user && $user->id, 'loaded or created user';
-    RT::Test::SMIME->import_key($user_email, $user);
+    $test->smime_import_key($user_email, $user);
 }
 
 my $queue = RT::Test->load_or_create_queue(
@@ -53,7 +53,7 @@ my %mail = (
 diag "check in read-only mode that queue's props influence create/update ticket pages" if $ENV{TEST_VERBOSE};
 {
     foreach my $variant ( @variants ) {
-        set_queue_crypt_options( %$variant );
+        t_set_queue_crypt_options( %$variant );
         $m->goto_create_ticket( $queue );
         $m->form_name('TicketCreate');
         if ( $variant->{'Encrypt'} ) {
@@ -69,7 +69,7 @@ diag "check in read-only mode that queue's props influence create/update ticket
     }
 
     # to avoid encryption/signing during create
-    set_queue_crypt_options();
+    t_set_queue_crypt_options();
 
     my $ticket = RT::Ticket->new( $RT::SystemUser );
     my ($id) = $ticket->Create(
@@ -80,7 +80,7 @@ diag "check in read-only mode that queue's props influence create/update ticket
     ok $id, 'ticket created';
 
     foreach my $variant ( @variants ) {
-        set_queue_crypt_options( %$variant );
+        t_set_queue_crypt_options( %$variant );
         $m->goto_ticket( $id );
         $m->follow_link_ok({text => 'Reply'}, '-> reply');
         $m->form_number(3);
@@ -99,9 +99,9 @@ diag "check in read-only mode that queue's props influence create/update ticket
 
 # create a ticket for each combination
 foreach my $queue_set ( @variants ) {
-    set_queue_crypt_options( %$queue_set );
+    t_set_queue_crypt_options( %$queue_set );
     foreach my $ticket_set ( @variants ) {
-        create_a_ticket( %$ticket_set );
+        t_create_a_ticket( %$ticket_set );
     }
 }
 
@@ -118,9 +118,9 @@ my $tid;
 
 # again for each combination add a reply message
 foreach my $queue_set ( @variants ) {
-    set_queue_crypt_options( %$queue_set );
+    t_set_queue_crypt_options( %$queue_set );
     foreach my $ticket_set ( @variants ) {
-        update_ticket( $tid, %$ticket_set );
+        t_update_ticket( $tid, %$ticket_set );
     }
 }
 
@@ -131,10 +131,10 @@ foreach my $queue_set ( @variants ) {
 # like we are on another side recieving emails
 # ------------------------------------------------------------------------------
 
-my $keyring = $test->keyring_path;
+my $keyring = $test->smime_keyring_path;
 unlink $_ foreach glob( $keyring ."/*" );
-RT::Test::SMIME->import_key('sender at example.com.crt');
-RT::Test::SMIME->import_key($user_email);
+$test->smime_import_key('sender at example.com.crt');
+$test->smime_import_key($user_email);
 
 $queue = RT::Test->load_or_create_queue(
     Name              => 'Regression',
@@ -245,7 +245,7 @@ foreach my $mail ( map cleanup_headers($_), @{ $mail{'signed_encrypted'} } ) {
         "RT's mail includes copy of ticket text";
 }
 
-sub create_a_ticket {
+sub t_create_a_ticket {
     my %args = (@_);
 
     RT::Test->clean_caught_mails;
@@ -274,10 +274,10 @@ sub create_a_ticket {
     $m->get_ok('/'); # ensure that the mail has been processed
 
     my @mail = RT::Test->fetch_caught_mails;
-    check_text_emails( \%args, @mail );
+    t_check_text_emails( \%args, @mail );
 }
 
-sub update_ticket {
+sub t_update_ticket {
     my $tid = shift;
     my %args = (@_);
 
@@ -305,12 +305,12 @@ sub update_ticket {
     $m->get_ok('/'); # ensure that the mail has been processed
 
     my @mail = RT::Test->fetch_caught_mails;
-    check_text_emails( \%args, @mail );
+    t_check_text_emails( \%args, @mail );
 }
 
 done_testing;
 
-sub check_text_emails {
+sub t_check_text_emails {
     my %args = %{ shift @_ };
     my @mail = @_;
 
@@ -343,18 +343,7 @@ sub check_text_emails {
     }
 }
 
-sub cleanup_headers {
-    my $mail = shift;
-    # strip id from subject to create new ticket
-    $mail =~ s/^(Subject:)\s*\[.*?\s+#\d+\]\s*/$1 /m;
-    # strip several headers
-    foreach my $field ( qw(Message-ID RT-Originator RT-Ticket X-RT-Loop-Prevention) ) {
-        $mail =~ s/^$field:.*?\n(?! |\t)//gmsi;
-    }
-    return $mail;
-}
-
-sub set_queue_crypt_options {
+sub t_set_queue_crypt_options {
     my %args = @_;
 
     describe_options('setting queue options: ', %args);

commit 216f0a66497deb317b0c2bbd7b2970aa491479c0
Author: Dianne Skoll <dianne at bestpractical.com>
Date:   Fri Nov 6 12:06:26 2020 -0500

    Allow specification of outbound signing/encryption protocol on a per-queue basis

diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 45bd479073..3c2ef6cc4a 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -931,9 +931,9 @@ sub Encrypt {
         RT->Config->Get('CorrespondAddress'),
         RT->Config->Get('CommentAddress'),
     ) {
-        my %res = RT::Crypt->GetKeysInfo( Key => $address, Type => 'private' );
+        my %res = RT::Crypt->GetKeysInfo( Queue => $queue, Key => $address, Type => 'private' );
         next if $res{'exit_code'} || !$res{'info'};
-        %res = RT::Crypt->GetKeysForEncryption( $address );
+        %res = RT::Crypt->GetKeysForEncryption( Queue => $queue, Recipient => $address );
         next if $res{'exit_code'} || !$res{'info'};
         $encrypt_for = $address;
     }
@@ -943,6 +943,7 @@ sub Encrypt {
 
     my $content = $self->Content;
     my %res = RT::Crypt->SignEncryptContent(
+        Queue => $queue,
         Content => \$content,
         Sign => 0,
         Encrypt => 1,
diff --git a/lib/RT/Crypt.pm b/lib/RT/Crypt.pm
index 6283ae5538..9de425b4e8 100644
--- a/lib/RT/Crypt.pm
+++ b/lib/RT/Crypt.pm
@@ -98,9 +98,9 @@ to limit this to a subset, you may, via:
         ...
     );
 
-RT can currently only use one protocol to encrypt and sign outgoing
-email; this defaults to the first enabled protocol.  You many specify it
-explicitly via:
+RT can currently only use one protocol per queue to encrypt and sign
+outgoing email; this defaults to the first enabled protocol.  You may
+specify it explicitly via:
 
     Set( %Crypt,
         ...
@@ -108,6 +108,17 @@ explicitly via:
         ...
     );
 
+which sets the protocol for all queues.  Alternatively, you can use:
+
+    Set( %Crypt,
+        ...
+        Outgoing => { Queue1 => 'GnuPG', Queue2 => 'SMIME', '' => 'GnuPG' },
+        ...
+    );
+
+which sets the outgoing protocol for Queue1 to GnuPG, for Queue2 to
+SMIME, and for all other queues to GnuPG (the '' key.)
+
 You can allow users to encrypt data in the database by setting the
 C<AllowEncryptDataInDB> key to a true value; by default, this is
 disabled.  Be aware that users must have rights to see and modify
@@ -226,15 +237,36 @@ sub EnabledProtocols {
     return grep RT->Config->Get($_)->{'Enable'}, $self->Protocols;
 }
 
-=head2 UseForOutgoing
+=head2 UseForOutgoing (Queue => QUEUE)
 
-Returns the configured outgoing encryption protocol; see
-L<RT_Config/Crypt>.
+Returns the configured outgoing encryption protocol for the given
+queue; see L<RT_Config/Crypt>.  The Queue argument can be either a
+queue name or an RT::Queue object.
 
 =cut
 
 sub UseForOutgoing {
-    return RT->Config->Get('Crypt')->{'Outgoing'};
+    my $self = shift;
+    my %args = (
+        Queue => undef,
+        @_
+    );
+    my $outgoing = RT->Config->Get('Crypt')->{'Outgoing'};
+
+    # Old-style config: Crypt->{'Outgoing'} is a scalar to use for all queues
+    if ( ( ref($outgoing) || '' ) ne 'HASH' ) {
+        return $outgoing;
+    }
+
+    # New-style config: Crypt->{'Outgoing'} is a hash keyed by queue name
+    my $qname = $args{Queue} || '';
+
+    # We accept either a queue name or an RT::Queue object;
+    # either way, boil it down to the name.
+    $qname = $qname->Name if ref($qname);
+
+    # Look for per-queue method; default to '' method in outgoing hash
+    return $outgoing->{$qname} || $outgoing->{''};
 }
 
 =head2 EnabledOnIncoming
@@ -276,12 +308,22 @@ Examines the caller of this method, and dispatches to the method of the
 same name on the correct L<RT::Crypt::Role> class based on the provided
 C<Protocol>.
 
+If C<Protocol> is not supplied, then C<Queue> must be so that we
+can figure out which outgoing protocol to use.  C<Queue> can
+be a queue name or an C<RT::Queue> object.
+
 =cut
 
 sub SimpleImplementationCall {
     my $self = shift;
     my %args = (@_);
-    my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
+    my $protocol = delete $args{'Protocol'};
+    if (!$protocol) {
+        if (!$args{'Queue'}) {
+            Carp::croak('If Protocol is not supplied, Queue must be supplied');
+        }
+        $protocol = $self->UseForOutgoing(@_);
+    }
 
     my $method = (caller(1))[3];
     $method =~ s/.*:://;
@@ -387,7 +429,7 @@ sub FindProtectedParts {
 
 =head2 SignEncrypt Entity => ENTITY, [Sign => 1], [Encrypt => 1],
 [Recipients => ARRAYREF], [Signer => NAME], [Protocol => NAME],
-[Passphrase => VALUE]
+[Passphrase => VALUE], [Queue => QUEUE]
 
 Takes a L<MIME::Entity> object, and signs and/or encrypts it using the
 given C<Protocol>.  If not set, C<Recipients> for encryption will be set
@@ -418,6 +460,7 @@ sub SignEncrypt {
     my %args = (
         Sign => 1,
         Encrypt => 1,
+        Queue => undef,
         @_,
     );
 
@@ -468,7 +511,7 @@ sub SignEncryptContent {
     return $self->SimpleImplementationCall( %args );
 }
 
-=head2 DrySign Signer => KEY
+=head2 DrySign Queue => QUEUE, Signer => KEY
 
 Signs a small message with the key, to make sure the key exists and we
 have a useable passphrase. The Signer argument MUST be a key identifier
@@ -640,31 +683,32 @@ sub UseKeyForEncryption {
     return ();
 }
 
-=head2 GetKeysForEncryption Recipient => EMAIL, Protocol => NAME
+=head2 CheckRecipients QUEUE, @RECIPIENTS
 
-Returns the list of keys which are suitable for encrypting mail to the
-given C<Recipient>.  Generally this is equivalent to L</GetKeysInfo>
-with a C<Type> of <private>, but encryption protocols may further limit
-which keys can be used for encryption, as opposed to signing.
+Check a list of recipients to make sure we have trustable public
+keys for all of them.  Returns (1, ()) if everything is OK, or
+(0, @list_of_problem_messages) if there are errors.
 
 =cut
 
 sub CheckRecipients {
     my $self = shift;
+    my $queue = shift;
     my @recipients = (@_);
 
     my ($status, @issues) = (1, ());
 
     my $trust = sub { 1 };
-    if ( $self->UseForOutgoing eq 'SMIME' ) {
+    my $proto = $self->UseForOutgoing(Queue => $queue);
+    if ( $proto eq 'SMIME' ) {
         $trust = sub { $_[0]->{'TrustLevel'} > 0 or RT->Config->Get('SMIME')->{AcceptUntrustedCAs} };
-    } elsif ( $self->UseForOutgoing eq 'GnuPG' ) {
+    } elsif ( $proto eq 'GnuPG' ) {
         $trust = sub { $_[0]->{'TrustLevel'} > 0 };
     }
 
     my %seen;
     foreach my $address ( grep !$seen{ lc $_ }++, map $_->address, @recipients ) {
-        my %res = $self->GetKeysForEncryption( Recipient => $address );
+        my %res = $self->GetKeysForEncryption( Queue => $queue, Recipient => $address );
         if ( $res{'info'} && @{ $res{'info'} } == 1 and $trust->($res{'info'}[0]) ) {
             # One key, which is trusted, or we can sign with an
             # untrusted key (aka SMIME with AcceptUntrustedCAs)
@@ -723,13 +767,23 @@ sub CheckRecipients {
     return ($status, @issues);
 }
 
+=head2 GetKeysForEncryption Recipient => EMAIL, Protocol => NAME, Queue => QUEUE
+
+Returns the list of keys which are suitable for encrypting mail to the
+given C<Recipient>.  Generally this is equivalent to L</GetKeysInfo>
+with a C<Type> of <private>, but encryption protocols may further limit
+which keys can be used for encryption, as opposed to signing.
+
+=cut
+
+
 sub GetKeysForEncryption {
     my $self = shift;
     my %args = @_%2? (Recipient => @_) : (Protocol => undef, Recipient => undef, @_ );
     return $self->SimpleImplementationCall( %args );
 }
 
-=head2 GetKeysForSigning Signer => EMAIL, Protocol => NAME
+=head2 GetKeysForSigning Signer => EMAIL, Protocol => NAME, Queue => QUEUE
 
 Returns the list of keys which are suitable for signing mail from the
 given C<Signer>.  Generally this is equivalent to L</GetKeysInfo>
@@ -778,7 +832,7 @@ sub GetKeyInfo {
     return %res;
 }
 
-=head2 GetKeysInfo Protocol => NAME, Type => ('public'|'private'), Key => EMAIL
+=head2 GetKeysInfo Protocol => NAME, Queue => QUEUE, Type => ('public'|'private'), Key => EMAIL
 
 Looks up information about the public or private keys (as determined by
 C<Type>) for the email address C<Key>.  As each protocol has its own key
@@ -796,6 +850,12 @@ protocol-dependent, but will at least contain:
 
 The name of the protocol of this key
 
+=item Queue
+
+An L<RT::Queue> or queue name. This is to infer the protocol to use from
+C<Outgoing> in L</%Crypt> configuration, only needed if Protocol is not
+provided.
+
 =item Created
 
 An L<RT::Date> of the date the key was created; undef if unset.
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index e88248e5b2..78ff123d3d 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -887,6 +887,9 @@ sub SendEmail {
             Attachment => $TransactionObj ? $TransactionObj->Attachments->First : undef,
             Ticket     => $TicketObj,
         );
+        if ($TicketObj) {
+            $args{'Queue'} = $TicketObj->QueueObj;
+        }
         my $res = SignEncrypt( %args );
         return $res unless $res > 0;
     }
diff --git a/lib/RT/User.pm b/lib/RT/User.pm
index 5184eb3fa4..85db5c30b5 100644
--- a/lib/RT/User.pm
+++ b/lib/RT/User.pm
@@ -2060,7 +2060,7 @@ sub PreferredKey
     return $prefkey->Content if $prefkey;
 
     # we don't have a preferred key for this user, so now we must query GPG
-    my %res = RT::Crypt->GetKeysForEncryption($self->EmailAddress);
+    my %res = RT::Crypt->GetKeysForEncryption(Recipient => $self->EmailAddress, Protocol => 'GnuPG');
     return undef unless defined $res{'info'};
     my @keys = @{ $res{'info'} };
     return undef if @keys == 0;
diff --git a/share/html/Elements/Crypt/KeyIssues b/share/html/Elements/Crypt/KeyIssues
index 0317537409..26d355d69c 100644
--- a/share/html/Elements/Crypt/KeyIssues
+++ b/share/html/Elements/Crypt/KeyIssues
@@ -76,6 +76,8 @@ There is a problem with key/certificate(s) for address <% $issue->{'EmailAddress
 <br />
 Select a key/certificate you want to use for encryption:
 <& /Elements/Crypt/SelectKeyForEncryption,
+    Protocol     => $Protocol,
+    Queue        => $Queue,
     Name         => 'UseKey-'. $issue->{'EmailAddress'},
     EmailAddress => $issue->{'EmailAddress'},
     Default      => ( $issue->{'User'}? $issue->{'User'}->PreferredKey : undef ),
@@ -90,5 +92,7 @@ Select a key/certificate you want to use for encryption:
 <%ARGS>
 $Issues => []
 $SignAddresses => []
+$Protocol => undef
+$Queue => undef
 </%ARGS>
 
diff --git a/share/html/Elements/Crypt/SelectKeyForEncryption b/share/html/Elements/Crypt/SelectKeyForEncryption
index 5ccb2d812b..07891b666e 100644
--- a/share/html/Elements/Crypt/SelectKeyForEncryption
+++ b/share/html/Elements/Crypt/SelectKeyForEncryption
@@ -58,7 +58,9 @@
 <%INIT>
 my $d;
 
-my %res = RT::Crypt->GetKeysForEncryption($EmailAddress);
+my %res = RT::Crypt->GetKeysForEncryption(Queue => $Queue,
+                                          Protocol => $Protocol,
+                                          Recipient => $EmailAddress);
 # move the preferred key to the top of the list
 my @keys = map {
                $_->{'Fingerprint'} eq ( $Default || '' )
@@ -76,5 +78,7 @@ unshift @keys, $d if defined $d;
 $Name         => 'PreferredKey'
 $EmailAddress => undef
 $Default      => undef
+$Queue        => undef
+$Protocol     => undef
 </%ARGS>
 
diff --git a/share/html/Elements/Crypt/SignEncryptWidget b/share/html/Elements/Crypt/SignEncryptWidget
index 815234c13b..0a8ff1964d 100644
--- a/share/html/Elements/Crypt/SignEncryptWidget
+++ b/share/html/Elements/Crypt/SignEncryptWidget
@@ -87,11 +87,15 @@ return { %$Arguments };
 <%METHOD ShowIssues>
 <%ARGS>
 $self => undef,
+$Protocol => undef
+$Queue => undef
 </%ARGS>
 <%INIT>
 return unless $self;
 
 return $m->comp( '/Elements/Crypt/KeyIssues',
+    Protocol => $Protocol,
+    Queue => $Queue,
     Issues => $self->{'GnuPGRecipientsKeyIssues'} || [],
     SignAddresses => $self->{'GnuPGCanNotSignAs'} || [],
 );
@@ -145,7 +149,7 @@ if ( $self->{'Sign'} ) {
     if ($address ne $private and $address ne $queue) {
         push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
         $checks_failure = 1;
-    } elsif ( not RT::Crypt->DrySign( Signer => $address ) ) {
+    } elsif ( not RT::Crypt->DrySign( Queue => $QueueObj, Signer => $address ) ) {
         push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
         $checks_failure = 1;
     } else {
@@ -183,7 +187,8 @@ if ( $self->{'Encrypt'} ) {
         keys %$self
     );
 
-    my ($status, @issues) = RT::Crypt->CheckRecipients( @recipients );
+    $QueueObj ||= $TicketObj->QueueObj if $TicketObj;
+    my ($status, @issues) = RT::Crypt->CheckRecipients( $QueueObj, @recipients );
     push @{ $self->{'GnuPGRecipientsKeyIssues'} ||= [] }, @issues;
     $checks_failure = 1 unless $status;
 }
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index ae425272e1..c0f95fc09f 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -82,8 +82,9 @@ my $LinkCallback = sub {
 };
 
 my $trustSub = sub {
+    my $queue = shift;
     my $user = shift;
-    my %key = RT::Crypt->GetKeyInfo( Key => $user->EmailAddress );
+    my %key = RT::Crypt->GetKeyInfo( Key => $user->EmailAddress, Queue => $queue );
     if (!defined $key{'info'}) {
         return $m->interp->apply_escapes(' ' . loc("(no pubkey!)"), "h");
     } elsif ($key{'info'}{'TrustLevel'} == 0) {
@@ -275,7 +276,7 @@ $COLUMN_MAP = {
     KeyRequestors => {
         title     => 'Requestors', # loc
         attribute => 'Requestor.EmailAddress',
-        value     => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->Requestor, PostUser => $trustSub ) ) }
+        value     => sub { my $ticket = $_[0]; return \($m->scomp("/Elements/ShowPrincipal", Object => $ticket->Requestor, PostUser => sub { my $user = shift; return $trustSub->($ticket->QueueObj, $user); }))}
     },
     KeyOwnerName => {
         title     => 'Owner', # loc
@@ -283,7 +284,7 @@ $COLUMN_MAP = {
         value     => sub {
             my $t = shift;
             my $name = $t->OwnerObj->Name;
-            my %key = RT::Crypt->GetKeyInfo( Key => $t->OwnerObj->EmailAddress );
+            my %key = RT::Crypt->GetKeyInfo( Key => $t->OwnerObj->EmailAddress, Queue => $t->QueueObj );
             if (!defined $key{'info'}) {
                 $name .= ' '. loc("(no pubkey!)");
             }
@@ -297,7 +298,8 @@ $COLUMN_MAP = {
     KeyOwner => {
         title     => 'Owner', # loc
         attribute => 'Owner',
-        value     => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->OwnerObj, PostUser => $trustSub ) ) }
+        value     => sub {
+            my $ticket = $_[0]; return \($m->scomp("/Elements/ShowPrincipal", Object => $ticket->OwnerObj, PostUser => sub { my $user = shift; return $trustSub->($ticket->QueueObj, $user); }))},
     },
 
     # Everything from LINKTYPEMAP
diff --git a/share/html/Prefs/Other.html b/share/html/Prefs/Other.html
index cf9fe4abab..e2526dbd91 100644
--- a/share/html/Prefs/Other.html
+++ b/share/html/Prefs/Other.html
@@ -69,7 +69,7 @@
 
 % if ( RT->Config->Get('Crypt')->{'Enable'} ) {
 <&|/Widgets/TitleBox, title => loc( 'Cryptography' ) &>
-<&|/l&>Preferred key</&>: <& /Elements/Crypt/SelectKeyForEncryption, EmailAddress => $UserObj->EmailAddress, Default => $UserObj->PreferredKey &>
+<&|/l&>Preferred GnuPG key</&>: <& /Elements/Crypt/SelectKeyForEncryption, Name => 'PreferredKey', EmailAddress => $UserObj->EmailAddress, Default => $UserObj->PreferredKey, Protocol => 'GnuPG' &>
 </&>
 % }
 
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index bbe1ccf0d7..da35ee9b3d 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -60,7 +60,7 @@
 % $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 
 % if ($gnupg_widget) {
-  <& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+  <& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget, Queue => $QueueObj &>
 % }
 
 <div id="Ticket-Create-basics">
diff --git a/share/html/Ticket/Forward.html b/share/html/Ticket/Forward.html
index 7e81b0c376..b4493b2cfe 100644
--- a/share/html/Ticket/Forward.html
+++ b/share/html/Ticket/Forward.html
@@ -56,7 +56,7 @@
 <input type="hidden" class="hidden" name="id" value="<% $id %>" /><br />
 <input type="hidden" class="hidden" name="QuoteTransaction" value="<% $ARGS{'QuoteTransaction'} || '' %>" />
 
-<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget, Queue => $TicketObj->QueueObj &>
 
 <table border="0">
 <tr><td align="right"><&|/l&>From</&>:</td>
diff --git a/share/html/Ticket/Update.html b/share/html/Ticket/Update.html
index 0439b74ace..70f5e7d605 100644
--- a/share/html/Ticket/Update.html
+++ b/share/html/Ticket/Update.html
@@ -59,7 +59,7 @@
 <input type="hidden" class="hidden" name="Action" value="<% $Action %>" />
 <input type="hidden" class="hidden" name="Token" value="<% $ARGS{'Token'} %>" />
 
-<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget, Queue => $TicketObj->QueueObj &>
 
 <div id="ticket-update-metadata">
   <&|/Widgets/TitleBox, title => loc('Ticket and Transaction') &>
diff --git a/share/html/m/ticket/create b/share/html/m/ticket/create
index 347810826c..912dde9268 100644
--- a/share/html/m/ticket/create
+++ b/share/html/m/ticket/create
@@ -217,7 +217,7 @@ if ((!exists $ARGS{'AddMoreAttach'}) and (defined($ARGS{'id'}) and $ARGS{'id'} e
 <input type="hidden" class="hidden" name="Token" value="<% $ARGS{'Token'} %>" />
 % $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 % if ($gnupg_widget) {
-<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget, Queue => $QueueObj &>
 % }
 
 
diff --git a/share/html/m/ticket/reply b/share/html/m/ticket/reply
index 4382b9e645..4d7cbb541c 100644
--- a/share/html/m/ticket/reply
+++ b/share/html/m/ticket/reply
@@ -57,7 +57,7 @@
 <input type="hidden" class="hidden" name="Token" value="<% $ARGS{'Token'} %>" />
 
 % if ($gnupg_widget) {
-<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+<& /Elements/Crypt/SignEncryptWidget:ShowIssues, self => $gnupg_widget, Queue => $t->QueueObj &>
 % }
 
 <div class="entry"><span class="label"><&|/l&>Status</&>:</span>

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


More information about the rt-commit mailing list