[pacman-dev] [PATCH 0/5] Manage signing keys using a WKD (FS#63171)
Hi, as explained in https://bugs.archlinux.org/task/63171, it would be nice if pacman could receive new PGP keys and refresh expired ones using a Web Key Directory (WKD) instead of using keyservers. This patch series adds the corresponding functionality to pacman and pacman-key. Since WKD is not enabled on archlinux.org yet, it might be a little early to merge this as I have only been able to test it locally on my machine. However since this is my first potential pacman contribution, I wanted to get it out early to gather some feedback on the code. Unfortunately GnuPG/GPGME handles WKD keys quite differently from keyserver keys, so you have to jump through some hoops to enable the usual cofirm-then-import workflow for keys. WKD support for pacman is complete, so it would be possible to remove the keyserver code and rely solely on WKD if the need should arise (though this would require changes to the Arch Linux packaging policy, see the bug report). pacman-key on the other hand is lacking a convenient way of refreshing all keys using WKD, currently every key needs to be refreshed manually by e-mail address using "pacman-key -r". This is because "gpg --refresh-keys" is hardwired to use keyservers. Hopefully the situation will change in future versions of GnuPG, see the corresponding commit message for reference, if not we need to work around this by listing every key in the keyring by email and doing a refresh using WKD. Cheers, Jonas Jonas Witschel (5): common: move rmrf to util-common signing: add ability to import keys using a WKD sync: lookup missing keys in the WKD using the packager email be_package: lookup missing keys in the WKD using the packager email pacman-key: receive keys from WKD with -r/--recv-keys lib/libalpm/alpm.h | 1 + lib/libalpm/be_package.c | 12 ++- lib/libalpm/signing.c | 175 ++++++++++++++++++++++++++++----------- lib/libalpm/signing.h | 2 +- lib/libalpm/sync.c | 9 +- lib/libalpm/util.c | 23 +++++ lib/libalpm/util.h | 1 + scripts/pacman-key.sh.in | 19 +++-- src/common/util-common.c | 42 ++++++++++ src/common/util-common.h | 2 + src/pacman/util.c | 40 --------- src/pacman/util.h | 1 - 12 files changed, 226 insertions(+), 101 deletions(-) -- 2.22.0
We will need to remove temporary directories in libalpm, therefore move
this helper function to the common utilities.
Signed-off-by: Jonas Witschel
Currently pacman relies on the SKS keyserver network to fetch unknown
PGP keys. These keyservers are vulnerable to signature spamming attacks,
potentionally making it impossible to import the required keys. An
alternative to keyservers is a so-called Web Key Directory (WKD), a
well-known, trusted location on a server from where the keys can be
fetched.
This commit adds the ability to retrieve keys from the WKD. Due to the
mentioned vulnerabilities, the WKD is tried first, falling back to the
keyservers only if no appropriate key is found there.
In contrast to keyservers, keys on the WKD are not looked up using their
fingerprint, but by email address. Since the email address of the
signing key is usually not included in the signature, we will use the
email packager email address. In contrast to the direct fingerprint
lookup, this might not work or result in a different key, so we check
the fingerprint of the received key and fall back to a keyserver if
necessary. The extraction of the email address is not performed here,
this will be included in the subsequent commits.
GnuPG/GPGME handles keys from a WKD very differently than keys from a
keyserver: gpgme_get_key directly imports the key into the keyring if it
is available without giving the user the choice to confirm it first. On
the other hand gpgme_op_import_keys does not import keys from a WKD
because it is hard-coded to use keyservers (gpg --recv-keys). Therefore
we set a temporary keyring for the initial lookup and use gpgme_get_key
after the user has confirmed he wants to import the key. This makes it
necessary to add a new member "location" to _alpm_pgpkey_t in order to
distinguish the two methods to retrieve the key.
Also see FS#63171.
Signed-off-by: Jonas Witschel
On 2019-07-17 22:06, Jonas Witschel wrote:
+ if((gpg_err_code(gpg_err) == GPG_ERR_NO_ERROR) && (strcmp(key->subkeys->fpr, fpr) == 0)) {
Sorry, I just realised this will never be true because "fpr" comes from "parse_subpacket" and is always the 8 byte key ID, while "key->subkeys->fpr" is the full 20 byte fingerprint. We need to compare with "fpr" with "key->subkeys->keyid" instead, see attached for the corrected patch that also adds some more debugging output in case of a key mismatch.
Currently pacman relies on the SKS keyserver network to fetch unknown
PGP keys. These keyservers are vulnerable to signature spamming attacks,
potentionally making it impossible to import the required keys. An
alternative to keyservers is a so-called Web Key Directory (WKD), a
well-known, trusted location on a server from where the keys can be
fetched.
This commit adds the ability to retrieve keys from the WKD. Due to the
mentioned vulnerabilities, the WKD is tried first, falling back to the
keyservers only if no appropriate key is found there.
In contrast to keyservers, keys on the WKD are not looked up using their
fingerprint, but by email address. Since the email address of the
signing key is usually not included in the signature, we will use the
email packager email address. In contrast to the direct fingerprint
lookup, this might not work or result in a different key, so we check
the fingerprint of the received key and fall back to a keyserver if
necessary. The extraction of the email address is not performed here,
this will be included in the subsequent commits.
GnuPG/GPGME handles keys from a WKD very differently than keys from a
keyserver: gpgme_get_key directly imports the key into the keyring if it
is available without giving the user the choice to confirm it first. On
the other hand gpgme_op_import_keys does not import keys from a WKD
because it is hard-coded to use keyservers (gpg --recv-keys). Therefore
we set a temporary keyring for the initial lookup and use gpgme_get_key
after the user has confirmed he wants to import the key. This makes it
necessary to add a new member "location" to _alpm_pgpkey_t in order to
distinguish the two methods to retrieve the key.
Also see FS#63171.
Signed-off-by: Jonas Witschel
Currently pacman relies on the SKS keyserver network to fetch unknown
PGP keys. These keyservers are vulnerable to signature spamming attacks,
potentionally making it impossible to import the required keys. An
alternative to keyservers is a so-called Web Key Directory (WKD), a
well-known, trusted location on a server from where the keys can be
fetched.
This commit adds the ability to retrieve keys from the WKD. Due to the
mentioned vulnerabilities, the WKD is tried first, falling back to the
keyservers only if no appropriate key is found there.
In contrast to keyservers, keys on the WKD are not looked up using their
fingerprint, but by email address. Since the email address of the
signing key is usually not included in the signature, we will use the
email packager email address. In contrast to the direct fingerprint
lookup, this might not work or result in a different key, so we check
the fingerprint of the received key and fall back to a keyserver if
necessary. The extraction of the email address is not performed here,
this will be included in the subsequent commits.
GnuPG/GPGME handles keys from a WKD very differently than keys from a
keyserver: gpgme_get_key directly imports the key into the keyring if it
is available without giving the user the choice to confirm it first. On
the other hand gpgme_op_import_keys does not import keys from a WKD
because it is hard-coded to use keyservers (gpg --recv-keys). Therefore
we set a temporary keyring for the initial lookup and use gpgme_get_key
after the user has confirmed he wants to import the key. This makes it
necessary to add a new member "location" to _alpm_pgpkey_t in order to
distinguish the two methods to retrieve the key.
Also see FS#63171.
Signed-off-by: Jonas Witschel
We assume that the packager is of the form
"Example Name
On 18/7/19 6:06 am, Jonas Witschel wrote:
We assume that the packager is of the form "Example Name
" and that the key used to sign the package can be resolved using WKD with this address. This means that the package signing key should have one user ID with the given email address, which does not need to be a valid address, but needs to be published in the WKD. Signed-off-by: Jonas Witschel
--- lib/libalpm/sync.c | 9 +++++++-- lib/libalpm/util.c | 23 +++++++++++++++++++++++ lib/libalpm/util.h | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index efad77ba..02acdf6d 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -872,6 +872,7 @@ static int check_keyring(alpm_handle_t *handle) size_t current = 0, numtargs; alpm_list_t *i, *errors = NULL; alpm_event_t event; + char *email;
event.type = ALPM_EVENT_KEYRING_START; EVENT(handle, &event); @@ -905,6 +906,8 @@ static int check_keyring(alpm_handle_t *handle) char *key = k->data; if(!alpm_list_find_str(errors, key) && _alpm_key_in_keychain(handle, key) == 0) { + _alpm_email_from_uid(pkg->packager, &email); + errors = alpm_list_add(errors, email); errors = alpm_list_add(errors, strdup(key));
I don't like this. Storing two strings as adjacent items in the list. I'd prefer a small two item struct. Any other opinions on this? <snip>
} diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index d33eef2a..2089f84d 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1491,3 +1491,26 @@ void _alpm_alloc_fail(size_t size) { fprintf(stderr, "alloc failure: could not allocate %zu bytes\n", size); } + +/** Extract the email address from a User ID + * @param uid User ID to parse in the form "Example Name
" + * @param email to hold email address + * @return 0 on success, -1 on error + */ +int _alpm_email_from_uid(const char *uid, char **email) +{ + char *start, *end; + + start = strrchr(uid, '<');
This makes a strong assumption that "<" is not used within an email address. The use of that character is technically valid, provided it is quoted. I am happy with that assumption, but we need to add a check in libmakpkeg to reject emails containing it. In fact, our PACKAGER variable has no enforced format at all...
+ if(start) { + end = strrchr(start, '>'); + } + + if(start && end) { + STRNDUP(*email, start+1, end-start-1, return -1); + return 0; + } else { + email = NULL; + return -1; + } +} diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 9a3942f1..1190f10f 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -147,6 +147,7 @@ int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string); int _alpm_fnmatch(const void *pattern, const void *string); void *_alpm_realloc(void **data, size_t *current, const size_t required); void *_alpm_greedy_grow(void **data, size_t *current, const size_t required); +int _alpm_email_from_uid(const char *uid, char **email);
Rename to: _alpm_email_from_packager()
#ifndef HAVE_STRSEP char *strsep(char **, const char *); -- 2.22.0 .
We assume that the packager is of the form
"Example Name
In contrast to the preceeding commit we do not have a database with the
required packager information to work with, so we need to extract the
package temporarily to obtain this information.
Signed-off-by: Jonas Witschel
If an email address is specified, we use --locate-key to look up the key
using WKD and keyserver as a fallback. If the key is specified as a key
ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for
refreshing, though the situation might potentially be improved in a new
version of GnuPG:
https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
On 6/8/19 1:32 am, Jonas Witschel wrote:
If an email address is specified, we use --locate-key to look up the key using WKD and keyserver as a fallback. If the key is specified as a key ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for refreshing, though the situation might potentially be improved in a new version of GnuPG: https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
---
Some fairly minor changes below.
scripts/pacman-key.sh.in | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index b05754e5..a4bdbaa9 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -455,22 +455,29 @@ lsign_keys() { }
receive_keys() { - local name id keyids + local name id keyids emails
# 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 + elif [[ $name = *@*.* ]]; then + emails+=("$name") + elif id=$(key_lookup_from_name "$name"); then + keyids+=("$id") fi done
- (( ${#keyids[*]} > 0 )) || exit 1 + (( ${#keyids[*]}+${#emails[*]} > 0 )) || exit 1 + + if (( ${#emails[*]} > 0 )) && \ + ! "${GPG_PACMAN[@]}" --auto-key-locate nodefault,clear,wkd,keyserver \
From the man page:
clear Clear all defined mechanisms. This is useful to override mechanisms given in a config file. Note that a nodefault in mechanisms will also be cleared unless it is given af‐ ter the clear. so clear,nodefault,wkd,keyserver ?
+ --locate-key "${emails[@]}" ; then + error "$(gettext "Remote key not fetched correctly from WKD or keyserver.")" + exit 1
Instead of exiting here, catch the failure (ret=1), both here and...
+ fi
- if ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then + if (( ${#keyids[*]} > 0 )) && ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then error "$(gettext "Remote key not fetched correctly from keyserver.")" exit 1
here...
fi
and exit here if there was a failure.
-- 2.22.0 .
If an email address is specified, we use --locate-key to look up the key
using WKD and keyserver as a fallback. If the key is specified as a key
ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for
refreshing, though the situation might potentially be improved in a new
version of GnuPG:
https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
On 7/10/19 8:56 pm, Jonas Witschel wrote:
If an email address is specified, we use --locate-key to look up the key using WKD and keyserver as a fallback. If the key is specified as a key ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for refreshing, though the situation might potentially be improved in a new version of GnuPG: https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
--- Apply suggested changes: - Use "clear,nodefault" instead of "nodefault,clear" (verified with GnuPG 2.2.17 that the latter indeed doesn't clear the default "local") - Attempt lookups by key ID instead of bailing out early if lookup by email address failed
Great - thanks!
scripts/pacman-key.sh.in | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index 117acc40..8c8ffc3f 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -461,25 +461,34 @@ lsign_keys() { }
receive_keys() { - local name id keyids + local ret=0 name id keyids emails
# 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 + elif [[ $name = *@*.* ]]; then + emails+=("$name") + elif id=$(key_lookup_from_name "$name"); then + keyids+=("$id") fi done
- (( ${#keyids[*]} > 0 )) || exit 1 + (( ${#keyids[*]}+${#emails[*]} > 0 )) || exit 1 + + if (( ${#emails[*]} > 0 )) && \ + ! "${GPG_PACMAN[@]}" --auto-key-locate clear,nodefault,wkd,keyserver \ + --locate-key "${emails[@]}" ; then + error "$(gettext "Remote key not fetched correctly from WKD or keyserver.")" + ret=1 + fi
- if ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then + if (( ${#keyids[*]} > 0 )) && ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then error "$(gettext "Remote key not fetched correctly from keyserver.")" - exit 1 + ret=1 fi + + exit $ret }
refresh_keys() {
pacman should be able to extract an email address from PACKAGER for WKD
lookup, so issue a warning if it is not of the form
"Example Name
On 8/5/19 11:36 AM, Jonas Witschel wrote:
pacman should be able to extract an email address from PACKAGER for WKD lookup, so issue a warning if it is not of the form "Example Name
". Neither the name nor the email address must contain additional angle brackets. Signed-off-by: Jonas Witschel
--- scripts/libmakepkg/lint_config/variable.sh.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/libmakepkg/lint_config/variable.sh.in b/scripts/libmakepkg/lint_config/variable.sh.in index 55ed6d6d..fe1e6d63 100644 --- a/scripts/libmakepkg/lint_config/variable.sh.in +++ b/scripts/libmakepkg/lint_config/variable.sh.in @@ -60,5 +60,10 @@ lint_config_variables() { fi done
+ # pacman should be able to extract an email address from PACKAGER for WKD key lookup + if ! [[ $PACKAGER =~ ^[^\<\>]*\ \<[^\<\>]*\>$ ]]; then
Too much escaping is making me seasick.
local match='^[^<>]* <[^<>]*>$'
if ! [[ $PACKAGER =~ $match ]]; then
Since you're making the portion before the
+ warning "$(gettext "PACKAGER should have the format 'Example Name
'")" + fi + return $ret } -- 2.22.0
-- Eli Schwartz Bug Wrangler and Trusted User
pacman should be able to extract an email address from PACKAGER for WKD
lookup, so issue a warning if it is not of the form
"Example Name
Hi, thank you for the review! On 2019-08-05 13:14, Allan McRae wrote:
+ errors = alpm_list_add(errors, email); errors = alpm_list_add(errors, strdup(key));
I don't like this. Storing two strings as adjacent items in the list.
I'd prefer a small two item struct.
Any other opinions on this?
Done, it now uses a struct with two members "email" and "keyid". A bit more work because we need to free the strings manually now, but I agree it is much cleaner.
+/** Extract the email address from a User ID + * @param uid User ID to parse in the form "Example Name
" [...] + start = strrchr(uid, '<'); This makes a strong assumption that "<" is not used within an email address. The use of that character is technically valid, provided it is quoted.
I am happy with that assumption, but we need to add a check in libmakpkeg to reject emails containing it.
In fact, our PACKAGER variable has no enforced format at all...
I sent a separate patch for libmakepkg to issue a warning if PACKAGER
doesn't have the expected format. I opted for a warning instead of a
hard error because I don't know what other distributions using pacman do
- for Arch the "Example Name
+int _alpm_email_from_uid(const char *uid, char **email);
Rename to:
_alpm_email_from_packager()
Done, this also affected "[PATCH 4/5] be_package: lookup missing keys in the WKD using the packager email" because the function is used there as well. I also published the updated patch series as the "wkd-v2" branch of https://gitlab.com/diabonas/pacman Kind regards, Jonas
On 8/5/19 11:37 AM, Jonas Witschel wrote:
Hi,
thank you for the review!
New suggestion: You can do inline comments for a patch using git send-email --annotate, and insert descriptions like: v2: changed foo to bar After the "---" which ends the commit message and before the "diff --git". There are already some comments there, e.g. scripts/libmakepkg/lint_config/variable.sh.in | 5 +++++ 1 file changed, 5 insertions(+) Common practice in many circles is to add commentary or changelogs on the patch, in between the "---" and this summary ... Describing what changed between v1 and v2 of a patch, in the patch email, makes it easier to follow the evolution of a patch, vs. consulting a followup email and trying to map each reply to the affected changeset. Could help. :) -- Eli Schwartz Bug Wrangler and Trusted User
On 2019-08-05 18:07, Eli Schwartz wrote:
New suggestion:
You can do inline comments for a patch using git send-email --annotate, and insert descriptions like:
v2: changed foo to bar
After the "---" which ends the commit message and before the "diff --git".
Thanks, that is useful indeed! I did this for v2 of the libmakepkg patch, thank you for your suggestions there as well! Regards, Jonas
In contrast to the preceeding commit we do not have a database with the
required packager information to work with, so we need to extract the
package temporarily to obtain this information.
Signed-off-by: Jonas Witschel
If an email address is specified, we use --locate-key to look up the key
using WKD and keyserver as a fallback. If the key is specified as a key
ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for
refreshing, though the situation might potentially be improved in a new
version of GnuPG:
https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
On 18/7/19 6:06 am, Jonas Witschel wrote:
If an email address is specified, we use --locate-key to look up the key using WKD and keyserver as a fallback. If the key is specified as a key ID, this doesn't work, so we use the normal keyserver-based --recv-keys.
Note that --refresh-keys still uses the keyservers exclusively for refreshing, though the situation might potentially be improved in a new version of GnuPG: https://lists.gnupg.org/pipermail/gnupg-users/2019-July/062169.html
Signed-off-by: Jonas Witschel
--- scripts/pacman-key.sh.in | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index b05754e5..cd214a2e 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -455,25 +455,30 @@ lsign_keys() { }
receive_keys() { - local name id keyids + local name id keyids emails
# 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 + elif [[ $name = *@*.* ]]; then + emails+=("$name") + elif id=$(key_lookup_from_name "$name"); then + keyids+=("$id") fi done
- (( ${#keyids[*]} > 0 )) || exit 1 + (( ${#keyids[*]}+${#emails[*]} > 0 )) || exit 1
- if ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then + if (( ${#keyids[*]} > 0 )) && ! "${GPG_PACMAN[@]}" --recv-keys "${keyids[@]}" ; then error "$(gettext "Remote key not fetched correctly from keyserver.")" exit 1 fi + + if (( ${#emails[*]} > 0 )) && ! "${GPG_PACMAN[@]}" --auto-key-locate nodefault,clear,wkd,keyserver --locate-key "${emails[@]}" ; then
Super long line. Please split across two or more lines. I would also like to see this block placed above the --recv-keys one.
+ error "$(gettext "Remote key not fetched correctly from WKD or keyserver.")" + exit 1 + fi }
refresh_keys() { -- 2.22.0 .
On 2019-08-05 13:31, Allan McRae wrote:
+ if (( ${#emails[*]} > 0 )) && ! "${GPG_PACMAN[@]}" --auto-key-locate nodefault,clear,wkd,keyserver --locate-key "${emails[@]}" ; then
Super long line. Please split across two or more lines.
I would also like to see this block placed above the --recv-keys one.
I split up the line and moved the block. Cheers, Jonas
Hi,
good news everyone, thanks to Florian Pritz we now have a working WKD
[1] I had to modify the fingerprint check again [2] because the key used
for signing might be a subkey, so we need to loop trough all subkeys and
check if one of these key IDs matches the one used for signing the package.
The latest patch series now works with the keys published in the Arch
Linux WKD. I tested this by creating a new keyring containing only the
master signing keys, then installing a random package from each of the
developers whose key is ready for WKD support (the ones with three "Yes"
in the table in [3]). This worked successfully, so from my side, this
code is now ready for merging. I welcome any feedback on the code and
any testing whether everything works as expected. For convenience I
cloned the pacman repository on Gitlab and provide the patch series in
the "wkd" branch there [4]. A possible test setup looks like this:
# Build pacman with WKD patches added
git clone --branch wkd https://gitlab.com/diabonas/pacman.git
mkdir pacman/build && cd pacman/build
meson .. && ninja
# Prepare keyring (similar to what pacman-key --populate archlinux would
# do, but only import the master signing keys)
fakeroot pacman-key --init --gpgdir keyring
fakeroot pacman-key --gpgdir keyring --recv-keys \
$(cut -d':' -f1 /usr/share/pacman/keyrings/archlinux-trusted)
fakeroot pacman-key --gpgdir keyring --lsign \
$(cut -d':' -f1 /usr/share/pacman/keyrings/archlinux-trusted)
gpg --homedir keyring --import-ownertrust \
/usr/share/pacman/keyrings/archlinux-trusted
mkdir -p root/var/lib/pacman
# Install a package, key will be looked up in the WKD
# Output should be:
# debug: looking up key for arojas@archlinux.org using WKD
# debug: unknown key, found Antonio Rojas
Based on the feedback on #archlinux-pacman, I have reworked the WKD patches: we now ask the user whether they want to import a missing PGP key before doing any remote lookup, which eliminates the need for a second temporary keyring. Without a remote lookup, we only know the ID of the package signing key, so we display the packager in addition to the key ID for user convenience. This patch series entirely replaces all previously sent patches regarding WKD support. - PATCH v3 1/3 restructures the user confirmation in the described way. It incorporates the previous patches 3/5 and 4/5 because to have a standalone patch, we need to retrieve the user ID to display a user-friendly confirmation message. Other than that, it's mostly moving existing code around to fit the new workflow. - PATCH v3 2/3 is a simplified version of the previous patch 2/5, since doing the confirmation first allows us to drop the temporary keyring. Note that in contrast to the previous approach, we don't check any more whether the key retrieved from the WKD has the correct key ID, it is now the responsibility of the WKD maintainer to ensure this. The reason for this change is that at the time we are able to check the key ID, we have already imported the key anyway. - PATCH v3 3/3 is unchanged from "[PATCH v2] libmakepkg: check if PACKAGER has the expected format for WKD lookup", included simply for the convenience of having a complete patch series. Jonas Witschel (3): signing: move key import confirmation before key_search signing: add ability to import keys using a WKD libmakepkg: check if PACKAGER has the expected format for WKD lookup lib/libalpm/be_package.c | 12 +- lib/libalpm/signing.c | 120 ++++++++++++++---- lib/libalpm/signing.h | 2 +- lib/libalpm/sync.c | 22 +++- scripts/libmakepkg/lint_config/variable.sh.in | 6 + src/pacman/callback.c | 13 +- 6 files changed, 136 insertions(+), 39 deletions(-) -- 2.23.0
Ask the user whether they want to import a missing key before even doing
a search on the keyserver. This will be useful for getting Web Key
Directory support in place: for a WKD, looking up and importing a key
are a single action, so the current key_search -> QUESTION -> key_import
workflow does not apply.
Since only the ID of the package signing key is available before
key_search, we display the packager variable in addition to the key ID
for user convenience.
Signed-off-by: Jonas Witschel
Currently pacman relies on the SKS keyserver network to fetch unknown
PGP keys. These keyservers are vulnerable to signature spamming attacks,
potentionally making it impossible to import the required keys. An
alternative to keyservers is a so-called Web Key Directory (WKD), a
well-known, trusted location on a server from where the keys can be
fetched.
This commit adds the ability to retrieve keys from a WKD. Due to the
mentioned vulnerabilities, the WKD is tried first, falling back to the
keyservers only if no appropriate key is found there.
In contrast to keyservers, keys in a WKD are not looked up using their
fingerprint, but by email address. Since the email address of the
signing key is usually not included in the signature, we will use the
packager email address to perform the lookup.
Also see FS#63171.
Signed-off-by: Jonas Witschel
On 3/10/19 12:40 am, Jonas Witschel wrote:
Currently pacman relies on the SKS keyserver network to fetch unknown PGP keys. These keyservers are vulnerable to signature spamming attacks, potentionally making it impossible to import the required keys. An alternative to keyservers is a so-called Web Key Directory (WKD), a well-known, trusted location on a server from where the keys can be fetched.
This commit adds the ability to retrieve keys from a WKD. Due to the mentioned vulnerabilities, the WKD is tried first, falling back to the keyservers only if no appropriate key is found there.
In contrast to keyservers, keys in a WKD are not looked up using their fingerprint, but by email address. Since the email address of the signing key is usually not included in the signature, we will use the packager email address to perform the lookup.
Also see FS#63171.
Signed-off-by: Jonas Witschel
--- lib/libalpm/signing.c | 96 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 13 deletions(-)
Thanks - looks good apart from one change I made:
+ /* Try to import the key from a WKD first */ + email_from_uid(uid, &email); + ret = key_import_wkd(handle, email);
CC libalpm_la-signing.lo signing.c: In function ‘_alpm_key_import’: signing.c:285:12: error: ‘email’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 285 | gpg_err = gpgme_get_key(ctx, email, &key, 0); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ signing.c:506:8: note: ‘email’ was declared here 506 | char *email; | ^~~~~ cc1: all warnings being treated as errors if(email_from_uid(uid, &email) == 0) { ret = key_import_wkd(handle, email); }
pacman should be able to extract an email address from PACKAGER for WKD
lookup, so issue a warning if it is not of the form
"Example Name
On 3/10/19 12:40 am, Jonas Witschel wrote:
pacman should be able to extract an email address from PACKAGER for WKD lookup, so issue a warning if it is not of the form "Example Name
". Neither the name nor the email address must contain additional angle brackets.
Thanks. I have applied and will send through changes to makepkg.conf.5 that mention this restriction. Allan
participants (4)
-
Allan McRae
-
Eli Schwartz
-
Jonas Witschel
-
Jonas Witschel