[Rt-commit] rt branch, 4.4/smime-separate-encrypt-and-sign-certs, created. rt-4.4.3-44-g7be3c0861

? sunnavy sunnavy at bestpractical.com
Mon Sep 24 16:01:25 EDT 2018


The branch, 4.4/smime-separate-encrypt-and-sign-certs has been created
        at  7be3c08615a89dea0019e35f6db6f90f206a7450 (commit)

- Log -----------------------------------------------------------------
commit 7be3c08615a89dea0019e35f6db6f90f206a7450
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Tue Sep 25 03:32:28 2018 +0800

    Support separate certificates for SMIME encryption and signing
    
    PEM files need to be named like "email.address at example.com.encryption.pem"
    and "email.address at example.com.signing.pem", respectively.
    
    If passphrases are also different, they can be specified in config like:
    
        'email.address at example.com' => {
            Encryption => 'passphrase for encryption certificate',
            Signing    => 'passphrase for signing certificate',
        }

diff --git a/lib/RT/Crypt/Role.pm b/lib/RT/Crypt/Role.pm
index 1e526f3f7..732d06d36 100644
--- a/lib/RT/Crypt/Role.pm
+++ b/lib/RT/Crypt/Role.pm
@@ -69,7 +69,7 @@ encounters.
 
 requires 'Probe';
 
-=head2 GetPassphrase Address => ADDRESS
+=head2 GetPassphrase Address => ADDRESS, For => Encryption|Signing
 
 Returns the passphrase for the given address.  It looks at the relevant
 configuration option for the encryption protocol
@@ -82,7 +82,7 @@ it is a hash, it looks up the address (using '' as a fallback key).
 
 sub GetPassphrase {
     my $self = shift;
-    my %args = ( Address => undef, @_ );
+    my %args = ( Address => undef, For => undef, @_ );
 
     my $class = ref($self) || $self;
     $class =~ s/^RT::Crypt:://;
@@ -94,6 +94,9 @@ sub GetPassphrase {
     if (not ref $config) {
         return $config;
     } elsif (ref $config eq "HASH") {
+        if ( ref $config->{$args{Address}} eq 'HASH' ) {
+            return $config->{$args{Address}}{$args{For} // ''} || $config->{$args{Address}}{''};
+        }
         return $config->{$args{Address}}
             || $config->{''};
     } elsif (ref $config eq "CODE") {
diff --git a/lib/RT/Crypt/SMIME.pm b/lib/RT/Crypt/SMIME.pm
index bcb792b66..5431f0fd8 100644
--- a/lib/RT/Crypt/SMIME.pm
+++ b/lib/RT/Crypt/SMIME.pm
@@ -79,6 +79,10 @@ You should start from reading L<RT::Crypt>.
         CAPath  => '/opt/rt4/var/data/smime/signing-ca.pem',
         Passphrase => {
             'queue.address at example.com' => 'passphrase',
+            'another.queue.address at example.com' => {
+                Encryption => 'passphrase for encryption certificate',
+                Signing    => 'passphrase for signing certificate',
+            },
             '' => 'fallback',
         },
     );
@@ -127,6 +131,11 @@ on users, private SSL keys are only loaded from disk.  Keys and
 certificates should be concatenated, in in PEM format, in files named
 C<email.address at example.com.pem>, for example.
 
+For addresses that have separate certificates for encryption/decryption
+and signing, the PEM files need to be named like
+C<email.address at example.com.encryption.pem> and
+C<email.address at example.com.signing.pem>, respectively.
+
 These files need be readable by the web server user which is running
 RT's web interface; however, if you are running cronjobs or other
 utilities that access RT directly via API, and may generate
@@ -296,7 +305,7 @@ sub _SignEncrypt {
         foreach my $address ( @addresses ) {
             $RT::Logger->debug( "Considering encrypting message to " . $address );
 
-            my %key_info = $self->GetKeysInfo( Key => $address );
+            my %key_info = $self->GetKeysInfo( Key => $address, For => 'Encryption' );
             unless ( defined $key_info{'info'} ) {
                 $res{'exit_code'} = 1;
                 my $reason = 'Key not found';
@@ -337,7 +346,7 @@ sub _SignEncrypt {
 
     my @commands;
     if ( $args{'Sign'} ) {
-        my $file = $self->CheckKeyring( Key => $args{'Signer'} );
+        my $file = $self->CheckKeyring( Key => $args{'Signer'}, For => 'Signing' );
         unless ($file) {
             $res{'status'} .= $self->FormatStatus({
                 Operation => "KeyCheck", Status => "MISSING",
@@ -348,7 +357,7 @@ sub _SignEncrypt {
             $res{exit_code} = 1;
             return (undef, %res);
         }
-        $args{'Passphrase'} = $self->GetPassphrase( Address => $args{'Signer'} )
+        $args{'Passphrase'} = $self->GetPassphrase( Address => $args{'Signer'}, For => 'Signing' )
             unless defined $args{'Passphrase'};
 
         push @commands, [
@@ -582,14 +591,14 @@ sub _Decrypt {
     my ($buf, $encrypted_to, %res);
 
     foreach my $address ( @addresses ) {
-        my $file = $self->CheckKeyring( Key => $address );
+        my $file = $self->CheckKeyring( Key => $address, For => 'Encryption' );
         unless ( $file ) {
             my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
             $RT::Logger->debug("No key found for $address in $keyring directory");
             next;
         }
 
-        local $ENV{SMIME_PASS} = $self->GetPassphrase( Address => $address );
+        local $ENV{SMIME_PASS} = $self->GetPassphrase( Address => $address, For => 'Encryption' );
         local $SIG{CHLD} = 'DEFAULT';
         my $cmd = [
             $self->OpenSSLPath,
@@ -802,13 +811,13 @@ sub CheckIfProtected {
 sub GetKeysForEncryption {
     my $self = shift;
     my %args = (Recipient => undef, @_);
-    return $self->GetKeysInfo( Key => delete $args{'Recipient'}, %args, Type => 'public' );
+    return $self->GetKeysInfo( Key => delete $args{'Recipient'}, %args, Type => 'public', For => 'Encryption' );
 }
 
 sub GetKeysForSigning {
     my $self = shift;
     my %args = (Signer => undef, @_);
-    return $self->GetKeysInfo( Key => delete $args{'Signer'}, %args, Type => 'private' );
+    return $self->GetKeysInfo( Key => delete $args{'Signer'}, %args, Type => 'private', For => 'Signing' );
 }
 
 sub GetKeysInfo {
@@ -817,6 +826,7 @@ sub GetKeysInfo {
         Key   => undef,
         Type  => 'public',
         Force => 0,
+        For   => undef,
         @_
     );
 
@@ -833,7 +843,7 @@ sub GetKeysInfo {
 
 sub GetKeyContent {
     my $self = shift;
-    my %args = ( Key => undef, @_ );
+    my %args = ( Key => undef, For => undef, @_ );
 
     my $key;
     if ( my $file = $self->CheckKeyring( %args ) ) {
@@ -854,11 +864,17 @@ sub CheckKeyring {
     my $self = shift;
     my %args = (
         Key => undef,
+        For => undef,
         @_,
     );
     my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
     return undef unless $keyring;
 
+    if ( $args{For} ) {
+        my $file = File::Spec->catfile( $keyring, $args{'Key'} . '.' . lc( $args{For} ) . '.pem' );
+        return $file if -f $file;
+    }
+
     my $file = File::Spec->catfile( $keyring, $args{'Key'} .'.pem' );
     return undef unless -f $file;
 

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


More information about the rt-commit mailing list