diff options
Diffstat (limited to 'lib/Devscripts/Uscan/Keyring.pm')
-rw-r--r-- | lib/Devscripts/Uscan/Keyring.pm | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/lib/Devscripts/Uscan/Keyring.pm b/lib/Devscripts/Uscan/Keyring.pm new file mode 100644 index 0000000..0af6088 --- /dev/null +++ b/lib/Devscripts/Uscan/Keyring.pm @@ -0,0 +1,168 @@ +package Devscripts::Uscan::Keyring; + +use strict; +use Devscripts::Uscan::Output; +use Devscripts::Uscan::Utils; +use Dpkg::IPC; +use File::Copy qw/copy move/; +use File::Which; +use File::Path qw/make_path remove_tree/; +use File::Temp qw/tempfile tempdir/; +use List::Util qw/first/; + +sub new { + my ($class) = @_; + my $keyring; + my $havegpgv = first { which $_ } qw(gpgv2 gpgv); + my $havegpg = first { which $_ } qw(gpg2 gpg); + uscan_die("Please install gpgv or gpgv2.") unless defined $havegpgv; + uscan_die("Please install gnupg or gnupg2.") unless defined $havegpg; + + # upstream/signing-key.pgp and upstream-signing-key.pgp are deprecated + # but supported + if (-r "debian/upstream/signing-key.asc") { + $keyring = "debian/upstream/signing-key.asc"; + } else { + my $binkeyring = first { -r $_ } qw( + debian/upstream/signing-key.pgp + debian/upstream-signing-key.pgp + ); + if (defined $binkeyring) { + make_path('debian/upstream', { mode => 0700, verbose => 'true' }); + + # convert to the policy complying armored key + uscan_verbose( + "Found upstream binary signing keyring: $binkeyring"); + + # Need to convert to an armored key + $keyring = "debian/upstream/signing-key.asc"; + uscan_warn "Found deprecated binary keyring ($binkeyring). " + . "Please save it in armored format in $keyring. For example:\n" + . " gpg --output $keyring --enarmor $binkeyring"; + spawn( + exec => [ + $havegpg, + '--homedir' => "/dev/null", + '--no-options', '-q', '--batch', '--no-default-keyring', + '--output' => $keyring, + '--enarmor', $binkeyring + ], + wait_child => 1 + ); + uscan_warn("Generated upstream signing keyring: $keyring"); + move $binkeyring, "$binkeyring.backup"; + uscan_verbose( + "Renamed upstream binary signing keyring: $binkeyring.backup"); + } + } + + # Need to convert an armored key to binary for use by gpgv + my $gpghome; + if (defined $keyring) { + uscan_verbose("Found upstream signing keyring: $keyring"); + if ($keyring =~ m/\.asc$/) { # always true + $gpghome = tempdir(CLEANUP => 1); + my $newkeyring = "$gpghome/trustedkeys.gpg"; + spawn( + exec => [ + $havegpg, + '--homedir' => $gpghome, + '--no-options', '-q', '--batch', '--no-default-keyring', + '--output' => $newkeyring, + '--dearmor', $keyring + ], + wait_child => 1 + ); + $keyring = $newkeyring; + } + } + + # Return undef if not key found + else { + return undef; + } + my $self = bless { + keyring => $keyring, + gpghome => $gpghome, + gpgv => $havegpgv, + gpg => $havegpg, + }, $class; + return $self; +} + +sub verify { + my ($self, $sigfile, $newfile) = @_; + uscan_verbose( + "Verifying OpenPGP self signature of $newfile and extract $sigfile"); + unless ( + uscan_exec_no_fail( + $self->{gpgv}, + '--homedir' => $self->{gpghome}, + '--keyring' => $self->{keyring}, + '-o' => "$sigfile", + "$newfile" + ) >> 8 == 0 + ) { + uscan_die("OpenPGP signature did not verify."); + } +} + +sub verifyv { + my ($self, $sigfile, $base) = @_; + uscan_verbose("Verifying OpenPGP signature $sigfile for $base"); + unless ( + uscan_exec_no_fail( + $self->{gpgv}, + '--homedir' => '/dev/null', + '--keyring' => $self->{keyring}, + $sigfile, $base + ) >> 8 == 0 + ) { + uscan_die("OpenPGP signature did not verify."); + } +} + +sub verify_git { + my ($self, $gitdir, $tag, $git_upstream) = @_; + my $commit; + my @dir = $git_upstream ? () : ('--git-dir', $gitdir); + spawn( + exec => ['git', @dir, 'show-ref', $tag], + to_string => \$commit + ); + uscan_die "git tag not found" unless ($commit); + $commit =~ s/\s.*$//; + chomp $commit; + my $file; + spawn( + exec => ['git', @dir, 'cat-file', '-p', $commit], + to_string => \$file + ); + my $dir; + spawn(exec => ['mktemp', '-d'], to_string => \$dir); + chomp $dir; + + unless ($file =~ /^(.*?\n)(\-+\s*BEGIN PGP SIGNATURE\s*\-+.*)$/s) { + uscan_die "Tag $tag is not signed"; + } + open F, ">$dir/txt" or die $!; + open S, ">$dir/sig" or die $!; + print F $1; + print S $2; + close F; + close S; + + unless ( + uscan_exec_no_fail( + $self->{gpgv}, + '--homedir' => $self->{gpghome}, + '--keyring' => $self->{keyring}, + "$dir/sig", "$dir/txt" + ) >> 8 == 0 + ) { + uscan_die("OpenPGP signature did not verify."); + } + remove_tree($dir); +} + +1; |