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>
(cherry picked from commit ec36eca08cdbf6653e7362e8e0e6c5f2c75b4a60)
This commit is contained in:
Werner Koch 2021-04-21 18:32:21 +02:00
parent b59af0e2a0
commit 2af217ecd7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 204 additions and 53 deletions

View File

@ -353,13 +353,18 @@ numbers 1-9 or "T" for 10 and above to indicate trust signature levels
@opindex locate-keys
@opindex locate-external-keys
Locate the keys given as arguments. This command basically uses the
same algorithm as used when locating keys for encryption or signing
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.
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} 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
@ -1811,14 +1816,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

View File

@ -710,7 +710,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);

View File

@ -1020,10 +1020,12 @@ 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;
size_t fprbuf_fprlen = 0;
/* If RETCTX is not NULL, then RET_KDBHD must be NULL. */
log_assert (retctx == NULL || ret_kdbhd == NULL);
@ -1045,6 +1047,30 @@ 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_FPR16
|| fprbuf.mode == KEYDB_SEARCH_MODE_FPR20
|| fprbuf.mode == KEYDB_SEARCH_MODE_FPR))
{
/* Note: We should get rid of the FPR16 because we don't
* support v3 keys anymore. However, in 2.3 the fingerprint
* code has already been reworked and thus it is
* questionable whether we should really tackle this here. */
if (fprbuf.mode == KEYDB_SEARCH_MODE_FPR16)
fprbuf_fprlen = 16;
else
fprbuf_fprlen = 20;
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
@ -1122,7 +1148,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
@ -1148,6 +1174,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;
}
@ -1168,44 +1196,88 @@ 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:
mechanism_string = "PKA";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
break;
if (is_fpr)
{
mechanism_string = "";
rc = GPG_ERR_NO_PUBKEY;
}
else
{
mechanism_string = "PKA";
glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--;
}
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;
}
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;
}
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;
}
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;
@ -1218,8 +1290,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
@ -1236,8 +1325,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;
@ -1250,21 +1352,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)

View File

@ -440,6 +440,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)
{

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

View File

@ -1175,28 +1175,38 @@ 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)
desc.mode=KEYDB_SEARCH_MODE_FPR16;
else if(fprint_len==20)
desc.mode=KEYDB_SEARCH_MODE_FPR20;
else
return -1;
return gpg_error (GPG_ERR_INV_ARG);
memcpy(desc.u.fpr,fprint,fprint_len);
memcpy (desc.u.fpr, fprint, 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,

View File

@ -198,6 +198,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)
{