diff options
author | Werner Koch <wk@gnupg.org> | 2021-04-21 18:32:21 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-04-21 18:32:21 +0200 |
commit | ec36eca08cdbf6653e7362e8e0e6c5f2c75b4a60 (patch) | |
tree | a6245bac6572285ae8958148e376677169e99a2d /g10 | |
parent | keyboxd: Fix searching for exact mail addresses. (diff) | |
download | gnupg2-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.c | 2 | ||||
-rw-r--r-- | g10/getkey.c | 155 | ||||
-rw-r--r-- | g10/gpgv.c | 10 | ||||
-rw-r--r-- | g10/keyserver-internal.h | 2 | ||||
-rw-r--r-- | g10/keyserver.c | 22 | ||||
-rw-r--r-- | g10/test-stubs.c | 10 |
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; |