diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/pacman-key.sh.in | 141 | 
1 files changed, 99 insertions, 42 deletions
| diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index 3efcb177..0f558a9c 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -85,45 +85,120 @@ This is free software; see the source for copying conditions.\n\  There is NO WARRANTY, to the extent permitted by law.\n")"  } +find_config() { +	# Prints on stdin the values of all the options from the configuration file that +	# are associated with the first parameter of this function. +	# The option names are stripped +	grep -e "^[[:blank:]]*$1[[:blank:]]*=.*" "$CONFIG" | cut -d= -f 2- +} +  reload_keyring() {  	local PACMAN_SHARE_DIR='@prefix@/share/pacman'  	local GPG_NOKEYRING="gpg --batch --quiet --ignore-time-conflict --no-options --no-default-keyring --homedir ${PACMAN_KEYRING_DIR}" -	# Read-only keyring with keys to be added to the keyring +	# Variable used for iterating on keyrings +	local key +	local key_id + +	# Keyring with keys to be added to the keyring  	local ADDED_KEYS="${PACMAN_SHARE_DIR}/addedkeys.gpg" -	# Read-only list of keys removed from the keyring. +	# Keyring with keys that were deprecated and will eventually be deleted +	local DEPRECATED_KEYS="${PACMAN_SHARE_DIR}/deprecatedkeys.gpg" + +	# List of keys removed from the keyring. This file is not a keyring, unlike the others. +	# It is a textual list of values that gpg recogniezes as identifiers for keys.  	local REMOVED_KEYS="${PACMAN_SHARE_DIR}/removedkeys" -	# Add keys from the current set of keys from pacman-keyring package. The web of trust will -	# be updated automatically. +	# Verify signatures of related files, if they exist  	if [[ -r "${ADDED_KEYS}" ]]; then  		msg "$(gettext "Verifying official keys file signature...")" -		if ! ${GPG_PACMAN} --quiet --verify "${ADDED_KEYS}.sig" 1>/dev/null; then +		if ! ${GPG_PACMAN} --quiet --batch --verify "${ADDED_KEYS}.sig" 1>/dev/null; then  			error "$(gettext "The signature of file %s is not valid.")" "${ADDED_KEYS}"  			exit 1  		fi +	fi -		msg "$(gettext "Appending official keys...")" -		local add_keys=$(${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5) -		for key in ${add_keys}; do -			msg "$(gettext "  key id: %s")" "$key" -			${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --export "${key}" | ${GPG_PACMAN} --import -		done +	if [[ -r "${DEPRECATED_KEYS}" ]]; then +		msg "$(gettext "Verifying deprecated keys file signature...")" +		if ! ${GPG_PACMAN} --quiet --batch --verify "${DEPRECATED_KEYS}.sig" 1>/dev/null; then +			error "$(gettext "The signature of file %s is not valid.")" "${DEPRECATED_KEYS}" +			exit 1 +		fi  	fi -	# Remove the keys from REMOVED_KEYS keyring  	if [[ -r "${REMOVED_KEYS}" ]]; then  		msg "$(gettext "Verifying deleted keys file signature...")" -		if ! ${GPG_PACMAN} --quiet --verify "${REMOVED_KEYS}.sig"; then +		if ! ${GPG_PACMAN} --quiet --batch --verify "${REMOVED_KEYS}.sig"; then  			error "$(gettext "The signature of file %s is not valid.")" "${REMOVED_KEYS}"  			exit 1  		fi +	fi + +	# Read the key ids to an array. The conversion from whatever is inside the file +	# to key ids is important, because key ids are the only guarantee of identification +	# for the keys. +	local -A removed_ids +	if [[ -r "${REMOVED_KEYS}" ]]; then +		while read key; do +			local key_values name +			key_values=$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5,10 --output-delimiter=' ') +			if [[ -n $key_values ]]; then +				# The first word is the key_id +				key_id=${key_values%% *} +				# the rest if the name of the owner +				name=${key_values#* } +				if [[ -n ${key_id} ]]; then +					# Mark this key to be deleted +					removed_ids[$key_id]="$name" +				fi +			fi +		done < "${REMOVED_KEYS}" +	fi + +	# List of keys that must be kept installed, even if in the list of keys to be removed +	local HOLD_KEYS=$(find_config "HoldKeys") + +	# Remove the keys that must be kept from the set of keys that should be removed +	if [[ -n ${HOLD_KEYS} ]]; then +		for key in ${HOLD_KEYS}; do +			key_id=$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5) +			if [[ -n "${removed_ids[$key_id]}" ]]; then +				unset removed_ids[$key_id] +			fi +		done +	fi + +	# Add keys from the current set of keys from pacman-keyring package. The web of trust will +	# be updated automatically. +	if [[ -r "${ADDED_KEYS}" ]]; then +		msg "$(gettext "Appending official keys...")" +		local add_keys=$(${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5) +		for key_id in ${add_keys}; do +			# There is no point in adding a key that will be deleted right after +			if [[ -z "${removed_ids[$key_id]}" ]]; then +				${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import +			fi +		done +	fi + +	if [[ -r "${DEPRECATED_KEYS}" ]]; then +		msg "$(gettext "Appending deprecated keys...")" +		local add_keys=$(${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5) +		for key_id in ${add_keys}; do +			# There is no point in adding a key that will be deleted right after +			if [[ -z "${removed_ids[$key_id]}" ]]; then +				${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import +			fi +		done +	fi +	# Remove the keys not marked to keep +	if (( ${#removed_ids[@]} > 0 )); then  		msg "$(gettext "Removing deleted keys from keyring...")" -		cat "${REMOVED_KEYS}" | while read key; do -			msg "$(gettext "  key id: %s")" "$key" -			${GPG_PACMAN} --quiet --batch --yes --delete-key "${key}" +		for key_id in "${!removed_ids[@]}"; do +			echo "  removing key $key_id - ${removed_ids[$key_id]}" +			${GPG_PACMAN} --quiet --batch --yes --delete-key "${key_id}"  		done  	fi @@ -169,8 +244,7 @@ fi  # Read GPGDIR from $CONFIG.  # The pattern is: any spaces or tabs, GPGDir, any spaces or tabs, equal sign  # and the rest of the line. The string is splitted after the first occurrence of = -if [[ GPGDIR=$(grep -e '^[[:blank:]]*GPGDir[[:blank:]]*=.*' "$CONFIG") == 0 ]]; then -  GPGDIR=${GPGDIR#*=} +if [[ GPGDIR=$(find_config "GPGDir") == 0 ]]; then  	PACMAN_KEYRING_DIR="${GPGDIR}"  fi  GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR}" @@ -185,15 +259,8 @@ shift  case "${command}" in  	-a|--add) -		if (( $# == 0 )); then -			error "$(gettext "You need to specify at least one key identifier")" -			usage -			exit 1 -		fi -		while (( $# > 0 )); do -			${GPG_PACMAN} --quiet --batch --import "$1" -			shift -		done +		# If there is no extra parameter, gpg will read stdin +		${GPG_PACMAN} --quiet --batch --import "$@"  		;;  	-d|--del)  		if (( $# == 0 )); then @@ -201,10 +268,7 @@ case "${command}" in  			usage  			exit 1  		fi -		while (( $# > 0 )); do -			${GPG_PACMAN} --quiet --batch --delete-key --yes "$1" -			shift -		done +		${GPG_PACMAN} --quiet --batch --delete-key --yes "$@"  		;;  	-u|--updatedb)  		${GPG_PACMAN} --batch --check-trustdb @@ -213,20 +277,13 @@ case "${command}" in  		reload_keyring  		;;  	-l|--list) -		${GPG_PACMAN} --batch --list-sigs +		${GPG_PACMAN} --batch --list-sigs "$@"  		;;  	-f|--finger)  		${GPG_PACMAN} --batch --fingerprint $*  		;;  	-e|--export) -		if (( $# == 0 )); then -			${GPG_PACMAN} --armor --export -		else -			while (( $# > 0 )); do -				${GPG_PACMAN} --armor --export "$1" -				shift -			done -		fi +		${GPG_PACMAN} --armor --export "$@"  		;;  	-r|--receive)  		if (( $# < 2 )); then @@ -236,7 +293,7 @@ case "${command}" in  		fi  		keyserver="$1"  		shift -		${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys $* +		${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys "$@"  		;;  	-t|--trust)  		if (( $# == 0 )); then @@ -257,7 +314,7 @@ case "${command}" in  		;;  	--adv)  		msg "$(gettext "Executing: %s ")$*" "${GPG_PACMAN}" -		${GPG_PACMAN} $* || ret=$? +		${GPG_PACMAN} "$@" || ret=$?  		exit $ret  		;;  	--help) | 
