convert gpg keyring processing to less nesting and abort earlier if possible

This commit is contained in:
Johannes 'josch' Schauer 2020-01-22 00:29:38 +01:00
parent c26ec4d6fc
commit ae15fe3d9f
Signed by: josch
GPG key ID: F2CBA5C78FBD83E1

View file

@ -3183,98 +3183,100 @@ sub main() {
) { ) {
$keyring $keyring
= '/usr/share/keyrings/debian-archive-keyring.gpg'; = '/usr/share/keyrings/debian-archive-keyring.gpg';
} else {
last;
} }
# we can only check if we need the signed-by entry if we u # we can only check if we need the signed-by entry if we u
# automatically chosen keyring exists # automatically chosen keyring exists
if (defined $keyring && -e $keyring) { if (!defined $keyring || !-e $keyring) {
# we can only check key material if gpg is installed last;
my $gpghome = tempdir( }
"mmdebstrap.gpghome.XXXXXXXXXXXX",
TMPDIR => 1, # we can only check key material if gpg is installed
CLEANUP => 1 my $gpghome = tempdir(
); "mmdebstrap.gpghome.XXXXXXXXXXXX",
my @gpgcmd = ( TMPDIR => 1,
'gpg', '--quiet', CLEANUP => 1
'--ignore-time-conflict', '--no-options', );
'--no-default-keyring', '--homedir', my @gpgcmd = (
$gpghome, '--no-auto-check-trustdb', 'gpg', '--quiet',
'--trust-model', 'always' '--ignore-time-conflict', '--no-options',
); '--no-default-keyring', '--homedir',
my ($ret, $fh, $message); $gpghome, '--no-auto-check-trustdb',
{ '--trust-model', 'always'
# change warning handler to prevent message );
# Can't exec "gpg": No such file or directory my ($ret, $fh, $message);
local $SIG{__WARN__} = sub { $message = shift; }; {
$ret = open $fh, '-|', @gpgcmd, '--version'; # change warning handler to prevent message
# Can't exec "gpg": No such file or directory
local $SIG{__WARN__} = sub { $message = shift; };
$ret = open $fh, '-|', @gpgcmd, '--version';
}
# we only want to check if the gpg command exists
close $fh;
if ($? != 0 || !defined $ret || defined $message) {
info "gpg --version failed: cannot determine the right"
. " signed-by value";
last;
}
# find all the fingerprints of the keys apt currently
# knows about
my @keyringopts = ();
opendir my $dh, "$options->{apttrustedparts}"
or error "cannot read $options->{apttrustedparts}";
while (my $filename = readdir $dh) {
if ($filename !~ /\.(asc|gpg)$/) {
next;
} }
# we only want to check if the gpg command exists push @keyringopts, '--keyring',
close $fh; "$options->{apttrustedparts}/$filename";
if ($? == 0 && defined $ret && !defined $message) { }
# find all the fingerprints of the keys apt currently if (-e $options->{apttrusted}) {
# knows about push @keyringopts, '--keyring', $options->{apttrusted};
my @aptfingerprints = (); }
my $collect_fingerprints = sub { my @aptfingerprints = ();
my $filename = shift; if (scalar @keyringopts == 0) {
open my $fh, '-|', @gpgcmd, '--keyring', $signedby = " [signed-by=\"$keyring\"]";
$filename, '--with-colons', last;
'--list-keys' // error "failed to fork(): $!"; }
while (my $line = <$fh>) { open my $fh, '-|', @gpgcmd, @keyringopts, '--with-colons',
if ($line !~ /^fpr:::::::::([^:]+):/) { '--list-keys' // error "failed to fork(): $!";
next; while (my $line = <$fh>) {
} if ($line !~ /^fpr:::::::::([^:]+):/) {
push @aptfingerprints, $1; next;
}
close $fh;
};
opendir my $dh, "$options->{apttrustedparts}"
or error "cannot read $options->{apttrustedparts}";
while (my $filename = readdir $dh) {
if ($filename !~ /\.(asc|gpg)$/) {
next;
}
$collect_fingerprints->(
"$options->{apttrustedparts}/$filename");
}
if (-e $options->{apttrusted}) {
$collect_fingerprints->($options->{apttrusted});
}
# check if all fingerprints from the keyring that we
# guessed are known by apt and only add signed-by
# option if that's not the case
my @suitefingerprints = ();
open my $suitefh, '-|', @gpgcmd, '--keyring',
$keyring, '--with-colons',
'--list-keys' // error "failed to fork(): $!";
while (my $line = <$suitefh>) {
if ($line !~ /^fpr:::::::::([^:]+):/) {
next;
}
# if this fingerprint is not known by apt, then we
# need to add the signed-by option
if (none { $_ eq $1 } @aptfingerprints) {
$signedby = " [signed-by=\"$keyring\"]";
last;
}
}
close $suitefh;
if ($? != 0) {
error "gpg failed";
}
} else {
info "gpg --version failed: cannot determine the right"
. " signed-by value";
} }
remove_tree($gpghome, { error => \my $err }); push @aptfingerprints, $1;
if (@$err) { }
for my $diag (@$err) { close $fh;
my ($file, $message) = %$diag; if ($? != 0) {
if ($file eq '') { error "gpg failed";
warning "general error: $message"; }
} else { if (scalar @aptfingerprints == 0) {
warning "problem unlinking $file: $message"; $signedby = " [signed-by=\"$keyring\"]";
} last;
} }
# check if all fingerprints from the keyring that we guessed
# are known by apt and only add signed-by option if that's not
# the case
my @suitefingerprints = ();
open my $suitefh, '-|', @gpgcmd, '--keyring', $keyring,
'--with-colons',
'--list-keys' // error "failed to fork(): $!";
while (my $line = <$suitefh>) {
if ($line !~ /^fpr:::::::::([^:]+):/) {
next;
} }
# if this fingerprint is not known by apt, then we need to
# add the signed-by option
if (none { $_ eq $1 } @aptfingerprints) {
$signedby = " [signed-by=\"$keyring\"]";
last;
}
}
close $suitefh;
if ($? != 0) {
error "gpg failed";
} }
} }
if (scalar @ARGV > 0) { if (scalar @ARGV > 0) {