mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02: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
7 changed files with 181 additions and 46 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue