gpg: With --auto-key-retrieve prefer WKD over keyservers.

* g10/mainproc.c (check_sig_and_print): Print a hint on how to make
use of the preferred keyserver.  Remove keyserver lookup just by the
keyid.  Try a WKD lookup before a keyserver lookup.
--

The use of the the keyid for lookups does not make much sense anymore
since for quite some time we do have the fingerprint as part of the
signature.

GnuPG-bug-id: 4595
Signed-off-by: Werner Koch <wk@gnupg.org>
(cherry picked from commit 96bf8f4778)
This commit is contained in:
Werner Koch 2019-07-05 09:31:58 +02:00
parent 6396f8d115
commit 3242837d20
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 84 additions and 55 deletions

View File

@ -1814,10 +1814,26 @@ These options enable or disable the automatic retrieving of keys from
a keyserver when verifying signatures made by keys that are not on the
local keyring. The default is @option{--no-auto-key-retrieve}.
If the method "wkd" is included in the list of methods given to
@option{auto-key-locate}, the signer's user ID is part of the
signature, and the option @option{--disable-signer-uid} is not used,
the "wkd" method may also be used to retrieve a key.
The order of methods tried to lookup the key is:
1. If a preferred keyserver is specified in the signature and the
option @option{honor-keyserver-url} is active (which is not the
default), that keyserver is tried. Note that the creator of the
signature uses the option @option{--sig-keyserver-url} to specify the
preferred keyserver for data signatures.
2. If the signature has the Signer's UID set (e.g. using
@option{--sender} while creating the signature) a Web Key Directory
(WKD) lookup is done. This is the default configuration but can be
disabled by removing WKD from the auto-key-locate list or by using the
option @option{--disable-signer-uid}.
3. If the option @option{honor-pka-record} is active, the legacy PKA
method is used.
4. If any keyserver is configured and the Issuer Fingerprint is part
of the signature (since GnuPG 2.1.16), the configured keyservers are
tried.
Note that this option makes a "web bug" like behavior possible.
Keyserver or Web Key Directory operators can see which keys you

View File

@ -333,7 +333,7 @@ parse_keyserver_uri (const char *string,int require_scheme)
{
/* Three slashes means network path with a default host name.
This is a hack because it does not crok all possible
combiantions. We should better repalce all code bythe parser
combinations. We should better replace all code by the parser
from http.c. */
keyserver->path = xstrdup (uri+2);
}

View File

@ -1746,7 +1746,6 @@ check_sig_and_print (CTX c, kbnode_t node)
int is_revkey = 0;
char *issuer_fpr = NULL;
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
int tried_ks_by_fpr;
if (opt.skip_verify)
{
@ -1897,12 +1896,17 @@ check_sig_and_print (CTX c, kbnode_t node)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
/* If the key isn't found, check for a preferred keyserver. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks)
/* If the key isn't found, check for a preferred keyserver. Note
* that this is only done if honor-keyserver-url has been set. We
* test for this in the loop so that we can show info about the
* preferred keyservers. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& sig->flags.pref_ks)
{
const byte *p;
int seq = 0;
size_t n;
int any_pref_ks = 0;
while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL)))
{
@ -1913,9 +1917,10 @@ check_sig_and_print (CTX c, kbnode_t node)
log_info(_("Key available at: ") );
print_utf8_buffer (log_get_stream(), p, n);
log_printf ("\n");
any_pref_ks = 1;
if (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE
&& opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)
if ((opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
&& (opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL))
{
struct keyserver_spec *spec;
@ -1924,6 +1929,10 @@ check_sig_and_print (CTX c, kbnode_t node)
{
int res;
if (DBG_LOOKUP)
log_debug ("trying auto-key-retrieve method %s\n",
"Pref-KS");
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
@ -1932,6 +1941,9 @@ check_sig_and_print (CTX c, kbnode_t node)
if (!res)
rc = do_check_sig (c, node, NULL,
&is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "Pref-KS",
gpg_strerror (res));
free_keyserver_spec (spec);
if (!rc)
@ -1939,10 +1951,43 @@ check_sig_and_print (CTX c, kbnode_t node)
}
}
}
if (any_pref_ks
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
&& !(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL))
log_info (_("Note: Use '%s' to make use of this info\n"),
"--keyserver-option honor-keyserver-url");
}
/* If the above methods didn't work, our next try is to retrieve the
* key from the WKD. This requires that WKD is in the AKL and the
* Signer's UID is in the signature. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
&& !opt.flags.disable_signer_uid
&& akl_has_wkd_method ()
&& sig->signers_uid)
{
int res;
if (DBG_LOOKUP)
log_debug ("trying auto-key-retrieve method %s\n", "WKD");
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL);
glo_ctrl.in_auto_key_retrieve--;
/* Fixme: If the fingerprint is embedded in the signature,
* compare it to the fingerprint of the returned key. */
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res));
}
/* If the avove methods didn't work, our next try is to use the URI
* from a DNS PKA record. */
* from a DNS PKA record. This is a legacy method which will
* eventually be removed. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
&& (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
@ -1959,6 +2004,9 @@ check_sig_and_print (CTX c, kbnode_t node)
spec = parse_keyserver_uri (uri, 1);
if (spec)
{
if (DBG_LOOKUP)
log_debug ("trying auto-key-retrieve method %s\n", "PKA");
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
@ -1967,16 +2015,16 @@ check_sig_and_print (CTX c, kbnode_t node)
free_keyserver_spec (spec);
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "PKA",
gpg_strerror (res));
}
}
}
/* If the above methods didn't work, our next try is to locate
* the key via its fingerprint from a keyserver. This requires
* that the signers fingerprint is encoded in the signature. We
* favor this over the WKD method (to be tried next), because an
* arbitrary keyserver is less subject to web bug like monitoring. */
tried_ks_by_fpr = 0;
* that the signers fingerprint is encoded in the signature. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
&& keyserver_any_configured (c->ctrl))
@ -1989,56 +2037,21 @@ check_sig_and_print (CTX c, kbnode_t node)
if (p)
{
/* v4 packet with a SHA-1 fingerprint. */
if (DBG_LOOKUP)
log_debug ("trying auto-key-retrieve method %s\n", "KS");
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, 1);
tried_ks_by_fpr = 1;
glo_ctrl.in_auto_key_retrieve--;
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res));
}
}
/* If the above methods didn't work, our next try is to retrieve the
* key from the WKD. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
&& !opt.flags.disable_signer_uid
&& akl_has_wkd_method ()
&& sig->signers_uid)
{
int res;
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL);
glo_ctrl.in_auto_key_retrieve--;
/* Fixme: If the fingerprint is embedded in the signature,
* compare it to the fingerprint of the returned key. */
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
}
/* If the above methods did't work, our next try is to use a
* keyserver. */
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
&& (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
&& !tried_ks_by_fpr
&& keyserver_any_configured (c->ctrl))
{
int res;
free_public_key (pk);
pk = NULL;
glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver, 1);
glo_ctrl.in_auto_key_retrieve--;
if (!res)
rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
}
if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
{
kbnode_t un, keyblock;