3 # pacman-key - manages pacman's keyring
4 # Based on apt-key, from Debian
7 # Copyright (c) 2010-2011 Pacman Development Team <pacman-dev@archlinux.org>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # gettext initialization
24 export TEXTDOMAIN
='pacman-scripts'
25 export TEXTDOMAINDIR
='@localedir@'
27 myver
="@PACKAGE_VERSION@"
40 m4_include
(library
/output_format.sh
)
42 m4_include
(library
/parse_options.sh
)
45 printf "pacman-key (pacman) %s\n" ${myver}
47 printf "$(gettext "Usage
: %s
[options
]")\n" $
(basename $0)
49 printf "$(gettext "Manage pacman
\'s list of trusted keys
")\n"
51 echo "$(gettext "Options
:")"
52 echo "$(gettext " -a, --add [<file(s
)>] Add the specified keys
(empty
for stdin
)")"
53 echo "$(gettext " -d, --delete <keyid
(s
)> Remove the specified keyids
")"
54 echo "$(gettext " -e, --export [<keyid
(s
)>] Export the specified or all keyids
")"
55 echo "$(gettext " -f, --finger [<keyid
(s
)>] List fingerprint
for specified or all keyids
")"
56 echo "$(gettext " -h, --help Show this
help message and
exit")"
57 echo "$(gettext " -l, --list List keys
")"
58 echo "$(gettext " -r, --receive <keyserver
> <keyid
(s
)> Fetch the specified keyids
")"
59 echo "$(gettext " -u, --updatedb Update the trustdb of pacman
")"
60 echo "$(gettext " -V, --version Show program version
")"
61 echo "$(gettext " --config <file> Use an alternate config
file")"
62 printf "$(gettext " (instead of
'%s')")\n" "@sysconfdir@/pacman.conf"
63 echo "$(gettext " --edit-key <keyid
(s
)> Present a menu
for key management task on keyids
")"
64 echo "$(gettext " --gpgdir <dir
> Set an alternate directory
for gnupg
")"
65 printf "$(gettext " (instead of
'%s')")\n" "@sysconfdir@/pacman.d/gnupg"
66 echo "$(gettext " --reload Reload the default keys
")"
70 printf "pacman-key (pacman) %s\n" "${myver}"
72 Copyright
(c
) 2010-2011 Pacman Development Team
<pacman-dev@archlinux.org
>.
\n\
73 This is free software
; see the
source for copying conditions.
\n\
74 There is NO WARRANTY
, to the extent permitted by law.
\n")"
77 # Read provided file and search for values matching the given key
78 # The contents of the file are expected to be in this format: key = value
79 # 'key', 'equal sign' and 'value' can be surrounded by random whitespace
80 # Usage: get_from "$file" "$key" # returns the value for the first matching key in the file
82 while read key _ value
; do
83 if [[ $key = $2 ]]; then
91 local PACMAN_SHARE_DIR
='@prefix@/share/pacman'
92 local GPG_NOKEYRING
="gpg --batch --quiet --ignore-time-conflict --no-options --no-default-keyring --homedir ${PACMAN_KEYRING_DIR}"
94 # Variable used for iterating on keyrings
98 # Keyring with keys to be added to the keyring
99 local ADDED_KEYS
="${PACMAN_SHARE_DIR}/addedkeys.gpg"
101 # Keyring with keys that were deprecated and will eventually be deleted
102 local DEPRECATED_KEYS
="${PACMAN_SHARE_DIR}/deprecatedkeys.gpg"
104 # List of keys removed from the keyring. This file is not a keyring, unlike the others.
105 # It is a textual list of values that gpg recogniezes as identifiers for keys.
106 local REMOVED_KEYS
="${PACMAN_SHARE_DIR}/removedkeys"
108 # Verify signatures of related files, if they exist
109 if [[ -r "${ADDED_KEYS}" ]]; then
110 msg
"$(gettext "Verifying official keys
file signature...
")"
111 if ! ${GPG_PACMAN} --verify "${ADDED_KEYS}.sig" &>/dev
/null
; then
112 error
"$(gettext "The signature of
file %s is not valid.
")" "${ADDED_KEYS}"
117 if [[ -r "${DEPRECATED_KEYS}" ]]; then
118 msg
"$(gettext "Verifying deprecated keys
file signature...
")"
119 if ! ${GPG_PACMAN} --verify "${DEPRECATED_KEYS}.sig" &>/dev
/null
; then
120 error
"$(gettext "The signature of
file %s is not valid.
")" "${DEPRECATED_KEYS}"
125 if [[ -r "${REMOVED_KEYS}" ]]; then
126 msg
"$(gettext "Verifying deleted keys
file signature...
")"
127 if ! ${GPG_PACMAN} --verify "${REMOVED_KEYS}.sig" &>/dev
/null
; then
128 error
"$(gettext "The signature of
file %s is not valid.
")" "${REMOVED_KEYS}"
133 # Read the key ids to an array. The conversion from whatever is inside the file
134 # to key ids is important, because key ids are the only guarantee of identification
137 if [[ -r "${REMOVED_KEYS}" ]]; then
139 local key_values name
140 key_values
="$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5,10 --output-delimiter=' ')"
141 if [[ -n $key_values ]]; then
142 # The first word is the key_id
143 key_id
="${key_values%% *}"
144 # the rest if the name of the owner
145 name
="${key_values#* }"
146 if [[ -n ${key_id} ]]; then
147 # Mark this key to be deleted
148 removed_ids
[$key_id]="$name"
151 done < "${REMOVED_KEYS}"
154 # List of keys that must be kept installed, even if in the list of keys to be removed
155 local HOLD_KEYS
="$(get_from "$CONFIG" "HoldKeys
")"
157 # Remove the keys that must be kept from the set of keys that should be removed
158 if [[ -n ${HOLD_KEYS} ]]; then
159 for key
in ${HOLD_KEYS}; do
160 key_id
="$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5)"
161 if [[ -n "${removed_ids[$key_id]}" ]]; then
162 unset removed_ids
[$key_id]
167 # Add keys from the current set of keys from pacman-keyring package. The web of trust will
168 # be updated automatically.
169 if [[ -r "${ADDED_KEYS}" ]]; then
170 msg
"$(gettext "Appending official keys...
")"
171 local add_keys
="$(${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5)"
172 for key_id
in ${add_keys}; do
173 # There is no point in adding a key that will be deleted right after
174 if [[ -z "${removed_ids[$key_id]}" ]]; then
175 ${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import
180 if [[ -r "${DEPRECATED_KEYS}" ]]; then
181 msg
"$(gettext "Appending deprecated keys...
")"
182 local add_keys
="$(${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5)"
183 for key_id
in ${add_keys}; do
184 # There is no point in adding a key that will be deleted right after
185 if [[ -z "${removed_ids[$key_id]}" ]]; then
186 ${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import
191 # Remove the keys not marked to keep
192 if (( ${#removed_ids[@]} > 0 )); then
193 msg
"$(gettext "Removing deleted keys from keyring...
")"
194 for key_id
in "${!removed_ids[@]}"; do
195 echo " removing key $key_id - ${removed_ids[$key_id]}"
196 ${GPG_PACMAN} --quiet --batch --yes --delete-key "${key_id}"
200 # Update trustdb, just to be sure
201 msg
"$(gettext "Updating trust database...
")"
202 ${GPG_PACMAN} --batch --check-trustdb
206 if [[ -z ${KEYIDS[@]} ]]; then
207 error
"$(gettext "You need to specify the keyserver and
at least one key identifier
")"
210 ${GPG_PACMAN} --keyserver "$KEYSERVER" --recv-keys "${KEYIDS[@]}"
215 for key
in ${KEYIDS[@]}; do
216 # Verify if the key exists in pacman's keyring
217 if ! ${GPG_PACMAN} --list-keys "$key" &>/dev
/null
; then
218 error
"$(gettext "The key identified by
%s does not exist
")" "$key"
222 (( errors
)) && exit 1;
224 for key
in ${KEYIDS[@]}; do
225 ${GPG_PACMAN} --edit-key "$key"
230 if ! type gettext &>/dev
/null
; then
236 OPT_SHORT
="a::d:e:f::hlr:uV"
237 OPT_LONG
="add::,config:,delete:,edit-key:,export::,finger::,gpgdir:"
238 OPT_LONG
+=",help,list,receive:,reload,updatedb,version"
239 if ! OPT_TEMP
="$(parse_options $OPT_SHORT $OPT_LONG "$@
")"; then
240 echo; usage
; exit 1 # E_INVALID_OPTION;
242 eval set -- "$OPT_TEMP"
243 unset OPT_SHORT OPT_LONG OPT_TEMP
245 if [[ $1 == "--" ]]; then
252 -a|
--add) ADD
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYFILES
=($1) ;;
253 --config) shift; CONFIG
=$1 ;;
254 -d|
--delete) DELETE
=1; shift; KEYIDS
=($1) ;;
255 --edit-key) EDITKEY
=1; shift; KEYIDS
=($1) ;;
256 -e|
--export) EXPORT
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS
=($1) ;;
257 -f|
--finger) FINGER
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS
=($1) ;;
258 --gpgdir) shift; PACMAN_KEYRING_DIR
=$1 ;;
260 -r|
--receive) RECEIVE
=1; shift; KEYSERVER
="${1[0]}"; KEYIDS
=("${1[@]:1}") ;;
261 --reload) RELOAD
=1 ;;
262 -u|
--updatedb) UPDATEDB
=1 ;;
264 -h|
--help) usage
; exit 0 ;;
265 -V|
--version) version
; exit 0 ;;
267 --) OPT_IND
=0; shift; break;;
274 if ! type -p gpg
>/dev
/null
; then
275 error
"$(gettext "Cannot
find the
%s binary required
for all
%s operations.
")" "gpg" "pacman-key"
279 if (( (ADD || DELETE || EDITKEY || RECEIVE || RELOAD || UPDATEDB
) && EUID
!= 0 )); then
280 error
"$(gettext "%s needs to be run as root
for this operation.
")" "pacman-key"
284 CONFIG
=${CONFIG:-@sysconfdir@/pacman.conf}
285 if [[ ! -r "${CONFIG}" ]]; then
286 error
"$(gettext "%s configuation
file '%s' not found.
")" "pacman" "$CONFIG"
290 # Get GPGDIR from pacman.conf iff not specified on command line
291 if [[ -z PACMAN_KEYRING_DIR
&& GPGDIR
="$(get_from "$CONFIG" "GPGDir
")" == 0 ]]; then
292 PACMAN_KEYRING_DIR
="${GPGDIR}"
294 PACMAN_KEYRING_DIR
=${PACMAN_KEYRING_DIR:-@sysconfdir@/pacman.d/gnupg}
296 # Try to create $PACMAN_KEYRING_DIR if non-existent
297 # Check for simple existence rather than for a directory as someone may want
298 # to use a symlink here
299 [[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir
-p -m 755 "${PACMAN_KEYRING_DIR}"
301 GPG_PACMAN
="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning"
304 (( ADD
)) && ${GPG_PACMAN} --quiet --batch --import "${KEYFILES[@]}"
305 (( DELETE
)) && ${GPG_PACMAN} --quiet --batch --delete-key --yes "${KEYIDS[@]}"
306 (( EDITKEY
)) && edit_keys
307 (( EXPORT
)) && ${GPG_PACMAN} --armor --export "${KEYIDS[@]}"
308 (( FINGER
)) && ${GPG_PACMAN} --batch --fingerprint "${KEYIDS[@]}"
309 (( LIST
)) && ${GPG_PACMAN} --batch --list-sigs "${KEYIDS[@]}"
310 (( RECEIVE
)) && receive_keys
311 (( RELOAD
)) && reload_keyring
312 (( UPDATEDB
)) && ${GPG_PACMAN} --batch --check-trustdb
314 # vim: set ts=2 sw=2 noet: