+run_cmd_on_keyring() {
+ local KEYRINGFILE="$1"
+ shift
+ # fingerprint and co will fail if key isn't in this keyring
+ aptkey_execute "$GPG_SH" --keyring "$KEYRINGFILE" --batch "$@" 2>/dev/null || true
+}
+
+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
+ if ! aptkey_execute "$GPG_SH" --keyring "$FROM" --export ${1:+"$1"} > "$TO" 2> "${GPGHOMEDIR}/gpgoutput.log"; then
+ cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
+ false
+ else
+ chmod 0644 -- "$TO"
+ fi
+ 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
+ if ! aptkey_execute "$GPG_SH" --keyring "$FROM" --export ${EXPORTLIMIT:+"$EXPORTLIMIT"} \
+ | aptkey_execute "$GPG_SH" --keyring "$TO" --batch --import "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+ cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
+ false
+ fi
+ 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="${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
+ # 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
+ elif [ -s "$TRUSTEDFILE" ]; then
+ cp --dereference "$TRUSTEDFILE" "$PUBRING"
+ fi
+ fi
+
+ if [ ! -s "$PUBRING" ]; then
+ touch "$PUBRING"
+ fi
+}
+
+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
+ 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
+ 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 "$TRUSTEDFILE" ]; then
+ if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
+ touch -- "$TRUSTEDFILE"
+ chmod 0644 -- "$TRUSTEDFILE"
+ fi
+ fi
+}
+
+aptkey_execute() { sh "$@"; }
+