Explorar el Código

apt-key: change to / before find to satisfy its CWD needs

First seen on hurd, but easily reproducible on all systems by removing
the 'execution' bit from the current working directory and watching some
tests (mostly the no-output expecting tests) fail due to find printing:
"find: Failed to restore initial working directory: …"

Samuel Thibault says in the bugreport:
| To do its work, find first records the $PWD, then goes to
| /etc/apt/trusted.gpg.d/ to find the files, and then goes back to $PWD.
|
| On Linux, getting $PWD from the 700 directory happens to work by luck
| (POSIX says that getcwd can return [EACCES]: Search permission was denied
| for the current directory, or read or search permission was denied for a
| directory above the current directory in the file hierarchy). And going
| back to $PWD fails, and thus find returns 1, but at least it emitted its
| output.
|
| On Hurd, getting $PWD from the 700 directory fails, and find thus aborts
| immediately, without emitting any output, and thus no keyring is found.
|
| So, to summarize, the issue is that since apt-get update runs find as a
| non-root user, running it from a 700 directory breaks find.

Solved as suggested by changing to '/' before running find, with some
paranoia extra care taking to ensure the paths we give to find are really
absolute paths first (they really should, but TMPDIR=. or a similar
Dir::Etc::trustedparts setting could exist somewhere in the wild).

The commit takes also the opportunity to make these lines slightly less
error ignoring and the two find calls using (mostly) the same parameters.

Thanks: Samuel Thibault for 'finding' the culprit!
Closes: 826043
David Kalnischkies hace 10 años
padre
commit
0cfec3ab58
Se han modificado 2 ficheros con 125 adiciones y 120 borrados
  1. 10 14
      cmdline/apt-key.in
  2. 115 106
      test/integration/test-apt-key

+ 10 - 14
cmdline/apt-key.in

@@ -238,12 +238,9 @@ foreach_keyring_do() {
 	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
 	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
 	eval "$(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)"
 	eval "$(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)"
 	if [ -d "$TRUSTEDPARTS" ]; then
 	if [ -d "$TRUSTEDPARTS" ]; then
-	    # strip / suffix as gpg will double-slash in that case (#665411)
-	    local STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}"
-	    if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then
-		TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS"
-	    fi
-	    for trusted in $(find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 -regex '^.*\.gpg$' | sort); do
+	    TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")"
+	    local TRUSTEDPARTSLIST="$(cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 -name '*.gpg')"
+	    for trusted in $(echo "$TRUSTEDPARTSLIST" | sort); do
 		if [ -s "$trusted" ]; then
 		if [ -s "$trusted" ]; then
 		    $ACTION "$trusted" "$@"
 		    $ACTION "$trusted" "$@"
 		fi
 		fi
@@ -301,7 +298,7 @@ merge_all_trusted_keyrings_into_pubring() {
     # does the same as:
     # does the same as:
     # foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
     # foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg"
     # but without using gpg, just cat and find
     # but without using gpg, just cat and find
-    local PUBRING="${GPGHOMEDIR}/pubring.gpg"
+    local PUBRING="$(readlink -f "${GPGHOMEDIR}/pubring.gpg")"
     # if a --keyring was given, just use this one
     # if a --keyring was given, just use this one
     if [ -n "$FORCED_KEYRING" ]; then
     if [ -n "$FORCED_KEYRING" ]; then
 	if [ -s "$FORCED_KEYRING" ]; then
 	if [ -s "$FORCED_KEYRING" ]; then
@@ -312,13 +309,12 @@ merge_all_trusted_keyrings_into_pubring() {
 	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
 	local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
 	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
 	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
 	if [ -d "$TRUSTEDPARTS" ]; then
 	if [ -d "$TRUSTEDPARTS" ]; then
-	    # ignore errors mostly for non-existing $TRUSTEDFILE
-	    {
-	       cat "$TRUSTEDFILE" || true
-	       for parts in $(find -L "$TRUSTEDPARTS" -type f -name '*.gpg'); do
-		  cat "$parts" || true
-	       done
-	    } > "$PUBRING" 2>/dev/null
+	    rm -f "$PUBRING"
+	    if [ -s "$TRUSTEDFILE" ]; then
+		cat "$TRUSTEDFILE" > "$PUBRING"
+	    fi
+	    TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")"
+	    (cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 -name '*.gpg' -exec cat {} + >> "$PUBRING";)
 	elif [ -s "$TRUSTEDFILE" ]; then
 	elif [ -s "$TRUSTEDFILE" ]; then
 	    cp --dereference "$TRUSTEDFILE" "$PUBRING"
 	    cp --dereference "$TRUSTEDFILE" "$PUBRING"
 	fi
 	fi

+ 115 - 106
test/integration/test-apt-key

@@ -16,52 +16,49 @@ configarchitecture 'amd64'
 
 
 # start from a clean plate again
 # start from a clean plate again
 cleanplate() {
 cleanplate() {
-	rm -rf rootdir/etc/apt/trusted.gpg.d/ rootdir/etc/apt/trusted.gpg
-	mkdir rootdir/etc/apt/trusted.gpg.d/
+	rm -rf "${ROOTDIR}/etc/apt/trusted.gpg.d/" "${ROOTDIR}/etc/apt/trusted.gpg"
+	mkdir "${ROOTDIR}/etc/apt/trusted.gpg.d/"
 }
 }
 testmultigpg() {
 testmultigpg() {
 	testfailure --nomsg aptkey --quiet --readonly "$@"
 	testfailure --nomsg aptkey --quiet --readonly "$@"
-	testsuccess grep "^gpgv: Can't check signature" rootdir/tmp/testfailure.output
-	testsuccess grep '^gpgv: Good signature from' rootdir/tmp/testfailure.output
+	testsuccess grep "^gpgv: Can't check signature" "${ROOTDIR}/tmp/testfailure.output"
+	testsuccess grep '^gpgv: Good signature from' "${ROOTDIR}/tmp/testfailure.output"
 }
 }
 
 
-echo 'APT::Key::ArchiveKeyring "./keys/joesixpack.pub";
-APT::Key::RemovedKeys "./keys/rexexpired.pub";' > rootdir/etc/apt/apt.conf.d/aptkey.conf
-
 testrun() {
 testrun() {
+	echo "APT::Key::ArchiveKeyring \"${KEYDIR}/joesixpack.pub\";
+APT::Key::RemovedKeys \"${KEYDIR}/rexexpired.pub\";" > "${ROOTDIR}/etc/apt/apt.conf.d/aptkey.conf"
+
 	cleanplate
 	cleanplate
-	ln -sf "${TMPWORKINGDIRECTORY}/keys/joesixpack.pub" rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	ln -sf "$(readlink -f "${KEYDIR}/joesixpack.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testaptkeys 'Joe Sixpack'
 
 
+	testsuccess aptkey list
 	msgtest 'Check that paths in list output are not' 'double-slashed'
 	msgtest 'Check that paths in list output are not' 'double-slashed'
-	aptkey list 2>&1 | grep -q '//' && msgfail || msgpass
+	testfailure --nomsg grep '//' "${ROOTDIR}/tmp/testsuccess.output"
 
 
+	testsuccess aptkey finger
 	msgtest 'Check that paths in finger output are not' 'double-slashed'
 	msgtest 'Check that paths in finger output are not' 'double-slashed'
-	aptkey finger 2>&1 | grep -q '//' && msgfail || msgpass
-	testaptkeys 'Joe Sixpack'
+	testfailure --nomsg grep '//' "${ROOTDIR}/tmp/testsuccess.output"
 
 
 	testsuccessequal 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 	testsuccessequal 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 gpg: Total number processed: 1
 gpg: Total number processed: 1
 gpg:              unchanged: 1' aptkey --fakeroot update
 gpg:              unchanged: 1' aptkey --fakeroot update
 
 
 	testaptkeys 'Joe Sixpack'
 	testaptkeys 'Joe Sixpack'
-	testfailure test -e rootdir/etc/apt/trusted.gpg
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg"
 
 
-	testsuccess aptkey --fakeroot add ./keys/rexexpired.pub
-	msgtest 'Check if trusted.gpg is created with permissions set to' '0644'
-	if [ "$(stat -c '%a' rootdir/etc/apt/trusted.gpg )" = '644' ]; then
-		msgpass
-	else
-		msgfail
-	fi
+	testsuccess aptkey --fakeroot add "${KEYDIR}/rexexpired.pub"
+	testfilestats "${ROOTDIR}/etc/apt/trusted.gpg" '%a' '=' '644'
 
 
 	testaptkeys 'Rex Expired' 'Joe Sixpack'
 	testaptkeys 'Rex Expired' 'Joe Sixpack'
 
 
 	msgtest 'Check that Sixpack key can be' 'exported'
 	msgtest 'Check that Sixpack key can be' 'exported'
-	aptkey export 'Sixpack' > aptkey.export
-	aptkey --keyring rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg exportall > aptkey.exportall
-	testsuccess --nomsg cmp aptkey.export aptkey.exportall
-	testsuccess test -s aptkey.export
-	testsuccess test -s aptkey.exportall
+	aptkey export 'Sixpack' > "${TMPWORKINGDIRECTORY}/aptkey.export"
+	aptkey --keyring "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg" exportall > "${TMPWORKINGDIRECTORY}/aptkey.exportall"
+	testsuccess --nomsg cmp "${TMPWORKINGDIRECTORY}/aptkey.export" "${TMPWORKINGDIRECTORY}/aptkey.exportall"
+	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.export"
+	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.exportall"
 
 
 	msgtest 'Execute update again to trigger removal of' 'Rex Expired key'
 	msgtest 'Execute update again to trigger removal of' 'Rex Expired key'
 	testsuccess --nomsg aptkey --fakeroot update
 	testsuccess --nomsg aptkey --fakeroot update
@@ -69,7 +66,7 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 	testaptkeys 'Joe Sixpack'
 	testaptkeys 'Joe Sixpack'
 
 
 	msgtest "Try to remove a key which exists, but isn't in the" 'forced keyring'
 	msgtest "Try to remove a key which exists, but isn't in the" 'forced keyring'
-	testsuccess --nomsg aptkey --fakeroot --keyring rootdir/etc/apt/trusted.gpg del DBAC8DAE
+	testsuccess --nomsg aptkey --fakeroot --keyring "${ROOTDIR}/etc/apt/trusted.gpg" del DBAC8DAE
 
 
 	testaptkeys 'Joe Sixpack'
 	testaptkeys 'Joe Sixpack'
 
 
@@ -78,92 +75,92 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 
 
 	msgtest 'Test key removal with' 'lowercase key ID' #keylength somewhere between 8byte and short
 	msgtest 'Test key removal with' 'lowercase key ID' #keylength somewhere between 8byte and short
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
 	testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
 	testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
 	testempty aptkey list
 	testempty aptkey list
 
 
 	msgtest 'Test key removal with' 'single key in real file'
 	msgtest 'Test key removal with' 'single key in real file'
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
 
 
 	msgtest 'Test key removal with' 'different key specs'
 	msgtest 'Test key removal with' 'different key specs'
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	cp -a keys/marvinparanoid.pub rootdir/etc/apt/trusted.gpg.d/marvinparanoid.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/marvinparanoid.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg"
 	testsuccess --nomsg aptkey --fakeroot del 0xDBAC8DAE 528144E2
 	testsuccess --nomsg aptkey --fakeroot del 0xDBAC8DAE 528144E2
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/marvinparanoid.gpg
-	testsuccess cmp keys/marvinparanoid.pub rootdir/etc/apt/trusted.gpg.d/marvinparanoid.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg"
+	testsuccess cmp "${KEYDIR}/marvinparanoid.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg~"
 
 
 	msgtest 'Test key removal with' 'long key ID'
 	msgtest 'Test key removal with' 'long key ID'
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
 	testsuccess --nomsg aptkey --fakeroot del 5A90D141DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del 5A90D141DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
 
 
 	msgtest 'Test key removal with' 'fingerprint'
 	msgtest 'Test key removal with' 'fingerprint'
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
 	testsuccess --nomsg aptkey --fakeroot del 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
 
 
 	msgtest 'Test key removal with' 'single key in softlink'
 	msgtest 'Test key removal with' 'single key in softlink'
 	cleanplate
 	cleanplate
-	ln -s "$(readlink -f ./keys/joesixpack.pub)" rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+	ln -s "$(readlink -f "${KEYDIR}/joesixpack.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess test -L rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
 
 
 	cleanplate
 	cleanplate
-	testsuccess aptkey --fakeroot add ./keys/joesixpack.pub
-	ln -sf "$(readlink -f ./keys/marvinparanoid.pub)" "./keys/marvin paránöid.pub"
-	testsuccess aptkey --fakeroot add "./keys/marvin paránöid.pub"
+	testsuccess aptkey --fakeroot add "${KEYDIR}/joesixpack.pub"
+	ln -sf "$(readlink -f "${KEYDIR}/marvinparanoid.pub")" "${KEYDIR}/marvin paránöid.pub"
+	testsuccess aptkey --fakeroot add "${KEYDIR}/marvin paránöid.pub"
 	testaptkeys 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Joe Sixpack' 'Marvin Paranoid'
-	cp -a rootdir/etc/apt/trusted.gpg keys/testcase-multikey.pub # store for reuse
+	cp -a "${ROOTDIR}/etc/apt/trusted.gpg" "${KEYDIR}/testcase-multikey.pub" # store for reuse
 
 
 	msgtest 'Test key removal with' 'multi key in real file'
 	msgtest 'Test key removal with' 'multi key in real file'
 	cleanplate
 	cleanplate
-	cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg
+	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
 
 
 	msgtest 'Test key removal with' 'multi key in softlink'
 	msgtest 'Test key removal with' 'multi key in softlink'
 	cleanplate
 	cleanplate
-	ln -s "$(readlink -f ./keys/testcase-multikey.pub)" rootdir/etc/apt/trusted.gpg.d/multikey.gpg
+	ln -s "$(readlink -f "${KEYDIR}/testcase-multikey.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~
-	testfailure test -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg
-	testsuccess test -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg~
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
+	testfailure test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
 
 
 	msgtest 'Test key removal with' 'multiple files including key'
 	msgtest 'Test key removal with' 'multiple files including key'
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
-	testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
 
 
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
 	testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	msgtest 'Test merge-back of' 'added keys'
 	msgtest 'Test merge-back of' 'added keys'
-	testsuccess --nomsg aptkey adv --batch --yes --import keys/rexexpired.pub
+	testsuccess --nomsg aptkey adv --batch --yes --import "${KEYDIR}/rexexpired.pub"
 	testaptkeys 'Rex Expired' 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Rex Expired' 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 
 
 	msgtest 'Test merge-back of' 'removed keys'
 	msgtest 'Test merge-back of' 'removed keys'
@@ -175,107 +172,119 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
 
 
 	cleanplate
 	cleanplate
-	cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
-	cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg
+	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	local SIGNATURE="${TMPWORKINGDIRECTORY}/signature"
 	msgtest 'Test signing a file' 'with a key'
 	msgtest 'Test signing a file' 'with a key'
-	echo 'Verify me. This is my signature.' > signature
-	echo 'lalalalala' > signature2
-	testsuccess --nomsg aptkey --quiet --keyring keys/marvinparanoid.pub --secret-keyring keys/marvinparanoid.sec --readonly \
-		adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output signature.gpg signature
-	testsuccess test -s signature.gpg -a -s signature
+	echo 'Verify me. This is my signature.' > "$SIGNATURE"
+	echo 'lalalalala' > "${SIGNATURE}2"
+	testsuccess --nomsg aptkey --quiet --keyring "${KEYDIR}/marvinparanoid.pub" --secret-keyring "${KEYDIR}/marvinparanoid.sec" --readonly \
+		adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
+	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 
 
 	msgtest 'Test verify a file' 'with no sig'
 	msgtest 'Test verify a file' 'with no sig'
-	testfailure --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature signature2
+	testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}" "${SIGNATURE}2"
 
 
 	for GPGV in '' 'gpgv' 'gpgv2'; do
 	for GPGV in '' 'gpgv' 'gpgv2'; do
-		echo "APT::Key::GPGVCommand \"$GPGV\";" > rootdir/etc/apt/apt.conf.d/00gpgvcmd
+		echo "APT::Key::GPGVCommand \"$GPGV\";" > "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 
 
 		msgtest 'Test verify a file' 'with all keys'
 		msgtest 'Test verify a file' 'with all keys'
-		testsuccess --nomsg aptkey --quiet --readonly verify signature.gpg signature
+		testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify a file' 'with good keyring'
 		msgtest 'Test verify a file' 'with good keyring'
-		testsuccess --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature.gpg signature
+		testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with bad keyring'
 		msgtest 'Test fail verify a file' 'with bad keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring keys/joesixpack.pub verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/joesixpack.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with non-existing keyring'
 		msgtest 'Test fail verify a file' 'with non-existing keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature
-		testfailure test -e keys/does-not-exist.pub
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure test -e "${KEYDIR}/does-not-exist.pub"
 
 
 		# note: this isn't how apts gpgv method implements keyid for verify
 		# note: this isn't how apts gpgv method implements keyid for verify
 		msgtest 'Test verify a file' 'with good keyid'
 		msgtest 'Test verify a file' 'with good keyid'
-		testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify signature.gpg signature
+		testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with bad keyid'
 		msgtest 'Test fail verify a file' 'with bad keyid'
-		testfailure --nomsg aptkey --quiet --readonly --keyid 'Sixpack' verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyid 'Sixpack' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with non-existing keyid'
 		msgtest 'Test fail verify a file' 'with non-existing keyid'
-		testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify fails on' 'bad file'
 		msgtest 'Test verify fails on' 'bad file'
-		testfailure --nomsg aptkey --quiet --readonly verify signature.gpg signature2
+		testfailure --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}2"
 	done
 	done
-	rm -f rootdir/etc/apt/apt.conf.d/00gpgvcmd
+	rm -f "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 
 
 	msgtest 'Test verify a file' 'with good keyring'
 	msgtest 'Test verify a file' 'with good keyring'
-	testsuccess --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature.gpg signature
+	testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 	cleanplate
 	cleanplate
-	cat keys/joesixpack.pub keys/marvinparanoid.pub > keys/double.pub
-	cat keys/joesixpack.sec keys/marvinparanoid.sec > keys/double.sec
-	cp -a keys/double.pub rootdir/etc/apt/trusted.gpg.d/double.gpg
-	cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg
-	testsuccess aptkey --quiet --keyring keys/double.pub --secret-keyring keys/double.sec --readonly \
-		adv --batch --yes -u 'Marvin' -u 'Joe' --armor --detach-sign --sign --output signature.gpg signature
-	testsuccess test -s signature.gpg -a -s signature
+	cat "${KEYDIR}/joesixpack.pub" "${KEYDIR}/marvinparanoid.pub" > "${KEYDIR}/double.pub"
+	cat "${KEYDIR}/joesixpack.sec" "${KEYDIR}/marvinparanoid.sec" > "${KEYDIR}/double.sec"
+	cp -a "${KEYDIR}/double.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/double.gpg"
+	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	rm -f "${SIGNATURE}.gpg"
+	testsuccess aptkey --quiet --keyring "${KEYDIR}/double.pub" --secret-keyring "${KEYDIR}/double.sec" --readonly \
+		adv --batch --yes -u 'Marvin' -u 'Joe' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
+	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 
 
 	for GPGV in '' 'gpgv' 'gpgv2'; do
 	for GPGV in '' 'gpgv' 'gpgv2'; do
-		echo "APT::Key::GPGVCommand \"$GPGV\";" > rootdir/etc/apt/apt.conf.d/00gpgvcmd
+		echo "APT::Key::GPGVCommand \"$GPGV\";" > "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 
 
 		msgtest 'Test verify a doublesigned file' 'with all keys'
 		msgtest 'Test verify a doublesigned file' 'with all keys'
-		testsuccess --nomsg aptkey --quiet --readonly verify signature.gpg signature
+		testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify a doublesigned file' 'with good keyring joe'
 		msgtest 'Test verify a doublesigned file' 'with good keyring joe'
-		testmultigpg --keyring keys/joesixpack.pub verify signature.gpg signature
+		testmultigpg --keyring "${KEYDIR}/joesixpack.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify a doublesigned file' 'with good keyring marvin'
 		msgtest 'Test verify a doublesigned file' 'with good keyring marvin'
-		testmultigpg --keyring keys/marvinparanoid.pub verify signature.gpg signature
+		testmultigpg --keyring "${KEYDIR}/marvinparanoid.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyring'
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring keys/rexexpired.pub verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/rexexpired.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyring'
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature
-		testfailure test -e keys/does-not-exist.pub
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure test -e "${KEYDIR}/does-not-exist.pub"
 
 
 		# note: this isn't how apts gpgv method implements keyid for verify
 		# note: this isn't how apts gpgv method implements keyid for verify
 		msgtest 'Test verify a doublesigned file' 'with good keyid'
 		msgtest 'Test verify a doublesigned file' 'with good keyid'
-		testmultigpg --keyid 'Paranoid' verify signature.gpg signature
+		testmultigpg --keyid 'Paranoid' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyid'
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyid'
-		testfailure --nomsg aptkey --quiet --readonly --keyid 'Rex' verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyid 'Rex' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyid'
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyid'
-		testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify signature.gpg signature
+		testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify fails on' 'bad doublesigned file'
 		msgtest 'Test verify fails on' 'bad doublesigned file'
-		testfailure --nomsg aptkey --quiet --readonly verify signature.gpg signature2
+		testfailure --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}2"
 	done
 	done
-	rm -f rootdir/etc/apt/apt.conf.d/00gpgvcmd
+	rm -f "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 }
 }
 
 
 setupgpgcommand() {
 setupgpgcommand() {
-	echo "APT::Key::GPGCommand \"$1\";" > rootdir/etc/apt/apt.conf.d/00gpgcmd
+	echo "APT::Key::GPGCommand \"$1\";" > "${ROOTDIR}/etc/apt/apt.conf.d/00gpgcmd"
 	msgmsg 'Force tests to be run with' "$1"
 	msgmsg 'Force tests to be run with' "$1"
 	testsuccess aptkey --readonly adv --version
 	testsuccess aptkey --readonly adv --version
-	cp rootdir/tmp/testsuccess.output aptkey.version
-	testsuccess grep "^gpg (GnuPG) $2\." aptkey.version
+	cp "${ROOTDIR}/tmp/testsuccess.output" "${TMPWORKINGDIRECTORY}/aptkey.version"
+	testsuccess grep "^gpg (GnuPG) $2\." "${TMPWORKINGDIRECTORY}/aptkey.version"
 }
 }
 
 
-# run with default (whatever this is)
+# run with default (whatever this is) in current CWD with relative paths
+ROOTDIR="./rootdir"
+KEYDIR="./keys"
 testrun
 testrun
-# run with …
+
+# run with … and up the game with a strange CWD & absolute paths
+ROOTDIR="${TMPWORKINGDIRECTORY}/rootdir"
+KEYDIR="${TMPWORKINGDIRECTORY}/keys"
+mkdir inaccessible
+cd inaccessible
+chmod 600 ../inaccessible
+testfilestats "${TMPWORKINGDIRECTORY}/inaccessible" '%a' '=' '600'
+
 setupgpgcommand 'gpg' '1'
 setupgpgcommand 'gpg' '1'
 testrun
 testrun
 setupgpgcommand 'gpg2' '2'
 setupgpgcommand 'gpg2' '2'