From a00fbbdb28cc31e78882301c2efe7218583ab4cb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 19 Dec 2024 22:11:04 +0100 Subject: Use sq in the test suite, remove apt-key Remove the test case for MD5 and expired signatures, as we can't create them (can't set signing digest, and can't set signature expiry). Tests for them have been added to test-method-gpgv instead. We override sq in a function with cert-store and key-store set to none. This supports both sq 0.40 and sq 1.0. --- debian/tests/control | 2 + test/integration/framework | 94 +-- test/integration/run-tests | 10 - .../integration/test-bug-733028-gpg-resource-limit | 1 - .../test-bug-921685-binary-detached-signature | 7 +- test/integration/test-method-gpgv | 52 ++ test/integration/test-method-gpgv-legacy-keyring | 14 +- test/integration/test-releasefile-verification | 36 +- .../test-releasefile-verification-noflat | 2 +- test/interactive-helper/CMakeLists.txt | 8 - test/interactive-helper/apt-key.in | 840 --------------------- 11 files changed, 102 insertions(+), 964 deletions(-) delete mode 100644 test/interactive-helper/apt-key.in diff --git a/debian/tests/control b/debian/tests/control index e4bcad998..3aef98710 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -8,6 +8,8 @@ Depends: @, @builddeps@, dpkg (>= 1.20.8), expect, fakeroot, wget, stunnel4, lso gnupg (>= 2) | gnupg2, gnupg1 | gnupg (<< 2), gpgv (>= 2) | gpgv2, gpgv1 | gpgv (<< 2), gpgv-sq, + sq (>= 0.40), + moreutils, jq, libfile-fcntllock-perl, python3-apt, aptitude, valgrind-if-available [!armhf !ppc64el], gdb-minimal | gdb diff --git a/test/integration/framework b/test/integration/framework index a93168278..bae14e984 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -199,7 +199,6 @@ aptcache() { runapt apt-cache "$@"; } aptcdrom() { runapt apt-cdrom "$@"; } aptget() { runapt apt-get "$@"; } aptftparchive() { runapt "${APTFTPARCHIVEBINDIR}/apt-ftparchive" "$@"; } -aptkey() { runapt "${APTTESTHELPERSBINDIR}/apt-key" "$@"; } aptmark() { runapt apt-mark "$@"; } aptsortpkgs() { runapt apt-sortpkgs "$@"; } apt() { runapt apt "$@"; } @@ -210,6 +209,7 @@ aptextracttemplates() { runapt apt-extracttemplates "$@"; } aptinternalsolver() { runapt "${APTINTERNALSOLVER}" "$@"; } aptdumpsolver() { runapt "${APTDUMPSOLVER}" "$@"; } aptinternalplanner() { runapt "${APTINTERNALPLANNER}" "$@"; } +sq() { command sq --key-store=none --cert-store=none "$@"; } dpkg() { "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" "$@" @@ -587,11 +587,6 @@ EOF echo 'DPkg::Path "";' >> aptconfig.conf echo 'Dir::Bin::ischroot "/bin/false";' >> aptconfig.conf - # If gpgv supports --weak-digest, pass it to make sure we can disable SHA1 - if aptkey verify --weak-digest SHA1 --help 2>/dev/null >/dev/null; then - echo 'Acquire::gpgv::Options { "--weak-digest"; "sha1"; };' > rootdir/etc/apt/apt.conf.d/no-sha1 - fi - # most tests just need one signed Release file, not both export APT_DONT_SIGN='Release.gpg' @@ -881,9 +876,8 @@ buildsimplenativepackage() { | while read SRC; do echo "pool/${SRC}" >> "${BUILDDIR}/../${RELEASE}.${DISTSECTION}.srclist" # if expr match "${SRC}" '.*\.dsc' >/dev/null 2>&1; then -# aptkey --keyring ./keys/joesixpack.pub --secret-keyring ./keys/joesixpack.sec --quiet --readonly \ -# adv --yes --default-key 'Joe Sixpack' \ -# --clearsign -o "${BUILDDIR}/../${SRC}.sign" "${BUILDDIR}/../$SRC" +# sq sign --signer-file ./keys/joesixpack.sec +# -o "${BUILDDIR}/../${SRC}.sign" --cleartext "${BUILDDIR}/../$SRC" # mv "${BUILDDIR}/../${SRC}.sign" "${BUILDDIR}/../$SRC" # fi done @@ -1301,22 +1295,7 @@ killgpgagent() { GNUPGHOME="${GPGHOME}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true rm -rf "$GPGHOME" } -dosigning() { - local KEY="$1" - shift - local GPGHOME="${TMPWORKINGDIRECTORY}/signinghome" - if [ -n "$APT_TEST_SIGNINGHOME" ]; then - GPGHOME="$APT_TEST_SIGNINGHOME" - else - if [ ! -e "$GPGHOME" ]; then - mkdir -p --mode=700 "${GPGHOME}" - addtrap 'prefix' 'killgpgagent;' - fi - fi - testsuccess aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly \ - --homedir "${GPGHOME}" adv --batch --yes --digest-algo "${APT_TESTS_DIGEST_ALGO:-SHA512}" \ - "$@" -} + signreleasefiles() { local SIGNERS="${1:-Joe Sixpack}" local REPODIR="${2:-aptarchive}" @@ -1348,20 +1327,22 @@ signreleasefiles() { cp "$SECUNEXPIRED" "${REXKEY}.sec" cp "$PUBUNEXPIRED" "${REXKEY}.pub" else - if ! printf "expire\n1w\nsave\n" | aptkey --quiet --keyring "${REXKEY}.pub" --secret-keyring "${REXKEY}.sec" \ - --readonly adv --batch --yes --digest-algo "${APT_TESTS_DIGEST_ALGO:-SHA512}" \ - --default-key "$SIGNER" --command-fd 0 --edit-key "${SIGNER}" >setexpire.gpg 2>&1; then - cat setexpire.gpg - exit 1 - fi - cp "${REXKEY}.sec" "$SECUNEXPIRED" - cp "${REXKEY}.pub" "$PUBUNEXPIRED" + chronic sq key expire --expiration 1w --cert-file "${REXKEY}.sec" --output "$SECUNEXPIRED" + chronic sq key subkey expire --expiration 1w --policy-as-of 2020-01-01 --cert-file "$SECUNEXPIRED" --output "$SECUNEXPIRED" --overwrite --key B3C9747B5FFD84E5585C3055DB4B332DD8DA0F4F + chronic sq key delete --cert-file "${SECUNEXPIRED}" --output "$PUBUNEXPIRED" + cp "${SECUNEXPIRED}" "${REXKEY}.sec" + cp "${PUBUNEXPIRED}" "${REXKEY}.pub" fi fi if [ ! -e "${KEY}.pub" ]; then local K="keys/$(echo "$SIGNER" | tr 'A-Z' 'a-z' | tr -d ' ,')" - cat "${K}.pub" >> "${KEY}.new.pub" - cat "${K}.sec" >> "${KEY}.new.sec" + if [ ! -e "${KEY}.new.pub" ]; then + cp "${K}.pub" "${KEY}.new.pub" + cp "${K}.sec" "${KEY}.new.sec" + else + chronic sq keyring merge "${KEY}.new.pub" "${K}.pub" --output "${KEY}.new.pub" --overwrite + chronic sq keyring merge "${KEY}.new.sec" "${K}.sec" --output "${KEY}.new.sec" --overwrite + fi fi done if [ ! -e "${KEY}.pub" ]; then @@ -1374,14 +1355,18 @@ signreleasefiles() { if [ "$APT_DONT_SIGN" = 'Release.gpg' ]; then rm -f "${RELEASE}.gpg" else - dosigning "$KEY" "$@" $SIGUSERS --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" + if command sq --cli-version 0.40 version 2>/dev/null; then + sq sign $time --signer-file "$KEY.sec" "$@" --overwrite --output "${RELEASE}.gpg" --signature-file "${RELEASE}" + else + sq sign $time --signer-file "$KEY.sec" "$@" --overwrite --signature-file "${RELEASE}.gpg" "${RELEASE}" + fi touch -d "$DATE" "${RELEASE}.gpg" fi local INRELEASE="${RELEASE%/*}/InRelease" if [ "$APT_DONT_SIGN" = 'InRelease' ]; then rm -f "$INRELEASE" else - dosigning "$KEY" "$@" $SIGUSERS --clearsign --output "$INRELEASE" "$RELEASE" + sq sign $time --signer-file "$KEY.sec" "$@" --overwrite --output "${INRELEASE}" --cleartext "${RELEASE}" touch -d "$DATE" "${INRELEASE}" fi done @@ -2024,27 +2009,14 @@ testfailure() { else local EXITCODE=$? if expr match "$1" '^apt.*' >/dev/null; then - if [ "$1" = 'aptkey' ]; then - if grep -q " Can't check signature: - BAD signature from - signature could not be verified" "$OUTPUT"; then - msgpass - elif [ -e "$OUTPUT" -a ! -s "$OUTPUT" ]; then - msgwarn "apt-key failed without output, this is normal for gpgv-sq (see sequoia-chameleon-gnupg#88)" - msgpass - else - msgfailoutput "run failed with exitcode ${EXITCODE}, but no signature error" "$OUTPUT" "$@" - fi + if grep -q -E ' runtime error: ' "$OUTPUT"; then + msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" + elif grep -q -E '==ERROR' "$OUTPUT"; then + msgfailoutput 'compiler sanitizers reported errors' "$OUTPUT" "$@" + elif ! grep -q -E '^E: ' "$OUTPUT"; then + msgfailoutput "run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" else - if grep -q -E ' runtime error: ' "$OUTPUT"; then - msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" - elif grep -q -E '==ERROR' "$OUTPUT"; then - msgfailoutput 'compiler sanitizers reported errors' "$OUTPUT" "$@" - elif ! grep -q -E '^E: ' "$OUTPUT"; then - msgfailoutput "run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" - else - msgpass - fi + msgpass fi else msgpass @@ -2182,14 +2154,6 @@ mapkeynametokeyid() { shift done } -testaptkeys() { - local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/aptkeylist.output" - if ! aptkey list --with-colon 2>/dev/null | grep '^pub' | cut -d':' -f 5 > "$OUTPUT"; then - echo -n > "$OUTPUT" - fi - testfileequal "$OUTPUT" "$(mapkeynametokeyid "$@")" -} - pause() { echo "STOPPED execution. Press enter to continue" local IGNORE diff --git a/test/integration/run-tests b/test/integration/run-tests index 331adfcfa..24d0cc00f 100755 --- a/test/integration/run-tests +++ b/test/integration/run-tests @@ -156,16 +156,6 @@ if [ -n "$APT_TEST_JOBS" ]; then exit $((FAIL <= 255 ? FAIL : 255)) fi -APT_TEST_SIGNINGHOME="$(mktemp --directory --tmpdir 'apt-key-signinghome.XXXXXXXXXX')" -removesigninghome() { - if [ -z "$APT_TEST_SIGNINGHOME" ]; then return; fi - GNUPGHOME="${APT_TEST_SIGNINGHOME}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true - rm -rf -- "$APT_TEST_SIGNINGHOME" -} -trap "exit 1" 0 HUP INT ILL ABRT FPE SEGV PIPE TERM -trap "removesigninghome" 0 QUIT -export APT_TEST_SIGNINGHOME - TOTAL="$(echo "$TESTLIST" | wc -l)" if [ "$MSGLEVEL" -le 1 ]; then printf "${CTEST}Running testcases${CRESET}: " diff --git a/test/integration/test-bug-733028-gpg-resource-limit b/test/integration/test-bug-733028-gpg-resource-limit index b44facda3..2fc5ed3ee 100755 --- a/test/integration/test-bug-733028-gpg-resource-limit +++ b/test/integration/test-bug-733028-gpg-resource-limit @@ -13,7 +13,6 @@ setupaptarchive --no-update for i in $(seq 1 50); do touch rootdir/etc/apt/trusted.gpg.d/emptykey-${i}.gpg done -testaptkeys 'Joe Sixpack' testsuccess aptget update msgtest 'Test for no gpg errors/warnings in' 'apt-get update' diff --git a/test/integration/test-bug-921685-binary-detached-signature b/test/integration/test-bug-921685-binary-detached-signature index df863197a..e9bbb809b 100755 --- a/test/integration/test-bug-921685-binary-detached-signature +++ b/test/integration/test-bug-921685-binary-detached-signature @@ -13,10 +13,13 @@ setupdistsaptarchive for RELEASE in $(find aptarchive -name 'Release'); do # note the missing --armor - dosigning "keys/joesixpack" --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" + if command sq --cli-version 0.40 version 2>/dev/null; then + sq sign --binary --signer-file "keys/joesixpack.sec" --output "${RELEASE}.gpg" --signature-file "${RELEASE}" + else + sq sign --binary --signer-file "keys/joesixpack.sec" --signature-file "${RELEASE}.gpg" "${RELEASE}" + fi done testfailure apt show foo testfailure aptget update -testsuccess grep 'W: .* Detached signature file .* is in unsupported binary format' rootdir/tmp/testfailure.output testfailure apt show foo diff --git a/test/integration/test-method-gpgv b/test/integration/test-method-gpgv index 5ce685c8b..7d0d867fe 100755 --- a/test/integration/test-method-gpgv +++ b/test/integration/test-method-gpgv @@ -38,61 +38,113 @@ testgpgv() { testrun() { testgpgv 'Good signed with long keyid' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Good signed with fingerprint' 'Good: GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Good signed with long keyid and asserted' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE [GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 rsa1024' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Good signed with fingerprint and asserted' 'Good: GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE [GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 rsa1024' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Not asserted in the next level' 'SoonWorthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE [GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 brainpoolP256r1' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Not asserted in the future level' 'LaterWorthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE [GNUPG:] ASSERT_PUBKEY_ALGO 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 1 nistp256' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Good subkey signed with long keyid' 'Good: GOODSIG 5B6896415D44C43E' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, 4281DEDBD466EAE8C1F4157E5B6896415D44C43E!' '[GNUPG:] GOODSIG 5B6896415D44C43E Sebastian Subkey [GNUPG:] VALIDSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E 2018-08-16 1534459673 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Good subkey signed with fingerprint' 'Good: GOODSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, 4281DEDBD466EAE8C1F4157E5B6896415D44C43E!' '[GNUPG:] GOODSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E Sebastian Subkey [GNUPG:] VALIDSIG 4281DEDBD466EAE8C1F4157E5B6896415D44C43E 2018-08-16 1534459673 0 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^201 URI Done$' method.output testgpgv 'Untrusted signed with long keyid' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 1 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^400 URI Failure$' method.output testsuccess grep '^\s\+Good:\s\+$' method.output testgpgv 'Untrusted signed with fingerprint' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 1 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output testgpgv 'Unasserted signed with long keyid' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [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 + testsuccess grep '^400 URI Failure$' method.output testgpgv 'Unaserted signed with fingerprint' 'Worthless: 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE, ' '' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [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 + testsuccess grep '^400 URI Failure$' method.output testgpgv 'Weak signed with long keyid' 'Good: GOODSIG 5A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 2 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' testsuccess grep '^Message: Signature by key 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE uses weak algorithm (SHA1)$' method.output + testsuccess grep '^201 URI Done$' method.output testgpgv 'Weak signed with fingerprint' 'Good: GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' '34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE!' '[GNUPG:] GOODSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) [GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-01 1472742625 0 4 0 1 2 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' testsuccess grep '^Message: Signature by key 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE uses weak algorithm (SHA1)$' method.output + testsuccess grep '^201 URI Done$' method.output testgpgv 'No Pubkey with long keyid' 'NoPubKey: NO_PUBKEY E8525D47528144E2' '' '[GNUPG:] ERRSIG E8525D47528144E2 1 11 00 1472744666 9 [GNUPG:] NO_PUBKEY E8525D47528144E2' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: .*public key is not available' method.output testgpgv 'No Pubkey with fingerprint' 'NoPubKey: NO_PUBKEY DE66AECA9151AFA1877EC31DE8525D47528144E2' '' '[GNUPG:] ERRSIG DE66AECA9151AFA1877EC31DE8525D47528144E2 1 11 00 1472744666 9 [GNUPG:] NO_PUBKEY DE66AECA9151AFA1877EC31DE8525D47528144E2' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: .*public key is not available' method.output testgpgv 'Expired key with long keyid' 'Worthless: EXPKEYSIG 4BC0A39C27CE74F9 Rex Expired , ' '' '[GNUPG:] EXPKEYSIG 4BC0A39C27CE74F9 Rex Expired [GNUPG:] VALIDSIG 891CC50E605796A0C6E733F74BC0A39C27CE74F9 2016-09-01 1472742629 0 4 0 1 11 00 891CC50E605796A0C6E733F74BC0A39C27CE74F9' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: The following signatures were invalid: EXPKEYSIG' method.output testgpgv 'Expired key with fingerprint' 'Worthless: EXPKEYSIG 891CC50E605796A0C6E733F74BC0A39C27CE74F9 Rex Expired , ' '' '[GNUPG:] EXPKEYSIG 891CC50E605796A0C6E733F74BC0A39C27CE74F9 Rex Expired [GNUPG:] VALIDSIG 891CC50E605796A0C6E733F74BC0A39C27CE74F9 2016-09-01 1472742629 0 4 0 1 11 00 891CC50E605796A0C6E733F74BC0A39C27CE74F9' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: The following signatures were invalid: EXPKEYSIG' method.output + + testgpgv 'Expired signature (gpgv-g10code)' 'Worthless: EXPSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) , ' '' '[GNUPG:] NEWSIG joe@example.org +[GNUPG:] KEY_CONSIDERED 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 +[GNUPG:] SIG_ID pwbegSQxpqXn4lSZ1N4DLwyM4rc 2016-09-24 1474732092 +[GNUPG:] KEY_CONSIDERED 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 +[GNUPG:] EXPSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) +[GNUPG:] VALIDSIG 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 2016-09-24 1474732092 1491040800 4 0 1 11 00 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: The following signatures were invalid: EXPSIG' method.output + + testgpgv 'Expired signature (gpgv-sq)' 'Bad: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) ' '' '[GNUPG:] NEWSIG joe@example.org +[GNUPG:] KEY_CONSIDERED 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 +[GNUPG:] KEYEXPIRED 1491040800 +[GNUPG:] BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) +' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: The following signatures were invalid: BADSIG' method.output + + testgpgv 'GPG-untrusted digest (MD5)' 'Worthless: ERRSIG 5A90D141DBAC8DAE, ' '' '[GNUPG:] NEWSIG joe@example.org +[GNUPG:] KEY_CONSIDERED 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE 0 +[GNUPG:] ERRSIG 5A90D141DBAC8DAE 1 1 00 1734647007 5 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE' + testsuccess grep '^\s\+Good:\s\+$' method.output + testsuccess grep '^400 URI Failure$' method.output + testsuccess grep 'Message: The following signatures were invalid: ERRSIG' method.output } echo 'Test' > message.data diff --git a/test/integration/test-method-gpgv-legacy-keyring b/test/integration/test-method-gpgv-legacy-keyring index 8afa5671b..cc7ddf097 100755 --- a/test/integration/test-method-gpgv-legacy-keyring +++ b/test/integration/test-method-gpgv-legacy-keyring @@ -12,8 +12,10 @@ insertpackage 'unstable' 'foo' 'all' '1' buildaptarchive setupaptarchive --no-update -testsuccessequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1420 B] -Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1420 B] +alias inrelease_size="stat -c %s aptarchive/dists/unstable/InRelease" + +testsuccessequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] +Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] Get:2 file:${TMPWORKINGDIRECTORY}/aptarchive unstable/main all Packages [246 B] Get:3 file:${TMPWORKINGDIRECTORY}/aptarchive unstable/main Translation-en [224 B] Reading package lists..." aptget update -q @@ -21,15 +23,15 @@ Reading package lists..." aptget update -q cat rootdir/etc/apt/trusted.gpg.d/*.gpg > rootdir/etc/apt/trusted.gpg rm rootdir/etc/apt/trusted.gpg.d/*.gpg -testwarningequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1420 B] -Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1420 B] +testwarningequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] +Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] Reading package lists... W: file:${TMPWORKINGDIRECTORY}/aptarchive/dists/unstable/InRelease: Key is stored in legacy trusted.gpg keyring (${TMPWORKINGDIRECTORY}/rootdir/etc/apt/trusted.gpg). Use Signed-By instead. See the USER CONFIGURATION section in apt-secure(8) for details." aptget update -q # 2.4.0 regression: If the InRelease file was signed with two keys, fallback to trusted.gpg did not # work: It ran the fallback, but then ignored the result, as keys were still missing. signreleasefiles 'Joe Sixpack,Marvin Paranoid' -testwarningequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1867 B] -Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [1867 B] +testwarningequal "Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] +Get:1 file:${TMPWORKINGDIRECTORY}/aptarchive unstable InRelease [$(inrelease_size) B] Reading package lists... W: file:${TMPWORKINGDIRECTORY}/aptarchive/dists/unstable/InRelease: Key is stored in legacy trusted.gpg keyring (${TMPWORKINGDIRECTORY}/rootdir/etc/apt/trusted.gpg). Use Signed-By instead. See the USER CONFIGURATION section in apt-secure(8) for details." aptget update -q -omsg=with-two-signatures diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 171792a10..1392a05d1 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -153,28 +153,6 @@ runtest() { failaptold rm -f rootdir/etc/apt/trusted.gpg.d/rexexpired.gpg - msgmsg 'Cold archive expired signed by' 'Joe Sixpack' - if dpkg --compare-versions "$(aptkey adv --version | head -n 2 | tail -n 1 | cut -d' ' -f 3)" '>=' '2.1' >/dev/null 2>&1; then - touch rootdir/etc/apt/apt.conf.d/99gnupg2 - elif gpg2 --version >/dev/null 2>&1; then - echo 'Apt::Key::gpgcommand "gpg2";' > rootdir/etc/apt/apt.conf.d/99gnupg2 - if ! dpkg --compare-versions "$(aptkey adv --version | head -n 2 | tail -n 1 | cut -d' ' -f 3)" '>=' '2.1' >/dev/null 2>&1; then - rm rootdir/etc/apt/apt.conf.d/99gnupg2 - fi - fi - if [ -e rootdir/etc/apt/apt.conf.d/99gnupg2 ]; then - prepare "${PKGFILE}" - rm -rf rootdir/var/lib/apt/lists - signreleasefiles 'Joe Sixpack' 'aptarchive' --faked-system-time "20160924T154812" --default-sig-expire 2017-04-01 - updatewithwarnings '^W: .* (BADSIG|EXPSIG)' - testsuccessequal "$(cat "${PKGFILE}") -" aptcache show apt - failaptold - rm -f rootdir/etc/apt/apt.conf.d/99gnupg2 - else - msgskip 'Not a new enough gpg available providing --fake-system-time' - fi - msgmsg 'Cold archive signed by' 'Joe Sixpack,Marvin Paranoid' prepare "${PKGFILE}" rm -rf rootdir/var/lib/apt/lists @@ -282,7 +260,7 @@ runtest() { installaptold sed -i "s# \[signed-by=[^]]\+\] # #" rootdir/etc/apt/sources.list.d/* - local MARVIN="$(aptkey --keyring $MARVIN finger --with-colons | grep '^fpr' | cut -d':' -f 10)" + local MARVIN="DE66AECA9151AFA1877EC31DE8525D47528144E2" msgmsg 'Cold archive signed by bad keyid' 'Joe Sixpack' rm -rf rootdir/var/lib/apt/lists signreleasefiles 'Joe Sixpack' @@ -306,7 +284,7 @@ runtest() { " aptcache show apt installaptold - local SIXPACK="$(aptkey --keyring keys/joesixpack.pub finger --with-colons | grep '^fpr' | cut -d':' -f 10)" + local SIXPACK="34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE" msgmsg 'Cold archive signed by good keyids' 'Joe Sixpack' rm -rf rootdir/var/lib/apt/lists signreleasefiles 'Joe Sixpack' @@ -376,7 +354,7 @@ Signed-By: ${MARVIN} ${MARVIN}, \\ installaptnew cp -a keys/sebastiansubkey.pub rootdir/etc/apt/trusted.gpg.d/sebastiansubkey.gpg - local SEBASTIAN="$(aptkey --keyring keys/sebastiansubkey.pub finger --with-colons | grep -m 1 '^fpr' | cut -d':' -f 10)" + local SEBASTIAN="648E6A33FDE5CB5BA2D896A3CA3E1DFF1E6BE149" msgmsg 'Warm archive with subkey signing' 'Sebastian Subkey' rm -rf rootdir/var/lib/apt/lists cp -a rootdir/var/lib/apt/lists-bak rootdir/var/lib/apt/lists @@ -400,7 +378,7 @@ Signed-By: ${SEBASTIAN}!" rootdir/var/lib/apt/lists/*Release " aptcache show apt installaptold - local SUBKEY="$(aptkey --keyring keys/sebastiansubkey.pub finger --with-colons | grep -m 2 '^fpr' | tail -n -1 | cut -d':' -f 10)" + local SUBKEY="4281DEDBD466EAE8C1F4157E5B6896415D44C43E" msgmsg 'Warm archive with correct exact subkey signing' 'Sebastian Subkey' rm -rf rootdir/var/lib/apt/lists cp -a rootdir/var/lib/apt/lists-bak rootdir/var/lib/apt/lists @@ -482,7 +460,7 @@ Acquire::AllowInsecureRepositories "1"; Acquire::AllowDowngradeToInsecureRepositories "1"; EOF # the hash marked as configurable in our gpgv method -export APT_TESTS_DIGEST_ALGO='SHA224' +export APT_TESTS_DIGEST_ALGO='SHA512' successfulaptgetupdate() { testsuccess aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::gpgv=1 @@ -536,7 +514,3 @@ runfailure() { done } foreachgpg runfailure - -msgmsg "Running test with gpgv-untrusted digest" -export APT_TESTS_DIGEST_ALGO='MD5' -foreachgpg runfailure diff --git a/test/integration/test-releasefile-verification-noflat b/test/integration/test-releasefile-verification-noflat index 3953c6492..d1b1d845f 100755 --- a/test/integration/test-releasefile-verification-noflat +++ b/test/integration/test-releasefile-verification-noflat @@ -12,7 +12,7 @@ insertpackage 'unstable' 'foo' 'i386' '1.0' setupaptarchive "now" "now + 1 year" changetowebserver -SIXPACK="$(aptkey --keyring keys/joesixpack.pub finger | grep 'Key fingerprint' | cut -d'=' -f 2 | tr -d ' ')" +SIXPACK="34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE" testsuccess aptget update diff --git a/test/interactive-helper/CMakeLists.txt b/test/interactive-helper/CMakeLists.txt index 0e0b57bcd..bfca6c8f6 100644 --- a/test/interactive-helper/CMakeLists.txt +++ b/test/interactive-helper/CMakeLists.txt @@ -31,11 +31,3 @@ target_include_directories(longest-dependency-chain PRIVATE ${APTPRIVATE_INCLUDE add_library(noprofile SHARED libnoprofile.c) target_link_libraries(noprofile ${CMAKE_DL_LIBS}) - -add_vendor_file(OUTPUT apt-key - INPUT apt-key.in - MODE 755 - VARIABLES keyring-filename - keyring-removed-filename - keyring-master-filename - keyring-uri keyring-package) diff --git a/test/interactive-helper/apt-key.in b/test/interactive-helper/apt-key.in deleted file mode 100644 index dd1c52ab0..000000000 --- a/test/interactive-helper/apt-key.in +++ /dev/null @@ -1,840 +0,0 @@ -#!/bin/sh - -set -e -unset GREP_OPTIONS GPGHOMEDIR CURRENTTRAP -export IFS="$(printf "\n\b")" - -MASTER_KEYRING='&keyring-master-filename;' -eval "$(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring)" -ARCHIVE_KEYRING='&keyring-filename;' -eval "$(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring)" -REMOVED_KEYS='&keyring-removed-filename;' -eval "$(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys)" -ARCHIVE_KEYRING_URI='&keyring-uri;' -eval "$(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI)" - -aptkey_echo() { echo "$@"; } - -find_gpgv_status_fd() { - while [ -n "$1" ]; do - if [ "$1" = '--status-fd' ]; then - shift - echo "$1" - break - fi - shift - done -} -GPGSTATUSFD="$(find_gpgv_status_fd "$@")" - -apt_warn() { - if [ -z "$GPGHOMEDIR" ]; then - echo >&2 'W:' "$@" - else - echo 'W:' "$@" > "${GPGHOMEDIR}/aptwarnings.log" - fi - if [ -n "$GPGSTATUSFD" ]; then - echo >&${GPGSTATUSFD} '[APTKEY:] WARNING' "$@" - fi -} -apt_error() { - if [ -z "$GPGHOMEDIR" ]; then - echo >&2 'E:' "$@" - else - echo 'E:' "$@" > "${GPGHOMEDIR}/aptwarnings.log" - fi - if [ -n "$GPGSTATUSFD" ]; then - echo >&${GPGSTATUSFD} '[APTKEY:] ERROR' "$@" - fi -} - -cleanup_gpg_home() { - if [ -z "$GPGHOMEDIR" ]; then return; fi - if [ -s "$GPGHOMEDIR/aptwarnings.log" ]; then - cat >&2 "$GPGHOMEDIR/aptwarnings.log" - fi - if command_available 'gpgconf'; then - GNUPGHOME="${GPGHOMEDIR}" gpgconf --kill all >/dev/null 2>&1 || true - fi - rm -rf "$GPGHOMEDIR" -} - -# gpg needs (in different versions more or less) files to function correctly, -# so we give it its own homedir and generate some valid content for it later on -create_gpg_home() { - # for cases in which we want to cache a homedir due to expensive setup - if [ -n "$GPGHOMEDIR" ]; then - return - fi - if [ -n "$TMPDIR" ]; then - # tmpdir is a directory and current user has rwx access to it - # same tests as in apt-pkg/contrib/fileutl.cc GetTempDir() - if [ ! -d "$TMPDIR" ] || [ ! -r "$TMPDIR" ] || [ ! -w "$TMPDIR" ] || [ ! -x "$TMPDIR" ]; then - unset TMPDIR - fi - fi - GPGHOMEDIR="$(mktemp --directory --tmpdir 'apt-key-gpghome.XXXXXXXXXX')" - CURRENTTRAP="${CURRENTTRAP} cleanup_gpg_home;" - trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM - if [ -z "$GPGHOMEDIR" ]; then - apt_error "Could not create temporary gpg home directory in $TMPDIR (wrong permissions?)" - exit 28 - fi - chmod 700 "$GPGHOMEDIR" -} - -requires_root() { - if [ "$(id -u)" -ne 0 ]; then - apt_error "This command can only be used by root." - exit 1 - fi -} - -command_available() { - if [ -x "$1" ]; then return 0; fi - command -v "$1" >/dev/null # required by policy, see #747320 -} - -escape_shell() { - echo "$@" | sed -e "s#'#'\"'\"'#g" -} - -get_fingerprints_of_keyring() { - aptkey_execute "$GPG_SH" --keyring "$1" --with-colons --fingerprint | while read publine; do - # search for a public key - if [ "${publine%%:*}" != 'pub' ]; then continue; fi - # search for the associated fingerprint (should be the very next line) - while read fprline; do - if [ "${fprline%%:*}" = 'sub' ]; then break; # should never happen - elif [ "${fprline%%:*}" != 'fpr' ]; then continue; fi - echo "$fprline" | cut -d':' -f 10 - done - # order in the keyring shouldn't be important - done | sort -} - -add_keys_with_verify_against_master_keyring() { - ADD_KEYRING="$1" - MASTER="$2" - - if [ ! -f "$ADD_KEYRING" ]; then - apt_error "Keyring '$ADD_KEYRING' to be added not found" - return - fi - if [ ! -f "$MASTER" ]; then - apt_error "Master-Keyring '$MASTER' not found" - return - fi - - # when adding new keys, make sure that the archive-master-keyring - # is honored. so: - # all keys that are exported must have a valid signature - # from a key in the $distro-master-keyring - add_keys="$(get_fingerprints_of_keyring "$ADD_KEYRING")" - all_add_keys="$(aptkey_execute "$GPG_SH" --keyring "$ADD_KEYRING" --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5)" - master_keys="$(aptkey_execute "$GPG_SH" --keyring "$MASTER" --with-colons --list-keys | grep ^pub | cut -d: -f5)" - - # ensure there are no colisions LP: #857472 - for all_add_key in $all_add_keys; do - for master_key in $master_keys; do - if [ "$all_add_key" = "$master_key" ]; then - echo >&2 "Keyid collision for '$all_add_key' detected, operation aborted" - return 1 - fi - done - done - - for add_key in $add_keys; do - # export the add keyring one-by-one - local TMP_KEYRING="${GPGHOMEDIR}/tmp-keyring.gpg" - aptkey_execute "$GPG_SH" --batch --yes --keyring "$ADD_KEYRING" --output "$TMP_KEYRING" --export "$add_key" - if ! aptkey_execute "$GPG_SH" --batch --yes --keyring "$TMP_KEYRING" --import "$MASTER" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi - # check if signed with the master key and only add in this case - ADDED=0 - for master_key in $master_keys; do - if aptkey_execute "$GPG_SH" --keyring "$TMP_KEYRING" --check-sigs --with-colons "$add_key" \ - | grep '^sig:!:' | cut -d: -f5 | grep -q "$master_key"; then - aptkey_execute "$GPG_SH" --batch --yes --keyring "$ADD_KEYRING" --export "$add_key" \ - | aptkey_execute "$GPG" --batch --yes --import - ADDED=1 - fi - done - if [ $ADDED = 0 ]; then - echo >&2 "Key '$add_key' not added. It is not signed with a master key" - fi - rm -f "${TMP_KEYRING}" - done -} - -# update the current archive signing keyring from a network URI -# the archive-keyring keys needs to be signed with the master key -# (otherwise it does not make sense from a security POV) -net_update() { - local APT_DIR='/' - eval $(apt-config shell APT_DIR Dir) - - # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) - APT_KEY_NET_UPDATE_ENABLED="" - eval $(apt-config shell APT_KEY_NET_UPDATE_ENABLED APT::Key::Net-Update-Enabled) - if [ -z "$APT_KEY_NET_UPDATE_ENABLED" ]; then - exit 1 - fi - - if [ -z "$ARCHIVE_KEYRING_URI" ]; then - apt_error 'Your distribution is not supported in net-update as no uri for the archive-keyring is set' - exit 1 - fi - # in theory we would need to depend on wget for this, but this feature - # isn't usable in debian anyway as we have no keyring uri nor a master key - if ! command_available 'wget'; then - apt_error 'wget is required for a network-based update, but it is not installed' - exit 1 - fi - if [ ! -d "${APT_DIR}/var/lib/apt/keyrings" ]; then - mkdir -p "${APT_DIR}/var/lib/apt/keyrings" - fi - keyring="${APT_DIR}/var/lib/apt/keyrings/$(basename "$ARCHIVE_KEYRING_URI")" - old_mtime=0 - if [ -e $keyring ]; then - old_mtime=$(stat -c %Y "$keyring") - fi - (cd "${APT_DIR}/var/lib/apt/keyrings"; wget --timeout=90 -q -N "$ARCHIVE_KEYRING_URI") - if [ ! -e "$keyring" ]; then - return - fi - new_mtime=$(stat -c %Y "$keyring") - if [ $new_mtime -ne $old_mtime ]; then - aptkey_echo "Checking for new archive signing keys now" - add_keys_with_verify_against_master_keyring "$keyring" "$MASTER_KEYRING" - fi -} - -update() { - if [ -z "$APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE" ]; then - echo >&2 "Warning: 'apt-key update' is deprecated and should not be used anymore!" - if [ -z "$ARCHIVE_KEYRING" ]; then - echo >&2 "Note: In your distribution this command is a no-op and can therefore be removed safely." - exit 0 - fi - fi - if [ ! -f "$ARCHIVE_KEYRING" ]; then - apt_error "Can't find the archive-keyring (Is the &keyring-package; package installed?)" - exit 1 - fi - - # add new keys from the package; - - # we do not use add_keys_with_verify_against_master_keyring here, - # because "update" is run on regular package updates. A - # attacker might as well replace the master-archive-keyring file - # in the package and add his own keys. so this check wouldn't - # add any security. we *need* this check on net-update though - import_keyring_into_keyring "$ARCHIVE_KEYRING" '' && cat "${GPGHOMEDIR}/gpgoutput.log" - - if [ -r "$REMOVED_KEYS" ]; then - # remove no-longer supported/used keys - get_fingerprints_of_keyring "$(dearmor_filename "$REMOVED_KEYS")" | while read key; do - foreach_keyring_do 'remove_key_from_keyring' "$key" - done - else - apt_warn "Removed keys keyring '$REMOVED_KEYS' missing or not readable" - fi -} - -remove_key_from_keyring() { - local KEYRINGFILE="$1" - shift - # non-existent keyrings have by definition no keys - if [ ! -e "$KEYRINGFILE" ]; then - return - fi - - local FINGERPRINTS="${GPGHOMEDIR}/keyringfile.keylst" - local DEARMOR="$(dearmor_filename "$KEYRINGFILE")" - get_fingerprints_of_keyring "$DEARMOR" > "$FINGERPRINTS" - - for KEY in "$@"; do - # strip leading 0x, if present: - KEY="$(echo "${KEY#0x}" | tr -d ' ')" - - # check if the key is in this keyring - if ! grep -iq "^[0-9A-F]*${KEY}$" "$FINGERPRINTS"; then - continue - fi - if [ ! -w "$KEYRINGFILE" ]; then - apt_warn "Key ${KEY} is in keyring ${KEYRINGFILE}, but can't be removed as it is read only." - continue - fi - # check if it is the only key in the keyring and if so remove the keyring altogether - if [ '1' = "$(uniq "$FINGERPRINTS" | wc -l)" ]; then - mv -f "$KEYRINGFILE" "${KEYRINGFILE}~" # behave like gpg - return - fi - # we can't just modify pointed to files as these might be in /usr or something - local REALTARGET - if [ -L "$DEARMOR" ]; then - REALTARGET="$(readlink -f "$DEARMOR")" - mv -f "$DEARMOR" "${DEARMOR}.dpkg-tmp" - cp -a "$REALTARGET" "$DEARMOR" - fi - # delete the key from the keyring - aptkey_execute "$GPG_SH" --keyring "$DEARMOR" --batch --delete-keys --yes "$KEY" - if [ -n "$REALTARGET" ]; then - # the real backup is the old link, not the copy we made - mv -f "${DEARMOR}.dpkg-tmp" "${DEARMOR}~" - fi - if [ "$DEARMOR" != "$KEYRINGFILE" ]; then - mv -f "$KEYRINGFILE" "${KEYRINGFILE}~" - create_new_keyring "$KEYRINGFILE" - aptkey_execute "$GPG_SH" --keyring "$DEARMOR" --armor --export > "$KEYRINGFILE" - fi - get_fingerprints_of_keyring "$DEARMOR" > "$FINGERPRINTS" - done -} - -accessible_file_exists() { - if ! test -s "$1"; then - return 1 - fi - if test -r "$1"; then - return 0 - fi - apt_warn "The key(s) in the keyring $1 are ignored as the file is not readable by user '$USER' executing apt-key." - return 1 -} - -is_supported_keyring() { - # empty files are always supported - if ! test -s "$1"; then - return 0 - fi - local FILEEXT="${1##*.}" - if [ "$FILEEXT" = 'gpg' -o "$FILEEXT" = 'pub' ]; then - # 0x98, 0x99 and 0xC6 via octal as hex isn't supported by dashs printf - if printf '\231' | cmp -s -n 1 - "$1"; then - true - elif printf '\230' | cmp -s -n 1 - "$1"; then - true - elif printf '\306' | cmp -s -n 1 - "$1"; then - true - else - apt_warn "The key(s) in the keyring $1 are ignored as the file has an unsupported filetype." - return 1 - fi - elif [ "$FILEEXT" = 'asc' ]; then - true #dearmor_filename will deal with them - else - # most callers ignore unsupported extensions silently - apt_warn "The key(s) in the keyring $1 are ignored as the file has an unsupported filename extension." - return 1 - fi - return 0 -} - -foreach_keyring_do() { - local ACTION="$1" - shift - # if a --keyring was given, just work on this one - if [ -n "$FORCED_KEYRING" ]; then - $ACTION "$FORCED_KEYRING" "$@" - else - # otherwise all known keyrings are up for inspection - if accessible_file_exists "$TRUSTEDFILE" && is_supported_keyring "$TRUSTEDFILE"; then - $ACTION "$TRUSTEDFILE" "$@" - fi - local TRUSTEDPARTS="/etc/apt/trusted.gpg.d" - eval "$(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)" - if [ -d "$TRUSTEDPARTS" ]; then - TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")" - local TRUSTEDPARTSLIST="$(cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 \( -name '*.gpg' -o -name '*.asc' \))" - for trusted in $(echo "$TRUSTEDPARTSLIST" | sort); do - if accessible_file_exists "$trusted" && is_supported_keyring "$trusted"; then - $ACTION "$trusted" "$@" - fi - done - fi - fi -} - -list_keys_in_keyring() { - local KEYRINGFILE="$1" - shift - # fingerprint and co will fail if key isn't in this keyring - aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$KEYRINGFILE")" "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2> "${GPGHOMEDIR}/gpgoutput.err" || true - if [ ! -s "${GPGHOMEDIR}/gpgoutput.log" ]; then - return - fi - # we fake gpg header here to refer to the real asc file rather than a temp file - if [ "${KEYRINGFILE##*.}" = 'asc' ]; then - if expr match "$(sed -n '2p' "${GPGHOMEDIR}/gpgoutput.log")" '^-\+$' >/dev/null 2>&1; then - echo "$KEYRINGFILE" - echo "$KEYRINGFILE" | sed 's#[^-]#-#g' - sed '1,2d' "${GPGHOMEDIR}/gpgoutput.log" || true - else - cat "${GPGHOMEDIR}/gpgoutput.log" - fi - else - cat "${GPGHOMEDIR}/gpgoutput.log" - fi - if [ -s "${GPGHOMEDIR}/gpgoutput.err" ]; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.err" - fi -} - -export_key_from_to() { - local FROM="$1" - local TO="$2" - shift 2 - if ! aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$FROM")" --export "$@" > "$TO" 2> "${GPGHOMEDIR}/gpgoutput.log"; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - else - chmod 0644 -- "$TO" - fi -} - -import_keyring_into_keyring() { - local FROM="${1:-${GPGHOMEDIR}/pubring.gpg}" - local TO="${2:-${GPGHOMEDIR}/pubring.gpg}" - shift 2 - rm -f "${GPGHOMEDIR}/gpgoutput.log" - # the idea is simple: We take keys from one keyring and copy it to another - # we do this with so many checks in between to ensure that WE control the - # creation, so we know that the (potentially) created $TO keyring is a - # simple keyring rather than a keybox as gpg2 would create it which in turn - # can't be read by gpgv. - # BEWARE: This is designed more in the way to work with the current - # callers, than to have a well defined it would be easy to add new callers to. - if [ ! -s "$TO" ]; then - if [ -s "$FROM" ]; then - if [ -z "$2" ]; then - local OPTS - if [ "${TO##*.}" = 'asc' ]; then - OPTS='--armor' - fi - export_key_from_to "$(dearmor_filename "$FROM")" "$TO" $OPTS ${1:+"$1"} - else - create_new_keyring "$TO" - fi - else - create_new_keyring "$TO" - fi - elif [ -s "$FROM" ]; then - local EXPORTLIMIT="$1" - if [ -n "$1$2" ]; then shift; fi - local DEARMORTO="$(dearmor_filename "$TO")" - if ! aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$FROM")" --export ${EXPORTLIMIT:+"$EXPORTLIMIT"} \ - | aptkey_execute "$GPG_SH" --keyring "$DEARMORTO" --batch --import "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi - if [ "$DEARMORTO" != "$TO" ]; then - export_key_from_to "$DEARMORTO" "${DEARMORTO}.asc" --armor - if ! cmp -s "$TO" "${DEARMORTO}.asc" 2>/dev/null; then - cp -a "$TO" "${TO}~" - mv -f "${DEARMORTO}.asc" "$TO" - fi - fi - fi -} - -dearmor_keyring() { - # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=831409#67 - # The awk script is more complex through to skip surrounding garbage and - # to support multiple keys in one file (old gpgs generate version headers - # which get printed with the original and hence result in garbage input for base64 - awk '{ gsub(/\r/,"") } -/^-----BEGIN/{ x = 1; } -/^$/{ if (x == 1) { x = 2; }; } -/^[^=-]/{ if (x == 2) { print $0; }; } -/^-----END/{ x = 0; }' | base64 -d -} -dearmor_filename() { - if [ "${1##*.}" = 'asc' ]; then - local trusted="${GPGHOMEDIR}/${1##*/}.gpg" - if [ -s "$1" ]; then - dearmor_keyring < "$1" > "$trusted" - fi - echo "$trusted" - elif [ "${1##*.}" = 'gpg' ]; then - echo "$1" - elif [ "$(head -n 1 "$1" 2>/dev/null)" = '-----BEGIN PGP PUBLIC KEY BLOCK-----' ]; then - local trusted="${GPGHOMEDIR}/${1##*/}.gpg" - dearmor_keyring < "$1" > "$trusted" - echo "$trusted" - else - echo "$1" - fi -} -catfile() { - if accessible_file_exists "$1" && is_supported_keyring "$1"; then - cat "$(dearmor_filename "$1")" >> "$2" - fi -} - -merge_all_trusted_keyrings_into_pubring() { - # does the same as: - # foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" - # but without using gpg, just cat and find - local PUBRING="$(readlink -f "${GPGHOMEDIR}")/pubring.gpg" - rm -f "$PUBRING" - touch "$PUBRING" - foreach_keyring_do 'catfile' "$PUBRING" -} - -import_keys_from_keyring() { - import_keyring_into_keyring "$1" "$2" -} - -merge_keys_into_keyrings() { - import_keyring_into_keyring "$2" "$1" '' --import-options 'merge-only' -} - -merge_back_changes() { - if [ -n "$FORCED_KEYRING" ]; then - # if the keyring was forced merge is already done - if [ "$FORCED_KEYRING" != "$TRUSTEDFILE" ]; then - mv -f "$FORCED_KEYRING" "${FORCED_KEYRING}~" - export_key_from_to "$TRUSTEDFILE" "$FORCED_KEYRING" --armor - fi - return - fi - if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then - # merge all updated keys - foreach_keyring_do 'merge_keys_into_keyrings' "${GPGHOMEDIR}/pubring.gpg" - fi - # look for keys which were added or removed - get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.orig.gpg" > "${GPGHOMEDIR}/pubring.orig.keylst" - get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.gpg" > "${GPGHOMEDIR}/pubring.keylst" - comm -3 "${GPGHOMEDIR}/pubring.keylst" "${GPGHOMEDIR}/pubring.orig.keylst" > "${GPGHOMEDIR}/pubring.diff" - # key isn't part of new keyring, so remove - cut -f 2 "${GPGHOMEDIR}/pubring.diff" | while read key; do - if [ -z "$key" ]; then continue; fi - foreach_keyring_do 'remove_key_from_keyring' "$key" - done - # key is only part of new keyring, so we need to import it - cut -f 1 "${GPGHOMEDIR}/pubring.diff" | while read key; do - if [ -z "$key" ]; then continue; fi - import_keyring_into_keyring '' "$TRUSTEDFILE" "$key" - done -} - -setup_merged_keyring() { - if [ -n "$FORCED_KEYID" ]; then - merge_all_trusted_keyrings_into_pubring - FORCED_KEYRING="${GPGHOMEDIR}/forcedkeyid.gpg" - TRUSTEDFILE="${FORCED_KEYRING}" - echo "#!/bin/sh -exec sh '($(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh" - GPG="${GPGHOMEDIR}/gpg.1.sh" - # ignore error as this "just" means we haven't found the forced keyid and the keyring will be empty - import_keyring_into_keyring '' "$TRUSTEDFILE" "$FORCED_KEYID" || true - elif [ -z "$FORCED_KEYRING" ]; then - merge_all_trusted_keyrings_into_pubring - if [ -r "${GPGHOMEDIR}/pubring.gpg" ]; then - cp -a "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg" - else - touch "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg" - fi - echo "#!/bin/sh -exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${GPGHOMEDIR}/pubring.gpg")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh" - GPG="${GPGHOMEDIR}/gpg.1.sh" - else - TRUSTEDFILE="$(dearmor_filename "$FORCED_KEYRING")" - create_new_keyring "$TRUSTEDFILE" - echo "#!/bin/sh -exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh" - GPG="${GPGHOMEDIR}/gpg.1.sh" - fi -} - -create_new_keyring() { - # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead. - if ! [ -e "$1" ]; then - if [ -w "$(dirname "$1")" ]; then - touch -- "$1" - chmod 0644 -- "$1" - fi - fi -} - -aptkey_execute() { sh "$@"; } - -usage() { - echo "Usage: apt-key [--keyring file] [command] [arguments]" - echo - echo "Manage apt's list of trusted keys" - echo - echo " apt-key add - add the key contained in ('-' for stdin)" - echo " apt-key del - remove the key " - echo " apt-key export - output the key " - echo " apt-key exportall - output all trusted keys" - echo " apt-key update - update keys using the keyring package" - echo " apt-key net-update - update keys using the network" - echo " apt-key list - list keys" - echo " apt-key finger - list fingerprints" - echo " apt-key adv - pass advanced options to gpg (download key)" - echo - echo "If no specific keyring file is given the command applies to all keyring files." -} - -while [ -n "$1" ]; do - case "$1" in - --keyring) - shift - if [ -z "$FORCED_KEYRING" -o "$FORCED_KEYRING" = '/dev/null' ]; then - TRUSTEDFILE="$1" - FORCED_KEYRING="$1" - elif [ "$TRUSTEDFILE" = "$FORCED_KEYRING" ]; then - create_gpg_home - FORCED_KEYRING="${GPGHOMEDIR}/mergedkeyrings.gpg" - echo -n '' > "$FORCED_KEYRING" - chmod 0644 -- "$FORCED_KEYRING" - catfile "$TRUSTEDFILE" "$FORCED_KEYRING" - catfile "$1" "$FORCED_KEYRING" - else - catfile "$1" "$FORCED_KEYRING" - fi - ;; - --keyid) - shift - if [ -n "$FORCED_KEYID" ]; then - apt_error 'Specifying --keyid multiple times is not supported' - exit 1 - fi - FORCED_KEYID="$1" - ;; - --secret-keyring) - shift - FORCED_SECRET_KEYRING="$1" - ;; - --readonly) - merge_back_changes() { true; } - create_new_keyring() { if [ ! -r "$FORCED_KEYRING" ]; then TRUSTEDFILE='/dev/null'; FORCED_KEYRING="$TRUSTEDFILE"; fi; } - ;; - --fakeroot) - requires_root() { true; } - ;; - --quiet) - aptkey_echo() { true; } - ;; - --debug1) - # some cmds like finger redirect stderr to /dev/null … - aptkey_execute() { echo 'EXEC:' "$@"; sh "$@"; } - ;; - --debug2) - # … other more complicated ones pipe gpg into gpg. - aptkey_execute() { echo >&2 'EXEC:' "$@"; sh "$@"; } - ;; - --homedir) - # force usage of a specific homedir instead of creating a temporary - shift - GPGHOMEDIR="$1" - ;; - --*) - echo >&2 "Unknown option: $1" - usage - exit 1;; - *) - break;; - esac - shift -done - -if [ -z "$TRUSTEDFILE" ]; then - TRUSTEDFILE="/etc/apt/trusted.gpg" - eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) - eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) - if [ "$APT_KEY_NO_LEGACY_KEYRING" ]; then - TRUSTEDFILE="/dev/null" - fi -fi - -command="$1" -if [ -z "$command" ]; then - usage - exit 1 -fi -shift - -prepare_gpg_home() { - # crude detection if we are called from a maintainerscript where the - # package depends on gnupg or not. We accept recommends here as - # well as the script hopefully uses apt-key optionally then like e.g. - # debian-archive-keyring for (upgrade) cleanup did - if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && [ -z "$APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE" ]; then - if ! dpkg-query --show --showformat '${Pre-Depends}${Depends}${Recommends}\n' "$DPKG_MAINTSCRIPT_PACKAGE" 2>/dev/null | grep -E -q 'gpg|gnupg'; then - cat >&2 < "${GPGHOMEDIR}/gpg.0.sh" - GPG_SH="${GPGHOMEDIR}/gpg.0.sh" - GPG="$GPG_SH" - - # create the trustdb with an (empty) dummy keyring - # older gpgs required it, newer gpgs even warn that it isn't needed, - # but require it nonetheless for some commands, so we just play safe - # here for the foreseeable future and create a dummy one - touch "${GPGHOMEDIR}/empty.gpg" - if ! "$GPG_EXE" --ignore-time-conflict --no-options --no-default-keyring \ - --homedir "$GPGHOMEDIR" --quiet --check-trustdb --keyring "${GPGHOMEDIR}/empty.gpg" >"${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi - - # We don't usually need a secret keyring, of course, but - # for advanced operations, we might really need a secret keyring after all - if [ -n "$FORCED_SECRET_KEYRING" ] && [ -r "$FORCED_SECRET_KEYRING" ]; then - if ! aptkey_execute "$GPG" -v --batch --import "$FORCED_SECRET_KEYRING" >"${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - # already imported keys cause gpg1 to fail for some reason… ignore this error - if ! grep -q 'already in secret keyring' "${GPGHOMEDIR}/gpgoutput.log"; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi - fi - else - # and then, there are older versions of gpg which panic and implode - # if there isn't one available - and writeable for imports - # and even if not output is littered with the creation of a secring, - # so lets call import once to have it create what it wants in silence - echo -n | aptkey_execute "$GPG" --batch --import >/dev/null 2>&1 || true - fi -} - -warn_on_script_usage() { - if [ -n "$APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE" ]; then - return - fi - # (Maintainer) scripts should not be using apt-key - if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ]; then - echo >&2 "Warning: apt-key should not be used in scripts (called from $DPKG_MAINTSCRIPT_NAME maintainerscript of the package ${DPKG_MAINTSCRIPT_PACKAGE})" - fi - - echo >&2 "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8))." -} - -warn_outside_maintscript() { - # In del, we want to warn in interactive use, but not inside maintainer - # scripts, so as to give people a chance to migrate keyrings. - # - # FIXME: We should always warn starting in 2022. - if [ -z "$DPKG_MAINTSCRIPT_PACKAGE" ]; then - echo >&2 "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8))." - fi -} - -if [ "$command" != 'help' ] && [ "$command" != 'verify' ]; then - prepare_gpg_home -fi - -case "$command" in - add) - warn_on_script_usage - requires_root - setup_merged_keyring - aptkey_execute "$GPG" --quiet --batch --import "$@" - merge_back_changes - aptkey_echo "OK" - ;; - del|rm|remove) - # no script warning here as removing 'add' usage needs 'del' for cleanup - warn_outside_maintscript - requires_root - foreach_keyring_do 'remove_key_from_keyring' "$@" - aptkey_echo "OK" - ;; - update) - warn_on_script_usage - requires_root - setup_merged_keyring - update - merge_back_changes - ;; - net-update) - warn_on_script_usage - requires_root - setup_merged_keyring - net_update - merge_back_changes - ;; - list|finger*) - warn_on_script_usage - foreach_keyring_do 'list_keys_in_keyring' --fingerprint "$@" - ;; - export|exportall) - warn_on_script_usage - merge_all_trusted_keyrings_into_pubring - aptkey_execute "$GPG_SH" --keyring "${GPGHOMEDIR}/pubring.gpg" --armor --export "$@" - ;; - adv*) - warn_on_script_usage - setup_merged_keyring - aptkey_echo "Executing: $GPG" "$@" - aptkey_execute "$GPG" "$@" - merge_back_changes - ;; - verify) - GPGV='' - 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-sq'; then GPGV='gpgv-sq'; - elif command_available 'gpgv'; then GPGV='gpgv'; - elif command_available 'gpgv2'; then GPGV='gpgv2'; - elif command_available 'gpgv1'; then GPGV='gpgv1'; - else - apt_error 'gpgv, gpgv2 or gpgv1 required for verification, but neither seems installed' - exit 29 - fi - GPGV_ARGS="" - if [ "$ASSERT_PUBKEY_ALGO" ] && $GPGV --dump-options | grep -q -- --assert-pubkey-algo; then - GPGV_ARGS="--assert-pubkey-algo=$ASSERT_PUBKEY_ALGO" - fi - # for a forced keyid we need gpg --export, so full wrapping required - if [ -n "$FORCED_KEYID" ]; then - prepare_gpg_home - else - create_gpg_home - fi - setup_merged_keyring - if [ -n "$FORCED_KEYRING" ]; then - "$GPGV" $GPGV_ARGS --homedir "${GPGHOMEDIR}" --keyring "$(dearmor_filename "${FORCED_KEYRING}")" --ignore-time-conflict "$@" - else - "$GPGV" $GPGV_ARGS --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" - fi - ;; - help) - usage - ;; - *) - usage - exit 1 - ;; -esac -- cgit v1.2.3-70-g09d2