mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Allow fingerprint based lookup with --locate-external-key.
* g10/keyserver.c (keyserver_import_fprint_ntds): New. * g10/getkey.c (get_pubkey_byname): Detect an attempt to search by fingerprint in no_local mode. -- See the man page. For testing use gpg --auto-key-locate local,wkd,keyserver --locate-external-key \ FINGERPRINT with at least one LDAP keyserver given in dirmngr.conf. On Windows "ntds" may be used instead or in addtion to "keyserver". Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
f79e9540ca
commit
ec36eca08c
26
doc/gpg.texi
26
doc/gpg.texi
@ -355,11 +355,17 @@ numbers 1-9 or "T" for 10 and above to indicate trust signature levels
|
||||
Locate the keys given as arguments. This command basically uses the
|
||||
same algorithm as used when locating keys for encryption and may thus
|
||||
be used to see what keys @command{@gpgname} might use. In particular
|
||||
external methods as defined by @option{--auto-key-locate} may be used
|
||||
to locate a key. Only public keys are listed. The variant
|
||||
@option{--locate-external-keys} does not consider a locally existing
|
||||
key and can thus be used to force the refresh of a key via the defined
|
||||
external methods.
|
||||
external methods as defined by @option{--auto-key-locate} are used to
|
||||
locate a key if the arguments comain valid mail addresses. Only
|
||||
public keys are listed.
|
||||
|
||||
The variant @option{--locate-external-keys} does not consider a
|
||||
locally existing key and can thus be used to force the refresh of a
|
||||
key via the defined external methods. If a fingerprint is given and
|
||||
and the methods defined by --auto-key-locate define LDAP servers, the
|
||||
key is fetched from these resources; defined non-LDAP keyservers are
|
||||
skipped.
|
||||
|
||||
|
||||
@item --show-keys
|
||||
@opindex show-keys
|
||||
@ -1842,14 +1848,20 @@ list. The default is "local,wkd".
|
||||
PGP Universal method of checking @samp{ldap://keys.(thedomain)}.
|
||||
|
||||
@item ntds
|
||||
Locate the key using the Active Directory (Windows only).
|
||||
Locate the key using the Active Directory (Windows only). This
|
||||
method also allows to search by fingerprint using the command
|
||||
@option{--locate-external-key}.
|
||||
|
||||
@item keyserver
|
||||
Locate a key using a keyserver.
|
||||
Locate a key using a keyserver. This method also allows to search
|
||||
by fingerprint using the command @option{--locate-external-key} if
|
||||
any of the configured keyservers is an LDAP server.
|
||||
|
||||
@item keyserver-URL
|
||||
In addition, a keyserver URL as used in the @command{dirmngr}
|
||||
configuration may be used here to query that particular keyserver.
|
||||
This method also allows to search by fingerprint using the command
|
||||
@option{--locate-external-key} if the URL specifies an LDAP server.
|
||||
|
||||
@item local
|
||||
Locate the key using the local keyrings. This mechanism allows the user to
|
||||
|
@ -678,7 +678,7 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
|
||||
|
||||
/* If we have an override keyserver we first indicate that the next
|
||||
user of the context needs to again setup the global keyservers and
|
||||
them we send the override keyserver. */
|
||||
then we send the override keyserver. */
|
||||
if (override_keyserver)
|
||||
{
|
||||
clear_context_flags (ctrl, ctx);
|
||||
|
155
g10/getkey.c
155
g10/getkey.c
@ -925,11 +925,13 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
int rc;
|
||||
strlist_t namelist = NULL;
|
||||
struct akl *akl;
|
||||
int is_mbox;
|
||||
int is_mbox, is_fpr;
|
||||
KEYDB_SEARCH_DESC fprbuf;
|
||||
int nodefault = 0;
|
||||
int anylocalfirst = 0;
|
||||
int mechanism_type = AKL_NODEFAULT;
|
||||
|
||||
|
||||
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
|
||||
log_assert (retctx == NULL || ret_kdbhd == NULL);
|
||||
|
||||
@ -950,6 +952,18 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
is_mbox = 1;
|
||||
}
|
||||
|
||||
/* If we are called due to --locate-external-key Check whether NAME
|
||||
* is a fingerprint and then try to lookup that key by configured
|
||||
* method which support lookup by fingerprint. FPRBUF carries the
|
||||
* parsed fingerpint iff IS_FPR is true. */
|
||||
is_fpr = 0;
|
||||
if (!is_mbox && mode == GET_PUBKEY_NO_LOCAL)
|
||||
{
|
||||
if (!classify_user_id (name, &fprbuf, 1)
|
||||
&& fprbuf.mode == KEYDB_SEARCH_MODE_FPR)
|
||||
is_fpr = 1;
|
||||
}
|
||||
|
||||
/* The auto-key-locate feature works as follows: there are a number
|
||||
* of methods to look up keys. By default, the local keyring is
|
||||
* tried first. Then, each method listed in the --auto-key-locate is
|
||||
@ -1027,7 +1041,7 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
retrieval has been enabled, we try to import the key. */
|
||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||
&& mode != GET_PUBKEY_NO_AKL
|
||||
&& is_mbox)
|
||||
&& (is_mbox || is_fpr))
|
||||
{
|
||||
/* NAME wasn't present in the local keyring (or we didn't try
|
||||
* the local keyring). Since the auto key locate feature is
|
||||
@ -1053,6 +1067,8 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
case AKL_LOCAL:
|
||||
if (mode == GET_PUBKEY_NO_LOCAL)
|
||||
{
|
||||
/* Note that we get here in is_fpr more, so there is
|
||||
* no extra check for it required. */
|
||||
mechanism_string = "";
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
}
|
||||
@ -1073,41 +1089,80 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
break;
|
||||
|
||||
case AKL_CERT:
|
||||
mechanism_string = "DNS CERT";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
break;
|
||||
if (is_fpr)
|
||||
{
|
||||
mechanism_string = "";
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
mechanism_string = "DNS CERT";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
break;
|
||||
|
||||
case AKL_PKA:
|
||||
/* This is now obsolete. */
|
||||
break;
|
||||
|
||||
case AKL_DANE:
|
||||
mechanism_string = "DANE";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (is_fpr)
|
||||
{
|
||||
mechanism_string = "";
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mechanism_string = "DANE";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
break;
|
||||
|
||||
case AKL_WKD:
|
||||
mechanism_string = "WKD";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (is_fpr)
|
||||
{
|
||||
mechanism_string = "";
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mechanism_string = "WKD";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
break;
|
||||
|
||||
case AKL_LDAP:
|
||||
mechanism_string = "LDAP";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
break;
|
||||
if (is_fpr)
|
||||
{
|
||||
mechanism_string = "";
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mechanism_string = "LDAP";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
break;
|
||||
|
||||
case AKL_NTDS:
|
||||
mechanism_string = "NTDS";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_ntds (ctrl, name, &fpr, &fpr_len);
|
||||
if (is_fpr)
|
||||
rc = keyserver_import_fprint_ntds (ctrl,
|
||||
fprbuf.u.fpr, fprbuf.fprlen);
|
||||
else
|
||||
rc = keyserver_import_ntds (ctrl, name, &fpr, &fpr_len);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
break;
|
||||
|
||||
@ -1120,8 +1175,25 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
{
|
||||
mechanism_string = "keyserver";
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
|
||||
opt.keyserver);
|
||||
if (is_fpr)
|
||||
{
|
||||
rc = keyserver_import_fprint (ctrl,
|
||||
fprbuf.u.fpr, fprbuf.fprlen,
|
||||
opt.keyserver,
|
||||
KEYSERVER_IMPORT_FLAG_LDAP);
|
||||
/* Map error codes because Dirmngr returns NO
|
||||
* DATA if the keyserver does not have the
|
||||
* requested key. It returns NO KEYSERVER if no
|
||||
* LDAP keyservers are configured. */
|
||||
if (gpg_err_code (rc) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (rc) == GPG_ERR_NO_KEYSERVER)
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
|
||||
opt.keyserver);
|
||||
}
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
else
|
||||
@ -1138,8 +1210,21 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
mechanism_string = akl->spec->uri;
|
||||
keyserver = keyserver_match (akl->spec);
|
||||
glo_ctrl.in_auto_key_retrieve++;
|
||||
rc = keyserver_import_name (ctrl,
|
||||
name, &fpr, &fpr_len, keyserver);
|
||||
if (is_fpr)
|
||||
{
|
||||
rc = keyserver_import_fprint (ctrl,
|
||||
fprbuf.u.fpr, fprbuf.fprlen,
|
||||
opt.keyserver,
|
||||
KEYSERVER_IMPORT_FLAG_LDAP);
|
||||
if (gpg_err_code (rc) == GPG_ERR_NO_DATA
|
||||
|| gpg_err_code (rc) == GPG_ERR_NO_KEYSERVER)
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = keyserver_import_name (ctrl, name,
|
||||
&fpr, &fpr_len, keyserver);
|
||||
}
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
}
|
||||
break;
|
||||
@ -1152,21 +1237,27 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
* requirement as the URL might point to a key put in by an
|
||||
* attacker. By forcing the use of the fingerprint, we
|
||||
* won't use the attacker's key here. */
|
||||
if (!rc && fpr)
|
||||
if (!rc && (fpr || is_fpr))
|
||||
{
|
||||
char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1];
|
||||
|
||||
log_assert (fpr_len <= MAX_FINGERPRINT_LEN);
|
||||
|
||||
free_strlist (namelist);
|
||||
namelist = NULL;
|
||||
|
||||
bin2hex (fpr, fpr_len, fpr_string);
|
||||
if (is_fpr)
|
||||
{
|
||||
log_assert (fprbuf.fprlen <= MAX_FINGERPRINT_LEN);
|
||||
bin2hex (fprbuf.u.fpr, fprbuf.fprlen, fpr_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_assert (fpr_len <= MAX_FINGERPRINT_LEN);
|
||||
bin2hex (fpr, fpr_len, fpr_string);
|
||||
}
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("auto-key-locate found fingerprint %s\n",
|
||||
fpr_string);
|
||||
|
||||
free_strlist (namelist);
|
||||
namelist = NULL;
|
||||
add_to_strlist (&namelist, fpr_string);
|
||||
}
|
||||
else if (!rc && !fpr && !did_akl_local)
|
||||
|
10
g10/gpgv.c
10
g10/gpgv.c
@ -443,6 +443,16 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_fprint_ntds (ctrl_t ctrl,
|
||||
const byte *fprint, size_t fprint_len)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fprint;
|
||||
(void)fprint_len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_cert (const char *name)
|
||||
{
|
||||
|
@ -41,6 +41,8 @@ int keyserver_import (ctrl_t ctrl, strlist_t users);
|
||||
int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags);
|
||||
int keyserver_import_fprint_ntds (ctrl_t ctrl,
|
||||
const byte *fprint, size_t fprint_len);
|
||||
int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags);
|
||||
|
@ -1155,27 +1155,37 @@ keyserver_import_ntds (ctrl_t ctrl, const char *mbox,
|
||||
|
||||
|
||||
int
|
||||
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint, size_t fprint_len,
|
||||
struct keyserver_spec *keyserver,
|
||||
unsigned int flags)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
memset(&desc,0,sizeof(desc));
|
||||
memset (&desc, 0, sizeof(desc));
|
||||
|
||||
if (fprint_len == 16 || fprint_len == 20 || fprint_len == 32)
|
||||
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
||||
else
|
||||
return -1;
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
memcpy(desc.u.fpr,fprint,fprint_len);
|
||||
memcpy (desc.u.fpr, fprint, fprint_len);
|
||||
desc.fprlen = fprint_len;
|
||||
|
||||
/* TODO: Warn here if the fingerprint we got doesn't match the one
|
||||
we asked for? */
|
||||
return keyserver_get (ctrl, &desc, 1, keyserver, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keyserver_import_fprint_ntds (ctrl_t ctrl,
|
||||
const byte *fprint, size_t fprint_len)
|
||||
{
|
||||
struct keyserver_spec keyserver = { NULL, "ldap:///" };
|
||||
|
||||
return keyserver_import_fprint (ctrl, fprint, fprint_len,
|
||||
&keyserver, KEYSERVER_IMPORT_FLAG_LDAP);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keyserver_import_keyid (ctrl_t ctrl,
|
||||
u32 *keyid,struct keyserver_spec *keyserver,
|
||||
|
@ -201,6 +201,16 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_fprint_ntds (ctrl_t ctrl,
|
||||
const byte *fprint, size_t fprint_len)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fprint;
|
||||
(void)fprint_len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
keyserver_import_cert (const char *name)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user