[Rt-commit] rt branch, 4.2/smime-v2, updated. rt-4.0.4-364-g3d4e06c
Ruslan Zakirov
ruz at bestpractical.com
Thu Jan 12 06:52:42 EST 2012
The branch, 4.2/smime-v2 has been updated
via 3d4e06c17077999ed62c561b80b06b90a6e8bea4 (commit)
via 91ea9a3061bfb7673ca4a7e1ff7d0b52f5614112 (commit)
via 51e4f88a0db9be04a96341b8759752accf2c5024 (commit)
via 919d86408bad2fe644d0e0410d5e5d49f5e66984 (commit)
via 8822b5cbc962c824778c74c34d1f291b68d763ed (commit)
from 85a312984d4eb3116751cd370c209df14b37eb16 (commit)
Summary of changes:
TODO.SMIME | 2 -
etc/RT_Config.pm.in | 8 +-
lib/RT/Attachment.pm | 46 ++++++---
lib/RT/Crypt.pm | 60 +++++------
lib/RT/Crypt/GnuPG.pm | 7 --
lib/RT/Crypt/SMIME.pm | 162 ++++++++++++++++++----------
share/html/Ticket/Elements/ShowTransaction | 4 +-
t/crypt/gnupg/attachments-in-db.t | 2 +-
8 files changed, 172 insertions(+), 119 deletions(-)
- Log -----------------------------------------------------------------
commit 8822b5cbc962c824778c74c34d1f291b68d763ed
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Tue Jan 10 21:23:59 2012 +0400
delay setting content type until all error checks are passed
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 081634b..53cb142 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -738,9 +738,6 @@ sub Encrypt {
return (0, $self->loc('No key suitable for encryption'));
}
- $self->__Set( Field => 'ContentType', Value => $type );
- $self->SetHeader( 'Content-Type' => $type );
-
my $content = $self->Content;
my %res = RT::Crypt->SignEncryptContent(
Content => \$content,
@@ -756,6 +753,9 @@ sub Encrypt {
unless ( $status ) {
return ($status, $self->loc("Couldn't replace content with encrypted data: [_1]", $msg));
}
+ $self->__Set( Field => 'ContentType', Value => $type );
+ $self->SetHeader( 'Content-Type' => $type );
+
return (1, $self->loc('Successfuly encrypted data'));
}
@@ -778,8 +778,6 @@ sub Decrypt {
} else {
return (1, $self->loc('Is not encrypted'));
}
- $self->__Set( Field => 'ContentType', Value => $type );
- $self->SetHeader( 'Content-Type' => $type );
my $content = $self->Content;
my %res = RT::Crypt->DecryptContent( Content => \$content );
@@ -791,6 +789,9 @@ sub Decrypt {
unless ( $status ) {
return ($status, $self->loc("Couldn't replace content with decrypted data: [_1]", $msg));
}
+ $self->__Set( Field => 'ContentType', Value => $type );
+ $self->SetHeader( 'Content-Type' => $type );
+
return (1, $self->loc('Successfuly decrypted data'));
}
commit 919d86408bad2fe644d0e0410d5e5d49f5e66984
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jan 11 01:49:18 2012 +0400
refactor common code
diff --git a/lib/RT/Crypt.pm b/lib/RT/Crypt.pm
index 3c2eaca..69ceb8e 100644
--- a/lib/RT/Crypt.pm
+++ b/lib/RT/Crypt.pm
@@ -97,6 +97,19 @@ sub LoadImplementation {
return $class;
} }
+sub SimpleImplementationCall {
+ my $self = shift;
+ my %args = (@_);
+ my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
+
+ my $method = (caller(1))[3];
+ $method =~ s/.*:://;
+
+ my %res = $self->LoadImplementation( $protocol )->$method( %args );
+ $res{'Protocol'} = $protocol if keys %res;
+ return %res;
+}
+
# encryption and signatures can be nested one over another, for example:
# GPG inline signed text can be signed with SMIME
@@ -196,11 +209,7 @@ sub SignEncrypt {
qw(To Cc Bcc)
];
}
-
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->SignEncrypt( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return $self->SimpleImplementationCall( %args );
}
sub SignEncryptContent {
@@ -214,10 +223,7 @@ sub SignEncryptContent {
$args{'Recipients'} = [ RT->Config->Get('CorrespondAddress') ];
}
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->SignEncryptContent( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return $self->SimpleImplementationCall( %args );
}
sub DrySign {
@@ -241,23 +247,15 @@ sub VerifyDecrypt {
my @protected = $self->FindProtectedParts( Entity => $args{'Entity'} );
foreach my $protected ( @protected ) {
- my $protocol = $protected->{'Protocol'};
- my $class = $self->LoadImplementation( $protocol );
- my %res = $class->VerifyDecrypt( %args, Info => $protected );
- $res{'Protocol'} = $protocol;
- push @res, \%res;
+ push @res, { $self->SimpleImplementationCall(
+ %args, Protocol => $protected->{'Protocol'}, Info => $protected
+ ) };
}
return @res;
}
sub DecryptContent {
- my $self = shift;
- my %args = (@_);
-
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->DecryptContent( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return shift->SimpleImplementationCall( @_ );
}
sub ParseStatus {
@@ -376,19 +374,13 @@ sub CheckRecipients {
sub GetKeysForEncryption {
my $self = shift;
my %args = @_%2? (Recipient => @_) : (Protocol => undef, For => undef, @_ );
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->GetKeysForEncryption( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return $self->SimpleImplementationCall( %args );
}
sub GetKeysForSigning {
my $self = shift;
my %args = @_%2? (Signer => @_) : (Protocol => undef, Signer => undef, @_);
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->GetKeysForSigning( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return $self->SimpleImplementationCall( %args );
}
sub GetPublicKeyInfo {
@@ -409,10 +401,7 @@ sub GetKeyInfo {
sub GetKeysInfo {
my $self = shift;
my %args = @_%2 ? (Key => @_) : ( Protocol => undef, Key => undef, @_ );
- my $protocol = delete $args{'Protocol'} || $self->UseForOutgoing;
- my %res = $self->LoadImplementation( $protocol )->GetKeysInfo( %args );
- $res{'Protocol'} = $protocol;
- return %res;
+ return $self->SimpleImplementationCall( %args );
}
1;
commit 51e4f88a0db9be04a96341b8759752accf2c5024
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jan 11 03:46:06 2012 +0400
use x-application-rt\/$protocol-encrypted content type
Use protocol name instead of storing 'gpg' in content type
when we encrypt attachments in DB. Get it from result of
SignEncryptContent.
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 53cb142..9c7d491 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -712,12 +712,10 @@ sub Encrypt {
require RT::Crypt::GnuPG;
my $type = $self->ContentType;
- if ( $type =~ /^x-application-rt\/gpg-encrypted/i ) {
+ if ( $type =~ /^x-application-rt\/[^-]+-encrypted/i ) {
return (1, $self->loc('Already encrypted'));
} elsif ( $type =~ /^multipart\//i ) {
return (1, $self->loc('No need to encrypt'));
- } else {
- $type = qq{x-application-rt\/gpg-encrypted; original-type="$type"};
}
my $queue = $txn->TicketObj->QueueObj;
@@ -753,6 +751,8 @@ sub Encrypt {
unless ( $status ) {
return ($status, $self->loc("Couldn't replace content with encrypted data: [_1]", $msg));
}
+
+ $type = qq{x-application-rt\/$res{'Protocol'}-encrypted; original-type="$type"};
$self->__Set( Field => 'ContentType', Value => $type );
$self->SetHeader( 'Content-Type' => $type );
@@ -772,7 +772,10 @@ sub Decrypt {
require RT::Crypt::GnuPG;
my $type = $self->ContentType;
- if ( $type =~ /^x-application-rt\/gpg-encrypted/i ) {
+ my $protocol;
+ if ( $type =~ /^x-application-rt\/([^-]+)-encrypted/i ) {
+ $protocol = $1;
+ $protocol =~ s/gpg/gnupg/; # backwards compatibility
($type) = ($type =~ /original-type="(.*)"/i);
$type ||= 'application/octet-stream';
} else {
@@ -780,7 +783,7 @@ sub Decrypt {
}
my $content = $self->Content;
- my %res = RT::Crypt->DecryptContent( Content => \$content );
+ my %res = RT::Crypt->DecryptContent( Protocol => $protocol, Content => \$content );
if ( $res{'exit_code'} ) {
return (0, $self->loc('GnuPG error. Contact with administrator'));
}
commit 91ea9a3061bfb7673ca4a7e1ff7d0b52f5614112
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jan 11 14:42:49 2012 +0400
Move AllowEncryptDataInDB into %Crypt option
diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 67ca67d..4e405fd 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1981,6 +1981,9 @@ emails encrypted for key RT doesn't have and can not decrypt.
Set C<RejectOnBadData> to false if you don't want to reject letters
with incorrect data.
+If you want to allow people to encrypt attachments inside the DB then
+set C<AllowEncryptDataInDB> to 1.
+
=back
=cut
@@ -1991,6 +1994,8 @@ Set( %Crypt,
RejectOnMissingPrivateKey => 1,
RejectOnBadData => 1,
+
+ AllowEncryptDataInDB => 0,
);
=head2 SMIME configuration
@@ -2041,9 +2046,6 @@ for encryptng and signing outgoing messages.
Set C<OutgoingMessagesFormat> to 'inline' to use inline encryption and
signatures instead of 'RFC' (GPG/MIME: RFC3156 and RFC1847) format.
-If you want to allow people to encrypt attachments inside the DB then
-set C<AllowEncryptDataInDB> to 1.
-
=cut
Set(%GnuPG,
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 9c7d491..260a8fc 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -704,10 +704,10 @@ sub Encrypt {
return (0, $self->loc('Permission Denied')) unless $txn->CurrentUserCanSee;
return (0, $self->loc('Permission Denied'))
unless $txn->TicketObj->CurrentUserHasRight('ModifyTicket');
- return (0, $self->loc('GnuPG integration is disabled'))
- unless RT->Config->Get('GnuPG')->{'Enable'};
+ return (0, $self->loc('Cryptography is disabled'))
+ unless RT->Config->Get('Crypt')->{'Enable'};
return (0, $self->loc('Attachments encryption is disabled'))
- unless RT->Config->Get('GnuPG')->{'AllowEncryptDataInDB'};
+ unless RT->Config->Get('Crypt')->{'AllowEncryptDataInDB'};
require RT::Crypt::GnuPG;
@@ -766,8 +766,8 @@ sub Decrypt {
return (0, $self->loc('Permission Denied')) unless $txn->CurrentUserCanSee;
return (0, $self->loc('Permission Denied'))
unless $txn->TicketObj->CurrentUserHasRight('ModifyTicket');
- return (0, $self->loc('GnuPG integration is disabled'))
- unless RT->Config->Get('GnuPG')->{'Enable'};
+ return (0, $self->loc('Cryptography is disabled'))
+ unless RT->Config->Get('Crypt')->{'Enable'};
require RT::Crypt::GnuPG;
diff --git a/lib/RT/Crypt.pm b/lib/RT/Crypt.pm
index 69ceb8e..c19bdee 100644
--- a/lib/RT/Crypt.pm
+++ b/lib/RT/Crypt.pm
@@ -65,6 +65,11 @@ first one value from above list.
...
);
+You can allow users to encrypt data in the database using
+option C<AllowEncryptDataInDB>. By default it's disabled.
+Users must have rights to see and modify tickets to use
+this feature.
+
=cut
our @PROTOCOLS = ('GnuPG', 'SMIME');
diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index 611a319..2ae6aeb 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -138,13 +138,6 @@ it well.
=back
-=head3 Encrypting data in the database
-
-You can allow users to encrypt data in the database using
-option C<AllowEncryptDataInDB>. By default it's disabled.
-Users must have rights to see and modify tickets to use
-this feature.
-
=head2 %GnuPGOptions
Use this hash to set options of the 'gnupg' program. You can define almost any
diff --git a/share/html/Ticket/Elements/ShowTransaction b/share/html/Ticket/Elements/ShowTransaction
index e99149c..9ce355e 100755
--- a/share/html/Ticket/Elements/ShowTransaction
+++ b/share/html/Ticket/Elements/ShowTransaction
@@ -223,8 +223,8 @@ else {
. "</a>]";
}
if ( $can_modify
- && RT->Config->Get('GnuPG')->{'Enable'}
- && RT->Config->Get('GnuPG')->{'AllowEncryptDataInDB'}
+ && RT->Config->Get('Crypt')->{'Enable'}
+ && RT->Config->Get('Crypt')->{'AllowEncryptDataInDB'}
&& $ticket->CurrentUserHasRight('ForwardMessage')
) {
$titlebar_commands .=
diff --git a/t/crypt/gnupg/attachments-in-db.t b/t/crypt/gnupg/attachments-in-db.t
index 4f98c28..dc0d87b 100644
--- a/t/crypt/gnupg/attachments-in-db.t
+++ b/t/crypt/gnupg/attachments-in-db.t
@@ -9,7 +9,7 @@ use RT::Test::GnuPG
}
;
-RT->Config->Get('GnuPG')->{'AllowEncryptDataInDB'} = 1;
+RT->Config->Get('Crypt')->{'AllowEncryptDataInDB'} = 1;
RT::Test->import_gnupg_key('general at example.com', 'public');
RT::Test->import_gnupg_key('general at example.com', 'secret');
commit 3d4e06c17077999ed62c561b80b06b90a6e8bea4
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Jan 11 19:37:41 2012 +0400
encrypting/decrypting attachments in DB with SMIME
diff --git a/TODO.SMIME b/TODO.SMIME
index 464fccc..949abca 100644
--- a/TODO.SMIME
+++ b/TODO.SMIME
@@ -1,5 +1,3 @@
-* port RT::Attachment::{Encrypt,Decrypt} over new API with SMIME support
-
* continue with share//html/Ticket/Elements/ShowGnuPGStatus
* work harder on re-verification
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 260a8fc..864e33f 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -782,8 +782,20 @@ sub Decrypt {
return (1, $self->loc('Is not encrypted'));
}
+ my $queue = $txn->TicketObj->QueueObj;
+ my @addresses =
+ $queue->CorrespondAddress,
+ $queue->CommentAddress,
+ RT->Config->Get('CorrespondAddress'),
+ RT->Config->Get('CommentAddress')
+ ;
+
my $content = $self->Content;
- my %res = RT::Crypt->DecryptContent( Protocol => $protocol, Content => \$content );
+ my %res = RT::Crypt->DecryptContent(
+ Protocol => $protocol,
+ Content => \$content,
+ Recipients => \@addresses,
+ );
if ( $res{'exit_code'} ) {
return (0, $self->loc('GnuPG error. Contact with administrator'));
}
diff --git a/lib/RT/Crypt/SMIME.pm b/lib/RT/Crypt/SMIME.pm
index 4ea999f..9a61163 100644
--- a/lib/RT/Crypt/SMIME.pm
+++ b/lib/RT/Crypt/SMIME.pm
@@ -114,16 +114,67 @@ sub SignEncrypt {
my $entity = $args{'Entity'};
+ if ( $args{'Encrypt'} ) {
+ my %seen;
+ $args{'Recipients'} = [
+ grep !$seen{$_}++, map $_->address, map Email::Address->parse($_),
+ grep defined && length, map $entity->head->get($_), qw(To Cc Bcc)
+ ];
+ }
+
+ $entity->make_multipart('mixed', Force => 1);
+ my ($buf, %res) = $self->_SignEncrypt(
+ %args,
+ Content => \$entity->parts(0)->stringify,
+ );
+ unless ( $buf ) {
+ $entity->make_singlepart;
+ return %res;
+ }
+
+ my $tmpdir = File::Temp::tempdir( TMPDIR => 1, CLEANUP => 1 );
+ my $parser = MIME::Parser->new();
+ $parser->output_dir($tmpdir);
+ my $newmime = $parser->parse_data($$buf);
+
+ $entity->parts([$newmime]);
+ $entity->make_singlepart;
+
+ return %res;
+}
+
+sub SignEncryptContent {
+ my $self = shift;
+ my %args = (
+ Content => undef,
+ @_
+ );
+
+ my ($buf, %res) = $self->_SignEncrypt(%args);
+ ${ $args{'Content'} } = $$buf if $buf;
+ return %res;
+}
+
+sub _SignEncrypt {
+ my $self = shift;
+ my %args = (
+ Content => undef,
+
+ Sign => 1,
+ Signer => undef,
+ Passphrase => undef,
+
+ Encrypt => 1,
+ Recipients => [],
+
+ @_
+ );
+
my %res = (exit_code => 0, status => '');
my @keys;
if ( $args{'Encrypt'} ) {
- my @addresses =
- map $_->address,
- map Email::Address->parse($_),
- grep defined && length,
- map $entity->head->get($_),
- qw(To Cc Bcc);
+ my @addresses = @{ $args{'Recipients'} };
foreach my $address ( @addresses ) {
$RT::Logger->debug( "Considering encrypting message to " . $address );
@@ -163,7 +214,7 @@ sub SignEncrypt {
push @keys, $key_info{'info'}[0]{'Content'};
}
}
- return %res if $res{'exit_code'};
+ return (undef, %res) if $res{'exit_code'};
my $opts = RT->Config->Get('SMIME');
@@ -194,28 +245,19 @@ sub SignEncrypt {
);
}
- $entity->make_multipart('mixed', Force => 1);
my ($buf, $err) = ('', '');
{
local $ENV{'SMIME_PASS'} = $args{'Passphrase'};
local $SIG{'CHLD'} = 'DEFAULT';
safe_run_child { run3(
join( ' | ', @command ),
- \$entity->parts(0)->stringify,
+ $args{'Content'},
\$buf, \$err
) };
}
$RT::Logger->debug( "openssl stderr: " . $err ) if length $err;
- my $tmpdir = File::Temp::tempdir( TMPDIR => 1, CLEANUP => 1 );
- my $parser = MIME::Parser->new();
- $parser->output_dir($tmpdir);
- my $newmime = $parser->parse_data($buf);
-
- $entity->parts([$newmime]);
- $entity->make_singlepart;
-
- return %res;
+ return (\$buf, %res);
}
sub VerifyDecrypt {
@@ -362,37 +404,52 @@ sub DecryptRFC3851 {
my $self = shift;
my %args = (Data => undef, Queue => undef, @_ );
- my %res;
-
my $msg = $args{'Data'}->as_string;
- my %addresses;
- $addresses{lc $_}++ foreach
- map $_->address,
- map Email::Address->parse($_),
- @{$args{'Recipients'}};
-
- my $action = 'correspond';
- $action = 'comment' if grep defined && $_ eq 'comment', @{ $args{'Actions'}||[] };
- if ( $action eq 'correspond' ) {
- my $i = 1;
- $addresses{lc $_} += $i++ foreach (
- $args{'Queue'}->CorrespondAddress, RT->Config->Get('CorrespondAddress'),
- $args{'Queue'}->CommentAddress, RT->Config->Get('CommentAddress')
- );
- } else {
- my $i = 1;
- $addresses{lc $_} += $i++ foreach (
- $args{'Queue'}->CorrespondAddress, RT->Config->Get('CorrespondAddress'),
- $args{'Queue'}->CommentAddress, RT->Config->Get('CommentAddress'),
- );
- }
- my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
+ push @{ $args{'Recipients'} ||= [] },
+ $args{'Queue'}->CorrespondAddress, RT->Config->Get('CorrespondAddress'),
+ $args{'Queue'}->CommentAddress, RT->Config->Get('CommentAddress')
+ ;
- my $buf;
+ my ($buf, %res) = $self->_Decrypt( %args, Content => \$args{'Data'}->as_string );
+ return %res unless $buf;
+
+ my $res_entity = _extract_msg_from_buf( $buf, 1 );
+ $res_entity->make_multipart( 'mixed', Force => 1 );
+
+ $args{'Data'}->make_multipart( 'mixed', Force => 1 );
+ $args{'Data'}->parts([ $res_entity->parts ]);
+ $args{'Data'}->make_singlepart;
+
+ return %res;
+}
+
+sub DecryptContent {
+ my $self = shift;
+ my %args = (
+ Content => undef,
+ @_
+ );
+
+ my ($buf, %res) = $self->_Decrypt( %args );
+ ${ $args{'Content'} } = $$buf if $buf;
+ return %res;
+}
+
+sub _Decrypt {
+ my $self = shift;
+ my %args = (Content => undef, @_ );
+
+ my %seen;
+ my @addresses =
+ grep !$seen{lc $_}++, map $_->address, map Email::Address->parse($_),
+ grep length && defined, @{$args{'Recipients'}};
+
+ my ($buf, $encrypted_to, %res);
+
+ my $keyring = RT->Config->Get('SMIME')->{'Keyring'};
my $found_key = 0;
- my $encrypted_to;
- foreach my $address ( sort { $addresses{$b} <=> $addresses{$a} } grep length, keys %addresses ) {
+ foreach my $address ( @addresses ) {
my $key_file = File::Spec->catfile( $keyring, $address .'.pem' );
next unless -e $key_file && -r _;
@@ -407,7 +464,7 @@ sub DecryptRFC3851 {
? (qw(-passin env:SMIME_PASS))
: (),
) );
- safe_run_child { run3( $cmd, \$msg, \$buf, \$res{'stderr'} ) };
+ safe_run_child { run3( $cmd, $args{'Content'}, \$buf, \$res{'stderr'} ) };
unless ( $? ) {
$encrypted_to = $address;
last;
@@ -424,7 +481,7 @@ sub DecryptRFC3851 {
Message => 'Decryption failed',
EncryptedTo => $address,
});
- return %res;
+ return (undef, %res);
}
unless ( $found_key ) {
$res{'exit_code'} = 1;
@@ -434,23 +491,16 @@ sub DecryptRFC3851 {
Message => "Secret key is not available",
KeyType => 'secret',
});
- return %res;
+ return (undef, %res);
}
- my $res_entity = _extract_msg_from_buf( \$buf, 1 );
- $res_entity->make_multipart( 'mixed', Force => 1 );
-
- $args{'Data'}->make_multipart( 'mixed', Force => 1 );
- $args{'Data'}->parts([ $res_entity->parts ]);
- $args{'Data'}->make_singlepart;
-
$res{'status'} = $self->FormatStatus({
Operation => 'Decrypt', Status => 'DONE',
Message => 'Decryption process succeeded',
EncryptedTo => $encrypted_to,
});
- return %res;
+ return (\$buf, %res);
}
sub FormatStatus {
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list