| line | stmt | bran | path | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | #  Interface.pm | 
| 2 |  |  |  |  |  |  |  | #    - providing an object-oriented approach to interacting with GnuPG | 
| 3 |  |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  |  | #  Copyright (C) 2000 Frank J. Tobin <ftobin@cpan.org> | 
| 5 |  |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  |  | #  This module is free software; you can redistribute it and/or modify it | 
| 7 |  |  |  |  |  |  |  | #  under the same terms as Perl itself. | 
| 8 |  |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  |  | #  This program is distributed in the hope that it will be useful, | 
| 10 |  |  |  |  |  |  |  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11 |  |  |  |  |  |  |  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
| 12 |  |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  |  | package GnuPG::Interface; | 
| 15 | 71 |  |  |  | 71 |  | 3881733 | use Moo; | 
|  | 71 |  |  |  |  |  | 678994 |  | 
|  | 71 |  |  |  |  |  | 371 |  | 
| 16 | 71 |  |  |  | 71 |  | 139406 | use MooX::late; | 
|  | 71 |  |  |  |  |  | 1906667 |  | 
|  | 71 |  |  |  |  |  | 515 |  | 
| 17 |  |  |  |  |  |  |  | with qw(GnuPG::HashInit); | 
| 18 |  |  |  |  |  |  |  |  | 
| 19 | 71 |  |  |  | 71 |  | 9374544 | use English qw( -no_match_vars ); | 
|  | 71 |  |  |  |  |  | 294 |  | 
|  | 71 |  |  |  |  |  | 655 |  | 
| 20 | 71 |  |  |  | 71 |  | 29271 | use Carp; | 
|  | 71 |  |  |  |  |  | 188 |  | 
|  | 71 |  |  |  |  |  | 5018 |  | 
| 21 | 71 |  |  |  | 71 |  | 516 | use Fcntl; | 
|  | 71 |  |  |  |  |  | 146 |  | 
|  | 71 |  |  |  |  |  | 16823 |  | 
| 22 | 71 |  |  |  | 71 |  | 548 | use vars qw( $VERSION ); | 
|  | 71 |  |  |  |  |  | 151 |  | 
|  | 71 |  |  |  |  |  | 4072 |  | 
| 23 | 71 |  |  |  | 71 |  | 3232 | use Fatal qw( open close pipe fcntl ); | 
|  | 71 |  |  |  |  |  | 58794 |  | 
|  | 71 |  |  |  |  |  | 757 |  | 
| 24 | 71 |  |  |  | 71 |  | 146673 | use Class::Struct; | 
|  | 71 |  |  |  |  |  | 8090 |  | 
|  | 71 |  |  |  |  |  | 672 |  | 
| 25 | 71 |  |  |  | 71 |  | 8173 | use IO::Handle; | 
|  | 71 |  |  |  |  |  | 175 |  | 
|  | 71 |  |  |  |  |  | 3403 |  | 
| 26 |  |  |  |  |  |  |  |  | 
| 27 | 71 |  |  |  | 71 |  | 87922 | use Math::BigInt try => 'GMP'; | 
|  | 71 |  |  |  |  |  | 1837650 |  | 
|  | 71 |  |  |  |  |  | 392 |  | 
| 28 | 71 |  |  |  | 71 |  | 1724668 | use GnuPG::Options; | 
|  | 71 |  |  |  |  |  | 1282 |  | 
|  | 71 |  |  |  |  |  | 3130 |  | 
| 29 | 71 |  |  |  | 71 |  | 39533 | use GnuPG::Handles; | 
|  | 71 |  |  |  |  |  | 282 |  | 
|  | 71 |  |  |  |  |  | 2761 |  | 
| 30 | 71 |  |  |  | 71 |  | 574 | use Scalar::Util 'tainted'; | 
|  | 71 |  |  |  |  |  | 142 |  | 
|  | 71 |  |  |  |  |  | 143630 |  | 
| 31 |  |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  |  | $VERSION = '1.01'; | 
| 33 |  |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  |  | has passphrase => ( | 
| 35 |  |  |  |  |  |  |  | isa     => 'Any', | 
| 36 |  |  |  |  |  |  |  | is      => 'rw', | 
| 37 |  |  |  |  |  |  |  | clearer => 'clear_passphrase', | 
| 38 |  |  |  |  |  |  |  | ); | 
| 39 |  |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  |  | has call => ( | 
| 41 |  |  |  |  |  |  |  | isa     => 'Any', | 
| 42 |  |  |  |  |  |  |  | is      => 'rw', | 
| 43 |  |  |  |  |  |  |  | trigger => 1, | 
| 44 |  |  |  |  |  |  |  | clearer => 'clear_call', | 
| 45 |  |  |  |  |  |  |  | ); | 
| 46 |  |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | # NB: GnuPG versions | 
| 48 |  |  |  |  |  |  |  | # | 
| 49 |  |  |  |  |  |  |  | # There are now two supported versions of GnuPG: legacy 1.4 and stable 2.2 | 
| 50 |  |  |  |  |  |  |  | # They are detected and each behave slightly differently. | 
| 51 |  |  |  |  |  |  |  | # | 
| 52 |  |  |  |  |  |  |  | # When using features specific to branches, check that the system's | 
| 53 |  |  |  |  |  |  |  | # version of gpg corresponds to the branch. | 
| 54 |  |  |  |  |  |  |  | # | 
| 55 |  |  |  |  |  |  |  | # legacy: 1.4 | 
| 56 |  |  |  |  |  |  |  | # stable: >= 2.2 | 
| 57 |  |  |  |  |  |  |  | # | 
| 58 |  |  |  |  |  |  |  | # You can find examples of version comparison in the tests. | 
| 59 |  |  |  |  |  |  |  | has version => ( | 
| 60 |  |  |  |  |  |  |  | isa      => 'Str', | 
| 61 |  |  |  |  |  |  |  | is       => 'ro', | 
| 62 |  |  |  |  |  |  |  | reader   => 'version', | 
| 63 |  |  |  |  |  |  |  | writer   => '_set_version', | 
| 64 |  |  |  |  |  |  |  | ); | 
| 65 |  |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  |  | has options => ( | 
| 67 |  |  |  |  |  |  |  | isa        => 'GnuPG::Options', | 
| 68 |  |  |  |  |  |  |  | is         => 'rw', | 
| 69 |  |  |  |  |  |  |  | lazy_build => 1, | 
| 70 |  |  |  |  |  |  |  | ); | 
| 71 |  |  |  |  |  |  |  |  | 
| 72 | 77 |  |  |  | 77 |  | 17538 | sub _build_options { GnuPG::Options->new() } | 
| 73 |  |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  |  | # deprecated! | 
| 75 | 4 |  |  |  | 4 | 0 | 1068 | sub gnupg_call { shift->call(@_); } | 
| 76 |  |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  |  | sub BUILD { | 
| 78 | 85 |  |  |  | 85 | 0 | 378090 | my ( $self, $args ) = @_; | 
| 79 | 85 |  |  |  |  |  | 1248 | $self->hash_init( call => 'gpg', %$args ); | 
| 80 |  |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  |  | struct( | 
| 83 |  |  |  |  |  |  |  | fh_setup => { | 
| 84 |  |  |  |  |  |  |  | parent_end       => '$', child_end      => '$', | 
| 85 |  |  |  |  |  |  |  | direct           => '$', is_std         => '$', | 
| 86 |  |  |  |  |  |  |  | parent_is_source => '$', name_shows_dup => '$', | 
| 87 |  |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | ); | 
| 89 |  |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  |  | # Update version if "call" is updated | 
| 91 |  |  |  |  |  |  |  | sub _trigger_call { | 
| 92 | 111 |  |  |  | 111 |  | 29981 | my ( $self, $gpg ) = @_; | 
| 93 | 111 |  |  |  |  |  | 598 | $self->_set_version( $self->_version() ); | 
| 94 |  |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  |  | ################################################################# | 
| 97 |  |  |  |  |  |  |  | # real worker functions | 
| 98 |  |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  |  | # This function does any 'extra' stuff that the user might | 
| 100 |  |  |  |  |  |  |  | # not want to handle himself, such as passing in the passphrase | 
| 101 |  |  |  |  |  |  |  | sub wrap_call( $% ) { | 
| 102 | 223 |  |  |  | 223 | 1 | 14425 | my ( $self, %args ) = @_; | 
| 103 |  |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  |  | my $handles = $args{handles} | 
| 105 | 223 | 50 |  |  |  |  | 1355 | or croak 'error: no handles defined'; | 
| 106 |  |  |  |  |  |  |  |  | 
| 107 | 223 | 100 |  |  |  |  | 5204 | $handles->stdin('<&STDIN')   unless $handles->stdin(); | 
| 108 | 223 | 50 |  |  |  |  | 12066 | $handles->stdout('>&STDOUT') unless $handles->stdout(); | 
| 109 | 223 | 100 |  |  |  |  | 6870 | $handles->stderr('>&STDERR') unless $handles->stderr(); | 
| 110 |  |  |  |  |  |  |  |  | 
| 111 | 223 | 100 |  |  |  |  | 12731 | $self->passphrase("\n") unless $self->passphrase(); | 
| 112 |  |  |  |  |  |  |  |  | 
| 113 | 223 | 100 |  | 66 |  |  | 7749 | my $needs_passphrase_handled | 
| 114 |  |  |  |  |  |  |  | = ( $self->passphrase() =~ m/\S/ and not $handles->passphrase() ) ? 1 : 0; | 
| 115 |  |  |  |  |  |  |  |  | 
| 116 | 223 | 100 |  |  |  |  | 9711 | if ($needs_passphrase_handled) { | 
| 117 | 174 |  |  |  |  |  | 1063 | $handles->passphrase( IO::Handle->new() ); | 
| 118 |  |  |  |  |  |  |  | } | 
| 119 |  |  |  |  |  |  |  |  | 
| 120 | 223 |  |  |  |  |  | 14307 | my $pid = $self->fork_attach_exec(%args); | 
| 121 |  |  |  |  |  |  |  |  | 
| 122 | 173 | 100 |  |  |  |  | 2933 | if ($needs_passphrase_handled) { | 
| 123 | 136 |  |  |  |  |  | 8367 | my $passphrase_handle = $handles->passphrase(); | 
| 124 | 136 |  |  |  |  |  | 8073 | print $passphrase_handle $self->passphrase(); | 
| 125 | 136 |  |  |  |  |  | 9663 | close $passphrase_handle; | 
| 126 |  |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  |  | # We put this in in case the user wants to re-use this object | 
| 128 | 136 |  |  |  |  |  | 7102 | $handles->clear_passphrase(); | 
| 129 |  |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  |  | 
| 131 | 173 |  |  |  |  |  | 8013 | return $pid; | 
| 132 |  |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  |  | # does does command-line creation, forking, and execcing | 
| 135 |  |  |  |  |  |  |  | # the reasing cli creation is done here is because we should | 
| 136 |  |  |  |  |  |  |  | # fork before finding the fd's for stuff like --status-fd | 
| 137 |  |  |  |  |  |  |  | sub fork_attach_exec( $% ) { | 
| 138 | 223 |  |  |  | 223 | 0 | 1150 | my ( $self, %args ) = @_; | 
| 139 |  |  |  |  |  |  |  |  | 
| 140 | 223 | 50 |  |  |  |  | 983 | my $handles = $args{handles} or croak 'no GnuPG::Handles passed'; | 
| 141 | 223 |  |  |  |  |  | 484 | my $use_loopback_pinentry = 0; | 
| 142 |  |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  |  | # Don't use loopback pintentry for legacy (1.4) GPG | 
| 144 |  |  |  |  |  |  |  | # | 
| 145 |  |  |  |  |  |  |  | # Check that $version is populated before running cmp_version. If | 
| 146 |  |  |  |  |  |  |  | # we are invoked as part of BUILD to populate $version, then any | 
| 147 |  |  |  |  |  |  |  | # methods that depend on $version will fail. We don't care about | 
| 148 |  |  |  |  |  |  |  | # loopback when we're called just to check gpg version. | 
| 149 | 223 | 50 |  | 100 |  |  | 4959 | $use_loopback_pinentry = 1 | 
|  |  |  |  | 66 |  |  |  |  | 
| 150 |  |  |  |  |  |  |  | if ($handles->passphrase() && $self->version && $self->cmp_version($self->version, '2.2') > 0 ); | 
| 151 |  |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  |  | # deprecation support | 
| 153 | 223 |  |  | 66 |  |  | 2267 | $args{commands} ||= $args{gnupg_commands}; | 
| 154 |  |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  |  | my @commands | 
| 156 | 223 |  |  |  |  |  | 1316 | = ref $args{commands} ? @{ $args{commands} } : ( $args{commands} ) | 
| 157 | 223 | 50 |  |  |  |  | 1540 | or croak "no gnupg commands passed"; | 
|  |  | 50 |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  |  | # deprecation support | 
| 160 | 223 |  |  | 100 |  |  | 1988 | $args{command_args} ||= $args{gnupg_command_args}; | 
| 161 |  |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  |  | my @command_args | 
| 163 |  |  |  |  |  |  |  | = ref $args{command_args} | 
| 164 | 15 |  |  |  |  |  | 76 | ? @{ $args{command_args} } | 
| 165 | 223 | 100 |  | 100 |  |  | 1598 | : ( $args{command_args} || () ); | 
| 166 | 223 | 100 |  | 66 |  |  | 1328 | unshift @command_args, "--" | 
| 167 |  |  |  |  |  |  |  | if @command_args and $command_args[0] ne "--"; | 
| 168 |  |  |  |  |  |  |  |  | 
| 169 | 223 |  |  |  |  |  | 483 | my %fhs; | 
| 170 | 223 |  |  |  |  |  | 984 | foreach my $fh_name ( | 
| 171 |  |  |  |  |  |  |  | qw( stdin stdout stderr status | 
| 172 |  |  |  |  |  |  |  | logger passphrase command | 
| 173 |  |  |  |  |  |  |  | ) | 
| 174 |  |  |  |  |  |  |  | ) { | 
| 175 | 1561 | 100 |  |  |  |  | 40350 | my $fh = $handles->$fh_name() or next; | 
| 176 | 852 |  |  |  |  |  | 19963 | $fhs{$fh_name} = fh_setup->new(); | 
| 177 | 852 |  |  |  |  |  | 56978 | $fhs{$fh_name}->parent_end($fh); | 
| 178 |  |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  |  | 
| 180 | 223 |  |  |  |  |  | 2718 | foreach my $fh_name (qw( stdin stdout stderr )) { | 
| 181 | 669 |  |  |  |  |  | 12546 | $fhs{$fh_name}->is_std(1); | 
| 182 |  |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  |  |  | 
| 184 | 223 |  |  |  |  |  | 1773 | foreach my $fh_name (qw( stdin passphrase command )) { | 
| 185 | 669 | 100 |  |  |  |  | 3979 | my $entry = $fhs{$fh_name} or next; | 
| 186 | 402 |  |  |  |  |  | 6037 | $entry->parent_is_source(1); | 
| 187 |  |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  |  | # Below is code derived heavily from | 
| 190 |  |  |  |  |  |  |  | # Marc Horowitz's IPC::Open3, a base Perl module | 
| 191 | 223 |  |  |  |  |  | 1002 | foreach my $fh_name ( keys %fhs ) { | 
| 192 | 852 |  |  |  |  |  | 15428 | my $entry = $fhs{$fh_name}; | 
| 193 |  |  |  |  |  |  |  |  | 
| 194 | 852 |  |  |  |  |  | 12243 | my $parent_end = $entry->parent_end(); | 
| 195 | 852 |  |  |  |  |  | 8526 | my $name_shows_dup = ( $parent_end =~ s/^[<>]&// ); | 
| 196 | 852 |  |  |  |  |  | 13301 | $entry->parent_end($parent_end); | 
| 197 |  |  |  |  |  |  |  |  | 
| 198 | 852 |  |  |  |  |  | 17126 | $entry->name_shows_dup($name_shows_dup); | 
| 199 |  |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  |  | $entry->direct( $name_shows_dup | 
| 201 |  |  |  |  |  |  |  | || $handles->options($fh_name)->{direct} | 
| 202 | 852 |  |  | 100 |  |  | 12300 | || 0 ); | 
| 203 |  |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  |  |  | 
| 205 | 223 |  |  |  |  |  | 5279 | foreach my $fh_name ( keys %fhs ) { | 
| 206 | 852 |  |  |  |  |  | 25840 | $fhs{$fh_name}->child_end( IO::Handle->new() ); | 
| 207 |  |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  |  | 
| 209 | 223 |  |  |  |  |  | 9135 | foreach my $fh_name ( keys %fhs ) { | 
| 210 | 852 |  |  |  |  |  | 24794 | my $entry = $fhs{$fh_name}; | 
| 211 | 852 | 100 |  |  |  |  | 14975 | next if $entry->direct(); | 
| 212 |  |  |  |  |  |  |  |  | 
| 213 | 590 |  |  |  |  |  | 4832 | my $reader_end; | 
| 214 |  |  |  |  |  |  |  | my $writer_end; | 
| 215 | 590 | 100 |  |  |  |  | 8796 | if ( $entry->parent_is_source() ) { | 
| 216 | 271 |  |  |  |  |  | 5503 | $reader_end = $entry->child_end(); | 
| 217 | 271 |  |  |  |  |  | 5225 | $writer_end = $entry->parent_end(); | 
| 218 |  |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | else { | 
| 220 | 319 |  |  |  |  |  | 6856 | $reader_end = $entry->parent_end(); | 
| 221 | 319 |  |  |  |  |  | 6424 | $writer_end = $entry->child_end(); | 
| 222 |  |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  |  |  | 
| 224 | 590 |  |  |  |  |  | 12820 | pipe $reader_end, $writer_end; | 
| 225 |  |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  |  | 
| 227 | 223 |  |  |  |  |  | 357959 | my $pid = fork; | 
| 228 |  |  |  |  |  |  |  |  | 
| 229 | 223 | 50 |  |  |  |  | 13796 | die "fork failed: $ERRNO" unless defined $pid; | 
| 230 |  |  |  |  |  |  |  |  | 
| 231 | 223 | 100 |  |  |  |  | 7075 | if ( $pid == 0 )    # child | 
| 232 |  |  |  |  |  |  |  | { | 
| 233 |  |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  |  | # these are for safety later to help lessen autovifying, | 
| 235 |  |  |  |  |  |  |  | # speed things up, and make the code smaller | 
| 236 | 50 |  |  |  |  |  | 4234 | my $stdin  = $fhs{stdin}; | 
| 237 | 50 |  |  |  |  |  | 1725 | my $stdout = $fhs{stdout}; | 
| 238 | 50 |  |  |  |  |  | 1458 | my $stderr = $fhs{stderr}; | 
| 239 |  |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  |  | # Paul Walmsley says: | 
| 241 |  |  |  |  |  |  |  | # Perl 5.6's POSIX.pm has a typo in it that prevents us from | 
| 242 |  |  |  |  |  |  |  | # importing STDERR_FILENO. So we resort to requiring it. | 
| 243 | 50 |  |  |  |  |  | 93391 | require POSIX; | 
| 244 |  |  |  |  |  |  |  |  | 
| 245 | 50 |  |  |  |  |  | 385361 | my $standard_out | 
| 246 |  |  |  |  |  |  |  | = IO::Handle->new_from_fd( &POSIX::STDOUT_FILENO, 'w' ); | 
| 247 | 50 |  |  |  |  |  | 14589 | my $standard_in | 
| 248 |  |  |  |  |  |  |  | = IO::Handle->new_from_fd( &POSIX::STDIN_FILENO, 'r' ); | 
| 249 |  |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  |  | # Paul Walmsley says: | 
| 251 |  |  |  |  |  |  |  | # this mess is due to a typo in POSIX.pm on Perl 5.6 | 
| 252 | 50 |  |  |  |  |  | 4013 | my $stderr_fd = eval {&POSIX::STDERR_FILENO}; | 
|  | 50 |  |  |  |  |  | 461 |  | 
| 253 | 50 | 50 |  |  |  |  | 533 | $stderr_fd = 2 unless defined $stderr_fd; | 
| 254 | 50 |  |  |  |  |  | 624 | my $standard_err = IO::Handle->new_from_fd( $stderr_fd, 'w' ); | 
| 255 |  |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  |  | # If she wants to dup the kid's stderr onto her stdout I need to | 
| 257 |  |  |  |  |  |  |  | # save a copy of her stdout before I put something else there. | 
| 258 | 50 | 50 |  | 66 |  |  | 6616 | if (    $stdout->parent_end() ne $stderr->parent_end() | 
|  |  |  |  | 66 |  |  |  |  | 
| 259 |  |  |  |  |  |  |  | and $stderr->direct() | 
| 260 |  |  |  |  |  |  |  | and my_fileno( $stderr->parent_end() ) | 
| 261 |  |  |  |  |  |  |  | == my_fileno($standard_out) ) { | 
| 262 | 0 |  |  |  |  |  | 0 | my $tmp = IO::Handle->new(); | 
| 263 | 0 |  |  |  |  |  | 0 | open $tmp, '>&' . my_fileno( $stderr->parent_end() ); | 
| 264 | 0 |  |  |  |  |  | 0 | $stderr->parent_end($tmp); | 
| 265 |  |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  |  | 
| 267 | 50 | 100 |  |  |  |  | 7299 | if ( $stdin->direct() ) { | 
| 268 | 19 | 100 |  |  |  |  | 604 | open $standard_in, '<&' . my_fileno( $stdin->parent_end() ) | 
| 269 |  |  |  |  |  |  |  | unless my_fileno($standard_in) | 
| 270 |  |  |  |  |  |  |  | == my_fileno( $stdin->parent_end() ); | 
| 271 |  |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | else { | 
| 273 | 31 |  |  |  |  |  | 1083 | close $stdin->parent_end(); | 
| 274 | 31 |  |  |  |  |  | 4470 | open $standard_in, '<&=' . my_fileno( $stdin->child_end() ); | 
| 275 |  |  |  |  |  |  |  | } | 
| 276 |  |  |  |  |  |  |  |  | 
| 277 | 50 | 100 |  |  |  |  | 4392 | if ( $stdout->direct() ) { | 
| 278 | 5 | 50 |  |  |  |  | 66 | open $standard_out, '>&' . my_fileno( $stdout->parent_end() ) | 
| 279 |  |  |  |  |  |  |  | unless my_fileno($standard_out) | 
| 280 |  |  |  |  |  |  |  | == my_fileno( $stdout->parent_end() ); | 
| 281 |  |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | else { | 
| 283 | 45 |  |  |  |  |  | 1304 | close $stdout->parent_end(); | 
| 284 | 45 |  |  |  |  |  | 3622 | open $standard_out, '>&=' . my_fileno( $stdout->child_end() ); | 
| 285 |  |  |  |  |  |  |  | } | 
| 286 |  |  |  |  |  |  |  |  | 
| 287 | 50 | 50 |  |  |  |  | 3546 | if ( $stdout->parent_end() ne $stderr->parent_end() ) { | 
| 288 |  |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  |  | # I have to use a fileno here because in this one case | 
| 290 |  |  |  |  |  |  |  | # I'm doing a dup but the filehandle might be a reference | 
| 291 |  |  |  |  |  |  |  | # (from the special case above). | 
| 292 | 50 | 100 |  |  |  |  | 1667 | if ( $stderr->direct() ) { | 
| 293 | 14 | 50 |  |  |  |  | 208 | open $standard_err, '>&' . my_fileno( $stderr->parent_end() ) | 
| 294 |  |  |  |  |  |  |  | unless my_fileno($standard_err) | 
| 295 |  |  |  |  |  |  |  | == my_fileno( $stderr->parent_end() ); | 
| 296 |  |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | else { | 
| 298 | 36 |  |  |  |  |  | 1177 | close $stderr->parent_end(); | 
| 299 | 36 |  |  |  |  |  | 2650 | open $standard_err, '>&=' . my_fileno( $stderr->child_end() ); | 
| 300 |  |  |  |  |  |  |  | } | 
| 301 |  |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  |  | else { | 
| 303 | 0 | 0 |  |  |  |  | 0 | open $standard_err, '>&STDOUT' | 
| 304 |  |  |  |  |  |  |  | unless my_fileno($standard_err) == my_fileno($standard_out); | 
| 305 |  |  |  |  |  |  |  | } | 
| 306 |  |  |  |  |  |  |  |  | 
| 307 | 50 |  |  |  |  |  | 2262 | foreach my $fh_name ( keys %fhs ) { | 
| 308 | 191 |  |  |  |  |  | 7190 | my $entry = $fhs{$fh_name}; | 
| 309 | 191 | 100 |  |  |  |  | 4125 | next if $entry->is_std(); | 
| 310 |  |  |  |  |  |  |  |  | 
| 311 | 41 |  |  |  |  |  | 1019 | my $parent_end = $entry->parent_end(); | 
| 312 | 41 |  |  |  |  |  | 1007 | my $child_end  = $entry->child_end(); | 
| 313 |  |  |  |  |  |  |  |  | 
| 314 | 41 | 100 |  |  |  |  | 1097 | if ( $entry->direct() ) { | 
| 315 | 1 | 50 |  |  |  |  | 36 | if ( $entry->name_shows_dup() ) { | 
| 316 | 0 | 0 |  |  |  |  | 0 | my $open_prefix | 
| 317 |  |  |  |  |  |  |  | = $entry->parent_is_source() ? '<&' : '>&'; | 
| 318 | 0 |  |  |  |  |  | 0 | open $child_end, $open_prefix . $parent_end; | 
| 319 |  |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  |  | else { | 
| 321 | 1 |  |  |  |  |  | 12 | $child_end = $parent_end; | 
| 322 | 1 |  |  |  |  |  | 16 | $entry->child_end($child_end); | 
| 323 |  |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | } | 
| 325 |  |  |  |  |  |  |  | else { | 
| 326 | 40 |  |  |  |  |  | 1014 | close $parent_end; | 
| 327 |  |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  |  | # we want these fh's to stay open after the exec | 
| 330 | 41 |  |  |  |  |  | 2495 | fcntl $child_end, F_SETFD, 0; | 
| 331 |  |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  |  | # now set the options for the call to GnuPG | 
| 333 | 41 |  |  |  |  |  | 1437 | my $fileno = my_fileno($child_end); | 
| 334 | 41 |  |  |  |  |  | 230 | my $option = $fh_name . '_fd'; | 
| 335 | 41 |  |  |  |  |  | 2091 | $self->options->$option($fileno); | 
| 336 |  |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  |  | 
| 338 | 50 |  |  |  |  |  | 5178 | my @args = $self->options->get_args(); | 
| 339 | 50 | 50 |  |  |  |  | 466 | push @args, '--pinentry-mode', 'loopback' | 
| 340 |  |  |  |  |  |  |  | if $use_loopback_pinentry; | 
| 341 |  |  |  |  |  |  |  |  | 
| 342 | 50 |  |  |  |  |  | 3058 | my @command = ( | 
| 343 |  |  |  |  |  |  |  | $self->call(), @args, | 
| 344 |  |  |  |  |  |  |  | @commands,     @command_args | 
| 345 |  |  |  |  |  |  |  | ); | 
| 346 |  |  |  |  |  |  |  |  | 
| 347 | 50 | 50 |  |  |  |  | 2667 | local $ENV{PATH} if tainted $ENV{PATH}; | 
| 348 | 50 | 0 |  |  |  |  | 0 | exec @command or die "exec() error: $ERRNO"; | 
| 349 |  |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  |  | # parent | 
| 352 |  |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  |  | # close the child end of any pipes (non-direct stuff) | 
| 354 | 173 |  |  |  |  |  | 16025 | foreach my $fh_name ( keys %fhs ) { | 
| 355 | 661 |  |  |  |  |  | 46431 | my $entry = $fhs{$fh_name}; | 
| 356 | 661 | 100 |  |  |  |  | 51780 | close $entry->child_end() unless $entry->direct(); | 
| 357 |  |  |  |  |  |  |  | } | 
| 358 |  |  |  |  |  |  |  |  | 
| 359 | 173 |  |  |  |  |  | 8076 | foreach my $fh_name ( keys %fhs ) { | 
| 360 | 661 |  |  |  |  |  | 3696 | my $entry = $fhs{$fh_name}; | 
| 361 | 661 | 100 |  |  |  |  | 13720 | next unless $entry->parent_is_source(); | 
| 362 |  |  |  |  |  |  |  |  | 
| 363 | 312 |  |  |  |  |  | 9187 | my $parent_end = $entry->parent_end(); | 
| 364 |  |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  |  | # close any writing handles if they were a dup | 
| 366 |  |  |  |  |  |  |  | #any real reason for this?  It bombs if we're doing | 
| 367 |  |  |  |  |  |  |  | #the automagic >& stuff. | 
| 368 |  |  |  |  |  |  |  | #close $parent_end if $entry->direct(); | 
| 369 |  |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  |  | # unbuffer pipes | 
| 371 | 312 | 50 |  |  |  |  | 13132 | select( ( select($parent_end), $OUTPUT_AUTOFLUSH = 1 )[0] ) | 
| 372 |  |  |  |  |  |  |  | if $parent_end; | 
| 373 |  |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  |  | 
| 375 | 173 |  |  |  |  |  | 41126 | return $pid; | 
| 376 |  |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  |  | sub my_fileno { | 
| 379 | 71 |  |  |  | 71 |  | 731 | no strict 'refs'; | 
|  | 71 |  |  |  |  |  | 183 |  | 
|  | 71 |  |  |  |  |  | 231622 |  | 
| 380 | 271 |  |  |  | 271 | 0 | 4441 | my ($fh) = @_; | 
| 381 | 271 | 50 |  |  |  |  | 857 | croak "fh is undefined" unless defined $fh; | 
| 382 | 271 | 50 |  |  |  |  | 2159 | return $1 if $fh =~ /^=?(\d+)$/;    # is it a fd in itself? | 
| 383 | 271 |  |  |  |  |  | 893 | my $fileno = fileno $fh; | 
| 384 | 271 | 50 |  |  |  |  | 707 | croak "error determining fileno for $fh: $ERRNO" unless defined $fileno; | 
| 385 | 271 |  |  |  |  |  | 5785 | return $fileno; | 
| 386 |  |  |  |  |  |  |  | } | 
| 387 |  |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  |  | sub unescape_string { | 
| 390 | 19 |  |  |  | 19 | 0 | 46 | my($str) = splice(@_); | 
| 391 | 19 |  |  |  |  |  | 51 | $str =~ s/\\x(..)/chr(hex($1))/eg; | 
|  | 0 |  |  |  |  |  | 0 |  | 
| 392 | 19 |  |  |  |  |  | 419 | return $str; | 
| 393 |  |  |  |  |  |  |  | } | 
| 394 |  |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  |  | ################################################################### | 
| 396 |  |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  |  | sub get_public_keys ( $@ ) { | 
| 398 | 4 |  |  |  | 4 | 1 | 5672 | my ( $self, @key_ids ) = @_; | 
| 399 |  |  |  |  |  |  |  |  | 
| 400 | 4 |  |  |  |  |  | 120 | return $self->get_keys( | 
| 401 |  |  |  |  |  |  |  | commands     => ['--list-public-keys'], | 
| 402 |  |  |  |  |  |  |  | command_args => [@key_ids], | 
| 403 |  |  |  |  |  |  |  | ); | 
| 404 |  |  |  |  |  |  |  | } | 
| 405 |  |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  |  | sub get_secret_keys ( $@ ) { | 
| 407 | 2 |  |  |  | 2 | 1 | 2352 | my ( $self, @key_ids ) = @_; | 
| 408 |  |  |  |  |  |  |  |  | 
| 409 | 2 |  |  |  |  |  | 32 | return $self->get_keys( | 
| 410 |  |  |  |  |  |  |  | commands     => ['--list-secret-keys'], | 
| 411 |  |  |  |  |  |  |  | command_args => [@key_ids], | 
| 412 |  |  |  |  |  |  |  | ); | 
| 413 |  |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  |  | sub get_public_keys_with_sigs ( $@ ) { | 
| 416 | 2 |  |  |  | 2 | 1 | 1762 | my ( $self, @key_ids ) = @_; | 
| 417 |  |  |  |  |  |  |  |  | 
| 418 | 2 |  |  |  |  |  | 12 | return $self->get_keys( | 
| 419 |  |  |  |  |  |  |  | commands     => ['--check-sigs'], | 
| 420 |  |  |  |  |  |  |  | command_args => [@key_ids], | 
| 421 |  |  |  |  |  |  |  | ); | 
| 422 |  |  |  |  |  |  |  | } | 
| 423 |  |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  |  | sub get_keys { | 
| 425 | 8 |  |  |  | 8 | 0 | 70 | my ( $self, %args ) = @_; | 
| 426 |  |  |  |  |  |  |  |  | 
| 427 | 8 |  |  |  |  |  | 252 | my $saved_options = $self->options(); | 
| 428 | 8 |  |  |  |  |  | 292 | my $new_options   = $self->options->copy(); | 
| 429 | 8 |  |  |  |  |  | 378 | $self->options($new_options); | 
| 430 | 8 |  |  |  |  |  | 618 | $self->options->push_extra_args( | 
| 431 |  |  |  |  |  |  |  | '--with-colons', | 
| 432 |  |  |  |  |  |  |  | '--fixed-list-mode', | 
| 433 |  |  |  |  |  |  |  | '--with-fingerprint', | 
| 434 |  |  |  |  |  |  |  | '--with-fingerprint', | 
| 435 |  |  |  |  |  |  |  | '--with-key-data', | 
| 436 |  |  |  |  |  |  |  | ); | 
| 437 |  |  |  |  |  |  |  |  | 
| 438 | 8 |  |  |  |  |  | 1026 | my $stdin  = IO::Handle->new(); | 
| 439 | 8 |  |  |  |  |  | 206 | my $stdout = IO::Handle->new(); | 
| 440 |  |  |  |  |  |  |  |  | 
| 441 | 8 |  |  |  |  |  | 380 | my $handles = GnuPG::Handles->new( | 
| 442 |  |  |  |  |  |  |  | stdin  => $stdin, | 
| 443 |  |  |  |  |  |  |  | stdout => $stdout, | 
| 444 |  |  |  |  |  |  |  | ); | 
| 445 |  |  |  |  |  |  |  |  | 
| 446 | 8 |  |  |  |  |  | 312 | my $pid = $self->wrap_call( | 
| 447 |  |  |  |  |  |  |  | handles => $handles, | 
| 448 |  |  |  |  |  |  |  | %args, | 
| 449 |  |  |  |  |  |  |  | ); | 
| 450 |  |  |  |  |  |  |  |  | 
| 451 | 5 |  |  |  |  |  | 217 | my @returned_keys; | 
| 452 |  |  |  |  |  |  |  | my $current_primary_key; | 
| 453 | 5 |  |  |  |  |  | 0 | my $current_signed_item; | 
| 454 | 5 |  |  |  |  |  | 0 | my $current_key; | 
| 455 |  |  |  |  |  |  |  |  | 
| 456 | 5 |  |  |  |  |  | 5482 | require GnuPG::PublicKey; | 
| 457 | 5 |  |  |  |  |  | 2674 | require GnuPG::SecretKey; | 
| 458 | 5 |  |  |  |  |  | 1737 | require GnuPG::SubKey; | 
| 459 | 5 |  |  |  |  |  | 2374 | require GnuPG::Fingerprint; | 
| 460 | 5 |  |  |  |  |  | 3319 | require GnuPG::UserId; | 
| 461 | 5 |  |  |  |  |  | 2435 | require GnuPG::UserAttribute; | 
| 462 | 5 |  |  |  |  |  | 2473 | require GnuPG::Signature; | 
| 463 | 5 |  |  |  |  |  | 2669 | require GnuPG::Revoker; | 
| 464 |  |  |  |  |  |  |  |  | 
| 465 | 5 |  |  |  |  |  | 2556974 | while (<$stdout>) { | 
| 466 | 75 |  |  |  |  |  | 108217 | my $line = $_; | 
| 467 | 75 |  |  |  |  |  | 147 | chomp $line; | 
| 468 | 75 |  |  |  |  |  | 385 | my @fields = split ':', $line, -1; | 
| 469 | 75 | 50 |  |  |  |  | 223 | next unless @fields > 3; | 
| 470 |  |  |  |  |  |  |  |  | 
| 471 | 75 |  |  |  |  |  | 147 | my $record_type = $fields[0]; | 
| 472 |  |  |  |  |  |  |  |  | 
| 473 | 75 | 100 |  | 100 |  |  | 889 | if ( $record_type eq 'pub' or $record_type eq 'sec' ) { | 
|  |  | 100 |  | 66 |  |  |  |  | 
|  |  | 100 |  | 100 |  |  |  |  | 
|  |  | 100 |  | 33 |  |  |  |  | 
|  |  | 50 |  |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  |  | 
| 474 | 5 | 50 |  |  |  |  | 24 | push @returned_keys, $current_primary_key | 
| 475 |  |  |  |  |  |  |  | if $current_primary_key; | 
| 476 |  |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  |  | my ( | 
| 478 | 5 |  |  |  |  |  | 62 | $user_id_validity, $key_length, $algo_num, $hex_key_id, | 
| 479 |  |  |  |  |  |  |  | $creation_date, $expiration_date, | 
| 480 |  |  |  |  |  |  |  | $local_id, $owner_trust, $user_id_string, | 
| 481 |  |  |  |  |  |  |  | $sigclass, #unused | 
| 482 |  |  |  |  |  |  |  | $usage_flags, | 
| 483 |  |  |  |  |  |  |  | ) = @fields[ 1 .. $#fields ]; | 
| 484 |  |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  |  | # --fixed-list-mode uses epoch time for creation and expiration date strings. | 
| 486 |  |  |  |  |  |  |  | # For backward compatibility, we convert them back using GMT; | 
| 487 | 5 |  |  |  |  |  | 20 | my $expiration_date_string; | 
| 488 | 5 | 50 |  |  |  |  | 23 | if ($expiration_date eq '') { | 
| 489 | 5 |  |  |  |  |  | 23 | $expiration_date = undef; | 
| 490 |  |  |  |  |  |  |  | } else { | 
| 491 | 0 |  |  |  |  |  | 0 | $expiration_date_string = $self->_downrez_date($expiration_date); | 
| 492 |  |  |  |  |  |  |  | } | 
| 493 | 5 |  |  |  |  |  | 81 | my $creation_date_string = $self->_downrez_date($creation_date); | 
| 494 |  |  |  |  |  |  |  |  | 
| 495 | 5 | 100 |  |  |  |  | 186 | $current_primary_key = $current_key | 
| 496 |  |  |  |  |  |  |  | = $record_type eq 'pub' | 
| 497 |  |  |  |  |  |  |  | ? GnuPG::PublicKey->new() | 
| 498 |  |  |  |  |  |  |  | : GnuPG::SecretKey->new(); | 
| 499 |  |  |  |  |  |  |  |  | 
| 500 | 5 |  |  |  |  |  | 88 | $current_primary_key->hash_init( | 
| 501 |  |  |  |  |  |  |  | length                 => $key_length, | 
| 502 |  |  |  |  |  |  |  | algo_num               => $algo_num, | 
| 503 |  |  |  |  |  |  |  | hex_id                 => $hex_key_id, | 
| 504 |  |  |  |  |  |  |  | local_id               => $local_id, | 
| 505 |  |  |  |  |  |  |  | owner_trust            => $owner_trust, | 
| 506 |  |  |  |  |  |  |  | creation_date          => $creation_date, | 
| 507 |  |  |  |  |  |  |  | expiration_date        => $expiration_date, | 
| 508 |  |  |  |  |  |  |  | creation_date_string   => $creation_date_string, | 
| 509 |  |  |  |  |  |  |  | expiration_date_string => $expiration_date_string, | 
| 510 |  |  |  |  |  |  |  | usage_flags            => $usage_flags, | 
| 511 |  |  |  |  |  |  |  | ); | 
| 512 |  |  |  |  |  |  |  |  | 
| 513 | 5 |  |  |  |  |  | 256 | $current_signed_item = $current_primary_key; | 
| 514 |  |  |  |  |  |  |  | } | 
| 515 |  |  |  |  |  |  |  | elsif ( $record_type eq 'fpr' ) { | 
| 516 | 10 |  |  |  |  |  | 28 | my $hex = $fields[9]; | 
| 517 | 10 |  |  |  |  |  | 232 | my $f = GnuPG::Fingerprint->new( as_hex_string => $hex ); | 
| 518 | 10 |  |  |  |  |  | 2073 | $current_key->fingerprint($f); | 
| 519 |  |  |  |  |  |  |  | } | 
| 520 |  |  |  |  |  |  |  | elsif ( $record_type eq 'sig' or | 
| 521 |  |  |  |  |  |  |  | $record_type eq 'rev' | 
| 522 |  |  |  |  |  |  |  | ) { | 
| 523 |  |  |  |  |  |  |  | my ( | 
| 524 | 9 |  |  |  |  |  | 26 | $validity, | 
| 525 |  |  |  |  |  |  |  | $algo_num,              $hex_key_id, | 
| 526 |  |  |  |  |  |  |  | $signature_date, | 
| 527 |  |  |  |  |  |  |  | $expiration_date, | 
| 528 |  |  |  |  |  |  |  | $user_id_string, | 
| 529 |  |  |  |  |  |  |  | $sig_type, | 
| 530 |  |  |  |  |  |  |  | ) = @fields[ 1, 3 .. 6, 9, 10 ]; | 
| 531 |  |  |  |  |  |  |  |  | 
| 532 | 9 |  |  |  |  |  | 11 | my $expiration_date_string; | 
| 533 | 9 | 50 |  |  |  |  | 14 | if ($expiration_date eq '') { | 
| 534 | 9 |  |  |  |  |  | 11 | $expiration_date = undef; | 
| 535 |  |  |  |  |  |  |  | } else { | 
| 536 | 0 |  |  |  |  |  | 0 | $expiration_date_string = $self->_downrez_date($expiration_date); | 
| 537 |  |  |  |  |  |  |  | } | 
| 538 | 9 |  |  |  |  |  | 19 | my $signature_date_string = $self->_downrez_date($signature_date); | 
| 539 |  |  |  |  |  |  |  |  | 
| 540 | 9 |  |  |  |  |  | 15 | my ($sig_class, $is_exportable); | 
| 541 | 9 | 50 |  |  |  |  | 27 | if ($sig_type =~ /^([[:xdigit:]]{2})([xl])$/ ) { | 
| 542 | 9 |  |  |  |  |  | 19 | $sig_class = hex($1); | 
| 543 | 9 |  |  |  |  |  | 19 | $is_exportable = ('x' eq $2); | 
| 544 |  |  |  |  |  |  |  | } | 
| 545 |  |  |  |  |  |  |  |  | 
| 546 | 9 |  |  |  |  |  | 20 | my $signature = GnuPG::Signature->new( | 
| 547 |  |  |  |  |  |  |  | validity       => $validity, | 
| 548 |  |  |  |  |  |  |  | algo_num       => $algo_num, | 
| 549 |  |  |  |  |  |  |  | hex_id         => $hex_key_id, | 
| 550 |  |  |  |  |  |  |  | date           => $signature_date, | 
| 551 |  |  |  |  |  |  |  | date_string    => $signature_date_string, | 
| 552 |  |  |  |  |  |  |  | expiration_date => $expiration_date, | 
| 553 |  |  |  |  |  |  |  | expiration_date_string => $expiration_date_string, | 
| 554 |  |  |  |  |  |  |  | user_id_string => unescape_string($user_id_string), | 
| 555 |  |  |  |  |  |  |  | sig_class      => $sig_class, | 
| 556 |  |  |  |  |  |  |  | is_exportable  => $is_exportable, | 
| 557 |  |  |  |  |  |  |  | ); | 
| 558 |  |  |  |  |  |  |  |  | 
| 559 | 9 | 50 |  | 100 |  |  | 5831 | if ( $current_signed_item->isa('GnuPG::Key') || | 
|  |  |  |  | 66 |  |  |  |  | 
|  |  |  |  | 33 |  |  |  |  | 
| 560 |  |  |  |  |  |  |  | $current_signed_item->isa('GnuPG::UserId') || | 
| 561 |  |  |  |  |  |  |  | $current_signed_item->isa('GnuPG::Revoker') || | 
| 562 |  |  |  |  |  |  |  | $current_signed_item->isa('GnuPG::UserAttribute')) { | 
| 563 | 9 | 50 |  |  |  |  | 19 | if ($record_type eq 'sig') { | 
|  |  | 0 |  |  |  |  |  |  | 
| 564 | 9 |  |  |  |  |  | 26 | $current_signed_item->push_signatures($signature); | 
| 565 |  |  |  |  |  |  |  | } elsif ($record_type eq 'rev') { | 
| 566 | 0 |  |  |  |  |  | 0 | $current_signed_item->push_revocations($signature); | 
| 567 |  |  |  |  |  |  |  | } | 
| 568 |  |  |  |  |  |  |  | } else { | 
| 569 | 0 |  |  |  |  |  | 0 | warn "do not know how to handle signature line: $line\n"; | 
| 570 |  |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | } | 
| 572 |  |  |  |  |  |  |  | elsif ( $record_type eq 'uid' ) { | 
| 573 | 10 |  |  |  |  |  | 43 | my ( $validity, $user_id_string ) = @fields[ 1, 9 ]; | 
| 574 |  |  |  |  |  |  |  |  | 
| 575 | 10 |  |  |  |  |  | 39 | $current_signed_item = GnuPG::UserId->new( | 
| 576 |  |  |  |  |  |  |  | validity  => $validity, | 
| 577 |  |  |  |  |  |  |  | as_string => unescape_string($user_id_string), | 
| 578 |  |  |  |  |  |  |  | ); | 
| 579 |  |  |  |  |  |  |  |  | 
| 580 | 10 |  |  |  |  |  | 609 | $current_primary_key->push_user_ids($current_signed_item); | 
| 581 |  |  |  |  |  |  |  | } | 
| 582 |  |  |  |  |  |  |  | elsif ( $record_type eq 'uat' ) { | 
| 583 | 0 |  |  |  |  |  | 0 | my ( $validity, $subpacket ) = @fields[ 1, 9 ]; | 
| 584 |  |  |  |  |  |  |  |  | 
| 585 | 0 |  |  |  |  |  | 0 | my ( $subpacket_count, $subpacket_total_size ) = split(/ /,$subpacket); | 
| 586 |  |  |  |  |  |  |  |  | 
| 587 | 0 |  |  |  |  |  | 0 | $current_signed_item = GnuPG::UserAttribute->new( | 
| 588 |  |  |  |  |  |  |  | validity  => $validity, | 
| 589 |  |  |  |  |  |  |  | subpacket_count => $subpacket_count, | 
| 590 |  |  |  |  |  |  |  | subpacket_total_size => $subpacket_total_size, | 
| 591 |  |  |  |  |  |  |  | ); | 
| 592 |  |  |  |  |  |  |  |  | 
| 593 | 0 |  |  |  |  |  | 0 | $current_primary_key->push_user_attributes($current_signed_item); | 
| 594 |  |  |  |  |  |  |  | } | 
| 595 |  |  |  |  |  |  |  | elsif ( $record_type eq 'sub' or $record_type eq 'ssb' ) { | 
| 596 |  |  |  |  |  |  |  | my ( | 
| 597 | 5 |  |  |  |  |  | 34 | $validity, $key_length, $algo_num, $hex_id, | 
| 598 |  |  |  |  |  |  |  | $creation_date, $expiration_date, | 
| 599 |  |  |  |  |  |  |  | $local_id, | 
| 600 |  |  |  |  |  |  |  | $dummy0, $dummy1, $dummy2, #unused | 
| 601 |  |  |  |  |  |  |  | $usage_flags, | 
| 602 |  |  |  |  |  |  |  | ) = @fields[ 1 .. 11 ]; | 
| 603 |  |  |  |  |  |  |  |  | 
| 604 | 5 |  |  |  |  |  | 18 | my $expiration_date_string; | 
| 605 | 5 | 50 |  |  |  |  | 19 | if ($expiration_date eq '') { | 
| 606 | 5 |  |  |  |  |  | 13 | $expiration_date = undef; | 
| 607 |  |  |  |  |  |  |  | } else { | 
| 608 | 0 |  |  |  |  |  | 0 | $expiration_date_string = $self->_downrez_date($expiration_date); | 
| 609 |  |  |  |  |  |  |  | } | 
| 610 | 5 |  |  |  |  |  | 26 | my $creation_date_string = $self->_downrez_date($creation_date); | 
| 611 |  |  |  |  |  |  |  |  | 
| 612 | 5 |  |  |  |  |  | 57 | $current_signed_item = $current_key | 
| 613 |  |  |  |  |  |  |  | = GnuPG::SubKey->new( | 
| 614 |  |  |  |  |  |  |  | validity               => $validity, | 
| 615 |  |  |  |  |  |  |  | length                 => $key_length, | 
| 616 |  |  |  |  |  |  |  | algo_num               => $algo_num, | 
| 617 |  |  |  |  |  |  |  | hex_id                 => $hex_id, | 
| 618 |  |  |  |  |  |  |  | creation_date          => $creation_date, | 
| 619 |  |  |  |  |  |  |  | expiration_date        => $expiration_date, | 
| 620 |  |  |  |  |  |  |  | creation_date_string   => $creation_date_string, | 
| 621 |  |  |  |  |  |  |  | expiration_date_string => $expiration_date_string, | 
| 622 |  |  |  |  |  |  |  | local_id               => $local_id, | 
| 623 |  |  |  |  |  |  |  | usage_flags            => $usage_flags, | 
| 624 |  |  |  |  |  |  |  | ); | 
| 625 |  |  |  |  |  |  |  |  | 
| 626 | 5 |  |  |  |  |  | 499 | $current_primary_key->push_subkeys($current_signed_item); | 
| 627 |  |  |  |  |  |  |  | } | 
| 628 |  |  |  |  |  |  |  | elsif ($record_type eq 'rvk') { | 
| 629 | 4 |  |  |  |  |  | 47 | my ($algo_num, $fpr, $class) = @fields[ 3,9,10 ]; | 
| 630 | 4 |  |  |  |  |  | 41 | my $rvk = GnuPG::Revoker->new( | 
| 631 |  |  |  |  |  |  |  | fingerprint => GnuPG::Fingerprint->new( as_hex_string => $fpr ), | 
| 632 |  |  |  |  |  |  |  | algo_num    => ($algo_num + 0), | 
| 633 |  |  |  |  |  |  |  | class       => hex($class), | 
| 634 |  |  |  |  |  |  |  | ); | 
| 635 |  |  |  |  |  |  |  | # pushing to either primary key or subkey, to handle | 
| 636 |  |  |  |  |  |  |  | # designated revokers to the subkeys too: | 
| 637 | 4 |  |  |  |  |  | 127 | $current_key->push_revokers($rvk); | 
| 638 |  |  |  |  |  |  |  | # revokers should be bound to the key with signatures: | 
| 639 | 4 |  |  |  |  |  | 59 | $current_signed_item = $rvk; | 
| 640 |  |  |  |  |  |  |  | } | 
| 641 |  |  |  |  |  |  |  | elsif ($record_type eq 'pkd') { | 
| 642 | 28 |  |  |  |  |  | 84 | my ($pos, $size, $data) = @fields[ 1,2,3 ]; | 
| 643 | 28 |  |  |  |  |  | 264 | $current_key->pubkey_data->[$pos+0] = Math::BigInt->from_hex('0x'.$data); | 
| 644 |  |  |  |  |  |  |  | } | 
| 645 |  |  |  |  |  |  |  | elsif ( $record_type ne 'tru' and $record_type ne 'grp' ) { | 
| 646 | 0 |  |  |  |  |  | 0 | warn "unknown record type $record_type"; | 
| 647 |  |  |  |  |  |  |  | } | 
| 648 |  |  |  |  |  |  |  | } | 
| 649 |  |  |  |  |  |  |  |  | 
| 650 | 5 |  |  |  |  |  | 13912 | waitpid $pid, 0; | 
| 651 |  |  |  |  |  |  |  |  | 
| 652 | 5 | 50 |  |  |  |  | 38 | push @returned_keys, $current_primary_key | 
| 653 |  |  |  |  |  |  |  | if $current_primary_key; | 
| 654 |  |  |  |  |  |  |  |  | 
| 655 | 5 |  |  |  |  |  | 183 | $self->options($saved_options); | 
| 656 |  |  |  |  |  |  |  |  | 
| 657 | 5 |  |  |  |  |  | 905 | return @returned_keys; | 
| 658 |  |  |  |  |  |  |  | } | 
| 659 |  |  |  |  |  |  |  |  | 
| 660 |  |  |  |  |  |  |  | sub _downrez_date { | 
| 661 | 19 |  |  |  | 19 |  | 54 | my $self = shift; | 
| 662 | 19 |  |  |  |  |  | 39 | my $date = shift; | 
| 663 | 19 | 50 |  |  |  |  | 203 | if ($date =~  /^\d+$/) { | 
| 664 | 19 |  |  |  |  |  | 301 | my ($year,$month,$day) = (gmtime($date))[5,4,3]; | 
| 665 | 19 |  |  |  |  |  | 66 | $year += 1900; | 
| 666 | 19 |  |  |  |  |  | 37 | $month += 1; | 
| 667 | 19 |  |  |  |  |  | 133 | return    sprintf('%04d-%02d-%02d',   $year, $month, $day); | 
| 668 |  |  |  |  |  |  |  | } | 
| 669 | 0 |  |  |  |  |  | 0 | return $date; | 
| 670 |  |  |  |  |  |  |  | } | 
| 671 |  |  |  |  |  |  |  |  | 
| 672 |  |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  |  | ################################################################ | 
| 674 |  |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  |  | sub list_public_keys { | 
| 676 | 9 |  |  |  | 9 | 1 | 8777 | my ( $self, %args ) = @_; | 
| 677 | 9 |  |  |  |  |  | 114 | return $self->wrap_call( | 
| 678 |  |  |  |  |  |  |  | %args, | 
| 679 |  |  |  |  |  |  |  | commands => ['--list-public-keys'], | 
| 680 |  |  |  |  |  |  |  | ); | 
| 681 |  |  |  |  |  |  |  | } | 
| 682 |  |  |  |  |  |  |  |  | 
| 683 |  |  |  |  |  |  |  | sub list_sigs { | 
| 684 | 9 |  |  |  | 9 | 1 | 8644 | my ( $self, %args ) = @_; | 
| 685 | 9 |  |  |  |  |  | 118 | return $self->wrap_call( | 
| 686 |  |  |  |  |  |  |  | %args, | 
| 687 |  |  |  |  |  |  |  | commands => ['--list-sigs'], | 
| 688 |  |  |  |  |  |  |  | ); | 
| 689 |  |  |  |  |  |  |  | } | 
| 690 |  |  |  |  |  |  |  |  | 
| 691 |  |  |  |  |  |  |  | sub list_secret_keys { | 
| 692 | 9 |  |  |  | 9 | 1 | 12029 | my ( $self, %args ) = @_; | 
| 693 | 9 |  |  |  |  |  | 76 | return $self->wrap_call( | 
| 694 |  |  |  |  |  |  |  | %args, | 
| 695 |  |  |  |  |  |  |  | commands => ['--list-secret-keys'], | 
| 696 |  |  |  |  |  |  |  | ); | 
| 697 |  |  |  |  |  |  |  | } | 
| 698 |  |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  |  | sub encrypt( $% ) { | 
| 700 | 10 |  |  |  | 10 | 1 | 814 | my ( $self, %args ) = @_; | 
| 701 | 10 |  |  |  |  |  | 229 | return $self->wrap_call( | 
| 702 |  |  |  |  |  |  |  | %args, | 
| 703 |  |  |  |  |  |  |  | commands => ['--encrypt'] | 
| 704 |  |  |  |  |  |  |  | ); | 
| 705 |  |  |  |  |  |  |  | } | 
| 706 |  |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  |  | sub encrypt_symmetrically( $% ) { | 
| 708 | 5 |  |  |  | 5 | 1 | 3270 | my ( $self, %args ) = @_; | 
| 709 |  |  |  |  |  |  |  | # Strip the homedir and put it back after encrypting; | 
| 710 | 5 |  |  |  |  |  | 111 | my $homedir = $self->options->homedir; | 
| 711 | 5 | 50 |  |  |  |  | 305 | $self->options->clear_homedir | 
| 712 |  |  |  |  |  |  |  | unless $self->cmp_version($self->version, '2.2') >= 0; | 
| 713 | 5 |  |  |  |  |  | 269 | my $pid = $self->wrap_call( | 
| 714 |  |  |  |  |  |  |  | %args, | 
| 715 |  |  |  |  |  |  |  | commands => ['--symmetric'] | 
| 716 |  |  |  |  |  |  |  | ); | 
| 717 | 3 | 50 |  |  |  |  | 256 | $self->options->homedir($homedir) | 
| 718 |  |  |  |  |  |  |  | unless $self->cmp_version($self->version, '2.2') >= 0; | 
| 719 | 3 |  |  |  |  |  | 614 | return $pid; | 
| 720 |  |  |  |  |  |  |  | } | 
| 721 |  |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  |  | sub sign( $% ) { | 
| 723 | 14 |  |  |  | 14 | 1 | 7747 | my ( $self, %args ) = @_; | 
| 724 | 14 |  |  |  |  |  | 132 | return $self->wrap_call( | 
| 725 |  |  |  |  |  |  |  | %args, | 
| 726 |  |  |  |  |  |  |  | commands => ['--sign'] | 
| 727 |  |  |  |  |  |  |  | ); | 
| 728 |  |  |  |  |  |  |  | } | 
| 729 |  |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  |  | sub clearsign( $% ) { | 
| 731 | 5 |  |  |  | 5 | 1 | 3254 | my ( $self, %args ) = @_; | 
| 732 | 5 |  |  |  |  |  | 55 | return $self->wrap_call( | 
| 733 |  |  |  |  |  |  |  | %args,, | 
| 734 |  |  |  |  |  |  |  | commands => ['--clearsign'] | 
| 735 |  |  |  |  |  |  |  | ); | 
| 736 |  |  |  |  |  |  |  | } | 
| 737 |  |  |  |  |  |  |  |  | 
| 738 |  |  |  |  |  |  |  | sub detach_sign( $% ) { | 
| 739 | 5 |  |  |  | 5 | 1 | 3212 | my ( $self, %args ) = @_; | 
| 740 | 5 |  |  |  |  |  | 54 | return $self->wrap_call( | 
| 741 |  |  |  |  |  |  |  | %args, | 
| 742 |  |  |  |  |  |  |  | commands => ['--detach-sign'] | 
| 743 |  |  |  |  |  |  |  | ); | 
| 744 |  |  |  |  |  |  |  | } | 
| 745 |  |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  |  | sub sign_and_encrypt( $% ) { | 
| 747 | 5 |  |  |  | 5 | 1 | 271 | my ( $self, %args ) = @_; | 
| 748 | 5 |  |  |  |  |  | 55 | return $self->wrap_call( | 
| 749 |  |  |  |  |  |  |  | %args, | 
| 750 |  |  |  |  |  |  |  | commands => [ | 
| 751 |  |  |  |  |  |  |  | '--sign', | 
| 752 |  |  |  |  |  |  |  | '--encrypt' | 
| 753 |  |  |  |  |  |  |  | ] | 
| 754 |  |  |  |  |  |  |  | ); | 
| 755 |  |  |  |  |  |  |  | } | 
| 756 |  |  |  |  |  |  |  |  | 
| 757 |  |  |  |  |  |  |  | sub decrypt( $% ) { | 
| 758 | 5 |  |  |  | 5 | 1 | 3042 | my ( $self, %args ) = @_; | 
| 759 | 5 |  |  |  |  |  | 40 | return $self->wrap_call( | 
| 760 |  |  |  |  |  |  |  | %args, | 
| 761 |  |  |  |  |  |  |  | commands => ['--decrypt'] | 
| 762 |  |  |  |  |  |  |  | ); | 
| 763 |  |  |  |  |  |  |  | } | 
| 764 |  |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  |  | sub verify( $% ) { | 
| 766 | 5 |  |  |  | 5 | 1 | 3059 | my ( $self, %args ) = @_; | 
| 767 | 5 |  |  |  |  |  | 44 | return $self->wrap_call( | 
| 768 |  |  |  |  |  |  |  | %args, | 
| 769 |  |  |  |  |  |  |  | commands => ['--verify'] | 
| 770 |  |  |  |  |  |  |  | ); | 
| 771 |  |  |  |  |  |  |  | } | 
| 772 |  |  |  |  |  |  |  |  | 
| 773 |  |  |  |  |  |  |  | sub import_keys( $% ) { | 
| 774 | 7 |  |  |  | 7 | 1 | 5344 | my ( $self, %args ) = @_; | 
| 775 | 7 |  |  |  |  |  | 76 | return $self->wrap_call( | 
| 776 |  |  |  |  |  |  |  | %args, | 
| 777 |  |  |  |  |  |  |  | commands => ['--import'] | 
| 778 |  |  |  |  |  |  |  | ); | 
| 779 |  |  |  |  |  |  |  | } | 
| 780 |  |  |  |  |  |  |  |  | 
| 781 |  |  |  |  |  |  |  | sub export_keys( $% ) { | 
| 782 | 5 |  |  |  | 5 | 1 | 2753 | my ( $self, %args ) = @_; | 
| 783 | 5 |  |  |  |  |  | 35 | return $self->wrap_call( | 
| 784 |  |  |  |  |  |  |  | %args, | 
| 785 |  |  |  |  |  |  |  | commands => ['--export'] | 
| 786 |  |  |  |  |  |  |  | ); | 
| 787 |  |  |  |  |  |  |  | } | 
| 788 |  |  |  |  |  |  |  |  | 
| 789 |  |  |  |  |  |  |  | sub recv_keys( $% ) { | 
| 790 | 0 |  |  |  | 0 | 1 | 0 | my ( $self, %args ) = @_; | 
| 791 | 0 |  |  |  |  |  | 0 | return $self->wrap_call( | 
| 792 |  |  |  |  |  |  |  | %args, | 
| 793 |  |  |  |  |  |  |  | commands => ['--recv-keys'] | 
| 794 |  |  |  |  |  |  |  | ); | 
| 795 |  |  |  |  |  |  |  | } | 
| 796 |  |  |  |  |  |  |  |  | 
| 797 |  |  |  |  |  |  |  | sub send_keys( $% ) { | 
| 798 | 0 |  |  |  | 0 | 1 | 0 | my ( $self, %args ) = @_; | 
| 799 | 0 |  |  |  |  |  | 0 | return $self->wrap_call( | 
| 800 |  |  |  |  |  |  |  | %args, | 
| 801 |  |  |  |  |  |  |  | commands => ['--send-keys'] | 
| 802 |  |  |  |  |  |  |  | ); | 
| 803 |  |  |  |  |  |  |  | } | 
| 804 |  |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  |  | sub search_keys( $% ) { | 
| 806 | 0 |  |  |  | 0 | 1 | 0 | my ( $self, %args ) = @_; | 
| 807 | 0 |  |  |  |  |  | 0 | return $self->wrap_call( | 
| 808 |  |  |  |  |  |  |  | %args, | 
| 809 |  |  |  |  |  |  |  | commands => ['--search-keys'] | 
| 810 |  |  |  |  |  |  |  | ); | 
| 811 |  |  |  |  |  |  |  | } | 
| 812 |  |  |  |  |  |  |  |  | 
| 813 |  |  |  |  |  |  |  | sub _version { | 
| 814 | 111 |  |  |  | 111 |  | 332 | my ( $self ) = @_; | 
| 815 |  |  |  |  |  |  |  |  | 
| 816 | 111 |  |  |  |  |  | 1596 | my $out = IO::Handle->new; | 
| 817 | 111 |  |  |  |  |  | 7307 | my $handles = GnuPG::Handles->new( stdout => $out ); | 
| 818 | 111 |  |  |  |  |  | 6336 | my $pid = $self->wrap_call( commands => [ '--no-options', '--version' ], handles => $handles ); | 
| 819 | 101 |  |  |  |  |  | 7753 | my $line = $out->getline; | 
| 820 | 101 |  |  |  |  |  | 54507307 | $line =~ /(\d+\.\d+\.\d+)/; | 
| 821 |  |  |  |  |  |  |  |  | 
| 822 | 101 |  |  |  |  |  | 1293 | my $version = $1; | 
| 823 | 101 | 50 |  | 33 |  |  | 2159 | unless ($self->cmp_version($version, '2.2') >= 0 or | 
|  |  |  |  | 66 |  |  |  |  | 
| 824 |  |  |  |  |  |  |  | ($self->cmp_version($version, '1.4') >= 0 and $self->cmp_version($version, '1.5') < 0 )) { | 
| 825 | 0 |  |  |  |  |  | 0 | croak "GnuPG Version 1.4 or 2.2+ required"; | 
| 826 |  |  |  |  |  |  |  | } | 
| 827 | 101 |  |  |  |  |  | 6660 | waitpid $pid, 0; | 
| 828 |  |  |  |  |  |  |  |  | 
| 829 | 101 |  |  |  |  |  | 21146 | return $version; | 
| 830 |  |  |  |  |  |  |  | } | 
| 831 |  |  |  |  |  |  |  |  | 
| 832 |  |  |  |  |  |  |  | sub cmp_version($$) { | 
| 833 | 426 |  |  |  | 426 | 0 | 2427133 | my ( $self, $a, $b ) = (@_); | 
| 834 | 426 |  |  |  |  |  | 11727 | my @a = split '\.', $a; | 
| 835 | 426 |  |  |  |  |  | 1811 | my @b = split '\.', $b; | 
| 836 | 426 | 50 |  |  |  |  | 2847 | @a > @b | 
| 837 |  |  |  |  |  |  |  | ? push @b, (0) x (@a-@b) | 
| 838 |  |  |  |  |  |  |  | : push @a, (0) x (@b-@a); | 
| 839 | 426 |  |  |  |  |  | 2256 | for ( my $i = 0; $i < @a; $i++ ) { | 
| 840 | 718 | 100 |  |  |  |  | 7395 | return $a[$i] <=> $b[$i] if $a[$i] <=> $b[$i]; | 
| 841 |  |  |  |  |  |  |  | } | 
| 842 | 0 |  |  |  |  |  | 0 | return 0; | 
| 843 |  |  |  |  |  |  |  | } | 
| 844 |  |  |  |  |  |  |  |  | 
| 845 |  |  |  |  |  |  |  | sub test_default_key_passphrase() { | 
| 846 | 4 |  |  |  | 4 | 1 | 4432 | my ($self) = @_; | 
| 847 |  |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  |  | # We can't do something like let the user pass | 
| 849 |  |  |  |  |  |  |  | # in a passphrase handle because we don't exist | 
| 850 |  |  |  |  |  |  |  | # anymore after the user runs off with the | 
| 851 |  |  |  |  |  |  |  | # attachments | 
| 852 | 4 | 50 |  |  |  |  | 80 | croak 'No passphrase defined to test!' | 
| 853 |  |  |  |  |  |  |  | unless defined $self->passphrase(); | 
| 854 |  |  |  |  |  |  |  |  | 
| 855 | 4 |  |  |  |  |  | 84 | my $stdin  = IO::Handle->new(); | 
| 856 | 4 |  |  |  |  |  | 84 | my $stdout = IO::Handle->new(); | 
| 857 | 4 |  |  |  |  |  | 64 | my $stderr = IO::Handle->new(); | 
| 858 | 4 |  |  |  |  |  | 64 | my $status = IO::Handle->new(); | 
| 859 |  |  |  |  |  |  |  |  | 
| 860 | 4 |  |  |  |  |  | 136 | my $handles = GnuPG::Handles->new( | 
| 861 |  |  |  |  |  |  |  | stdin  => $stdin, | 
| 862 |  |  |  |  |  |  |  | stdout => $stdout, | 
| 863 |  |  |  |  |  |  |  | stderr => $stderr, | 
| 864 |  |  |  |  |  |  |  | status => $status | 
| 865 |  |  |  |  |  |  |  | ); | 
| 866 |  |  |  |  |  |  |  |  | 
| 867 |  |  |  |  |  |  |  | # save this setting since we need to be in non-interactive mode | 
| 868 | 4 |  |  |  |  |  | 192 | my $saved_meta_interactive_option = $self->options->meta_interactive(); | 
| 869 | 4 |  |  |  |  |  | 196 | $self->options->clear_meta_interactive(); | 
| 870 |  |  |  |  |  |  |  |  | 
| 871 | 4 |  |  |  |  |  | 116 | my $pid = $self->sign( handles => $handles ); | 
| 872 |  |  |  |  |  |  |  |  | 
| 873 | 3 |  |  |  |  |  | 198 | close $stdin; | 
| 874 |  |  |  |  |  |  |  |  | 
| 875 |  |  |  |  |  |  |  | # restore this setting to its original setting | 
| 876 | 3 |  |  |  |  |  | 192 | $self->options->meta_interactive($saved_meta_interactive_option); | 
| 877 |  |  |  |  |  |  |  |  | 
| 878 |  |  |  |  |  |  |  | # all we realy want to check is the status fh | 
| 879 | 3 |  |  |  |  |  | 1720290 | while (<$status>) { | 
| 880 | 9 | 100 |  |  |  |  | 7458 | if (/^\[GNUPG:\]\s*(GOOD_PASSPHRASE|SIG_CREATED)/) { | 
| 881 | 3 |  |  |  |  |  | 11247 | waitpid $pid, 0; | 
| 882 | 3 |  |  |  |  |  | 507 | return 1; | 
| 883 |  |  |  |  |  |  |  | } | 
| 884 |  |  |  |  |  |  |  | } | 
| 885 |  |  |  |  |  |  |  |  | 
| 886 |  |  |  |  |  |  |  | # If we didn't catch the regexp above, we'll assume | 
| 887 |  |  |  |  |  |  |  | # that the passphrase was incorrect | 
| 888 | 0 |  |  |  |  |  |  | waitpid $pid, 0; | 
| 889 | 0 |  |  |  |  |  |  | return 0; | 
| 890 |  |  |  |  |  |  |  | } | 
| 891 |  |  |  |  |  |  |  |  | 
| 892 |  |  |  |  |  |  |  | 1; | 
| 893 |  |  |  |  |  |  |  |  | 
| 894 |  |  |  |  |  |  |  | ############################################################## | 
| 895 |  |  |  |  |  |  |  |  | 
| 896 |  |  |  |  |  |  |  | =head1 NAME | 
| 897 |  |  |  |  |  |  |  |  | 
| 898 |  |  |  |  |  |  |  | GnuPG::Interface - Perl interface to GnuPG | 
| 899 |  |  |  |  |  |  |  |  | 
| 900 |  |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 901 |  |  |  |  |  |  |  |  | 
| 902 |  |  |  |  |  |  |  | # A simple example | 
| 903 |  |  |  |  |  |  |  | use IO::Handle; | 
| 904 |  |  |  |  |  |  |  | use GnuPG::Interface; | 
| 905 |  |  |  |  |  |  |  |  | 
| 906 |  |  |  |  |  |  |  | # setting up the situation | 
| 907 |  |  |  |  |  |  |  | my $gnupg = GnuPG::Interface->new(); | 
| 908 |  |  |  |  |  |  |  | $gnupg->options->hash_init( armor   => 1, | 
| 909 |  |  |  |  |  |  |  | homedir => '/home/foobar' ); | 
| 910 |  |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  |  | # Note you can set the recipients even if you aren't encrypting! | 
| 912 |  |  |  |  |  |  |  | $gnupg->options->push_recipients( 'ftobin@cpan.org' ); | 
| 913 |  |  |  |  |  |  |  | $gnupg->options->meta_interactive( 0 ); | 
| 914 |  |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  |  | # how we create some handles to interact with GnuPG | 
| 916 |  |  |  |  |  |  |  | my $input   = IO::Handle->new(); | 
| 917 |  |  |  |  |  |  |  | my $output  = IO::Handle->new(); | 
| 918 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new( stdin  => $input, | 
| 919 |  |  |  |  |  |  |  | stdout => $output ); | 
| 920 |  |  |  |  |  |  |  |  | 
| 921 |  |  |  |  |  |  |  | # Now we'll go about encrypting with the options already set | 
| 922 |  |  |  |  |  |  |  | my @plaintext = ( 'foobar' ); | 
| 923 |  |  |  |  |  |  |  | my $pid = $gnupg->encrypt( handles => $handles ); | 
| 924 |  |  |  |  |  |  |  |  | 
| 925 |  |  |  |  |  |  |  | # Now we write to the input of GnuPG | 
| 926 |  |  |  |  |  |  |  | print $input @plaintext; | 
| 927 |  |  |  |  |  |  |  | close $input; | 
| 928 |  |  |  |  |  |  |  |  | 
| 929 |  |  |  |  |  |  |  | # now we read the output | 
| 930 |  |  |  |  |  |  |  | my @ciphertext = <$output>; | 
| 931 |  |  |  |  |  |  |  | close $output; | 
| 932 |  |  |  |  |  |  |  |  | 
| 933 |  |  |  |  |  |  |  | waitpid $pid, 0; | 
| 934 |  |  |  |  |  |  |  |  | 
| 935 |  |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 936 |  |  |  |  |  |  |  |  | 
| 937 |  |  |  |  |  |  |  | GnuPG::Interface and its associated modules are designed to | 
| 938 |  |  |  |  |  |  |  | provide an object-oriented method for interacting with GnuPG, | 
| 939 |  |  |  |  |  |  |  | being able to perform functions such as but not limited | 
| 940 |  |  |  |  |  |  |  | to encrypting, signing, | 
| 941 |  |  |  |  |  |  |  | decryption, verification, and key-listing parsing. | 
| 942 |  |  |  |  |  |  |  |  | 
| 943 |  |  |  |  |  |  |  | =head2 How Data Member Accessor Methods are Created | 
| 944 |  |  |  |  |  |  |  |  | 
| 945 |  |  |  |  |  |  |  | Each module in the GnuPG::Interface bundle relies | 
| 946 |  |  |  |  |  |  |  | on Moo to generate the get/set methods | 
| 947 |  |  |  |  |  |  |  | used to set the object's data members. | 
| 948 |  |  |  |  |  |  |  | I<This is very important to realize.>  This means that | 
| 949 |  |  |  |  |  |  |  | any data member which is a list has special | 
| 950 |  |  |  |  |  |  |  | methods assigned to it for pushing, popping, and | 
| 951 |  |  |  |  |  |  |  | clearing the list. | 
| 952 |  |  |  |  |  |  |  |  | 
| 953 |  |  |  |  |  |  |  | =head2 Understanding Bidirectional Communication | 
| 954 |  |  |  |  |  |  |  |  | 
| 955 |  |  |  |  |  |  |  | It is also imperative to realize that this package | 
| 956 |  |  |  |  |  |  |  | uses interprocess communication methods similar to | 
| 957 |  |  |  |  |  |  |  | those used in L<IPC::Open3> | 
| 958 |  |  |  |  |  |  |  | and L<perlipc/"Bidirectional Communication with Another Process">, | 
| 959 |  |  |  |  |  |  |  | and that users of this package | 
| 960 |  |  |  |  |  |  |  | need to understand how to use this method because this package | 
| 961 |  |  |  |  |  |  |  | does not abstract these methods for the user greatly. | 
| 962 |  |  |  |  |  |  |  | This package is not designed | 
| 963 |  |  |  |  |  |  |  | to abstract this away entirely (partly for security purposes), but rather | 
| 964 |  |  |  |  |  |  |  | to simply help create 'proper', clean calls to GnuPG, and to implement | 
| 965 |  |  |  |  |  |  |  | key-listing parsing. | 
| 966 |  |  |  |  |  |  |  | Please see L<perlipc/"Bidirectional Communication with Another Process"> | 
| 967 |  |  |  |  |  |  |  | to learn how to deal with these methods. | 
| 968 |  |  |  |  |  |  |  |  | 
| 969 |  |  |  |  |  |  |  | Using this package to do message processing generally | 
| 970 |  |  |  |  |  |  |  | invovlves creating a GnuPG::Interface object, creating | 
| 971 |  |  |  |  |  |  |  | a GnuPG::Handles object, | 
| 972 |  |  |  |  |  |  |  | setting some options in its B<options> data member, | 
| 973 |  |  |  |  |  |  |  | and then calling a method which invokes GnuPG, such as | 
| 974 |  |  |  |  |  |  |  | B<clearsign>.  One then interacts with with the handles | 
| 975 |  |  |  |  |  |  |  | appropriately, as described in | 
| 976 |  |  |  |  |  |  |  | L<perlipc/"Bidirectional Communication with Another Process">. | 
| 977 |  |  |  |  |  |  |  |  | 
| 978 |  |  |  |  |  |  |  | =head1 GnuPG Versions | 
| 979 |  |  |  |  |  |  |  |  | 
| 980 |  |  |  |  |  |  |  | As of this version of GnuPG::Interface, there are two supported | 
| 981 |  |  |  |  |  |  |  | versions of GnuPG: 1.4.x and 2.2.x. The | 
| 982 |  |  |  |  |  |  |  | L<GnuPG download page|https://gnupg.org/download/index.html> has | 
| 983 |  |  |  |  |  |  |  | updated information on the currently supported versions. | 
| 984 |  |  |  |  |  |  |  |  | 
| 985 |  |  |  |  |  |  |  | GnuPG released 2.0 and 2.1 versions in the past and some packaging | 
| 986 |  |  |  |  |  |  |  | systems may still provide these if you install the default C<gpg>, | 
| 987 |  |  |  |  |  |  |  | C<gnupg>, C<gnupg2>, etc. packages. This modules supports only | 
| 988 |  |  |  |  |  |  |  | version 2.2.x, so you may need to find additional package | 
| 989 |  |  |  |  |  |  |  | repositories or build from source to get the updated version. | 
| 990 |  |  |  |  |  |  |  |  | 
| 991 |  |  |  |  |  |  |  | =head1 OBJECT METHODS | 
| 992 |  |  |  |  |  |  |  |  | 
| 993 |  |  |  |  |  |  |  | =head2 Initialization Methods | 
| 994 |  |  |  |  |  |  |  |  | 
| 995 |  |  |  |  |  |  |  | =over 4 | 
| 996 |  |  |  |  |  |  |  |  | 
| 997 |  |  |  |  |  |  |  | =item new( I<%initialization_args> ) | 
| 998 |  |  |  |  |  |  |  |  | 
| 999 |  |  |  |  |  |  |  | This methods creates a new object.  The optional arguments are | 
| 1000 |  |  |  |  |  |  |  | initialization of data members. | 
| 1001 |  |  |  |  |  |  |  |  | 
| 1002 |  |  |  |  |  |  |  | =item hash_init( I<%args> ). | 
| 1003 |  |  |  |  |  |  |  |  | 
| 1004 |  |  |  |  |  |  |  |  | 
| 1005 |  |  |  |  |  |  |  | =back | 
| 1006 |  |  |  |  |  |  |  |  | 
| 1007 |  |  |  |  |  |  |  | =head2 Object Methods which use a GnuPG::Handles Object | 
| 1008 |  |  |  |  |  |  |  |  | 
| 1009 |  |  |  |  |  |  |  | =over 4 | 
| 1010 |  |  |  |  |  |  |  |  | 
| 1011 |  |  |  |  |  |  |  | =item list_public_keys( % ) | 
| 1012 |  |  |  |  |  |  |  |  | 
| 1013 |  |  |  |  |  |  |  | =item list_sigs( % ) | 
| 1014 |  |  |  |  |  |  |  |  | 
| 1015 |  |  |  |  |  |  |  | =item list_secret_keys( % ) | 
| 1016 |  |  |  |  |  |  |  |  | 
| 1017 |  |  |  |  |  |  |  | =item encrypt( % ) | 
| 1018 |  |  |  |  |  |  |  |  | 
| 1019 |  |  |  |  |  |  |  | =item encrypt_symmetrically( % ) | 
| 1020 |  |  |  |  |  |  |  |  | 
| 1021 |  |  |  |  |  |  |  | =item sign( % ) | 
| 1022 |  |  |  |  |  |  |  |  | 
| 1023 |  |  |  |  |  |  |  | =item clearsign( % ) | 
| 1024 |  |  |  |  |  |  |  |  | 
| 1025 |  |  |  |  |  |  |  | =item detach_sign( % ) | 
| 1026 |  |  |  |  |  |  |  |  | 
| 1027 |  |  |  |  |  |  |  | =item sign_and_encrypt( % ) | 
| 1028 |  |  |  |  |  |  |  |  | 
| 1029 |  |  |  |  |  |  |  | =item decrypt( % ) | 
| 1030 |  |  |  |  |  |  |  |  | 
| 1031 |  |  |  |  |  |  |  | =item verify( % ) | 
| 1032 |  |  |  |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  |  | =item import_keys( % ) | 
| 1034 |  |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  |  | =item export_keys( % ) | 
| 1036 |  |  |  |  |  |  |  |  | 
| 1037 |  |  |  |  |  |  |  | =item recv_keys( % ) | 
| 1038 |  |  |  |  |  |  |  |  | 
| 1039 |  |  |  |  |  |  |  | =item send_keys( % ) | 
| 1040 |  |  |  |  |  |  |  |  | 
| 1041 |  |  |  |  |  |  |  | =item search_keys( % ) | 
| 1042 |  |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  |  | These methods each correspond directly to or are very similar | 
| 1044 |  |  |  |  |  |  |  | to a GnuPG command described in L<gpg>.  Each of these methods | 
| 1045 |  |  |  |  |  |  |  | takes a hash, which currently must contain a key of B<handles> | 
| 1046 |  |  |  |  |  |  |  | which has the value of a GnuPG::Handles object. | 
| 1047 |  |  |  |  |  |  |  | Another optional key is B<command_args> which should have the value of an | 
| 1048 |  |  |  |  |  |  |  | array reference; these arguments will be passed to GnuPG as command arguments. | 
| 1049 |  |  |  |  |  |  |  | These command arguments are used for such things as determining the keys to | 
| 1050 |  |  |  |  |  |  |  | list in the B<export_keys> method.  I<Please note that GnuPG command arguments | 
| 1051 |  |  |  |  |  |  |  | are not the same as GnuPG options>.  To understand what are options and | 
| 1052 |  |  |  |  |  |  |  | what are command arguments please read L<gpg/"COMMANDS"> and L<gpg/"OPTIONS">. | 
| 1053 |  |  |  |  |  |  |  |  | 
| 1054 |  |  |  |  |  |  |  | Each of these calls returns the PID for the resulting GnuPG process. | 
| 1055 |  |  |  |  |  |  |  | One can use this PID in a C<waitpid> call instead of a C<wait> call | 
| 1056 |  |  |  |  |  |  |  | if more precise process reaping is needed. | 
| 1057 |  |  |  |  |  |  |  |  | 
| 1058 |  |  |  |  |  |  |  | These methods will attach the handles specified in the B<handles> object | 
| 1059 |  |  |  |  |  |  |  | to the running GnuPG object, so that bidirectional communication | 
| 1060 |  |  |  |  |  |  |  | can be established.  That is, the optionally-defined B<stdin>, | 
| 1061 |  |  |  |  |  |  |  | B<stdout>, B<stderr>, B<status>, B<logger>, and | 
| 1062 |  |  |  |  |  |  |  | B<passphrase> handles will be attached to | 
| 1063 |  |  |  |  |  |  |  | GnuPG's input, output, standard error, | 
| 1064 |  |  |  |  |  |  |  | the handle created by setting B<status-fd>, the handle created by setting B<logger-fd>, and the handle created by setting | 
| 1065 |  |  |  |  |  |  |  | B<passphrase-fd> respectively. | 
| 1066 |  |  |  |  |  |  |  | This tying of handles of similar to the process | 
| 1067 |  |  |  |  |  |  |  | done in I<IPC::Open3>. | 
| 1068 |  |  |  |  |  |  |  |  | 
| 1069 |  |  |  |  |  |  |  | If you want the GnuPG process to read or write directly to an already-opened | 
| 1070 |  |  |  |  |  |  |  | filehandle, you cannot do this via the normal I<IPC::Open3> mechanisms. | 
| 1071 |  |  |  |  |  |  |  | In order to accomplish this, set the appropriate B<handles> data member | 
| 1072 |  |  |  |  |  |  |  | to the already-opened filehandle, and then set the option B<direct> to be true | 
| 1073 |  |  |  |  |  |  |  | for that handle, as described in L<GnuPG::Handles/options>.  For example, | 
| 1074 |  |  |  |  |  |  |  | to have GnuPG read from the file F<input.txt> and write to F<output.txt>, | 
| 1075 |  |  |  |  |  |  |  | the following snippet may do: | 
| 1076 |  |  |  |  |  |  |  |  | 
| 1077 |  |  |  |  |  |  |  | my $infile  = IO::File->new( 'input.txt' ); | 
| 1078 |  |  |  |  |  |  |  | my $outfile = IO::File->new( '>output.txt' ); | 
| 1079 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new( stdin  => $infile, | 
| 1080 |  |  |  |  |  |  |  | stdout => $outfile, | 
| 1081 |  |  |  |  |  |  |  | ); | 
| 1082 |  |  |  |  |  |  |  | $handles->options( 'stdin'  )->{direct} = 1; | 
| 1083 |  |  |  |  |  |  |  | $handles->options( 'stdout' )->{direct} = 1; | 
| 1084 |  |  |  |  |  |  |  |  | 
| 1085 |  |  |  |  |  |  |  | If any handle in the B<handles> object is not defined, GnuPG's input, output, | 
| 1086 |  |  |  |  |  |  |  | and standard error will be tied to the running program's standard error, | 
| 1087 |  |  |  |  |  |  |  | standard output, or standard error.  If the B<status> or B<logger> handle | 
| 1088 |  |  |  |  |  |  |  | is not defined, this channel of communication is never established with GnuPG, | 
| 1089 |  |  |  |  |  |  |  | and so this information is not generated and does not come into play. | 
| 1090 |  |  |  |  |  |  |  |  | 
| 1091 |  |  |  |  |  |  |  | If the B<passphrase> data member handle of the B<handles> object | 
| 1092 |  |  |  |  |  |  |  | is not defined, but the the B<passphrase> data member handle of GnuPG::Interface | 
| 1093 |  |  |  |  |  |  |  | object is, GnuPG::Interface will handle passing this information into GnuPG | 
| 1094 |  |  |  |  |  |  |  | for the user as a convenience.  Note that this will result in | 
| 1095 |  |  |  |  |  |  |  | GnuPG::Interface storing the passphrase in memory, instead of having | 
| 1096 |  |  |  |  |  |  |  | it simply 'pass-through' to GnuPG via a handle. | 
| 1097 |  |  |  |  |  |  |  |  | 
| 1098 |  |  |  |  |  |  |  | If neither the B<passphrase> data member of the GnuPG::Interface nor | 
| 1099 |  |  |  |  |  |  |  | the B<passphrase> data member of the B<handles> object is defined, | 
| 1100 |  |  |  |  |  |  |  | then GnuPG::Interface assumes that access and control over the secret | 
| 1101 |  |  |  |  |  |  |  | key will be handled by the running gpg-agent process.  This represents | 
| 1102 |  |  |  |  |  |  |  | the simplest mode of operation with the GnuPG "stable" suite (version | 
| 1103 |  |  |  |  |  |  |  | 2.2 and later).  It is also the preferred mode for tools intended to | 
| 1104 |  |  |  |  |  |  |  | be user-facing, since the user will be prompted directly by gpg-agent | 
| 1105 |  |  |  |  |  |  |  | for use of the secret key material.  Note that for programmatic use, | 
| 1106 |  |  |  |  |  |  |  | this mode requires the gpg-agent and pinentry to already be correctly | 
| 1107 |  |  |  |  |  |  |  | configured. | 
| 1108 |  |  |  |  |  |  |  |  | 
| 1109 |  |  |  |  |  |  |  | =back | 
| 1110 |  |  |  |  |  |  |  |  | 
| 1111 |  |  |  |  |  |  |  | =head2 Other Methods | 
| 1112 |  |  |  |  |  |  |  |  | 
| 1113 |  |  |  |  |  |  |  | =over 4 | 
| 1114 |  |  |  |  |  |  |  |  | 
| 1115 |  |  |  |  |  |  |  | =item get_public_keys( @search_strings ) | 
| 1116 |  |  |  |  |  |  |  |  | 
| 1117 |  |  |  |  |  |  |  | =item get_secret_keys( @search_strings ) | 
| 1118 |  |  |  |  |  |  |  |  | 
| 1119 |  |  |  |  |  |  |  | =item get_public_keys_with_sigs( @search_strings ) | 
| 1120 |  |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  |  | These methods create and return objects of the type GnuPG::PublicKey | 
| 1122 |  |  |  |  |  |  |  | or GnuPG::SecretKey respectively.  This is done by parsing the output | 
| 1123 |  |  |  |  |  |  |  | of GnuPG with the option B<with-colons> enabled.  The objects created | 
| 1124 |  |  |  |  |  |  |  | do or do not have signature information stored in them, depending | 
| 1125 |  |  |  |  |  |  |  | if the method ends in I<_sigs>; this separation of functionality is there | 
| 1126 |  |  |  |  |  |  |  | because of performance hits when listing information with signatures. | 
| 1127 |  |  |  |  |  |  |  |  | 
| 1128 |  |  |  |  |  |  |  | =item test_default_key_passphrase() | 
| 1129 |  |  |  |  |  |  |  |  | 
| 1130 |  |  |  |  |  |  |  | This method will return a true or false value, depending | 
| 1131 |  |  |  |  |  |  |  | on whether GnuPG reports a good passphrase was entered | 
| 1132 |  |  |  |  |  |  |  | while signing a short message using the values of | 
| 1133 |  |  |  |  |  |  |  | the B<passphrase> data member, and the default | 
| 1134 |  |  |  |  |  |  |  | key specified in the B<options> data member. | 
| 1135 |  |  |  |  |  |  |  |  | 
| 1136 |  |  |  |  |  |  |  | =item version() | 
| 1137 |  |  |  |  |  |  |  |  | 
| 1138 |  |  |  |  |  |  |  | Returns the version of GnuPG that GnuPG::Interface is running. | 
| 1139 |  |  |  |  |  |  |  |  | 
| 1140 |  |  |  |  |  |  |  | =back | 
| 1141 |  |  |  |  |  |  |  |  | 
| 1142 |  |  |  |  |  |  |  |  | 
| 1143 |  |  |  |  |  |  |  | =head1 Invoking GnuPG with a custom call | 
| 1144 |  |  |  |  |  |  |  |  | 
| 1145 |  |  |  |  |  |  |  | GnuPG::Interface attempts to cover a lot of the commands | 
| 1146 |  |  |  |  |  |  |  | of GnuPG that one would want to perform; however, there may be a lot | 
| 1147 |  |  |  |  |  |  |  | more calls that GnuPG is and will be capable of, so a generic command | 
| 1148 |  |  |  |  |  |  |  | interface is provided, C<wrap_call>. | 
| 1149 |  |  |  |  |  |  |  |  | 
| 1150 |  |  |  |  |  |  |  | =over 4 | 
| 1151 |  |  |  |  |  |  |  |  | 
| 1152 |  |  |  |  |  |  |  | =item wrap_call( %args ) | 
| 1153 |  |  |  |  |  |  |  |  | 
| 1154 |  |  |  |  |  |  |  | Call GnuPG with a custom command.  The %args hash must contain | 
| 1155 |  |  |  |  |  |  |  | at least the following keys: | 
| 1156 |  |  |  |  |  |  |  |  | 
| 1157 |  |  |  |  |  |  |  | =over 4 | 
| 1158 |  |  |  |  |  |  |  |  | 
| 1159 |  |  |  |  |  |  |  | =item commands | 
| 1160 |  |  |  |  |  |  |  |  | 
| 1161 |  |  |  |  |  |  |  | The value of this key in the hash must be a reference to a a list of | 
| 1162 |  |  |  |  |  |  |  | commands for GnuPG, such as C<[ qw( --encrypt --sign ) ]>. | 
| 1163 |  |  |  |  |  |  |  |  | 
| 1164 |  |  |  |  |  |  |  | =item handles | 
| 1165 |  |  |  |  |  |  |  |  | 
| 1166 |  |  |  |  |  |  |  | As with most other GnuPG::Interface methods, B<handles> | 
| 1167 |  |  |  |  |  |  |  | must be a GnuPG::Handles object. | 
| 1168 |  |  |  |  |  |  |  |  | 
| 1169 |  |  |  |  |  |  |  | =back | 
| 1170 |  |  |  |  |  |  |  |  | 
| 1171 |  |  |  |  |  |  |  | The following keys are optional. | 
| 1172 |  |  |  |  |  |  |  |  | 
| 1173 |  |  |  |  |  |  |  | =over 4 | 
| 1174 |  |  |  |  |  |  |  |  | 
| 1175 |  |  |  |  |  |  |  | =item command_args | 
| 1176 |  |  |  |  |  |  |  |  | 
| 1177 |  |  |  |  |  |  |  | As with other GnuPG::Interface methods, the value in hash | 
| 1178 |  |  |  |  |  |  |  | for this key must be a reference to a list of arguments | 
| 1179 |  |  |  |  |  |  |  | to be passed to the GnuPG command, such as which | 
| 1180 |  |  |  |  |  |  |  | keys to list in a key-listing. | 
| 1181 |  |  |  |  |  |  |  |  | 
| 1182 |  |  |  |  |  |  |  | =back | 
| 1183 |  |  |  |  |  |  |  |  | 
| 1184 |  |  |  |  |  |  |  | =back | 
| 1185 |  |  |  |  |  |  |  |  | 
| 1186 |  |  |  |  |  |  |  |  | 
| 1187 |  |  |  |  |  |  |  | =head1 OBJECT DATA MEMBERS | 
| 1188 |  |  |  |  |  |  |  |  | 
| 1189 |  |  |  |  |  |  |  | =over 4 | 
| 1190 |  |  |  |  |  |  |  |  | 
| 1191 |  |  |  |  |  |  |  | =item call | 
| 1192 |  |  |  |  |  |  |  |  | 
| 1193 |  |  |  |  |  |  |  | This defines the call made to invoke GnuPG.  Defaults to 'gpg'; this | 
| 1194 |  |  |  |  |  |  |  | should be changed if 'gpg' is not in your path, or there is a different | 
| 1195 |  |  |  |  |  |  |  | name for the binary on your system. | 
| 1196 |  |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  |  | =item passphrase | 
| 1198 |  |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  |  | In order to lessen the burden of using handles by the user of this package, | 
| 1200 |  |  |  |  |  |  |  | setting this option to one's passphrase for a secret key will allow | 
| 1201 |  |  |  |  |  |  |  | the package to enter the passphrase via a handle to GnuPG by itself | 
| 1202 |  |  |  |  |  |  |  | instead of leaving this to the user.  See also L<GnuPG::Handles/passphrase>. | 
| 1203 |  |  |  |  |  |  |  |  | 
| 1204 |  |  |  |  |  |  |  | =item options | 
| 1205 |  |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  |  | This data member, of the type GnuPG::Options; the setting stored in this | 
| 1207 |  |  |  |  |  |  |  | data member are used to determine the options used when calling GnuPG | 
| 1208 |  |  |  |  |  |  |  | via I<any> of the object methods described in this package. | 
| 1209 |  |  |  |  |  |  |  | See L<GnuPG::Options> for more information. | 
| 1210 |  |  |  |  |  |  |  |  | 
| 1211 |  |  |  |  |  |  |  | =back | 
| 1212 |  |  |  |  |  |  |  |  | 
| 1213 |  |  |  |  |  |  |  | =head1 EXAMPLES | 
| 1214 |  |  |  |  |  |  |  |  | 
| 1215 |  |  |  |  |  |  |  | The following setup can be done before any of the following examples: | 
| 1216 |  |  |  |  |  |  |  |  | 
| 1217 |  |  |  |  |  |  |  | use IO::Handle; | 
| 1218 |  |  |  |  |  |  |  | use GnuPG::Interface; | 
| 1219 |  |  |  |  |  |  |  |  | 
| 1220 |  |  |  |  |  |  |  | my @original_plaintext = ( "How do you doo?" ); | 
| 1221 |  |  |  |  |  |  |  | my $passphrase = "Three Little Pigs"; | 
| 1222 |  |  |  |  |  |  |  |  | 
| 1223 |  |  |  |  |  |  |  | my $gnupg = GnuPG::Interface->new(); | 
| 1224 |  |  |  |  |  |  |  |  | 
| 1225 |  |  |  |  |  |  |  | $gnupg->options->hash_init( armor    => 1, | 
| 1226 |  |  |  |  |  |  |  | recipients => [ 'ftobin@uiuc.edu', | 
| 1227 |  |  |  |  |  |  |  | '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ], | 
| 1228 |  |  |  |  |  |  |  | meta_interactive => 0 , | 
| 1229 |  |  |  |  |  |  |  | ); | 
| 1230 |  |  |  |  |  |  |  |  | 
| 1231 |  |  |  |  |  |  |  | $gnupg->options->debug_level(4); | 
| 1232 |  |  |  |  |  |  |  |  | 
| 1233 |  |  |  |  |  |  |  | $gnupg->options->logger_file("/tmp/gnupg-$$-decrypt-".time().".log"); | 
| 1234 |  |  |  |  |  |  |  |  | 
| 1235 |  |  |  |  |  |  |  |  | 
| 1236 |  |  |  |  |  |  |  | =head2 Encrypting | 
| 1237 |  |  |  |  |  |  |  |  | 
| 1238 |  |  |  |  |  |  |  | # We'll let the standard error of GnuPG pass through | 
| 1239 |  |  |  |  |  |  |  | # to our own standard error, by not creating | 
| 1240 |  |  |  |  |  |  |  | # a stderr-part of the $handles object. | 
| 1241 |  |  |  |  |  |  |  | my ( $input, $output ) = ( IO::Handle->new(), | 
| 1242 |  |  |  |  |  |  |  | IO::Handle->new() ); | 
| 1243 |  |  |  |  |  |  |  |  | 
| 1244 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new( stdin    => $input, | 
| 1245 |  |  |  |  |  |  |  | stdout   => $output ); | 
| 1246 |  |  |  |  |  |  |  |  | 
| 1247 |  |  |  |  |  |  |  | # this sets up the communication | 
| 1248 |  |  |  |  |  |  |  | # Note that the recipients were specified earlier | 
| 1249 |  |  |  |  |  |  |  | # in the 'options' data member of the $gnupg object. | 
| 1250 |  |  |  |  |  |  |  | my $pid = $gnupg->encrypt( handles => $handles ); | 
| 1251 |  |  |  |  |  |  |  |  | 
| 1252 |  |  |  |  |  |  |  | # this passes in the plaintext | 
| 1253 |  |  |  |  |  |  |  | print $input @original_plaintext; | 
| 1254 |  |  |  |  |  |  |  |  | 
| 1255 |  |  |  |  |  |  |  | # this closes the communication channel, | 
| 1256 |  |  |  |  |  |  |  | # indicating we are done | 
| 1257 |  |  |  |  |  |  |  | close $input; | 
| 1258 |  |  |  |  |  |  |  |  | 
| 1259 |  |  |  |  |  |  |  | my @ciphertext = <$output>;  # reading the output | 
| 1260 |  |  |  |  |  |  |  |  | 
| 1261 |  |  |  |  |  |  |  | waitpid $pid, 0;  # clean up the finished GnuPG process | 
| 1262 |  |  |  |  |  |  |  |  | 
| 1263 |  |  |  |  |  |  |  | =head2 Signing | 
| 1264 |  |  |  |  |  |  |  |  | 
| 1265 |  |  |  |  |  |  |  | # This time we'll catch the standard error for our perusing | 
| 1266 |  |  |  |  |  |  |  | my ( $input, $output, $error ) = ( IO::Handle->new(), | 
| 1267 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1268 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1269 |  |  |  |  |  |  |  | ); | 
| 1270 |  |  |  |  |  |  |  |  | 
| 1271 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new( stdin    => $input, | 
| 1272 |  |  |  |  |  |  |  | stdout   => $output, | 
| 1273 |  |  |  |  |  |  |  | stderr   => $error, | 
| 1274 |  |  |  |  |  |  |  | ); | 
| 1275 |  |  |  |  |  |  |  |  | 
| 1276 |  |  |  |  |  |  |  | # indicate our pasphrase through the | 
| 1277 |  |  |  |  |  |  |  | # convenience method | 
| 1278 |  |  |  |  |  |  |  | $gnupg->passphrase( $passphrase ); | 
| 1279 |  |  |  |  |  |  |  |  | 
| 1280 |  |  |  |  |  |  |  | # this sets up the communication | 
| 1281 |  |  |  |  |  |  |  | my $pid = $gnupg->sign( handles => $handles ); | 
| 1282 |  |  |  |  |  |  |  |  | 
| 1283 |  |  |  |  |  |  |  | # this passes in the plaintext | 
| 1284 |  |  |  |  |  |  |  | print $input @original_plaintext; | 
| 1285 |  |  |  |  |  |  |  |  | 
| 1286 |  |  |  |  |  |  |  | # this closes the communication channel, | 
| 1287 |  |  |  |  |  |  |  | # indicating we are done | 
| 1288 |  |  |  |  |  |  |  | close $input; | 
| 1289 |  |  |  |  |  |  |  |  | 
| 1290 |  |  |  |  |  |  |  | my @ciphertext   = <$output>;  # reading the output | 
| 1291 |  |  |  |  |  |  |  | my @error_output = <$error>;   # reading the error | 
| 1292 |  |  |  |  |  |  |  |  | 
| 1293 |  |  |  |  |  |  |  | close $output; | 
| 1294 |  |  |  |  |  |  |  | close $error; | 
| 1295 |  |  |  |  |  |  |  |  | 
| 1296 |  |  |  |  |  |  |  | waitpid $pid, 0;  # clean up the finished GnuPG process | 
| 1297 |  |  |  |  |  |  |  |  | 
| 1298 |  |  |  |  |  |  |  | =head2 Decryption | 
| 1299 |  |  |  |  |  |  |  |  | 
| 1300 |  |  |  |  |  |  |  | # This time we'll catch the standard error for our perusing | 
| 1301 |  |  |  |  |  |  |  | # as well as passing in the passphrase manually | 
| 1302 |  |  |  |  |  |  |  | # as well as the status information given by GnuPG | 
| 1303 |  |  |  |  |  |  |  | my ( $input, $output, $error, $passphrase_fh, $status_fh ) | 
| 1304 |  |  |  |  |  |  |  | = ( IO::Handle->new(), | 
| 1305 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1306 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1307 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1308 |  |  |  |  |  |  |  | IO::Handle->new(), | 
| 1309 |  |  |  |  |  |  |  | ); | 
| 1310 |  |  |  |  |  |  |  |  | 
| 1311 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new( stdin      => $input, | 
| 1312 |  |  |  |  |  |  |  | stdout     => $output, | 
| 1313 |  |  |  |  |  |  |  | stderr     => $error, | 
| 1314 |  |  |  |  |  |  |  | passphrase => $passphrase_fh, | 
| 1315 |  |  |  |  |  |  |  | status     => $status_fh, | 
| 1316 |  |  |  |  |  |  |  | ); | 
| 1317 |  |  |  |  |  |  |  |  | 
| 1318 |  |  |  |  |  |  |  | # this time we'll also demonstrate decrypting | 
| 1319 |  |  |  |  |  |  |  | # a file written to disk | 
| 1320 |  |  |  |  |  |  |  | # Make sure you "use IO::File" if you use this module! | 
| 1321 |  |  |  |  |  |  |  | my $cipher_file = IO::File->new( 'encrypted.gpg' ); | 
| 1322 |  |  |  |  |  |  |  |  | 
| 1323 |  |  |  |  |  |  |  | # this sets up the communication | 
| 1324 |  |  |  |  |  |  |  | my $pid = $gnupg->decrypt( handles => $handles ); | 
| 1325 |  |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  |  | # This passes in the passphrase | 
| 1327 |  |  |  |  |  |  |  | print $passphrase_fh $passphrase; | 
| 1328 |  |  |  |  |  |  |  | close $passphrase_fh; | 
| 1329 |  |  |  |  |  |  |  |  | 
| 1330 |  |  |  |  |  |  |  | # this passes in the plaintext | 
| 1331 |  |  |  |  |  |  |  | print $input $_ while <$cipher_file>; | 
| 1332 |  |  |  |  |  |  |  |  | 
| 1333 |  |  |  |  |  |  |  | # this closes the communication channel, | 
| 1334 |  |  |  |  |  |  |  | # indicating we are done | 
| 1335 |  |  |  |  |  |  |  | close $input; | 
| 1336 |  |  |  |  |  |  |  | close $cipher_file; | 
| 1337 |  |  |  |  |  |  |  |  | 
| 1338 |  |  |  |  |  |  |  | my @plaintext    = <$output>;    # reading the output | 
| 1339 |  |  |  |  |  |  |  | my @error_output = <$error>;     # reading the error | 
| 1340 |  |  |  |  |  |  |  | my @status_info  = <$status_fh>; # read the status info | 
| 1341 |  |  |  |  |  |  |  |  | 
| 1342 |  |  |  |  |  |  |  | # clean up... | 
| 1343 |  |  |  |  |  |  |  | close $output; | 
| 1344 |  |  |  |  |  |  |  | close $error; | 
| 1345 |  |  |  |  |  |  |  | close $status_fh; | 
| 1346 |  |  |  |  |  |  |  |  | 
| 1347 |  |  |  |  |  |  |  | waitpid $pid, 0;  # clean up the finished GnuPG process | 
| 1348 |  |  |  |  |  |  |  |  | 
| 1349 |  |  |  |  |  |  |  | =head2 Printing Keys | 
| 1350 |  |  |  |  |  |  |  |  | 
| 1351 |  |  |  |  |  |  |  | # This time we'll just let GnuPG print to our own output | 
| 1352 |  |  |  |  |  |  |  | # and read from our input, because no input is needed! | 
| 1353 |  |  |  |  |  |  |  | my $handles = GnuPG::Handles->new(); | 
| 1354 |  |  |  |  |  |  |  |  | 
| 1355 |  |  |  |  |  |  |  | my @ids = ( 'ftobin', '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ); | 
| 1356 |  |  |  |  |  |  |  |  | 
| 1357 |  |  |  |  |  |  |  | # this time we need to specify something for | 
| 1358 |  |  |  |  |  |  |  | # command_args because --list-public-keys takes | 
| 1359 |  |  |  |  |  |  |  | # search ids as arguments | 
| 1360 |  |  |  |  |  |  |  | my $pid = $gnupg->list_public_keys( handles      => $handles, | 
| 1361 |  |  |  |  |  |  |  | command_args => [ @ids ] ); | 
| 1362 |  |  |  |  |  |  |  |  | 
| 1363 |  |  |  |  |  |  |  | waitpid $pid, 0; | 
| 1364 |  |  |  |  |  |  |  |  | 
| 1365 |  |  |  |  |  |  |  | =head2 Creating GnuPG::PublicKey Objects | 
| 1366 |  |  |  |  |  |  |  |  | 
| 1367 |  |  |  |  |  |  |  | my @ids = [ 'ftobin', '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ]; | 
| 1368 |  |  |  |  |  |  |  |  | 
| 1369 |  |  |  |  |  |  |  | my @keys = $gnupg->get_public_keys( @ids ); | 
| 1370 |  |  |  |  |  |  |  |  | 
| 1371 |  |  |  |  |  |  |  | # no wait is required this time; it's handled internally | 
| 1372 |  |  |  |  |  |  |  | # since the entire call is encapsulated | 
| 1373 |  |  |  |  |  |  |  |  | 
| 1374 |  |  |  |  |  |  |  | =head2 Custom GnuPG call | 
| 1375 |  |  |  |  |  |  |  |  | 
| 1376 |  |  |  |  |  |  |  | # assuming $handles is a GnuPG::Handles object | 
| 1377 |  |  |  |  |  |  |  | my $pid = $gnupg->wrap_call | 
| 1378 |  |  |  |  |  |  |  | ( commands     => [ qw( --list-packets ) ], | 
| 1379 |  |  |  |  |  |  |  | command_args => [ qw( test/key.1.asc ) ], | 
| 1380 |  |  |  |  |  |  |  | handles      => $handles, | 
| 1381 |  |  |  |  |  |  |  | ); | 
| 1382 |  |  |  |  |  |  |  |  | 
| 1383 |  |  |  |  |  |  |  | my @out = <$handles->stdout()>; | 
| 1384 |  |  |  |  |  |  |  | waitpid $pid, 0; | 
| 1385 |  |  |  |  |  |  |  |  | 
| 1386 |  |  |  |  |  |  |  |  | 
| 1387 |  |  |  |  |  |  |  | =head1 FAQ | 
| 1388 |  |  |  |  |  |  |  |  | 
| 1389 |  |  |  |  |  |  |  | =over 4 | 
| 1390 |  |  |  |  |  |  |  |  | 
| 1391 |  |  |  |  |  |  |  | =item How do I get GnuPG::Interface to read/write directly from | 
| 1392 |  |  |  |  |  |  |  | a filehandle? | 
| 1393 |  |  |  |  |  |  |  |  | 
| 1394 |  |  |  |  |  |  |  | You need to set GnuPG::Handles B<direct> option to be true for the | 
| 1395 |  |  |  |  |  |  |  | filehandles in concern.  See L<GnuPG::Handles/options> and | 
| 1396 |  |  |  |  |  |  |  | L<"Object Methods which use a GnuPG::Handles Object"> for more | 
| 1397 |  |  |  |  |  |  |  | information. | 
| 1398 |  |  |  |  |  |  |  |  | 
| 1399 |  |  |  |  |  |  |  | =item Why do you make it so difficult to get GnuPG to write/read | 
| 1400 |  |  |  |  |  |  |  | from a filehandle?  In the shell, I can just call GnuPG | 
| 1401 |  |  |  |  |  |  |  | with the --outfile option! | 
| 1402 |  |  |  |  |  |  |  |  | 
| 1403 |  |  |  |  |  |  |  | There are lots of issues when trying to tell GnuPG to read/write | 
| 1404 |  |  |  |  |  |  |  | directly from a file, such as if the file isn't there, or | 
| 1405 |  |  |  |  |  |  |  | there is a file, and you want to write over it!  What do you | 
| 1406 |  |  |  |  |  |  |  | want to happen then?  Having the user of this module handle | 
| 1407 |  |  |  |  |  |  |  | these questions beforehand by opening up filehandles to GnuPG | 
| 1408 |  |  |  |  |  |  |  | lets the user know fully what is going to happen in these circumstances, | 
| 1409 |  |  |  |  |  |  |  | and makes the module less error-prone. | 
| 1410 |  |  |  |  |  |  |  |  | 
| 1411 |  |  |  |  |  |  |  | =item When having GnuPG process a large message, sometimes it just | 
| 1412 |  |  |  |  |  |  |  | hanges there. | 
| 1413 |  |  |  |  |  |  |  |  | 
| 1414 |  |  |  |  |  |  |  | Your problem may be due to buffering issues; when GnuPG reads/writes | 
| 1415 |  |  |  |  |  |  |  | to B<non-direct> filehandles (those that are sent to filehandles | 
| 1416 |  |  |  |  |  |  |  | which you read to from into memory, not that those access the disk), | 
| 1417 |  |  |  |  |  |  |  | buffering issues can mess things up.  I recommend looking into | 
| 1418 |  |  |  |  |  |  |  | L<GnuPG::Handles/options>. | 
| 1419 |  |  |  |  |  |  |  |  | 
| 1420 |  |  |  |  |  |  |  | =back | 
| 1421 |  |  |  |  |  |  |  |  | 
| 1422 |  |  |  |  |  |  |  | =head1 NOTES | 
| 1423 |  |  |  |  |  |  |  |  | 
| 1424 |  |  |  |  |  |  |  | This package is the successor to PGP::GPG::MessageProcessor, | 
| 1425 |  |  |  |  |  |  |  | which I found to be too inextensible to carry on further. | 
| 1426 |  |  |  |  |  |  |  | A total redesign was needed, and this is the resulting | 
| 1427 |  |  |  |  |  |  |  | work. | 
| 1428 |  |  |  |  |  |  |  |  | 
| 1429 |  |  |  |  |  |  |  | After any call to a GnuPG-command method of GnuPG::Interface | 
| 1430 |  |  |  |  |  |  |  | in which one passes in the handles, | 
| 1431 |  |  |  |  |  |  |  | one should all B<wait> to clean up GnuPG from the process table. | 
| 1432 |  |  |  |  |  |  |  |  | 
| 1433 |  |  |  |  |  |  |  |  | 
| 1434 |  |  |  |  |  |  |  | =head1 BUGS | 
| 1435 |  |  |  |  |  |  |  |  | 
| 1436 |  |  |  |  |  |  |  | =head2 Large Amounts of Data | 
| 1437 |  |  |  |  |  |  |  |  | 
| 1438 |  |  |  |  |  |  |  | Currently there are problems when transmitting large quantities | 
| 1439 |  |  |  |  |  |  |  | of information over handles; I'm guessing this is due | 
| 1440 |  |  |  |  |  |  |  | to buffering issues.  This bug does not seem specific to this package; | 
| 1441 |  |  |  |  |  |  |  | IPC::Open3 also appears affected. | 
| 1442 |  |  |  |  |  |  |  |  | 
| 1443 |  |  |  |  |  |  |  | =head2 OpenPGP v3 Keys | 
| 1444 |  |  |  |  |  |  |  |  | 
| 1445 |  |  |  |  |  |  |  | I don't know yet how well this module handles parsing OpenPGP v3 keys. | 
| 1446 |  |  |  |  |  |  |  |  | 
| 1447 |  |  |  |  |  |  |  | =head2 RHEL 7 Test Failures | 
| 1448 |  |  |  |  |  |  |  |  | 
| 1449 |  |  |  |  |  |  |  | Testing with the updates for version 1.00 we saw intermittent test failures | 
| 1450 |  |  |  |  |  |  |  | on RHEL 7 with GnuPG version 2.2.20. In some cases the tests would all pass | 
| 1451 |  |  |  |  |  |  |  | for several runs, then one would fail. We're unable to reliably reproduce | 
| 1452 |  |  |  |  |  |  |  | this so we would be interested in feedback from other users. | 
| 1453 |  |  |  |  |  |  |  |  | 
| 1454 |  |  |  |  |  |  |  | =head1 SEE ALSO | 
| 1455 |  |  |  |  |  |  |  |  | 
| 1456 |  |  |  |  |  |  |  | L<GnuPG::Options>, | 
| 1457 |  |  |  |  |  |  |  | L<GnuPG::Handles>, | 
| 1458 |  |  |  |  |  |  |  | L<GnuPG::PublicKey>, | 
| 1459 |  |  |  |  |  |  |  | L<GnuPG::SecretKey>, | 
| 1460 |  |  |  |  |  |  |  | L<gpg>, | 
| 1461 |  |  |  |  |  |  |  | L<perlipc/"Bidirectional Communication with Another Process"> | 
| 1462 |  |  |  |  |  |  |  |  | 
| 1463 |  |  |  |  |  |  |  | =head1 LICENSE | 
| 1464 |  |  |  |  |  |  |  |  | 
| 1465 |  |  |  |  |  |  |  | This module is free software; you can redistribute it and/or modify it | 
| 1466 |  |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 1467 |  |  |  |  |  |  |  |  | 
| 1468 |  |  |  |  |  |  |  | =head1 AUTHOR | 
| 1469 |  |  |  |  |  |  |  |  | 
| 1470 |  |  |  |  |  |  |  | GnuPG::Interface is currently maintained by Best Practical Solutions <BPS@cpan.org>. | 
| 1471 |  |  |  |  |  |  |  |  | 
| 1472 |  |  |  |  |  |  |  | Frank J. Tobin, ftobin@cpan.org was the original author of the package. | 
| 1473 |  |  |  |  |  |  |  |  | 
| 1474 |  |  |  |  |  |  |  | =cut | 
| 1475 |  |  |  |  |  |  |  |  | 
| 1476 |  |  |  |  |  |  |  | 1; | 
| 1477 |  |  |  |  |  |  |  |  |