]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-key.in
Merge commit 'e2073b0276226b625897ef475f225bf8f508719e' as 'triehash'
[apt.git] / cmdline / apt-key.in
index ede6be4c3279fdec2304c40d0d2623554a936d1e..0c10e59554972fc62603306daa7c4370e822096f 100644 (file)
@@ -23,6 +23,7 @@ requires_root() {
 }
 
 command_available() {
+    if [ -x "$1" ]; then return 0; fi
     # command -v "$1" >/dev/null 2>&1 # not required by policy, see #747320
     # which "$1" >/dev/null 2>&1 # is in debianutils (essential) but not on non-debian systems
     local OLDIFS="$IFS"
@@ -155,6 +156,13 @@ net_update() {
 }
 
 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
        echo >&2 "ERROR: Can't find the archive-keyring"
        echo >&2 "Is the &keyring-package; package installed?"
@@ -192,8 +200,8 @@ remove_key_from_keyring() {
        local FINGERPRINTS="${GPGHOMEDIR}/keyringfile.keylst"
        get_fingerprints_of_keyring "$KEYRINGFILE" > "$FINGERPRINTS"
 
-        # strip leading 0x, if present:
-        KEY="${KEY#0x}"
+       # 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
@@ -224,6 +232,17 @@ remove_key_from_keyring() {
     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
@@ -232,7 +251,7 @@ foreach_keyring_do() {
        $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"
@@ -241,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
-               if [ -s "$trusted" ]; then
+               if accessible_file_exists "$trusted"; then
                    $ACTION "$trusted" "$@"
                fi
            done
@@ -294,35 +313,18 @@ import_keyring_into_keyring() {
     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")"
-    # 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
+    local PUBRING="$(readlink -f "${GPGHOMEDIR}")/pubring.gpg"
+    rm -f "$PUBRING"
+    touch "$PUBRING"
+    foreach_keyring_do 'catfile' "$PUBRING"
 }
 
 import_keys_from_keyring() {
@@ -472,6 +474,40 @@ if [ -z "$command" ]; then
 fi
 shift
 
+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 "$@")"
+
+warn() {
+    if [ -z "$GPGHOMEDIR" ]; then
+       echo >&2 'W:' "$@"
+    else
+       echo 'W:' "$@" > "${GPGHOMEDIR}/aptwarnings.log"
+    fi
+    if [ -n "$GPGSTATUSFD" ]; then
+       echo >&${GPGSTATUSFD} '[APTKEY:] WARNING' "$@"
+    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
+    rm -rf "$GPGHOMEDIR"
+}
+
 create_gpg_home() {
     # 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
@@ -483,8 +519,12 @@ create_gpg_home() {
        fi
     fi
     GPGHOMEDIR="$(mktemp -d)"
-    CURRENTTRAP="${CURRENTTRAP} rm -rf '$(escape_shell "${GPGHOMEDIR}")';"
+    CURRENTTRAP="${CURRENTTRAP} cleanup_gpg_home;"
     trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+    if [ -z "$GPGHOMEDIR" ]; then
+       echo "ERROR: Could not create temporary gpg home directory in apt-key ($TMPDIR)"
+       exit 28
+    fi
     chmod 700 "$GPGHOMEDIR"
 }
 
@@ -493,7 +533,7 @@ prepare_gpg_home() {
     # 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" ]; then
+    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 -q gnupg; then
            cat >&2 <<EOF
 Warning: The $DPKG_MAINTSCRIPT_NAME maintainerscript of the package $DPKG_MAINTSCRIPT_PACKAGE
@@ -510,9 +550,11 @@ EOF
        GPG_EXE="gpg"
     elif command_available 'gpg2'; then
        GPG_EXE="gpg2"
+    elif command_available 'gpg1'; then
+       GPG_EXE="gpg1"
     else
-       echo >&2 "Error: gnupg or gnupg2 do not seem to be installed,"
-       echo >&2 "Error: but apt-key requires gnupg or gnupg2 for this operation."
+       echo >&2 "Error: gnupg, gnupg2 and gnupg1 do not seem to be installed,"
+       echo >&2 "Error: but apt-key requires gnupg, gnupg2 or gnupg1 for this operation."
        echo >&2
        exit 255
     fi
@@ -553,12 +595,25 @@ exec '$(escape_shell "${GPG_EXE}")' --ignore-time-conflict --no-options --no-def
     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})"
+    elif [ ! -t 1 ]; then
+       echo >&2 "Warning: apt-key output should not be parsed (stdout is not a terminal)"
+    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 "$@"
@@ -566,11 +621,13 @@ case "$command" in
        aptkey_echo "OK"
         ;;
     del|rm|remove)
+       # no script warning here as removing 'add' usage needs 'del' for cleanup
        requires_root
        foreach_keyring_do 'remove_key_from_keyring' "$@"
        aptkey_echo "OK"
         ;;
     update)
+       warn_on_script_usage
        requires_root
        setup_merged_keyring
        update
@@ -582,17 +639,17 @@ case "$command" in
        net_update
        merge_back_changes
        ;;
-    list)
-       foreach_keyring_do 'run_cmd_on_keyring' --list-keys "$@"
-       ;;
-    finger*)
+    list|finger*)
+       warn_on_script_usage
        foreach_keyring_do 'run_cmd_on_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" "$@"
@@ -604,8 +661,9 @@ case "$command" in
        if [ -n "$GPGV" ] && command_available "$GPGV"; then true;
        elif command_available 'gpgv'; then GPGV='gpgv';
        elif command_available 'gpgv2'; then GPGV='gpgv2';
+       elif command_available 'gpgv1'; then GPGV='gpgv1';
        else
-          echo >&2 'ERROR: gpgv or gpgv2 required for verification'
+          echo >&2 'ERROR: gpgv, gpgv2 or gpgv1 required for verification'
           exit 29
        fi
        # for a forced keyid we need gpg --export, so full wrapping required