summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Crypt/GnuPG.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Crypt/GnuPG.pm')
-rw-r--r--rt/lib/RT/Crypt/GnuPG.pm93
1 files changed, 65 insertions, 28 deletions
diff --git a/rt/lib/RT/Crypt/GnuPG.pm b/rt/lib/RT/Crypt/GnuPG.pm
index 5581df1..449b8ae 100644
--- a/rt/lib/RT/Crypt/GnuPG.pm
+++ b/rt/lib/RT/Crypt/GnuPG.pm
@@ -1026,46 +1026,62 @@ sub FindProtectedParts {
=cut
sub VerifyDecrypt {
- my %args = ( Entity => undef, Detach => 1, SetStatus => 1, @_ );
+ my %args = (
+ Entity => undef,
+ Detach => 1,
+ SetStatus => 1,
+ AddStatus => 0,
+ @_
+ );
my @protected = FindProtectedParts( Entity => $args{'Entity'} );
my @res;
# XXX: detaching may brake nested signatures
foreach my $item( grep $_->{'Type'} eq 'signed', @protected ) {
+ my $status_on;
if ( $item->{'Format'} eq 'RFC3156' ) {
push @res, { VerifyRFC3156( %$item, SetStatus => $args{'SetStatus'} ) };
if ( $args{'Detach'} ) {
$item->{'Top'}->parts( [ $item->{'Data'} ] );
$item->{'Top'}->make_singlepart;
}
- $item->{'Top'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Top'};
} elsif ( $item->{'Format'} eq 'Inline' ) {
push @res, { VerifyInline( %$item ) };
- $item->{'Data'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Data'};
} elsif ( $item->{'Format'} eq 'Attachment' ) {
push @res, { VerifyAttachment( %$item ) };
if ( $args{'Detach'} ) {
- $item->{'Top'}->parts( [ grep "$_" ne $item->{'Signature'}, $item->{'Top'}->parts ] );
+ $item->{'Top'}->parts( [
+ grep "$_" ne $item->{'Signature'}, $item->{'Top'}->parts
+ ] );
$item->{'Top'}->make_singlepart;
}
- $item->{'Data'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Data'};
+ }
+ if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
+ my $method = $args{'AddStatus'} ? 'add' : 'set';
+ $status_on->head->$method(
+ 'X-RT-GnuPG-Status' => $res[-1]->{'status'}
+ );
}
}
foreach my $item( grep $_->{'Type'} eq 'encrypted', @protected ) {
+ my $status_on;
if ( $item->{'Format'} eq 'RFC3156' ) {
push @res, { DecryptRFC3156( %$item ) };
- $item->{'Top'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Top'};
} elsif ( $item->{'Format'} eq 'Inline' ) {
push @res, { DecryptInline( %$item ) };
- $item->{'Data'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Data'};
} elsif ( $item->{'Format'} eq 'Attachment' ) {
push @res, { DecryptAttachment( %$item ) };
- $item->{'Data'}->head->set( 'X-RT-GnuPG-Status' => $res[-1]->{'status'} )
- if $args{'SetStatus'};
+ $status_on = $item->{'Data'};
+ }
+ if ( $args{'SetStatus'} || $args{'AddStatus'} ) {
+ my $method = $args{'AddStatus'} ? 'add' : 'set';
+ $status_on->head->$method(
+ 'X-RT-GnuPG-Status' => $res[-1]->{'status'}
+ );
}
}
return @res;
@@ -1290,11 +1306,12 @@ sub DecryptInline {
die "Entity has no body, never should happen";
}
+ my %res;
+
my ($had_literal, $in_block) = ('', 0);
my ($block_fh, $block_fn) = File::Temp::tempfile( UNLINK => 1 );
binmode $block_fh, ':raw';
- my %res;
while ( defined(my $str = $io->getline) ) {
if ( $in_block && $str =~ /^-----END PGP (?:MESSAGE|SIGNATURE)-----/ ) {
print $block_fh $str;
@@ -1335,6 +1352,26 @@ sub DecryptInline {
}
$io->close;
+ if ( $in_block ) {
+ # we're still in a block, this not bad not good. let's try to
+ # decrypt what we have, it can be just missing -----END PGP...
+ seek $block_fh, 0, 0;
+
+ my ($res_fh, $res_fn);
+ ($res_fh, $res_fn, %res) = _DecryptInlineBlock(
+ %args,
+ GnuPG => $gnupg,
+ BlockHandle => $block_fh,
+ );
+ return %res unless $res_fh;
+
+ print $tmp_fh "-----BEGIN OF PGP PROTECTED PART-----\n" if $had_literal;
+ while (my $buf = <$res_fh> ) {
+ print $tmp_fh $buf;
+ }
+ print $tmp_fh "-----END OF PART-----\n" if $had_literal;
+ }
+
seek $tmp_fh, 0, 0;
$args{'Data'}->bodyhandle( new MIME::Body::File $tmp_fn );
$args{'Data'}->{'__store_tmp_handle_to_avoid_early_cleanup'} = $tmp_fh;
@@ -2399,11 +2436,17 @@ sub Probe {
# it's general error system error or incorrect command, command is correct,
# but there is no way to get actuall error
if ( $? && ($? >> 8) != 2 ) {
- $RT::Logger->debug(
- "Probe for GPG failed."
+ my $msg = "Probe for GPG failed."
." Process exitted with code ". ($? >> 8)
. ($? & 127 ? (" as recieved signal ". ($? & 127)) : '')
- );
+ . ".";
+ foreach ( qw(stderr logger status) ) {
+ my $tmp = do { local $/; readline $handle{$_} };
+ next unless $tmp && $tmp =~ /\S/s;
+ close $handle{$_};
+ $msg .= "\n$_:\n$tmp\n";
+ }
+ $RT::Logger->debug( $msg );
return 0;
}
return 1;
@@ -2411,16 +2454,10 @@ sub Probe {
sub _make_gpg_handles {
- my %handle_map = (
- stdin => IO::Handle->new(),
- stdout => IO::Handle->new(),
- stderr => IO::Handle->new(),
- logger => IO::Handle->new(),
- status => IO::Handle->new(),
- command => IO::Handle->new(),
-
-
- @_);
+ my %handle_map = (@_);
+ $handle_map{$_} = IO::Handle->new
+ foreach grep !defined $handle_map{$_},
+ qw(stdin stdout stderr logger status command);
my $handles = GnuPG::Handles->new(%handle_map);
return ($handles, \%handle_map);