File Coverage

blib/lib/Dpkg/OpenPGP.pm
Criterion Covered Total %
statement 57 108 52.7
branch 16 50 32.0
condition 0 16 0.0
subroutine 11 13 84.6
pod 0 3 0.0
total 84 190 44.2


line stmt bran cond sub pod time code
1             # Copyright © 2017 Guillem Jover
2             #
3             # This program is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation; either version 2 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16             package Dpkg::OpenPGP;
17              
18 2     2   100675 use strict;
  2         4  
  2         60  
19 2     2   11 use warnings;
  2         5  
  2         61  
20              
21 2     2   12 use POSIX qw(:sys_wait_h);
  2         5  
  2         14  
22 2     2   359 use Exporter qw(import);
  2         4  
  2         54  
23 2     2   805 use File::Temp;
  2         10317  
  2         154  
24 2     2   525 use File::Copy;
  2         2425  
  2         109  
25              
26 2     2   12 use Dpkg::Gettext;
  2         5  
  2         102  
27 2     2   12 use Dpkg::ErrorHandling;
  2         4  
  2         156  
28 2     2   475 use Dpkg::IPC;
  2         6  
  2         116  
29 2     2   458 use Dpkg::Path qw(find_command);
  2         5  
  2         2242  
30              
31             our $VERSION = '0.01';
32             our @EXPORT = qw(
33             openpgp_sig_to_asc
34             );
35              
36             sub openpgp_sig_to_asc
37             {
38 3     3 0 608 my ($sig, $asc) = @_;
39              
40 3 100       63 if (-e $sig) {
41 2         7 my $is_openpgp_ascii_armor = 0;
42              
43 2 50       82 open my $fh_sig, '<', $sig or syserr(g_('cannot open %s'), $sig);
44 2         55 while (<$fh_sig>) {
45 5 100       37 if (m/^-----BEGIN PGP /) {
46 1         8 $is_openpgp_ascii_armor = 1;
47 1         7 last;
48             }
49             }
50 2         23 close $fh_sig;
51              
52 2 100       8 if ($is_openpgp_ascii_armor) {
53 1         23 notice(g_('signature file is already OpenPGP ASCII armor, copying'));
54 1         23 copy($sig, $asc);
55 1         436 return $asc;
56             }
57              
58 1 50       5 if (not find_command('gpg')) {
59 0         0 warning(g_('cannot OpenPGP ASCII armor signature file due to missing gpg'));
60             }
61              
62 1         4 my @gpg_opts = qw(--no-options);
63              
64 1 50       2417 open my $fh_asc, '>', $asc
65             or syserr(g_('cannot create signature file %s'), $asc);
66 1 50       3567 open my $fh_gpg, '-|', 'gpg', @gpg_opts, '-o', '-', '--enarmor', $sig
67             or syserr(g_('cannot execute %s program'), 'gpg');
68 1         2156 while (my $line = <$fh_gpg>) {
69 18 100       84 next if $line =~ m/^Version: /;
70 17 100       151 next if $line =~ m/^Comment: /;
71              
72 16         55 $line =~ s/ARMORED FILE/SIGNATURE/;
73              
74 16         26 print { $fh_asc } $line;
  16         137  
75             }
76              
77 1 50       47 close $fh_gpg or subprocerr('gpg');
78 1 50       72 close $fh_asc or syserr(g_('cannot write signature file %s'), $asc);
79              
80 1         114 return $asc;
81             }
82              
83 1         7 return;
84             }
85              
86             sub import_key {
87 0     0 0   my ($asc, %opts) = @_;
88              
89 0   0       $opts{require_valid_signature} //= 1;
90              
91 0           my @exec;
92 0 0         if (find_command('gpg')) {
    0          
93 0           push @exec, 'gpg';
94             } elsif ($opts{require_valid_signature}) {
95 0           error(g_('cannot import key in %s since GnuPG is not installed'),
96             $asc);
97             } else {
98 0           warning(g_('cannot import key in %s since GnuPG is not installed'),
99             $asc);
100 0           return;
101             }
102              
103 0           my $gpghome = File::Temp->newdir('dpkg-import-key.XXXXXXXX', TMPDIR => 1);
104              
105 0           push @exec, '--homedir', $gpghome;
106 0           push @exec, '--no-options', '--no-default-keyring', '-q', '--import';
107 0           push @exec, '--keyring', $opts{keyring};
108 0           push @exec, $asc;
109              
110 0           my ($stdout, $stderr);
111 0           spawn(exec => \@exec, wait_child => 1, nocheck => 1, timeout => 10,
112             to_string => \$stdout, error_to_string => \$stderr);
113 0 0         if (WIFEXITED($?)) {
114 0           my $status = WEXITSTATUS($?);
115 0 0         print { *STDERR } "$stdout$stderr" if $status;
  0            
116 0 0 0       if ($status == 1 or ($status && $opts{require_valid_signature})) {
    0 0        
117 0           error(g_('failed to import key in %s'), $asc);
118             } elsif ($status) {
119 0           warning(g_('failed to import key in %s'), $asc);
120             }
121             } else {
122 0           subprocerr("@exec");
123             }
124             }
125              
126             sub verify_signature {
127 0     0 0   my ($sig, %opts) = @_;
128              
129 0   0       $opts{require_valid_signature} //= 1;
130              
131 0           my @exec;
132 0 0         if (find_command('gpgv')) {
    0          
    0          
133 0           push @exec, 'gpgv';
134             } elsif (find_command('gpg')) {
135 0           my @gpg_opts = qw(--no-options --no-default-keyring -q);
136 0           push @exec, 'gpg', @gpg_opts, '--verify';
137             } elsif ($opts{require_valid_signature}) {
138 0           error(g_('cannot verify signature on %s since GnuPG is not installed'),
139             $sig);
140             } else {
141 0           warning(g_('cannot verify signature on %s since GnuPG is not installed'),
142             $sig);
143 0           return;
144             }
145              
146 0           my $gpghome = File::Temp->newdir('dpkg-verify-sig.XXXXXXXX', TMPDIR => 1);
147 0           push @exec, '--homedir', $gpghome;
148 0           foreach my $keyring (@{$opts{keyrings}}) {
  0            
149 0           push @exec, '--keyring', $keyring;
150             }
151 0           push @exec, $sig;
152 0 0         push @exec, $opts{datafile} if exists $opts{datafile};
153              
154 0           my ($stdout, $stderr);
155 0           spawn(exec => \@exec, wait_child => 1, nocheck => 1, timeout => 10,
156             to_string => \$stdout, error_to_string => \$stderr);
157 0 0         if (WIFEXITED($?)) {
158 0           my $status = WEXITSTATUS($?);
159 0 0         print { *STDERR } "$stdout$stderr" if $status;
  0            
160 0 0 0       if ($status == 1 or ($status && $opts{require_valid_signature})) {
    0 0        
161 0           error(g_('failed to verify signature on %s'), $sig);
162             } elsif ($status) {
163 0           warning(g_('failed to verify signature on %s'), $sig);
164             }
165             } else {
166 0           subprocerr("@exec");
167             }
168             }
169              
170             1;