From 3dc55197095e0536aae4d5c0c91e28bfd4740ec6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jul 2013 19:20:09 +0200 Subject: add a not documented apt-key --fakeroot option Usually, most apt-key commands require root, so the script is checking for being run as root, but in your tests we use a non-root location, so we don't need to be root and therefore need an option to skip the check. Git-Dch: Ignore --- cmdline/apt-key | 73 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index 2c087acbc..89e224923 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -158,39 +158,48 @@ usage() { echo "If no specific keyring file is given the command applies to all keyring files." } -# Determine on which keyring we want to work -if [ "$1" = "--keyring" ]; then - #echo "keyfile given" - shift - TRUSTEDFILE="$1" - if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then - GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" - else - echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" - exit 1 - fi - shift -# otherwise use the default -else - #echo "generate list" - TRUSTEDFILE="/etc/apt/trusted.gpg" - eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) - eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) - if [ -r "$TRUSTEDFILE" ]; then - GPG="$GPG --keyring $TRUSTEDFILE" - fi - GPG="$GPG --primary-keyring $TRUSTEDFILE" - TRUSTEDPARTS="/etc/apt/trusted.gpg.d" - eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) - if [ -d "$TRUSTEDPARTS" ]; then - #echo "parts active" - for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do - #echo "part -> $trusted" - GPG="$GPG --keyring $trusted" - done - fi +while [ -n "$1" ]; do + case "$1" in + --keyring) + shift + TRUSTEDFILE="$1" + if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then + GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" + else + echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" + exit 1 + fi + shift + ;; + --fakeroot) + requires_root() { true; } + shift + ;; + --*) + echo >&2 "Unknown option: $1" + usage + exit 1;; + *) + break;; + esac +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 [ -r "$TRUSTEDFILE" ]; then + GPG="$GPG --keyring $TRUSTEDFILE" + fi + GPG="$GPG --primary-keyring $TRUSTEDFILE" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do + GPG="$GPG --keyring $trusted" + done + fi fi -#echo "COMMAND: $GPG" command="$1" if [ -z "$command" ]; then -- cgit v1.2.3 From c0a013221d296e97d68b4e9a66fef5c886d2bbb0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jul 2013 20:07:22 +0200 Subject: always use our own trustdb.gpg in apt-key APT doesn't care for the trustdb.gpg, but gnupg requires one even for the simplest commands, so we either use the one root has available in /etc or if we don't have access to it (as only root can read that file) we create a temporary directory to store a trustdb.gpg in it. We can't create just a temporary file as gpg requires the given trustdb.gpg file to be valid (if it exists), so we would have to remove the file before calling gnupg which would allow mktemp (and co) to hand exactly this filename out to another program (unlikely, but still). --- cmdline/apt-key | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index 89e224923..4596e4a47 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -6,15 +6,23 @@ unset GREP_OPTIONS # We don't use a secret keyring, of course, but gpg panics and # implodes if there isn't one available SECRETKEYRING="$(mktemp)" -trap "rm -f '${SECRETKEYRING}'" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +CURRENTTRAP="rm -f '${SECRETKEYRING}';" +trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}" -if [ "$(id -u)" -eq 0 ]; then - # we could use a tmpfile here too, but creation of this tends to be time-consuming - eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) - GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" +eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) +if [ "$(id -u)" -eq 0 ] || [ -r "${TRUSTDBDIR}/trustdb.gpg" ]; then + # root can read/create the file as needed, so use the default + true +else + # gpg needs a trustdb to function, but it can't be invalid (not even empty) + # so we create a tempory directory to store our fresh readable trustdb in + TRUSTDBDIR="$(mktemp -d)" + CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" + trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM + chmod 700 "$TRUSTDBDIR" fi - +GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" GPG="$GPG_CMD" MASTER_KEYRING="" -- cgit v1.2.3 From f9e64e7bb0c125b54f0699d9e08956a88b467a7f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:19:10 +0200 Subject: use a tmpfile for trustdb.gpg in apt-key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit for some "interesting" reason gpg decides that it needs to update its trustdb.gpg file in a --list-keys command even if right before gpg is asked to --check-trustdb. That wouldn't be as bad if it wouldn't modify the keyring being listed at that moment as well, which generates not only warnings which are not a problem for us, but as the keyring modified can be in /usr it modified files which aren't allowed to be modified. The suggested solution in the bugreport is running --check-trustdb unconditionally in an 'apt-key update' call, but this command will not be used in the future and this could still potentially bite us in net-update or adv calls. All of this just to keep a file around, which we do not need… The commit therefore switches to the use of a temporary created trusted.gpg file for everyone and asks gpg to not try to update the trustdb after its intial creation, which seems to avoid the problem altogether. It is using your also faked secring btw as calling the check-trustdb without a keyring is a lot slower … Closes: #687611 Thanks: Andreas Beckmann for the initial patch! --- cmdline/apt-key | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index 4596e4a47..e010e6e90 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -3,26 +3,26 @@ set -e unset GREP_OPTIONS -# We don't use a secret keyring, of course, but gpg panics and -# implodes if there isn't one available -SECRETKEYRING="$(mktemp)" -CURRENTTRAP="rm -f '${SECRETKEYRING}';" -trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}" +GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" -eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) -if [ "$(id -u)" -eq 0 ] || [ -r "${TRUSTDBDIR}/trustdb.gpg" ]; then - # root can read/create the file as needed, so use the default - true -else - # gpg needs a trustdb to function, but it can't be invalid (not even empty) - # so we create a tempory directory to store our fresh readable trustdb in - TRUSTDBDIR="$(mktemp -d)" - CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" - trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM - chmod 700 "$TRUSTDBDIR" -fi +# gpg needs a trustdb to function, but it can't be invalid (not even empty) +# so we create a temporary directory to store our fresh readable trustdb in +TRUSTDBDIR="$(mktemp -d)" +CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" +trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +chmod 700 "$TRUSTDBDIR" +# We also don't use a secret keyring, of course, but gpg panics and +# implodes if there isn't one available - and writeable for imports +SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" +touch $SECRETKEYRING +GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" + +# now create the trustdb with an (empty) dummy keyring +$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING +# and make sure that gpg isn't trying to update the file +GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" + GPG="$GPG_CMD" MASTER_KEYRING="" -- cgit v1.2.3 From 59f46f3ace16e769383a61ee336a76c6d03931ea Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:33:37 +0200 Subject: do not double-slash paths in apt-key Closes: 665411 --- cmdline/apt-key | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index e010e6e90..7038be265 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -203,7 +203,12 @@ if [ -z "$TRUSTEDFILE" ]; then TRUSTEDPARTS="/etc/apt/trusted.gpg.d" eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) if [ -d "$TRUSTEDPARTS" ]; then - for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do + # strip / suffix as gpg will double-slash in that case (#665411) + STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}" + if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then + TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS" + fi + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do GPG="$GPG --keyring $trusted" done fi -- cgit v1.2.3 From 80f3aeb04d043356bd98de7714fc164b3fff3861 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:36:52 +0200 Subject: make the keyring locations in apt-key configurable Might come in handy for more than just a simple testcase. --- cmdline/apt-key | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index 7038be265..a9cbea55c 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -26,12 +26,16 @@ GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" MASTER_KEYRING="" -ARCHIVE_KEYRING_URI="" #MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg +eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) +ARCHIVE_KEYRING_URI="" #ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg +eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg +eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg +eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) requires_root() { if [ "$(id -u)" -ne 0 ]; then -- cgit v1.2.3 From 04937adc655ceda0b3367f540e76df10296cfba1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 16:19:37 +0200 Subject: let apt-key del work better with softlink and single key keyrings Having fragement files means there is a good chance that there is one key per keyring, so deal with that as well as with setups in which keyrings are linked into trusted.gpg.d as we can't just modify those files (they might be in /usr for example). --- cmdline/apt-key | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) (limited to 'cmdline/apt-key') diff --git a/cmdline/apt-key b/cmdline/apt-key index a9cbea55c..713a41c07 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -151,6 +151,60 @@ update() { fi } +remove_key_from_keyring() { + local GPG="$GPG_CMD --keyring $1" + # check if the key is in this keyring: the key id is in the 5 column at the end + if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then + return + fi + if [ ! -w "$1" ]; then + echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only." + return + fi + # check if it is the only key in the keyring and if so remove the keyring alltogether + if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then + mv -f "$1" "${1}~" # 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 "$1" ]; then + REALTARGET="$(readlink -f "$1")" + mv -f "$1" "${1}.dpkg-tmp" + cp -a "$REALTARGET" "$1" + ls "$(dirname $1)" + fi + # delete the key from the keyring + $GPG --batch --delete-key --yes "$2" + if [ -n "$REALTARGET" ]; then + # the real backup is the old link, not the copy we made + mv -f "${1}.dpkg-tmp" "${1}~" + fi +} + +remove_key() { + requires_root + + # if a --keyring was given, just remove from there + if [ -n "$FORCED_KEYRING" ]; then + remove_key_from_keyring "$FORCED_KEYRING" "$1" + else + # otherwise all known keyrings are up for inspection + local TRUSTEDFILE="/etc/apt/trusted.gpg" + eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) + eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) + remove_key_from_keyring "$TRUSTEDFILE" "$1" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do + remove_key_from_keyring "$trusted" "$1" + done + fi + fi + echo "OK" +} + usage() { echo "Usage: apt-key [--keyring file] [command] [arguments]" @@ -175,6 +229,7 @@ while [ -n "$1" ]; do --keyring) shift TRUSTEDFILE="$1" + FORCED_KEYRING="$1" if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" else @@ -239,10 +294,8 @@ case "$command" in echo "OK" ;; del|rm|remove) - requires_root init_keyring "$TRUSTEDFILE" - $GPG --quiet --batch --delete-key --yes "$1" - echo "OK" + remove_key "$1" ;; update) init_keyring "$TRUSTEDFILE" -- cgit v1.2.3