1
0
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:
Werner Koch 2021-04-21 18:32:21 +02:00
parent f79e9540ca
commit ec36eca08c
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 181 additions and 46 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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,

View File

@ -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)
{ {