]> git.saurik.com Git - apt.git/commitdiff
apt-key: warn instead of fail on unreadable keyrings
authorDavid Kalnischkies <david@kalnischkies.de>
Thu, 25 Aug 2016 10:42:36 +0000 (12:42 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Thu, 25 Aug 2016 10:42:36 +0000 (12:42 +0200)
apt-key has inconsistent behaviour if it can't read a keyring file:
Commands like 'list' skipped silently over such keyrings while 'verify'
failed hard resulting in apt to report cconfusing gpg errors (#834973).

As a first step we teach apt-key to be more consistent here skipping in
all commands over unreadable keyrings, but issuing a warning in the
process, which is as usual for apt commands displayed at the end of the
run.

cmdline/apt-key.in
test/integration/test-apt-key

index 81314c7f5fab1a4d94fb67afae5ed804bffae12c..d34f59497cbe47f2765be4f56ff970711e28fa8a 100644 (file)
@@ -232,6 +232,17 @@ remove_key_from_keyring() {
     done
 }
 
     done
 }
 
+accessible_file_exists() {
+   if ! test -s "$1"; then
+      return 1
+   fi
+   if test -r "$1"; then
+      return 0
+   fi
+   warn "The key(s) in the keyring $1 are ignored as the file is not readable by user '$USER' executing apt-key."
+   return 1
+}
+
 foreach_keyring_do() {
    local ACTION="$1"
    shift
 foreach_keyring_do() {
    local ACTION="$1"
    shift
@@ -240,7 +251,7 @@ foreach_keyring_do() {
        $ACTION "$FORCED_KEYRING" "$@"
    else
        # otherwise all known keyrings are up for inspection
        $ACTION "$FORCED_KEYRING" "$@"
    else
        # otherwise all known keyrings are up for inspection
-       if [ -s "$TRUSTEDFILE" ]; then
+       if accessible_file_exists "$TRUSTEDFILE"; then
            $ACTION "$TRUSTEDFILE" "$@"
        fi
        local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
            $ACTION "$TRUSTEDFILE" "$@"
        fi
        local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
@@ -249,7 +260,7 @@ foreach_keyring_do() {
            TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")"
            local TRUSTEDPARTSLIST="$(cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 -name '*.gpg')"
            for trusted in $(echo "$TRUSTEDPARTSLIST" | 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 accessible_file_exists "$trusted"; then
                    $ACTION "$trusted" "$@"
                fi
            done
                    $ACTION "$trusted" "$@"
                fi
            done
@@ -302,35 +313,18 @@ import_keyring_into_keyring() {
     fi
 }
 
     fi
 }
 
+catfile() {
+   cat "$1" >> "$2"
+}
+
 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")"
 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")"
-    # if a --keyring was given, just use this one
-    if [ -n "$FORCED_KEYRING" ]; then
-       if [ -s "$FORCED_KEYRING" ]; then
-           cp --dereference "$FORCED_KEYRING" "$PUBRING"
-       fi
-    else
-       # otherwise all known keyrings are merged
-       local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
-       eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
-       if [ -d "$TRUSTEDPARTS" ]; then
-           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
-           cp --dereference "$TRUSTEDFILE" "$PUBRING"
-       fi
-    fi
-
-    if [ ! -s "$PUBRING" ]; then
-       touch "$PUBRING"
-    fi
+    rm -f "$PUBRING"
+    touch "$PUBRING"
+    foreach_keyring_do 'catfile' "$PUBRING"
 }
 
 import_keys_from_keyring() {
 }
 
 import_keys_from_keyring() {
@@ -480,8 +474,19 @@ if [ -z "$command" ]; then
 fi
 shift
 
 fi
 shift
 
+warn() {
+    if [ -z "$GPGHOMEDIR" ]; then
+       echo >&2 'W:' "$@"
+    else
+       echo 'W:' "$@" > "${GPGHOMEDIR}/aptwarnings.log"
+    fi
+}
+
 cleanup_gpg_home() {
     if [ -z "$GPGHOMEDIR" ]; then return; 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 gpg-agent >/dev/null 2>&1 || true
     fi
     if command_available 'gpgconf'; then
        GNUPGHOME="${GPGHOMEDIR}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true
     fi
index 759ce148767af1aa1be0f9061f5aa3dccf3105ef..96cfe41fa62c1686c0374695fdbc2f3b74dca391 100755 (executable)
@@ -81,6 +81,20 @@ gpg:              unchanged: 1' aptkey --fakeroot update
        testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
        testempty aptkey list
 
        testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
        testempty aptkey list
 
+       if [ "$(id -u)" != '0' ]; then
+               msgtest 'Test key removal with' 'unreadable key'
+               cleanplate
+               cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+               echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+               chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+               testwarning --nomsg aptkey --fakeroot del d141dbac8dae
+               testwarning aptkey list
+               chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+               rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+               grep -v '^W: ' "${ROOTDIR}/tmp/testwarning.output" > "${ROOTDIR}/aptkeylist.output" || true
+               testempty cat "${ROOTDIR}/aptkeylist.output"
+       fi
+
        msgtest 'Test key removal with' 'single key in real file'
        cleanplate
        cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
        msgtest 'Test key removal with' 'single key in real file'
        cleanplate
        cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
@@ -202,6 +216,16 @@ gpg:              unchanged: 1' aptkey --fakeroot update
                msgtest 'Test verify a file' 'with all keys'
                testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
                msgtest 'Test verify a file' 'with all keys'
                testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
+               if [ "$(id -u)" != '0' ]; then
+                       msgtest 'Test verify a file' 'with unreadable key'
+                       echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+                       chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+                       testwarning --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+                       testwarning aptkey list
+                       chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+                       rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+               fi
+
                msgtest 'Test verify a file' 'with good keyring'
                testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
                msgtest 'Test verify a file' 'with good keyring'
                testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"