summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2021-04-21 18:32:21 +0200
committerWerner Koch <wk@gnupg.org>2021-04-21 18:32:21 +0200
commitec36eca08cdbf6653e7362e8e0e6c5f2c75b4a60 (patch)
treea6245bac6572285ae8958148e376677169e99a2d /g10
parentkeyboxd: Fix searching for exact mail addresses. (diff)
downloadgnupg2-ec36eca08cdbf6653e7362e8e0e6c5f2c75b4a60.tar.xz
gnupg2-ec36eca08cdbf6653e7362e8e0e6c5f2c75b4a60.zip
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>
Diffstat (limited to 'g10')
-rw-r--r--g10/call-dirmngr.c2
-rw-r--r--g10/getkey.c155
-rw-r--r--g10/gpgv.c10
-rw-r--r--g10/keyserver-internal.h2
-rw-r--r--g10/keyserver.c22
-rw-r--r--g10/test-stubs.c10
6 files changed, 162 insertions, 39 deletions
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 434b46795..484395afb 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -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);
diff --git a/g10/getkey.c b/g10/getkey.c
index 6b8d44332..2d89fc4e5 100644
--- a/g10/getkey.c
+++ b/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)
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 09c694c6a..4c5cccb4e 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -444,6 +444,16 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
}
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)
{
(void)name;
diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h
index ebbd6e914..4b507b227 100644
--- a/g10/keyserver-internal.h
+++ b/g10/keyserver-internal.h
@@ -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);
diff --git a/g10/keyserver.c b/g10/keyserver.c
index a0620565c..492ce0ce5 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -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,
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index 174af82f7..3d3c73716 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -202,6 +202,16 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
}
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)
{
(void)name;