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
|
Locate the keys given as arguments. This command basically uses the
|
||||||
same algorithm as used when locating keys for encryption and may thus
|
same algorithm as used when locating keys for encryption and may thus
|
||||||
be used to see what keys @command{@gpgname} might use. In particular
|
be used to see what keys @command{@gpgname} might use. In particular
|
||||||
external methods as defined by @option{--auto-key-locate} may be used
|
external methods as defined by @option{--auto-key-locate} are used to
|
||||||
to locate a key. Only public keys are listed. The variant
|
locate a key if the arguments comain valid mail addresses. Only
|
||||||
@option{--locate-external-keys} does not consider a locally existing
|
public keys are listed.
|
||||||
key and can thus be used to force the refresh of a key via the defined
|
|
||||||
external methods.
|
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
|
@item --show-keys
|
||||||
@opindex show-keys
|
@opindex show-keys
|
||||||
@ -1842,14 +1848,20 @@ list. The default is "local,wkd".
|
|||||||
PGP Universal method of checking @samp{ldap://keys.(thedomain)}.
|
PGP Universal method of checking @samp{ldap://keys.(thedomain)}.
|
||||||
|
|
||||||
@item ntds
|
@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
|
@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
|
@item keyserver-URL
|
||||||
In addition, a keyserver URL as used in the @command{dirmngr}
|
In addition, a keyserver URL as used in the @command{dirmngr}
|
||||||
configuration may be used here to query that particular keyserver.
|
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
|
@item local
|
||||||
Locate the key using the local keyrings. This mechanism allows the user to
|
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
|
/* If we have an override keyserver we first indicate that the next
|
||||||
user of the context needs to again setup the global keyservers and
|
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)
|
if (override_keyserver)
|
||||||
{
|
{
|
||||||
clear_context_flags (ctrl, ctx);
|
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;
|
int rc;
|
||||||
strlist_t namelist = NULL;
|
strlist_t namelist = NULL;
|
||||||
struct akl *akl;
|
struct akl *akl;
|
||||||
int is_mbox;
|
int is_mbox, is_fpr;
|
||||||
|
KEYDB_SEARCH_DESC fprbuf;
|
||||||
int nodefault = 0;
|
int nodefault = 0;
|
||||||
int anylocalfirst = 0;
|
int anylocalfirst = 0;
|
||||||
int mechanism_type = AKL_NODEFAULT;
|
int mechanism_type = AKL_NODEFAULT;
|
||||||
|
|
||||||
|
|
||||||
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
|
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
|
||||||
log_assert (retctx == NULL || ret_kdbhd == 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;
|
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
|
/* The auto-key-locate feature works as follows: there are a number
|
||||||
* of methods to look up keys. By default, the local keyring is
|
* of methods to look up keys. By default, the local keyring is
|
||||||
* tried first. Then, each method listed in the --auto-key-locate 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. */
|
retrieval has been enabled, we try to import the key. */
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
|
||||||
&& mode != GET_PUBKEY_NO_AKL
|
&& mode != GET_PUBKEY_NO_AKL
|
||||||
&& is_mbox)
|
&& (is_mbox || is_fpr))
|
||||||
{
|
{
|
||||||
/* NAME wasn't present in the local keyring (or we didn't try
|
/* NAME wasn't present in the local keyring (or we didn't try
|
||||||
* the local keyring). Since the auto key locate feature is
|
* 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:
|
case AKL_LOCAL:
|
||||||
if (mode == GET_PUBKEY_NO_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 = "";
|
mechanism_string = "";
|
||||||
rc = GPG_ERR_NO_PUBKEY;
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
}
|
}
|
||||||
@ -1073,41 +1089,80 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AKL_CERT:
|
case AKL_CERT:
|
||||||
mechanism_string = "DNS CERT";
|
if (is_fpr)
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
{
|
||||||
rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
|
mechanism_string = "";
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
break;
|
}
|
||||||
|
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:
|
case AKL_PKA:
|
||||||
/* This is now obsolete. */
|
/* This is now obsolete. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AKL_DANE:
|
case AKL_DANE:
|
||||||
mechanism_string = "DANE";
|
if (is_fpr)
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
{
|
||||||
rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
|
mechanism_string = "";
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
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;
|
break;
|
||||||
|
|
||||||
case AKL_WKD:
|
case AKL_WKD:
|
||||||
mechanism_string = "WKD";
|
if (is_fpr)
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
{
|
||||||
rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
|
mechanism_string = "";
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
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;
|
break;
|
||||||
|
|
||||||
case AKL_LDAP:
|
case AKL_LDAP:
|
||||||
mechanism_string = "LDAP";
|
if (is_fpr)
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
{
|
||||||
rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
|
mechanism_string = "";
|
||||||
glo_ctrl.in_auto_key_retrieve--;
|
rc = GPG_ERR_NO_PUBKEY;
|
||||||
break;
|
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:
|
case AKL_NTDS:
|
||||||
mechanism_string = "NTDS";
|
mechanism_string = "NTDS";
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
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--;
|
glo_ctrl.in_auto_key_retrieve--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1120,8 +1175,25 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
|||||||
{
|
{
|
||||||
mechanism_string = "keyserver";
|
mechanism_string = "keyserver";
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
|
if (is_fpr)
|
||||||
opt.keyserver);
|
{
|
||||||
|
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--;
|
glo_ctrl.in_auto_key_retrieve--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1138,8 +1210,21 @@ get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
|||||||
mechanism_string = akl->spec->uri;
|
mechanism_string = akl->spec->uri;
|
||||||
keyserver = keyserver_match (akl->spec);
|
keyserver = keyserver_match (akl->spec);
|
||||||
glo_ctrl.in_auto_key_retrieve++;
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
rc = keyserver_import_name (ctrl,
|
if (is_fpr)
|
||||||
name, &fpr, &fpr_len, keyserver);
|
{
|
||||||
|
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--;
|
glo_ctrl.in_auto_key_retrieve--;
|
||||||
}
|
}
|
||||||
break;
|
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
|
* requirement as the URL might point to a key put in by an
|
||||||
* attacker. By forcing the use of the fingerprint, we
|
* attacker. By forcing the use of the fingerprint, we
|
||||||
* won't use the attacker's key here. */
|
* won't use the attacker's key here. */
|
||||||
if (!rc && fpr)
|
if (!rc && (fpr || is_fpr))
|
||||||
{
|
{
|
||||||
char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1];
|
char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1];
|
||||||
|
|
||||||
log_assert (fpr_len <= MAX_FINGERPRINT_LEN);
|
if (is_fpr)
|
||||||
|
{
|
||||||
free_strlist (namelist);
|
log_assert (fprbuf.fprlen <= MAX_FINGERPRINT_LEN);
|
||||||
namelist = NULL;
|
bin2hex (fprbuf.u.fpr, fprbuf.fprlen, fpr_string);
|
||||||
|
}
|
||||||
bin2hex (fpr, fpr_len, fpr_string);
|
else
|
||||||
|
{
|
||||||
|
log_assert (fpr_len <= MAX_FINGERPRINT_LEN);
|
||||||
|
bin2hex (fpr, fpr_len, fpr_string);
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info ("auto-key-locate found fingerprint %s\n",
|
log_info ("auto-key-locate found fingerprint %s\n",
|
||||||
fpr_string);
|
fpr_string);
|
||||||
|
|
||||||
|
free_strlist (namelist);
|
||||||
|
namelist = NULL;
|
||||||
add_to_strlist (&namelist, fpr_string);
|
add_to_strlist (&namelist, fpr_string);
|
||||||
}
|
}
|
||||||
else if (!rc && !fpr && !did_akl_local)
|
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;
|
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
|
int
|
||||||
keyserver_import_cert (const char *name)
|
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,
|
int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
|
||||||
struct keyserver_spec *keyserver,
|
struct keyserver_spec *keyserver,
|
||||||
unsigned int flags);
|
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,
|
int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
|
||||||
struct keyserver_spec *keyserver,
|
struct keyserver_spec *keyserver,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
@ -1155,27 +1155,37 @@ keyserver_import_ntds (ctrl_t ctrl, const char *mbox,
|
|||||||
|
|
||||||
|
|
||||||
int
|
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,
|
struct keyserver_spec *keyserver,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
|
||||||
memset(&desc,0,sizeof(desc));
|
memset (&desc, 0, sizeof(desc));
|
||||||
|
|
||||||
if (fprint_len == 16 || fprint_len == 20 || fprint_len == 32)
|
if (fprint_len == 16 || fprint_len == 20 || fprint_len == 32)
|
||||||
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
||||||
else
|
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;
|
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);
|
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
|
int
|
||||||
keyserver_import_keyid (ctrl_t ctrl,
|
keyserver_import_keyid (ctrl_t ctrl,
|
||||||
u32 *keyid,struct keyserver_spec *keyserver,
|
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;
|
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
|
int
|
||||||
keyserver_import_cert (const char *name)
|
keyserver_import_cert (const char *name)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user