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