summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2014-01-24 22:40:52 +0100
committerDavid Kalnischkies <david@kalnischkies.de>2014-09-27 00:12:14 +0200
commit5beb682d2de2003e1c022cb298d6c2ec0cf91c0d (patch)
tree620843b17c01c27830b55c4d6868c4e44a411e7e
parent4b30c1dc053278a6b9bdb50f0d91b3f934e8613d (diff)
merge fragment keyrings in apt-key to avoid hitting gpg limits
gnupg has a hardlimit of 40 (at the moment) keyrings per invocation, which can be exceeded with (many) repositories. That is rather misfortune as the longrun goal was to drop gnupg dependency at some point in the future, but this can now be considered missed and dropped. It also means that 'apt-key adv' commands might not have the behaviour one would expect it to have as it mainly operates on a big temporary keyring, so commands modifying keys will break. Doing this was never a good idea anyway through, so lets just hope nothing break too badly. Closes: 733028
-rw-r--r--cmdline/apt-key.in134
1 files changed, 77 insertions, 57 deletions
diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in
index 9adbd6443..9d8e60ec0 100644
--- a/cmdline/apt-key.in
+++ b/cmdline/apt-key.in
@@ -23,7 +23,6 @@ GPG_CMD="$GPG_CMD --homedir $GPGHOMEDIR"
$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING >/dev/null 2>&1
# tell gpg that it shouldn't try to maintain a trustdb file
GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
-
GPG="$GPG_CMD"
APT_DIR="/"
@@ -113,7 +112,6 @@ net_update() {
echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set"
exit 1
fi
- requires_root
# in theory we would need to depend on wget for this, but this feature
# isn't useable in debian anyway as we have no keyring uri nor a master key
if ! which wget >/dev/null 2>&1; then
@@ -145,7 +143,6 @@ update() {
echo >&2 "Is the &keyring-package; package installed?"
exit 1
fi
- requires_root
# add new keys from the package;
@@ -158,11 +155,8 @@ update() {
if [ -r "$REMOVED_KEYS" ]; then
# remove no-longer supported/used keys
- keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5`
- for key in $keys; do
- if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then
- $GPG --quiet --batch --delete-key --yes ${key}
- fi
+ $GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5 | while read key; do
+ foreach_keyring_do 'remove_key_from_keyring' "$key"
done
else
echo >&2 "Warning: removed keys keyring $REMOVED_KEYS missing or not readable"
@@ -172,12 +166,17 @@ update() {
remove_key_from_keyring() {
local KEYRINGFILE="$1"
shift
+ # non-existent keyrings have by definition no keys
+ if [ ! -e "$KEYRINGFILE" ]; then
+ return
+ fi
+
local GPG="$GPG_CMD --keyring $KEYRINGFILE"
while [ -n "$1" ]; do
local KEY="$1"
shift
# 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]\+${KEY}:"; then
+ if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]*${KEY}:"; then
continue
fi
if [ ! -w "$KEYRINGFILE" ]; then
@@ -205,12 +204,6 @@ remove_key_from_keyring() {
done
}
-remove_key() {
- requires_root
- foreach_keyring_do 'remove_key_from_keyring' "$@"
- aptkey_echo "OK"
- }
-
foreach_keyring_do() {
local ACTION="$1"
shift
@@ -219,20 +212,62 @@ foreach_keyring_do() {
$ACTION "$FORCED_KEYRING" "$@"
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)
- $ACTION "$TRUSTEDFILE" "$@"
+ if [ -s "$TRUSTEDFILE" ]; then
+ $ACTION "$TRUSTEDFILE" "$@"
+ fi
local TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
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 $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
- $ACTION "$trusted" "$@"
+ if [ -s "$trusted" ]; then
+ $ACTION "$trusted" "$@"
+ fi
done
fi
fi
}
+list_keys_from_keyring() {
+ local KEYRINGFILE="$1"
+ shift
+ # don't show the error message if this keyring doesn't include the key
+ $GPG_CMD --keyring "$KEYRINGFILE" --batch --list-keys "$@" 2>/dev/null || true
+}
+
+fingerprint_keys_from_keyring() {
+ local KEYRINGFILE="$1"
+ shift
+ # don't show the error message if this keyring doesn't include the fingerprint
+ $GPG_CMD --keyring "$KEYRINGFILE" --batch --fingerprint "$@" 2>/dev/null || true
+}
+
+import_keys_from_keyring() {
+ local IMPORT="$1"
+ local KEYRINGFILE="$2"
+ $GPG_CMD --keyring "$KEYRINGFILE" --batch --import "$IMPORT" >/dev/null 2>&1
+}
+
+setup_merged_keyring() {
+ local TRUSTEDFILE_BAK="$TRUSTEDFILE"
+ TRUSTEDFILE='/dev/null'
+ foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
+ TRUSTEDFILE="$TRUSTEDFILE_BAK"
+ # mark it as non-writeable so users get errors if gnupg tries to modify it
+ if [ -s "${GPGHOMEDIR}/trusted.gpg" ]; then
+ chmod -w "${GPGHOMEDIR}/trusted.gpg"
+ GPG="$GPG --keyring ${GPGHOMEDIR}/trusted.gpg"
+ fi
+ if [ -r "$TRUSTEDFILE" ]; then
+ GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
+ fi
+}
+
+
usage() {
echo "Usage: apt-key [--keyring file] [command] [arguments]"
echo
@@ -257,12 +292,6 @@ while [ -n "$1" ]; do
shift
TRUSTEDFILE="$1"
FORCED_KEYRING="$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)
@@ -286,22 +315,6 @@ 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"
- GPG="$GPG --primary-keyring $TRUSTEDFILE"
- fi
- TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
- eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
- if [ -d "$TRUSTEDPARTS" ]; then
- # 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
fi
command="$1"
@@ -323,40 +336,47 @@ if [ "$command" != "help" ]; then
if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
touch -- "$TRUSTEDFILE"
chmod 0644 -- "$TRUSTEDFILE"
- GPG="$GPG --keyring $TRUSTEDFILE"
- GPG="$GPG --primary-keyring $TRUSTEDFILE"
fi
fi
fi
case "$command" in
add)
- requires_root
- $GPG --quiet --batch --import "$@"
- aptkey_echo "OK"
+ requires_root
+ setup_merged_keyring
+ $GPG --quiet --batch --import "$@"
+ aptkey_echo "OK"
;;
del|rm|remove)
- remove_key "$@"
+ requires_root
+ foreach_keyring_do 'remove_key_from_keyring' "$@"
+ aptkey_echo "OK"
;;
update)
+ requires_root
+ setup_merged_keyring
update
;;
net-update)
+ requires_root
+ setup_merged_keyring
net_update
;;
list)
- $GPG --batch --list-keys "$@"
- ;;
+ foreach_keyring_do 'list_keys_from_keyring' "$@"
+ ;;
finger*)
- $GPG --batch --fingerprint "$@"
- ;;
+ foreach_keyring_do 'fingerprint_keys_from_keyring' "$@"
+ ;;
export|exportall)
- $GPG --armor --export "$@"
- ;;
+ foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/trusted.gpg"
+ $GPG_CMD --keyring "${GPGHOMEDIR}/trusted.gpg" --armor --export "$@"
+ ;;
adv*)
- aptkey_echo "Executing: $GPG $*"
- $GPG "$@"
- ;;
+ setup_merged_keyring
+ aptkey_echo "Executing: $GPG $*"
+ $GPG "$@"
+ ;;
help)
usage
;;