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
|
|
|
|
|
|
|
|
|