This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=a01be4c05a8f780fdc59a25e66c1c83e4930f28e commit a01be4c05a8f780fdc59a25e66c1c83e4930f28e (HEAD -> main) Author: Guillem Jover <[email protected]> AuthorDate: Thu Oct 27 20:13:07 2022 +0200 Dpkg::OpenPGP::KeyHandle: Refactor new key handle from dpkg-buildpackage Add a new class to be able to refer to OpenPGP keys, be those via keyids, userids, or automatic detection. Then sanitize the handle values and. This will make it possible to add transparent keyfile or keystore support in the future. --- scripts/Dpkg/OpenPGP/KeyHandle.pm | 89 ++++++++++++++++++++++++++++++++++++ scripts/Makefile.am | 2 + scripts/dpkg-buildpackage.pl | 26 +++++++---- scripts/t/Dpkg_OpenPGP_KeyHandle.t | 92 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 8 deletions(-) diff --git a/scripts/Dpkg/OpenPGP/KeyHandle.pm b/scripts/Dpkg/OpenPGP/KeyHandle.pm new file mode 100644 index 000000000..44a872c45 --- /dev/null +++ b/scripts/Dpkg/OpenPGP/KeyHandle.pm @@ -0,0 +1,89 @@ +# Copyright © 2022 Guillem Jover <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +package Dpkg::OpenPGP::KeyHandle; + +use strict; +use warnings; + +our $VERSION = '0.01'; + +use Carp; +use List::Util qw(none); + +sub new { + my ($this, %opts) = @_; + my $class = ref($this) || $this; + + my $self = { + type => $opts{type} // 'auto', + handle => $opts{handle}, + }; + bless $self, $class; + + $self->_sanitize(); + + return $self; +} + +my $keyid_regex = qr/^(?:0x)?([[:xdigit:]]+)$/; + +sub _sanitize { + my ($self) = shift; + + my $type = $self->{type}; + if ($type eq 'auto' or $type eq 'autoid') { + if ($self->{handle} =~ m/$keyid_regex/) { + $self->{handle} = $1; + $type = 'keyid'; + } else { + $type = 'userid'; + } + $self->{type} = $type; + } elsif ($type eq 'keyid') { + if ($self->{handle} =~ m/$keyid_regex/) { + $self->{handle} = $1; + } + } + + if (none { $type eq $_ } qw(userid keyid)) { + croak "unknown type parameter value $type"; + } + + return; +} + +sub set { + my ($self, $type, $handle) = @_; + + $self->{type} = $type; + $self->{handle} = $handle; + + $self->_sanitize(); +} + +sub type { + my $self = shift; + + return $self->{type}; +} + +sub handle { + my $self = shift; + + return $self->{handle}; +} + +1; diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 699993ec7..5d5a73a61 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -106,6 +106,7 @@ nobase_dist_perllib_DATA = \ Dpkg/IPC.pm \ Dpkg/Lock.pm \ Dpkg/OpenPGP.pm \ + Dpkg/OpenPGP/KeyHandle.pm \ Dpkg/Package.pm \ Dpkg/Path.pm \ Dpkg/Shlibs.pm \ @@ -227,6 +228,7 @@ test_scripts = \ t/Dpkg_Path.t \ t/Dpkg_Vars.t \ t/Dpkg_Interface_Storable.t \ + t/Dpkg_OpenPGP_KeyHandle.t \ t/Dpkg_OpenPGP.t \ t/Dpkg_Vendor.t \ t/Dpkg_Changelog.t \ diff --git a/scripts/dpkg-buildpackage.pl b/scripts/dpkg-buildpackage.pl index 7cef9241e..c36cdc6e6 100755 --- a/scripts/dpkg-buildpackage.pl +++ b/scripts/dpkg-buildpackage.pl @@ -42,6 +42,7 @@ use Dpkg::Version; use Dpkg::Control; use Dpkg::Control::Info; use Dpkg::Changelog::Parse; +use Dpkg::OpenPGP::KeyHandle; use Dpkg::Path qw(find_command); use Dpkg::IPC; use Dpkg::Vendor qw(run_vendor_hook); @@ -523,6 +524,19 @@ if (build_has_any(BUILD_ARCH_DEP)) { my $pv = "${pkg}_$sversion"; my $pva = "${pkg}_${sversion}_$arch"; +my $signkeytype; +my $signkeyhandle; +if (defined $signkeyid) { + $signkeytype = 'autoid'; + $signkeyhandle = $signkeyid; +} else { + $signkeytype = 'userid'; + $signkeyhandle = $maintainer; +} +my $signkey = Dpkg::OpenPGP::KeyHandle->new( + type => $signkeytype, + handle => $signkeyhandle, +); signkey_validate(); if (not $signcommand) { @@ -868,17 +882,13 @@ sub update_files_field { } sub signkey_validate { - return unless defined $signkeyid; - # Make sure this is an hex keyid. - return unless $signkeyid =~ m/^(?:0x)?([[:xdigit:]]+)$/; - - my $keyid = $1; + return unless $signkey->type eq 'keyid'; - if (length $keyid <= 8) { + if (length $signkey->handle <= 8) { error(g_('short OpenPGP key IDs are broken; ' . 'please use key fingerprints in %s or %s instead'), '-k', 'DEB_SIGN_KEYID'); - } elsif (length $keyid <= 16) { + } elsif (length $signkey->handle <= 16) { warning(g_('long OpenPGP key IDs are strongly discouraged; ' . 'please use key fingerprints in %s or %s instead'), '-k', 'DEB_SIGN_KEYID'); @@ -900,7 +910,7 @@ sub signfile { close $signfh or syserr(g_('cannot close %s'), $signfile); system($signcommand, '--utf8-strings', '--textmode', '--armor', - '--local-user', $signkeyid || $maintainer, '--clearsign', + '--local-user', $signkey->handle, '--clearsign', '--weak-digest', 'SHA1', '--weak-digest', 'RIPEMD160', '--output', "$signfile.asc", $signfile); my $status = $?; diff --git a/scripts/t/Dpkg_OpenPGP_KeyHandle.t b/scripts/t/Dpkg_OpenPGP_KeyHandle.t new file mode 100644 index 000000000..35c8b43bd --- /dev/null +++ b/scripts/t/Dpkg_OpenPGP_KeyHandle.t @@ -0,0 +1,92 @@ +#!/usr/bin/perl +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +use strict; +use warnings; + +use Test::More tests => 21; + +BEGIN { + use_ok('Dpkg::OpenPGP::KeyHandle'); +} + +my @ref_keys = ( + { + type => 'auto', + handle => '0x12345678', + exp_type => 'keyid', + exp_handle => '12345678', + }, { + type => 'auto', + handle => '0x1234567890abcdef', + exp_type => 'keyid', + exp_handle => '1234567890abcdef', + }, { + type => 'auto', + handle => '0x1234567890abcdef1234567890abcdef', + exp_type => 'keyid', + exp_handle => '1234567890abcdef1234567890abcdef', + }, { + type => 'auto', + handle => 'Alice Auster', + exp_type => 'userid', + exp_handle => 'Alice Auster', + }, { + type => 'auto', + handle => 'Alice Auster <[email protected]>', + exp_type => 'userid', + exp_handle => 'Alice Auster <[email protected]>', + }, { + type => 'keyid', + handle => '0x12345678', + exp_type => 'keyid', + exp_handle => '12345678', + }, { + type => 'keyid', + handle => '0x1234567890abcdef', + exp_type => 'keyid', + exp_handle => '1234567890abcdef', + }, { + type => 'keyid', + handle => '0x1234567890abcdef1234567890abcdef', + exp_type => 'keyid', + exp_handle => '1234567890abcdef1234567890abcdef', + }, { + type => 'userid', + handle => 'Alice Auster', + exp_type => 'userid', + exp_handle => 'Alice Auster', + }, { + type => 'userid', + handle => 'Alice Auster <[email protected]>', + exp_type => 'userid', + exp_handle => 'Alice Auster <[email protected]>', + } +); + +foreach my $ref_key (@ref_keys) { + my $key = Dpkg::OpenPGP::KeyHandle->new( + type => $ref_key->{type}, + handle => $ref_key->{handle}, + ); + is($key->type, $ref_key->{exp_type}, + 'key type ' . $key->type . " sanitized as $ref_key->{exp_type}"); + is($key->handle, $ref_key->{exp_handle}, + 'key handle ' . $key->handle . " sanitized as $ref_key->{exp_handle}"); +} + +# TODO: Add actual test cases. + +1; -- Dpkg.Org's dpkg

