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
90 verify_keyring_input
() {
93 # Verify signatures of related files, if they exist
94 if [[ -r "${ADDED_KEYS}" ]]; then
95 msg
"$(gettext "Verifying official keys
file signature...
")"
96 if ! ${GPG_PACMAN} --verify "${ADDED_KEYS}.sig" &>/dev
/null
; then
97 error
"$(gettext "The signature of
file %s is not valid.
")" "${ADDED_KEYS}"
102 if [[ -r "${DEPRECATED_KEYS}" ]]; then
103 msg
"$(gettext "Verifying deprecated keys
file signature...
")"
104 if ! ${GPG_PACMAN} --verify "${DEPRECATED_KEYS}.sig" &>/dev
/null
; then
105 error
"$(gettext "The signature of
file %s is not valid.
")" "${DEPRECATED_KEYS}"
110 if [[ -r "${REMOVED_KEYS}" ]]; then
111 msg
"$(gettext "Verifying deleted keys
file signature...
")"
112 if ! ${GPG_PACMAN} --verify "${REMOVED_KEYS}.sig" &>/dev
/null
; then
113 error
"$(gettext "The signature of
file %s is not valid.
")" "${REMOVED_KEYS}"
122 local PACMAN_SHARE_DIR
='@prefix@/share/pacman'
123 local GPG_NOKEYRING
="gpg --batch --quiet --ignore-time-conflict --no-options --no-default-keyring --homedir ${PACMAN_KEYRING_DIR}"
125 # Variable used for iterating on keyrings
129 # Keyring with keys to be added to the keyring
130 local ADDED_KEYS
="${PACMAN_SHARE_DIR}/addedkeys.gpg"
132 # Keyring with keys that were deprecated and will eventually be deleted
133 local DEPRECATED_KEYS
="${PACMAN_SHARE_DIR}/deprecatedkeys.gpg"
135 # List of keys removed from the keyring. This file is not a keyring, unlike the others.
136 # It is a textual list of values that gpg recogniezes as identifiers for keys.
137 local REMOVED_KEYS
="${PACMAN_SHARE_DIR}/removedkeys"
139 verify_keyring_input ||
exit 1
141 # Read the key ids to an array. The conversion from whatever is inside the file
142 # to key ids is important, because key ids are the only guarantee of identification
145 if [[ -r "${REMOVED_KEYS}" ]]; then
147 local key_values name
148 key_values
="$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5,10 --output-delimiter=' ')"
149 if [[ -n $key_values ]]; then
150 # The first word is the key_id
151 key_id
="${key_values%% *}"
152 # the rest if the name of the owner
153 name
="${key_values#* }"
154 if [[ -n ${key_id} ]]; then
155 # Mark this key to be deleted
156 removed_ids
[$key_id]="$name"
159 done < "${REMOVED_KEYS}"
162 # List of keys that must be kept installed, even if in the list of keys to be removed
163 local HOLD_KEYS
="$(get_from "$CONFIG" "HoldKeys
")"
165 # Remove the keys that must be kept from the set of keys that should be removed
166 if [[ -n ${HOLD_KEYS} ]]; then
167 for key
in ${HOLD_KEYS}; do
168 key_id
="$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5)"
169 if [[ -n "${removed_ids[$key_id]}" ]]; then
170 unset removed_ids
[$key_id]
175 # Add keys from the current set of keys from pacman-keyring package. The web of trust will
176 # be updated automatically.
177 if [[ -r "${ADDED_KEYS}" ]]; then
178 msg
"$(gettext "Appending official keys...
")"
179 local add_keys
="$(${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5)"
180 for key_id
in ${add_keys}; do
181 # There is no point in adding a key that will be deleted right after
182 if [[ -z "${removed_ids[$key_id]}" ]]; then
183 ${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import
188 if [[ -r "${DEPRECATED_KEYS}" ]]; then
189 msg
"$(gettext "Appending deprecated keys...
")"
190 local add_keys
="$(${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5)"
191 for key_id
in ${add_keys}; do
192 # There is no point in adding a key that will be deleted right after
193 if [[ -z "${removed_ids[$key_id]}" ]]; then
194 ${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import
199 # Remove the keys not marked to keep
200 if (( ${#removed_ids[@]} > 0 )); then
201 msg
"$(gettext "Removing deleted keys from keyring...
")"
202 for key_id
in "${!removed_ids[@]}"; do
203 echo " removing key $key_id - ${removed_ids[$key_id]}"
204 ${GPG_PACMAN} --quiet --batch --yes --delete-key "${key_id}"
208 # Update trustdb, just to be sure
209 msg
"$(gettext "Updating trust database...
")"
210 ${GPG_PACMAN} --batch --check-trustdb
214 if [[ -z ${KEYIDS[@]} ]]; then
215 error
"$(gettext "You need to specify the keyserver and
at least one key identifier
")"
218 ${GPG_PACMAN} --keyserver "$KEYSERVER" --recv-keys "${KEYIDS[@]}"
223 for key
in ${KEYIDS[@]}; do
224 # Verify if the key exists in pacman's keyring
225 if ! ${GPG_PACMAN} --list-keys "$key" &>/dev
/null
; then
226 error
"$(gettext "The key identified by
%s does not exist
")" "$key"
230 (( errors
)) && exit 1;
232 for key
in ${KEYIDS[@]}; do
233 ${GPG_PACMAN} --edit-key "$key"
238 if ! type gettext &>/dev
/null
; then
244 OPT_SHORT
="a::d:e:f::hlr:uV"
245 OPT_LONG
="add::,config:,delete:,edit-key:,export::,finger::,gpgdir:"
246 OPT_LONG
+=",help,list,receive:,reload,updatedb,version"
247 if ! OPT_TEMP
="$(parse_options $OPT_SHORT $OPT_LONG "$@
")"; then
248 echo; usage
; exit 1 # E_INVALID_OPTION;
250 eval set -- "$OPT_TEMP"
251 unset OPT_SHORT OPT_LONG OPT_TEMP
253 if [[ $1 == "--" ]]; then
260 -a|
--add) ADD
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYFILES
=($1) ;;
261 --config) shift; CONFIG
=$1 ;;
262 -d|
--delete) DELETE
=1; shift; KEYIDS
=($1) ;;
263 --edit-key) EDITKEY
=1; shift; KEYIDS
=($1) ;;
264 -e|
--export) EXPORT
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS
=($1) ;;
265 -f|
--finger) FINGER
=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS
=($1) ;;
266 --gpgdir) shift; PACMAN_KEYRING_DIR
=$1 ;;
268 -r|
--receive) RECEIVE
=1; shift; KEYSERVER
="${1[0]}"; KEYIDS
=("${1[@]:1}") ;;
269 --reload) RELOAD
=1 ;;
270 -u|
--updatedb) UPDATEDB
=1 ;;
272 -h|
--help) usage
; exit 0 ;;
273 -V|
--version) version
; exit 0 ;;
275 --) OPT_IND
=0; shift; break;;
282 if ! type -p gpg
>/dev
/null
; then
283 error
"$(gettext "Cannot
find the
%s binary required
for all
%s operations.
")" "gpg" "pacman-key"
287 if (( (ADD || DELETE || EDITKEY || RECEIVE || RELOAD || UPDATEDB
) && EUID
!= 0 )); then
288 error
"$(gettext "%s needs to be run as root
for this operation.
")" "pacman-key"
292 CONFIG
=${CONFIG:-@sysconfdir@/pacman.conf}
293 if [[ ! -r "${CONFIG}" ]]; then
294 error
"$(gettext "%s configuation
file '%s' not found.
")" "pacman" "$CONFIG"
298 # Get GPGDIR from pacman.conf iff not specified on command line
299 if [[ -z PACMAN_KEYRING_DIR
&& GPGDIR
="$(get_from "$CONFIG" "GPGDir
")" == 0 ]]; then
300 PACMAN_KEYRING_DIR
="${GPGDIR}"
302 PACMAN_KEYRING_DIR
=${PACMAN_KEYRING_DIR:-@sysconfdir@/pacman.d/gnupg}
304 # Try to create $PACMAN_KEYRING_DIR if non-existent
305 # Check for simple existence rather than for a directory as someone may want
306 # to use a symlink here
307 [[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir
-p -m 755 "${PACMAN_KEYRING_DIR}"
309 GPG_PACMAN
="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning"
311 # check only a single operation has been given
312 numopt
=$
(( ADD
+ DELETE
+ EDITKEY
+ EXPORT
+ FINGER
+ LIST
+ RECEIVE
+ RELOAD
+ UPDATEBD
))
314 if (( ! numopt
)); then
315 error
"$(gettext "No operations specified
")"
321 if (( numopt
!= 1 )); then
322 error
"$(gettext "Multiple operations specified
")"
323 printf "$(gettext "Please run
%s with each operation separately
\n")" "pacman-key"
328 (( ADD
)) && ${GPG_PACMAN} --quiet --batch --import "${KEYFILES[@]}"
329 (( DELETE
)) && ${GPG_PACMAN} --quiet --batch --delete-key --yes "${KEYIDS[@]}"
330 (( EDITKEY
)) && edit_keys
331 (( EXPORT
)) && ${GPG_PACMAN} --armor --export "${KEYIDS[@]}"
332 (( FINGER
)) && ${GPG_PACMAN} --batch --fingerprint "${KEYIDS[@]}"
333 (( LIST
)) && ${GPG_PACMAN} --batch --list-sigs "${KEYIDS[@]}"
334 (( RECEIVE
)) && receive_keys
335 (( RELOAD
)) && reload_keyring
336 (( UPDATEDB
)) && ${GPG_PACMAN} --batch --check-trustdb
338 # vim: set ts=2 sw=2 noet: