Skip to content

Commit

Permalink
Implement gpgv --assert-pubkey-algo=>=rsa2048,ed25519,ed448
Browse files Browse the repository at this point in the history
The assertion can be overriden using apt::key::assert-pubkey-algo,
the default is the most opinionated one.

This will inform the user during apt-cdrom add as we do not
pass --quiet to user, so adjust test case.

Add a simple test case for it to test-method-gpgv.

LP: #2055193
  • Loading branch information
julian-klode committed Feb 28, 2024
1 parent 60d6536 commit 50e3fee
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 5 deletions.
1 change: 1 addition & 0 deletions apt-pkg/init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ bool pkgInitConfig(Configuration &Cnf)
Cnf.Set("APT::Build-Essential::", "build-essential");
Cnf.CndSet("APT::Install-Recommends", true);
Cnf.CndSet("APT::Install-Suggests", false);
Cnf.CndSet("APT::Key::Assert-Pubkey-Algo", ">=rsa2048,ed25519,ed448");
Cnf.CndSet("Dir","/");

// State
Expand Down
21 changes: 18 additions & 3 deletions cmdline/apt-key.in
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,8 @@ case "$command" in
;;
verify)
GPGV=''
eval $(apt-config shell GPGV Apt::Key::gpgvcommand)
ASSERT_PUBKEY_ALGO=''
eval $(apt-config shell GPGV Apt::Key::gpgvcommand ASSERT_PUBKEY_ALGO Apt::Key::assert-pubkey-algo)
if [ -n "$GPGV" ] && command_available "$GPGV"; then true;
elif command_available 'gpgv'; then GPGV='gpgv';
elif command_available 'gpgv2'; then GPGV='gpgv2';
Expand All @@ -809,6 +810,20 @@ case "$command" in
apt_error 'gpgv, gpgv2 or gpgv1 required for verification, but neither seems installed'
exit 29
fi
GPGV_ARGS=""
if [ "$ASSERT_PUBKEY_ALGO" ]; then
test="$(LC_ALL=C.UTF-8 "$GPGV" --assert-pubkey-algo 2>&1 || :)"
case "$test" in
*"missing argument"*)
GPGV_ARGS="--assert-pubkey-algo=$ASSERT_PUBKEY_ALGO"
;;
*[Ii]"nvalid option"*"assert-pubkey-algo"*)
;;
*)
apt_warn "Unknown response from gpgv to --assert-pubkey-algo check: $test"
;;
esac
fi
# for a forced keyid we need gpg --export, so full wrapping required
if [ -n "$FORCED_KEYID" ]; then
prepare_gpg_home
Expand All @@ -817,9 +832,9 @@ case "$command" in
fi
setup_merged_keyring
if [ -n "$FORCED_KEYRING" ]; then
"$GPGV" --homedir "${GPGHOMEDIR}" --keyring "$(dearmor_filename "${FORCED_KEYRING}")" --ignore-time-conflict "$@"
"$GPGV" $GPGV_ARGS --homedir "${GPGHOMEDIR}" --keyring "$(dearmor_filename "${FORCED_KEYRING}")" --ignore-time-conflict "$@"
else
"$GPGV" --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@"
"$GPGV" $GPGV_ARGS --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@"
fi
;;
help)
Expand Down
1 change: 1 addition & 0 deletions doc/examples/configure-index
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ apt::key::gpgcommand "<STRING>";
apt::key::masterkeyring "<STRING>";
apt::key::archivekeyringuri "<STRING>";
apt::key::net-update-enabled "<STRING>";
apt::key::assert-pubkey-algo "<STRING>";

apt::ftparchive::release::patterns "<LIST>";
apt::ftparchive::release::validtime "<INT>";
Expand Down
20 changes: 20 additions & 0 deletions methods/gpgv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using std::vector;
#define GNUPGNODATA "[GNUPG:] NODATA"
#define GNUPGWARNING "[GNUPG:] WARNING"
#define GNUPGERROR "[GNUPG:] ERROR"
#define GNUPGASSERT_PUBKEY_ALGO "[GNUPG:] ASSERT_PUBKEY_ALGO"
#define APTKEYWARNING "[APTKEY:] WARNING"
#define APTKEYERROR "[APTKEY:] ERROR"

Expand Down Expand Up @@ -242,6 +243,25 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
PushEntryWithUID(Signers.Worthless, buffer, Debug);
else if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0)
PushEntryWithUID(Signers.Worthless, buffer, Debug);
else if (strncmp(buffer, GNUPGASSERT_PUBKEY_ALGO, sizeof(GNUPGASSERT_PUBKEY_ALGO) - 1) == 0)
{
std::istringstream iss(buffer + sizeof(GNUPGASSERT_PUBKEY_ALGO));
vector<string> tokens{std::istream_iterator<string>{iss},
std::istream_iterator<string>{}};

auto const fpr = tokens[0];
auto const asserted = atoi(tokens[1].c_str());
auto const pkstr = tokens[2];
if (not asserted)
{
std::string reason;
strprintf(reason, _("untrusted public key algorithm: %s"), pkstr.c_str());
Signers.Worthless.push_back({fpr, reason});
Signers.Good.erase(std::remove_if(Signers.Good.begin(), Signers.Good.end(), [&](std::string const &goodsig)
{ return IsTheSameKey(fpr, goodsig); }),
Signers.Good.end());
}
}
else if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0)
PushEntryWithKeyID(Signers.Good, buffer, Debug);
else if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0)
Expand Down
20 changes: 19 additions & 1 deletion test/integration/test-apt-cdrom
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,32 @@ aptcdromlog() {
}
aptautotest_aptcdromlog_add() { aptautotest_aptget_update "$@"; }


msgtest "Checking --assert-pubkey-algo support"
gpgv_msg=""
test="$(LC_ALL=C.UTF-8 gpgv --assert-pubkey-algo 2>&1 || :)"
case "$test" in
*"missing argument"*)
gpgv_msg="
gpgv: asserted signer '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' with algo rsa2048"
msgpass
;;
*[Ii]"nvalid option"*"assert-pubkey-algo"*)
msgskip
;;
*)
msgfail "Unknown response from gpgv to --assert-pubkey-algo check: $test"
;;
esac

CDROM_PRE="Using CD-ROM mount point $(readlink -f ./rootdir/media)/cdrom/
Unmounting CD-ROM...
Waiting for disc...
Please insert a Disc in the drive and press [Enter]
Mounting CD-ROM...
Scanning disc for index files..."
CDROM_POST="This disc is called:
'Debian APT Testdisk 0.8.15'
'Debian APT Testdisk 0.8.15'$gpgv_msg
Writing new source list
Source list entries for this disc are:
deb cdrom:[Debian APT Testdisk 0.8.15]/ stable main
Expand Down
17 changes: 16 additions & 1 deletion test/integration/test-method-gpgv
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,34 @@ testrun() {
testgpgv 'Good signed with fingerprint' 'Good: GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'

testgpgv 'Good signed with long keyid and asserted' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
[GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 rsa1024'
testgpgv 'Good signed with fingerprint and asserted' 'Good: GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
[GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 rsa1024'

testgpgv 'Good subkey signed with long keyid' 'Good: GOODSIG 5B6896415D44C43E' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, 4281DEDBD466EAE8C1F4157E5B6896415D44C43E!' '[GNUPG:] GOODSIG 5B6896415D44C43E Sebastian Subkey <subkey@example.org>
[GNUPG:] VALIDSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E 2018-08-16 1534459673 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'
testgpgv 'Good subkey signed with fingerprint' 'Good: GOODSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, 4281DEDBD466EAE8C1F4157E5B6896415D44C43E!' '[GNUPG:] GOODSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E Sebastian Subkey <subkey@example.org>
[GNUPG:] VALIDSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E 2018-08-16 1534459673 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'

testgpgv 'Untrusted signed with long keyid' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 1 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'
exit
testsuccess grep '^\s\+Good:\s\+$' method.output
testgpgv 'Untrusted signed with fingerprint' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 1 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'
testsuccess grep '^\s\+Good:\s\+$' method.output

testgpgv 'Unasserted signed with long keyid' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
[GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 rsa1024'
testsuccess grep '^\s\+Good:\s\+$' method.output
testgpgv 'Unaserted signed with fingerprint' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
[GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 rsa1024'
testsuccess grep '^\s\+Good:\s\+$' method.output

testgpgv 'Weak signed with long keyid' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 2 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE'
testsuccess grep '^Message: Signature by key 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE uses weak digest algorithm (SHA1)$' method.output
Expand Down

0 comments on commit 50e3fee

Please sign in to comment.