summaryrefslogtreecommitdiffstats
path: root/lib/Devscripts/Uscan/Keyring.pm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/Devscripts/Uscan/Keyring.pm168
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;