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=3a17b8bcf3a32050cd23f4d491c819f5754ab262 commit 3a17b8bcf3a32050cd23f4d491c819f5754ab262 Author: Guillem Jover <[email protected]> AuthorDate: Wed Jul 20 03:32:28 2022 +0200 Dpkg::OpenPGP: Refactor signing code from dpkg-buildpackage This adds a few methods (can_use_secrets() and inline_sign()) to abstract the signing code into this module, which will have all the OpenPGP implementation knowledge. Add Dpkg::OpenPGP::ErrorCodes for signing. We will add unit tests once we have added keyfile support. --- scripts/Dpkg/OpenPGP.pm | 37 +++++++++++++++++++++++++++++++++++++ scripts/Dpkg/OpenPGP/ErrorCodes.pm | 6 ++++++ scripts/dpkg-buildpackage.pl | 30 +++++++++++++----------------- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/scripts/Dpkg/OpenPGP.pm b/scripts/Dpkg/OpenPGP.pm index e28d9678e..be358ab66 100644 --- a/scripts/Dpkg/OpenPGP.pm +++ b/scripts/Dpkg/OpenPGP.pm @@ -54,6 +54,21 @@ sub new { return $self; } +sub _gpg_has_keystore { + my $self = shift; + + return 1 if ($ENV{GNUPGHOME} && -e $ENV{GNUPGHOME}) || + ($ENV{HOME} && -e "$ENV{HOME}/.gnupg"); + return 0; +} + +sub can_use_secrets { + my ($self, $key) = @_; + + return 0 unless $self->{cmd}; + return $self->_gpg_has_keystore(); +} + sub get_trusted_keyrings { my $self = shift; @@ -231,4 +246,26 @@ sub verify { return $self->_gpg_verify($data, $sig, undef, @certs); } +sub _gpg_inline_sign { + my ($self, $data, $inlinesigned, $key) = @_; + + return OPENPGP_MISSING_CMD if ! $self->{cmd}; + + my @exec = ($self->{cmd}); + push @exec, _gpg_options_weak_digests(); + push @exec, qw(--utf8-strings --textmode --armor); + push @exec, '--local-user', $key->handle; + push @exec, '--output', $inlinesigned; + + my $rc = $self->_gpg_exec(@exec, '--clearsign', $data); + return OPENPGP_KEY_CANNOT_SIGN if $rc; + return OPENPGP_OK; +} + +sub inline_sign { + my ($self, $data, $inlinesigned, $key) = @_; + + return $self->_gpg_inline_sign($data, $inlinesigned, $key); +} + 1; diff --git a/scripts/Dpkg/OpenPGP/ErrorCodes.pm b/scripts/Dpkg/OpenPGP/ErrorCodes.pm index 43b4e02d0..764148cba 100644 --- a/scripts/Dpkg/OpenPGP/ErrorCodes.pm +++ b/scripts/Dpkg/OpenPGP/ErrorCodes.pm @@ -28,7 +28,9 @@ our @EXPORT = qw( OPENPGP_EXPECTED_TEXT OPENPGP_OUTPUT_EXISTS OPENPGP_MISSING_INPUT + OPENPGP_KEY_IS_PROTECTED OPENPGP_UNSUPPORTED_SUBCMD + OPENPGP_KEY_CANNOT_SIGN OPENPGP_MISSING_CMD @@ -54,7 +56,9 @@ use constant { OPENPGP_EXPECTED_TEXT => 53, OPENPGP_OUTPUT_EXISTS => 59, OPENPGP_MISSING_INPUT => 61, + OPENPGP_KEY_IS_PROTECTED => 67, OPENPGP_UNSUPPORTED_SUBCMD => 69, + OPENPGP_KEY_CANNOT_SIGN => 79, OPENPGP_MISSING_CMD => -1, }; @@ -68,7 +72,9 @@ my %code2error = ( OPENPGP_EXPECTED_TEXT() => N_('non-text input where text expected'), OPENPGP_OUTPUT_EXISTS() => N_('output file already exists'), OPENPGP_MISSING_INPUT() => N_('input file does not exist'), + OPENPGP_KEY_IS_PROTECTED() => N_('cannot unlock password-protected key'), OPENPGP_UNSUPPORTED_SUBCMD() => N_('unsupported subcommand'), + OPENPGP_KEY_CANNOT_SIGN() => N_('key is not signature-capable'), OPENPGP_MISSING_CMD() => N_('missing OpenPGP implementation'), ); diff --git a/scripts/dpkg-buildpackage.pl b/scripts/dpkg-buildpackage.pl index 0d5a58e0c..cc32cd8b8 100755 --- a/scripts/dpkg-buildpackage.pl +++ b/scripts/dpkg-buildpackage.pl @@ -42,6 +42,8 @@ use Dpkg::Version; use Dpkg::Control; use Dpkg::Control::Info; use Dpkg::Changelog::Parse; +use Dpkg::OpenPGP; +use Dpkg::OpenPGP::ErrorCodes; use Dpkg::OpenPGP::KeyHandle; use Dpkg::Path qw(find_command); use Dpkg::IPC; @@ -425,15 +427,8 @@ if ($check_command and not find_command($check_command)) { error(g_("check-command '%s' not found"), $check_command); } -if ($signcommand) { - if (!find_command($signcommand)) { - error(g_("sign-command '%s' not found"), $signcommand); - } -} elsif (($ENV{GNUPGHOME} && -e $ENV{GNUPGHOME}) || - ($ENV{HOME} && -e "$ENV{HOME}/.gnupg")) { - if (find_command('gpg')) { - $signcommand = 'gpg'; - } +if ($signcommand and not find_command($signcommand)) { + error(g_("sign-command '%s' not found"), $signcommand); } # Default to auto if none of parallel=N, -J or -j have been specified. @@ -539,7 +534,11 @@ my $signkey = Dpkg::OpenPGP::KeyHandle->new( ); signkey_validate(); -if (not $signcommand) { +my $openpgp = Dpkg::OpenPGP->new( + cmd => $signcommand // 'auto', +); + +if (not $openpgp->can_use_secrets($signkey)) { $signsource = 0; $signbuildinfo = 0; $signchanges = 0; @@ -907,16 +906,13 @@ sub signfile { print { $signfh } "\n"; close $signfh or syserr(g_('cannot close %s'), $signfile); - system($signcommand, '--utf8-strings', '--textmode', '--armor', - '--local-user', $signkey->handle, '--clearsign', - '--weak-digest', 'SHA1', '--weak-digest', 'RIPEMD160', - '--output', "$signfile.asc", $signfile); - my $status = $?; - if ($status == 0) { + my $status = $openpgp->inline_sign($signfile, "$signfile.asc", $signkey); + if ($status == OPENPGP_OK) { move("$signfile.asc", "../$file") or syserror(g_('cannot move %s to %s'), "$signfile.asc", "../$file"); } else { - error(g_('failed to sign %s file'), $file); + error(g_('failed to sign %s file: %s'), $file, + openpgp_errorcode_to_string($status)); } return $status -- Dpkg.Org's dpkg

