From 1ffbdfc48b0a5ba17bf7419c0d61c2d34d96f281 Mon Sep 17 00:00:00 2001 From: Tobias Powalowski Date: Thu, 13 Nov 2014 08:25:02 +0100 Subject: [PATCH] fix pacman-key until pacman has fix for gnupg issue --- usr/lib/initcpio/install/arch_base | 5 +- usr/share/archboot/pacman/usr/bin/pacman-key | 821 +++++++++++++++++++ 2 files changed, 825 insertions(+), 1 deletion(-) create mode 100644 usr/share/archboot/pacman/usr/bin/pacman-key diff --git a/usr/lib/initcpio/install/arch_base b/usr/lib/initcpio/install/arch_base index a76c8e443..58d5bb4db 100644 --- a/usr/lib/initcpio/install/arch_base +++ b/usr/lib/initcpio/install/arch_base @@ -176,11 +176,14 @@ build () add_file "/usr/share/archboot/base/etc/sysctl.d/99-sysctl.conf" "/etc/sysctl.d/99-sysctl.conf" ### add pacman - apps="pacman pacman-db-upgrade pacman-key pacsort pactree cleanupdelta makepkg pacman-optimize pkgdelta \ + apps="pacman pacman-db-upgrade pacsort pactree cleanupdelta makepkg pacman-optimize pkgdelta \ rankmirrors repo-add testdb repo-elephant testpkg vercmp curl gpg-agent haveged" for i in $apps; do add_binary "$i" done + ### HACK until pacman-key is fixed for gnupg-2.1.x, readd to array above when fixed! + add_binary "/usr/share/archboot/pacman/usr/bin/pacman-key" "/usr/bin/pacman-key" + symlinks="/usr/bin/gpg /usr/bin/repo-remove" for i in $symlinks; do # echo "Checking $i" diff --git a/usr/share/archboot/pacman/usr/bin/pacman-key b/usr/share/archboot/pacman/usr/bin/pacman-key new file mode 100644 index 000000000..59e252fba --- /dev/null +++ b/usr/share/archboot/pacman/usr/bin/pacman-key @@ -0,0 +1,821 @@ +#!/usr/bin/bash +# +# pacman-key - manages pacman's keyring +# Based on apt-key, from Debian +# Generated from pacman-key.sh.in; do not edit by hand. +# +# Copyright (c) 2010-2013 Pacman Development Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# gettext initialization +export TEXTDOMAIN='pacman-scripts' +export TEXTDOMAINDIR='/usr/share/locale' + +declare -r myver="4.1.2" + +# Options +ADD=0 +DELETE=0 +EDITKEY=0 +EXPORT=0 +FINGER=0 +IMPORT=0 +IMPORT_TRUSTDB=0 +INIT=0 +KEYSERVER='' +LISTKEYS=0 +LISTSIGS=0 +LSIGNKEY=0 +POPULATE=0 +RECEIVE=0 +REFRESH=0 +UPDATEDB=0 +USE_COLOR='y' +VERIFY=0 + +DEFAULT_KEYSERVER='hkp://pool.sks-keyservers.net' + +plain() { + (( QUIET )) && return + local mesg=$1; shift + printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 +} + +msg() { + (( QUIET )) && return + local mesg=$1; shift + printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 +} + +msg2() { + (( QUIET )) && return + local mesg=$1; shift + printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 +} + +ask() { + local mesg=$1; shift + printf "${BLUE}::${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}" "$@" >&1 +} + +warning() { + local mesg=$1; shift + printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 +} + +error() { + local mesg=$1; shift + printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 +} + + +# getopt-like parser +parseopts() { + local opt= optarg= i= shortopts=$1 + local -a longopts=() unused_argv=() + + shift + while [[ $1 && $1 != '--' ]]; do + longopts+=("$1") + shift + done + shift + + longoptmatch() { + local o longmatch=() + for o in "${longopts[@]}"; do + if [[ ${o%:} = "$1" ]]; then + longmatch=("$o") + break + fi + [[ ${o%:} = "$1"* ]] && longmatch+=("$o") + done + + case ${#longmatch[*]} in + 1) + # success, override with opt and return arg req (0 == none, 1 == required) + opt=${longmatch%:} + if [[ $longmatch = *: ]]; then + return 1 + else + return 0 + fi ;; + 0) + # fail, no match found + return 255 ;; + *) + # fail, ambiguous match + printf "pacman-key: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1" + printf " '%s'" "${longmatch[@]%:}" + printf '\n' + return 254 ;; + esac >&2 + } + + while (( $# )); do + case $1 in + --) # explicit end of options + shift + break + ;; + -[!-]*) # short option + for (( i = 1; i < ${#1}; i++ )); do + opt=${1:i:1} + + # option doesn't exist + if [[ $shortopts != *$opt* ]]; then + printf "pacman-key: $(gettext "invalid option") -- '%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + fi + + OPTRET+=("-$opt") + # option requires optarg + if [[ $shortopts = *$opt:* ]]; then + # if we're not at the end of the option chunk, the rest is the optarg + if (( i < ${#1} - 1 )); then + OPTRET+=("${1:i+1}") + break + # if we're at the end, grab the the next positional, if it exists + elif (( i == ${#1} - 1 )) && [[ $2 ]]; then + OPTRET+=("$2") + shift + break + # parse failure + else + printf "pacman-key: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + fi + fi + done + ;; + --?*=*|--?*) # long option + IFS='=' read -r opt optarg <<< "${1#--}" + longoptmatch "$opt" + case $? in + 0) + # parse failure + if [[ $optarg ]]; then + printf "pacman-key: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2 + OPTRET=(--) + return 1 + # --longopt + else + OPTRET+=("--$opt") + fi + ;; + 1) + # --longopt=optarg + if [[ $optarg ]]; then + OPTRET+=("--$opt" "$optarg") + # --longopt optarg + elif [[ $2 ]]; then + OPTRET+=("--$opt" "$2" ) + shift + # parse failure + else + printf "pacman-key: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2 + OPTRET=(--) + return 1 + fi + ;; + 254) + # ambiguous option -- error was reported for us by longoptmatch() + OPTRET=(--) + return 1 + ;; + 255) + # parse failure + printf "pacman-key: $(gettext "invalid option") '--%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + ;; + esac + ;; + *) # non-option arg encountered, add it as a parameter + unused_argv+=("$1") + ;; + esac + shift + done + + # add end-of-opt terminator and any leftover positional parameters + OPTRET+=('--' "${unused_argv[@]}" "$@") + unset longoptmatch + + return 0 +} + + +usage() { + printf "pacman-key (pacman) %s\n" ${myver} + echo + printf -- "$(gettext "Usage: %s [options] operation [targets]")\n" $(basename $0) + echo + printf -- "$(gettext "Manage pacman's list of trusted keys")\n" + echo + printf -- "$(gettext "Operations:")\n" + printf -- "$(gettext " -a, --add Add the specified keys (empty for stdin)")\n" + printf -- "$(gettext " -d, --delete Remove the specified keyids")\n" + printf -- "$(gettext " -e, --export Export the specified or all keyids")\n" + printf -- "$(gettext " -f, --finger List fingerprint for specified or all keyids")\n" + printf -- "$(gettext " -l, --list-keys List the specified or all keys")\n" + printf -- "$(gettext " -r, --recv-keys Fetch the specified keyids")\n" + printf -- "$(gettext " -u, --updatedb Update the trustdb of pacman")\n" + printf -- "$(gettext " -v, --verify Verify the file(s) specified by the signature(s)")\n" + printf -- "$(gettext " --edit-key Present a menu for key management task on keyids")\n" + printf -- "$(gettext " --import Imports pubring.gpg from dir(s)")\n" + printf -- "$(gettext " --import-trustdb Imports ownertrust values from trustdb.gpg in dir(s)")\n" + printf -- "$(gettext " --init Ensure the keyring is properly initialized")\n" + printf -- "$(gettext " --list-sigs List keys and their signatures")\n" + printf -- "$(gettext " --lsign-key Locally sign the specified keyid")\n" + printf -- "$(gettext " --populate Reload the default keys from the (given) keyrings\n\ + in '%s'")\n" "/usr/share/pacman/keyrings" + printf -- "$(gettext " --refresh-keys Update specified or all keys from a keyserver")\n" + echo + printf -- "$(gettext "Options:")\n" + printf -- "$(gettext " --config Use an alternate config file (instead of\n\ + '%s')")\n" "/etc/pacman.conf" + printf -- "$(gettext " --gpgdir Set an alternate directory for GnuPG (instead\n\ + of '%s')")\n" "/etc/pacman.d/gnupg" + printf -- "$(gettext " --keyserver Specify a keyserver to use if necessary")\n" + echo + printf -- "$(gettext " -h, --help Show this help message and exit")\n" + printf -- "$(gettext " -V, --version Show program version")\n" +} + +version() { + printf "pacman-key (pacman) %s\n" "${myver}" + printf -- "$(gettext "\ +Copyright (c) 2010-2013 Pacman Development Team .\n\ +This is free software; see the source for copying conditions.\n\ +There is NO WARRANTY, to the extent permitted by law.\n")" +} + +# read the config file "$1" which has key=value pairs, and return the key which +# matches "$2". the equals sign between pairs may be surrounded by any amount +# of whitespace. Optionally, "$3" can be specified which is the default value +# when no key is found. +get_from() { + while IFS='=' read -r key value; do + [[ -z $key || ${key:0:1} = '#' ]] && continue + + if [[ ${key%% *} = "$2" && -n ${value##* } ]]; then + echo "${value##* }" + return 0 + fi + done < "$1" + if [[ -n "$3" ]]; then + printf '%s\n' "$3" + return 0 + fi + return 1 +} + +key_lookup_from_name() { + local ids + + mapfile -t ids < \ + <("${GPG_PACMAN[@]}" --search-keys --batch --with-colons "$1" 2>/dev/null | + awk -F: '$1 == "pub" { print $2 }') + + # only return success on non-ambiguous lookup + case ${#ids[*]} in + 0) + error "$(gettext "Failed to lookup key by name:") %s" "$name" + return 1 + ;; + 1) + printf '%s' "${ids[0]}" + return 0 + ;; + *) + error "$(gettext "Key name is ambiguous:") %s" "$name" + return 1 + ;; + esac +} + +generate_master_key() { + # Generate the master key, which will be in both pubring and secring + "${GPG_PACMAN[@]}" --gen-key --batch </dev/null; then + printf '%s\n' "$*" >> "$conffile" + fi +} + +check_keyids_exist() { + local ret=0 + for key in "$@"; do + # Verify if the key exists in pacman's keyring + if ! "${GPG_PACMAN[@]}" --list-keys "$key" &>/dev/null ; then + error "$(gettext "The key identified by %s could not be found locally.")" "$key" + ret=1 + fi + done + if (( ret )); then + exit 1 + fi +} + +initialize() { + local conffile keyserv + # Check for simple existence rather than for a directory as someone + # may want to use a symlink here + [[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir -p -m 755 "${PACMAN_KEYRING_DIR}" + + # keyring files + [[ -f ${PACMAN_KEYRING_DIR}/pubring.gpg ]] || touch ${PACMAN_KEYRING_DIR}/pubring.gpg + [[ -f ${PACMAN_KEYRING_DIR}/secring.gpg ]] || touch ${PACMAN_KEYRING_DIR}/secring.gpg + [[ -f ${PACMAN_KEYRING_DIR}/trustdb.gpg ]] || "${GPG_PACMAN[@]}" --update-trustdb + chmod 644 ${PACMAN_KEYRING_DIR}/{pubring,trustdb}.gpg + chmod 600 ${PACMAN_KEYRING_DIR}/secring.gpg + + # gpg.conf + conffile="${PACMAN_KEYRING_DIR}/gpg.conf" + [[ -f $conffile ]] || touch "$conffile" + chmod 644 "$conffile" + add_gpg_conf_option "$conffile" 'no-greeting' + add_gpg_conf_option "$conffile" 'no-permission-warning' + add_gpg_conf_option "$conffile" 'lock-never' + keyserv=${KEYSERVER:-$DEFAULT_KEYSERVER} + add_gpg_conf_option "$conffile" 'keyserver' "$keyserv" + add_gpg_conf_option "$conffile" 'keyserver-options' 'timeout=10' + + # set up a private signing key (if none available) + if [[ $(secret_keys_available) -lt 1 ]]; then + generate_master_key + UPDATEDB=1 + fi +} + +check_keyring() { + if [[ ! -r ${PACMAN_KEYRING_DIR}/pubring.gpg || \ + ! -r ${PACMAN_KEYRING_DIR}/trustdb.gpg ]]; then + error "$(gettext "You do not have sufficient permissions to read the %s keyring.")" "pacman" + msg "$(gettext "Use '%s' to correct the keyring permissions.")" "pacman-key --init" + exit 1 + fi + + if (( (EXPORT || FINGER || LIST || VERIFY) && EUID != 0 )); then + if ! grep -q "^[[:space:]]*lock-never[[:space:]]*$" ${PACMAN_KEYRING_DIR}/gpg.conf &>/dev/null; then + error "$(gettext "You do not have sufficient permissions to run this command.")" + msg "$(gettext "Use '%s' to correct the keyring permissions.")" "pacman-key --init" + exit 1 + fi + fi + + if (( LSIGNKEY )); then + if [[ $(secret_keys_available) -lt 1 ]]; then + error "$(gettext "There is no secret key available to sign with.")" + msg "$(gettext "Use '%s' to generate a default secret key.")" "pacman-key --init" + exit 1 + fi + fi +} + +populate_keyring() { + local KEYRING_IMPORT_DIR='/usr/share/pacman/keyrings' + + local keyring KEYRINGIDS=("$@") + local ret=0 + if (( ${#KEYRINGIDS[*]} == 0 )); then + # get list of all available keyrings + shopt -s nullglob + KEYRINGIDS=("$KEYRING_IMPORT_DIR"/*.gpg) + shopt -u nullglob + KEYRINGIDS=("${KEYRINGIDS[@]##*/}") + KEYRINGIDS=("${KEYRINGIDS[@]%.gpg}") + if (( ${#KEYRINGIDS[*]} == 0 )); then + error "$(gettext "No keyring files exist in %s.")" "$KEYRING_IMPORT_DIR" + ret=1 + fi + else + # verify listed keyrings exist + for keyring in "${KEYRINGIDS[@]}"; do + if [[ ! -f "$KEYRING_IMPORT_DIR/$keyring.gpg" ]]; then + error "$(gettext "The keyring file %s does not exist.")" "$KEYRING_IMPORT_DIR/$keyring.gpg" + ret=1 + fi + done + fi + + if (( ret )); then + exit 1 + fi + + # Variable used for iterating on keyrings + local keys key_id + + # Add keys from requested keyrings + for keyring in "${KEYRINGIDS[@]}"; do + msg "$(gettext "Appending keys from %s.gpg...")" "$keyring" + "${GPG_PACMAN[@]}" --quiet --import "${KEYRING_IMPORT_DIR}/${keyring}.gpg" + done + + # Read the trusted key IDs to an array. Because this is an ownertrust + # file, we know we have the full 40 hex digit fingerprint values. + # Format of ownertrust dump file: + # 40CHARFINGERPRINTXXXXXXXXXXXXXXXXXXXXXXX:6: + # 40CHARFINGERPRINTXXXXXXXXXXXXXXXXXXXXXXX:5: + local -A trusted_ids + for keyring in "${KEYRINGIDS[@]}"; do + if [[ -s "${KEYRING_IMPORT_DIR}/${keyring}-trusted" ]]; then + while IFS=: read key_id _; do + # skip blank lines, comments; these are valid in this file + [[ -z $key_id || ${key_id:0:1} = \# ]] && continue + + # Mark this key to be lsigned + trusted_ids[$key_id]=$keyring + done < "${KEYRING_IMPORT_DIR}/${keyring}-trusted" + fi + done + + if (( ${#trusted_ids[@]} > 0 )); then + msg "$(gettext "Locally signing trusted keys in keyring...")" + lsign_keys "${!trusted_ids[@]}" + msg "$(gettext "Importing owner trust values...")" + for keyring in "${KEYRINGIDS[@]}"; do + if [[ -s "${KEYRING_IMPORT_DIR}/${keyring}-trusted" ]]; then + "${GPG_PACMAN[@]}" --import-ownertrust "${KEYRING_IMPORT_DIR}/${keyring}-trusted" + fi + done + fi + + local -A revoked_ids + for keyring in "${KEYRINGIDS[@]}"; do + if [[ -s $KEYRING_IMPORT_DIR/$keyring-revoked ]]; then + while read -r key_id; do + revoked_ids["$key_id"]=1 + done <"$KEYRING_IMPORT_DIR/$keyring-revoked" + fi + done + + if (( ${#revoked_ids[@]} > 0 )); then + msg "$(gettext "Disabling revoked keys in keyring...")" + for key_id in "${!revoked_ids[@]}"; do + msg2 "$(gettext "Disabling key %s...")" "${key_id}" + printf 'disable\nquit\n' | LANG=C "${GPG_PACMAN[@]}" --command-fd 0 --quiet --batch --edit-key "${key_id}" 2>/dev/null + done + fi +} + +add_keys() { + if ! "${GPG_PACMAN[@]}" --quiet --batch --import "$@" ; then + error "$(gettext "A specified keyfile could not be added to the keyring.")" + exit 1 + fi +} + +delete_keys() { + check_keyids_exist "$@" + if ! "${GPG_PACMAN[@]}" --quiet --batch --delete-key --yes "$@" ; then + error "$(gettext "A specified key could not be removed from the keyring.")" + exit 1 + fi +} + +edit_keys() { + check_keyids_exist "$@" + local ret=0 + for key in "$@"; do + if ! "${GPG_PACMAN[@]}" --edit-key "$key" ; then + error "$(gettext "The key identified by %s could not be edited.")" "$key" + ret=1 + fi + done + if (( ret )); then + exit 1 + fi +} + +export_keys() { + check_keyids_exist "$@" + if ! "${GPG_PACMAN[@]}" --armor --export "$@" ; then + error "$(gettext "A specified key could not be exported from the keyring.")" + exit 1 + fi +} + +finger_keys() { + check_keyids_exist + if ! "${GPG_PACMAN[@]}" --batch --fingerprint "$@" ; then + error "$(gettext "The fingerprint of a specified key could not be determined.")" + exit 1 + fi +} + +import_trustdb() { + local importdir + local ret=0 + for importdir in "$@"; do + if [[ -f "${importdir}/trustdb.gpg" ]]; then + gpg --homedir "${importdir}" --export-ownertrust | \ + "${GPG_PACMAN[@]}" --import-ownertrust - + if (( PIPESTATUS )); then + error "$(gettext "%s could not be imported.")" "${importdir}/trustdb.gpg" + ret=1 + fi + else + error "$(gettext "File %s does not exist and could not be imported.")" "${importdir}/trustdb.gpg" + ret=1 + fi + done + if (( ret )); then + exit 1 + fi +} + +import() { + local importdir + local ret=0 + for importdir in "$@"; do + if [[ -f "${importdir}/pubring.gpg" ]]; then + if ! "${GPG_PACMAN[@]}" --quiet --batch --import "${importdir}/pubring.gpg" ; then + error "$(gettext "%s could not be imported.")" "${importdir}/pubring.gpg" + ret=1 + fi + else + error "$(gettext "File %s does not exist and could not be imported.")" "${importdir}/pubring.gpg" + ret=1 + fi + done + if (( ret )); then + exit 1 + fi +} + +list_keys() { + check_keyids_exist + if ! "${GPG_PACMAN[@]}" --batch --list-keys "$@" ; then + error "$(gettext "A specified key could not be listed.")" + exit 1 + fi +} + +list_sigs() { + check_keyids_exist + if ! "${GPG_PACMAN[@]}" --batch --list-sigs "$@" ; then + error "$(gettext "A specified signature could not be listed.")" + exit 1 + fi +} + +lsign_keys() { + check_keyids_exist + + local ret=0 + for key_id in "$@"; do + msg2 "$(gettext "Locally signing key %s...")" "${key_id}" + # we cannot use --yes here as gpg would still ask for confirmation if a key has more than one uid + printf 'y\ny\n' | LANG=C "${GPG_PACMAN[@]}" --command-fd 0 --quiet --batch --lsign-key "${key_id}" 2>/dev/null + if (( PIPESTATUS[1] )); then + error "$(gettext "%s could not be locally signed.")" "${key_id}" + ret=1 + fi + done + + if (( ret )); then + exit 1 + fi +} + +receive_keys() { + local name id keyids + + # if the key is not a hex ID, do a lookup + for name; do + if [[ $name = ?(0x)+([0-9a-fA-F]) ]]; then + keyids+=("$name") + else + if id=$(key_lookup_from_name "$name"); then + keyids+=("$id") + fi + fi + done + + (( ${#keyids[*]} > 0 )) || exit 1 + + if ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then + error "$(gettext "Remote key not fetched correctly from keyserver.")" + exit 1 + fi +} + +refresh_keys() { + check_keyids_exist "$@" + if ! "${GPG_PACMAN[@]}" --refresh-keys "$@" ; then + error "$(gettext "A specified local key could not be updated from a keyserver.")" + exit 1 + fi +} + +verify_sig() { + local ret=0 + for sig; do + msg "Checking %s ..." "$sig" + if ! "${GPG_PACMAN[@]}" --status-fd 1 --verify "$sig" | grep -qE 'TRUST_(FULLY|ULTIMATE)'; then + error "$(gettext "The signature identified by %s could not be verified.")" "$sig" + ret=1 + fi + done + exit $ret +} + +updatedb() { + msg "$(gettext "Updating trust database...")" + if ! "${GPG_PACMAN[@]}" --batch --check-trustdb ; then + error "$(gettext "Trust database could not be updated.")" + exit 1 + fi +} + +# PROGRAM START +if ! type gettext &>/dev/null; then + gettext() { + echo "$@" + } +fi + +OPT_SHORT="adefhlruvV" +OPT_LONG=('add' 'config:' 'delete' 'edit-key' 'export' 'finger' 'gpgdir:' + 'help' 'import' 'import-trustdb' 'init' 'keyserver:' 'list-keys' 'list-sigs' + 'lsign-key' 'nocolor' 'populate' 'recv-keys' 'refresh-keys' 'updatedb' + 'verify' 'version') +if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then + exit 1 # E_INVALID_OPTION; +fi +set -- "${OPTRET[@]}" +unset OPT_SHORT OPT_LONG OPTRET + +if [[ $1 == "--" ]]; then + usage; + exit 0; +fi + +while (( $# )); do + case $1 in + -a|--add) ADD=1 UPDATEDB=1 ;; + --config) shift; CONFIG=$1 ;; + -d|--delete) DELETE=1 UPDATEDB=1 ;; + --edit-key) EDITKEY=1 UPDATEDB=1 ;; + -e|--export) EXPORT=1 ;; + -f|--finger) FINGER=1 ;; + --gpgdir) shift; PACMAN_KEYRING_DIR=$1 ;; + --import) IMPORT=1 UPDATEDB=1 ;; + --import-trustdb) IMPORT_TRUSTDB=1 UPDATEDB=1 ;; + --init) INIT=1 ;; + --keyserver) shift; KEYSERVER=$1 ;; + -l|--list-keys) LISTKEYS=1 ;; + --list-sigs) LISTSIGS=1 ;; + --lsign-key) LSIGNKEY=1 UPDATEDB=1 ;; + --nocolor) USE_COLOR='n';; + --populate) POPULATE=1 UPDATEDB=1 ;; + -r|--recv-keys) RECEIVE=1 UPDATEDB=1 ;; + --refresh-keys) REFRESH=1 ;; + -u|--updatedb) UPDATEDB=1 ;; + -v|--verify) VERIFY=1 ;; + + -h|--help) usage; exit 0 ;; + -V|--version) version; exit 0 ;; + + --) shift; break 2 ;; + esac + shift +done + +# check if messages are to be printed using color +unset ALL_OFF BOLD BLUE GREEN RED YELLOW +if [[ -t 2 && ! $USE_COLOR = "n" ]]; then + # prefer terminal safe colored and bold text when tput is supported + if tput setaf 0 &>/dev/null; then + ALL_OFF="$(tput sgr0)" + BOLD="$(tput bold)" + BLUE="${BOLD}$(tput setaf 4)" + GREEN="${BOLD}$(tput setaf 2)" + RED="${BOLD}$(tput setaf 1)" + YELLOW="${BOLD}$(tput setaf 3)" + else + ALL_OFF="\e[1;0m" + BOLD="\e[1;1m" + BLUE="${BOLD}\e[1;34m" + GREEN="${BOLD}\e[1;32m" + RED="${BOLD}\e[1;31m" + YELLOW="${BOLD}\e[1;33m" + fi +fi +readonly ALL_OFF BOLD BLUE GREEN RED YELLOW + + +if ! type -p gpg >/dev/null; then + error "$(gettext "Cannot find the %s binary required for all %s operations.")" "gpg" "pacman-key" + exit 1 +fi + +if (( (ADD || DELETE || EDITKEY || IMPORT || IMPORT_TRUSTDB || INIT || LSIGNKEY || POPULATE || RECEIVE || REFRESH || UPDATEDB) && EUID != 0 )); then + error "$(gettext "%s needs to be run as root for this operation.")" "pacman-key" + exit 1 +fi + +CONFIG=${CONFIG:-/etc/pacman.conf} +if [[ ! -r "${CONFIG}" ]]; then + error "$(gettext "%s configuration file '%s' not found.")" "pacman" "$CONFIG" + exit 1 +fi + +# if PACMAN_KEYRING_DIR isn't assigned, try to get it from the config +# file, falling back on a hard default +PACMAN_KEYRING_DIR=${PACMAN_KEYRING_DIR:-$(get_from "$CONFIG" "GPGDir" "/etc/pacman.d/gnupg")} + +GPG_PACMAN=(gpg --homedir "${PACMAN_KEYRING_DIR}" --no-permission-warning) +if [[ -n ${KEYSERVER} ]]; then + GPG_PACMAN+=(--keyserver "${KEYSERVER}") +fi + +# check only a single operation has been given +# don't include UPDATEDB in here as other opts can induce it +numopt=$(( ADD + DELETE + EDITKEY + EXPORT + FINGER + IMPORT + IMPORT_TRUSTDB + + INIT + LISTKEYS + LISTSIGS + LSIGNKEY + POPULATE + RECEIVE + REFRESH + VERIFY )) + +case $numopt in + 0) + if (( ! UPDATEDB )); then + error "$(gettext "no operation specified (use -h for help)")" + exit 1 + fi + ;; + [!1]) + error "$(gettext "Multiple operations specified.")" + msg "$(gettext "Please run %s with each operation separately.")" "pacman-key" + exit 1 + ;; +esac + +# check for targets where needed +if (( (ADD || DELETE || EDIT || IMPORT || IMPORT_TRUSTDB || + LSIGNKEY || RECEIVE || VERIFY) && $# == 0 )); then + error "$(gettext "No targets specified")" + exit 1 +fi + +(( ! INIT )) && check_keyring + +(( ADD )) && add_keys "$@" +(( DELETE )) && delete_keys "$@" +(( EDITKEY )) && edit_keys "$@" +(( EXPORT )) && export_keys "$@" +(( FINGER )) && finger_keys "$@" +(( IMPORT )) && import "$@" +(( IMPORT_TRUSTDB)) && import_trustdb "$@" +(( INIT )) && initialize +(( LISTKEYS )) && list_keys "$@" +(( LISTSIGS )) && list_sigs "$@" +(( LSIGNKEY )) && lsign_keys "$@" +(( POPULATE )) && populate_keyring "$@" +(( RECEIVE )) && receive_keys "$@" +(( REFRESH )) && refresh_keys "$@" +(( VERIFY )) && verify_sig "$@" + +(( UPDATEDB )) && updatedb + +exit 0 + +# vim: set ts=2 sw=2 noet: