diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c index 0c547947f..c2d8c374d 100644 --- a/dirmngr/ks-action.c +++ b/dirmngr/ks-action.c @@ -211,7 +211,7 @@ ks_action_search (ctrl_t ctrl, uri_item_t keyservers, keyservers and write the result to the provided output stream. */ gpg_error_t ks_action_get (ctrl_t ctrl, uri_item_t keyservers, - strlist_t patterns, estream_t outfp) + strlist_t patterns, int ldap_only, estream_t outfp) { gpg_error_t err = 0; gpg_error_t first_err = 0; @@ -238,6 +238,9 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers, || strcmp (uri->parsed_uri->scheme, "https") == 0); int is_ldap = 0; + if (ldap_only) + is_hkp_s = is_http_s = 0; + #if USE_LDAP is_ldap = (strcmp (uri->parsed_uri->scheme, "ldap") == 0 || strcmp (uri->parsed_uri->scheme, "ldaps") == 0 diff --git a/dirmngr/ks-action.h b/dirmngr/ks-action.h index d576ef00f..36e0cf05e 100644 --- a/dirmngr/ks-action.h +++ b/dirmngr/ks-action.h @@ -26,7 +26,7 @@ gpg_error_t ks_action_resolve (ctrl_t ctrl, uri_item_t keyservers); gpg_error_t ks_action_search (ctrl_t ctrl, uri_item_t keyservers, strlist_t patterns, estream_t outfp); gpg_error_t ks_action_get (ctrl_t ctrl, uri_item_t keyservers, - strlist_t patterns, estream_t outfp); + strlist_t patterns, int ldap_only, estream_t outfp); gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp); gpg_error_t ks_action_put (ctrl_t ctrl, uri_item_t keyservers, void *data, size_t datalen, diff --git a/dirmngr/server.c b/dirmngr/server.c index f6c2c45f1..0ccba2987 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -2403,11 +2403,12 @@ cmd_ks_search (assuan_context_t ctx, char *line) static const char hlp_ks_get[] = - "KS_GET {}\n" + "KS_GET [--quick] [--ldap] {}\n" "\n" "Get the keys matching PATTERN from the configured OpenPGP keyservers\n" "(see command KEYSERVER). Each pattern should be a keyid, a fingerprint,\n" - "or an exact name indicated by the '=' prefix."; + "or an exact name indicated by the '=' prefix. Option --quick uses a\n" + "shorter timeout; --ldap will use only ldap servers"; static gpg_error_t cmd_ks_get (assuan_context_t ctx, char *line) { @@ -2416,9 +2417,11 @@ cmd_ks_get (assuan_context_t ctx, char *line) strlist_t list, sl; char *p; estream_t outfp; + int ldap_only; if (has_option (line, "--quick")) ctrl->timeout = opt.connect_quick_timeout; + ldap_only = has_option (line, "--ldap"); line = skip_options (line); /* Break the line into a strlist. Each pattern is by @@ -2460,7 +2463,8 @@ cmd_ks_get (assuan_context_t ctx, char *line) ctrl->server_local->inhibit_data_logging = 1; ctrl->server_local->inhibit_data_logging_now = 0; ctrl->server_local->inhibit_data_logging_count = 0; - err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp); + err = ks_action_get (ctrl, ctrl->server_local->keyservers, + list, ldap_only, outfp); es_fclose (outfp); ctrl->server_local->inhibit_data_logging = 0; } diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index 21edab639..434b46795 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -38,6 +38,7 @@ #include "../common/asshelp.h" #include "../common/keyserver.h" #include "../common/status.h" +#include "keyserver-internal.h" #include "call-dirmngr.h" @@ -637,7 +638,9 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen) don't need to escape the patterns before sending them to the server. - If QUICK is set the dirmngr is advised to use a shorter timeout. + Bit values for FLAGS are: + - KEYSERVER_IMPORT_FLAG_QUICK :: dirmngr shall use a shorter timeout. + - KEYSERVER_IMPORT_FLAG_LDAP :: dirmngr shall only use LDAP or NTDS. If R_SOURCE is not NULL the source of the data is stored as a malloced string there. If a source is not known NULL is stored. @@ -649,7 +652,8 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen) are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once. */ gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, - keyserver_spec_t override_keyserver, int quick, + keyserver_spec_t override_keyserver, + unsigned int flags, estream_t *r_fp, char **r_source) { gpg_error_t err; @@ -695,7 +699,12 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, /* Lump all patterns into one string. */ init_membuf (&mb, 1024); - put_membuf_str (&mb, quick? "KS_GET --quick --" : "KS_GET --"); + put_membuf_str (&mb, "KS_GET"); + if ((flags & KEYSERVER_IMPORT_FLAG_QUICK)) + put_membuf_str (&mb, " --quick"); + if ((flags & KEYSERVER_IMPORT_FLAG_LDAP)) + put_membuf_str (&mb, " --ldap"); + put_membuf_str (&mb, " --"); for (idx=0; pattern[idx]; idx++) { put_membuf (&mb, " ", 1); /* Append Delimiter. */ diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h index 8679777c2..c0f1e0cec 100644 --- a/g10/call-dirmngr.h +++ b/g10/call-dirmngr.h @@ -26,7 +26,8 @@ gpg_error_t gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr, gpg_error_t (*cb)(void*, int, char *), void *cb_value); gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char *pattern[], - keyserver_spec_t override_keyserver, int quick, + keyserver_spec_t override_keyserver, + unsigned int flags, estream_t *r_fp, char **r_source); gpg_error_t gpg_dirmngr_ks_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp); diff --git a/g10/getkey.c b/g10/getkey.c index 70405c89d..6b8d44332 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -3875,6 +3875,24 @@ get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk, else if (fpr_card) { err = get_pubkey_byfprint (ctrl, pk, NULL, fpr_card, fpr_len); + if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) + { + if (opt.debug) + log_debug ("using LDAP to find public key for current card\n"); + err = keyserver_import_fprint (ctrl, fpr_card, fpr_len, + opt.keyserver, + KEYSERVER_IMPORT_FLAG_LDAP); + if (!err) + err = get_pubkey_byfprint (ctrl, pk, NULL, fpr_card, fpr_len); + else if (gpg_err_code (err) == GPG_ERR_NO_DATA + || gpg_err_code (err) == GPG_ERR_NO_KEYSERVER) + { + /* Dirmngr returns NO DATA is the selected keyserver + * does not have the requested key. It returns NO + * KEYSERVER if no LDAP keyservers are configured. */ + err = gpg_error (GPG_ERR_NO_PUBKEY); + } + } /* The key on card can be not suitable for requested usage. */ if (gpg_err_code (err) == GPG_ERR_UNUSABLE_PUBKEY) diff --git a/g10/gpgv.c b/g10/gpgv.c index 82fbf8fce..09c694c6a 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -423,23 +423,23 @@ keyserver_any_configured (ctrl_t ctrl) } int -keyserver_import_keyid (u32 *keyid, void *dummy, int quick) +keyserver_import_keyid (u32 *keyid, void *dummy, unsigned int flags) { (void)keyid; (void)dummy; - (void)quick; + (void)flags; return -1; } int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len, - struct keyserver_spec *keyserver, int quick) + struct keyserver_spec *keyserver, unsigned int flags) { (void)ctrl; (void)fprint; (void)fprint_len; (void)keyserver; - (void)quick; + (void)flags; return -1; } @@ -451,12 +451,12 @@ keyserver_import_cert (const char *name) } gpg_error_t -keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, +keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags, unsigned char **fpr, size_t *fpr_len) { (void)ctrl; (void)name; - (void)quick; + (void)flags; (void)fpr; (void)fpr_len; return GPG_ERR_BUG; diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index 6d0e7f4ae..ebbd6e914 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -25,6 +25,10 @@ #include "../common/iobuf.h" #include "../common/types.h" +/* Flags for the keyserver import functions. */ +#define KEYSERVER_IMPORT_FLAG_QUICK 1 +#define KEYSERVER_IMPORT_FLAG_LDAP 2 + int parse_keyserver_options(char *options); void free_keyserver_spec(struct keyserver_spec *keyserver); struct keyserver_spec *keyserver_match(struct keyserver_spec *spec); @@ -35,15 +39,18 @@ int keyserver_any_configured (ctrl_t ctrl); int keyserver_export (ctrl_t ctrl, strlist_t users); 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, int quick); + struct keyserver_spec *keyserver, + unsigned int flags); int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid, - struct keyserver_spec *keyserver, int quick); + struct keyserver_spec *keyserver, + unsigned int flags); gpg_error_t keyserver_refresh (ctrl_t ctrl, strlist_t users); gpg_error_t keyserver_search (ctrl_t ctrl, strlist_t tokens); int keyserver_fetch (ctrl_t ctrl, strlist_t urilist, int origin); int keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode, unsigned char **fpr,size_t *fpr_len); -gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, +gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name, + unsigned int flags, unsigned char **fpr, size_t *fpr_len); int keyserver_import_ntds (ctrl_t ctrl, const char *name, unsigned char **fpr,size_t *fpr_len); diff --git a/g10/keyserver.c b/g10/keyserver.c index c4a1d5e19..a0620565c 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -105,7 +105,7 @@ static struct parse_options keyserver_opts[]= static gpg_error_t keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, struct keyserver_spec *override_keyserver, - int quick, + unsigned int flags, unsigned char **r_fpr, size_t *r_fprlen); static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs); @@ -1156,7 +1156,8 @@ keyserver_import_ntds (ctrl_t ctrl, const char *mbox, int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len, - struct keyserver_spec *keyserver, int quick) + struct keyserver_spec *keyserver, + unsigned int flags) { KEYDB_SEARCH_DESC desc; @@ -1172,12 +1173,13 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t 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, quick, NULL, NULL); + return keyserver_get (ctrl, &desc, 1, keyserver, flags, NULL, NULL); } int keyserver_import_keyid (ctrl_t ctrl, - u32 *keyid,struct keyserver_spec *keyserver, int quick) + u32 *keyid,struct keyserver_spec *keyserver, + unsigned int flags) { KEYDB_SEARCH_DESC desc; @@ -1187,7 +1189,7 @@ keyserver_import_keyid (ctrl_t ctrl, desc.u.kid[0]=keyid[0]; desc.u.kid[1]=keyid[1]; - return keyserver_get (ctrl, &desc, 1, keyserver, quick, NULL, NULL); + return keyserver_get (ctrl, &desc, 1, keyserver, flags, NULL, NULL); } @@ -1579,7 +1581,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, int *r_ndesc_used, import_stats_t stats_handle, struct keyserver_spec *override_keyserver, - int quick, + unsigned int flags, unsigned char **r_fpr, size_t *r_fprlen) { @@ -1608,7 +1610,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, single request will be rejected only later by gpg_dirmngr_ks_get but we are sure that R_NDESC_USED has been updated. This avoids a possible indefinite loop. */ - linelen = 17; /* "KS_GET --quick --" */ + linelen = 24; /* "KS_GET --quick --ldap --" */ for (npat=npat_fpr=0, idx=0; idx < ndesc; idx++) { int quiet = 0; @@ -1732,7 +1734,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, only_fprs = (npat && npat == npat_fpr); - err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, quick, + err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, flags, &datastream, &source); for (idx=0; idx < npat; idx++) xfree (pattern[idx]); @@ -1786,11 +1788,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, (DESC,NDESC). Allowed search modes are keyid, fingerprint, and exact searches. OVERRIDE_KEYSERVER gives an optional override keyserver. If (R_FPR,R_FPRLEN) are not NULL, they may return the - fingerprint of a single imported key. If QUICK is set, dirmngr is - advised to use a shorter timeout. */ + fingerprint of a single imported key. If the FLAG bit + KEYSERVER_IMPORT_FLAG_QUICK is set, dirmngr is advised to use a + shorter timeout. */ static gpg_error_t keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, - struct keyserver_spec *override_keyserver, int quick, + struct keyserver_spec *override_keyserver, unsigned int flags, unsigned char **r_fpr, size_t *r_fprlen) { gpg_error_t err; @@ -1803,7 +1806,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, for (;;) { err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle, - override_keyserver, quick, r_fpr, r_fprlen); + override_keyserver, flags, r_fpr, r_fprlen); if (!err) any_good = 1; if (err || ndesc_used >= ndesc) @@ -2031,7 +2034,7 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode, /* Import a key using the Web Key Directory protocol. */ gpg_error_t -keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, +keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags, unsigned char **fpr, size_t *fpr_len) { gpg_error_t err; @@ -2050,7 +2053,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, return err; } - err = gpg_dirmngr_wkd_get (ctrl, mbox, quick, &key, &url); + err = gpg_dirmngr_wkd_get (ctrl, mbox, flags, &key, &url); if (err) ; else if (key) diff --git a/g10/mainproc.c b/g10/mainproc.c index a75755ee3..10cc69758 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -2011,7 +2011,8 @@ check_sig_and_print (CTX c, kbnode_t node) free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; - res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1); + res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, + KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, @@ -2050,7 +2051,8 @@ check_sig_and_print (CTX c, kbnode_t node) free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; - res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL); + res = keyserver_import_wkd (c->ctrl, sig->signers_uid, + KEYSERVER_IMPORT_FLAG_QUICK, NULL, NULL); glo_ctrl.in_auto_key_retrieve--; /* Fixme: If the fingerprint is embedded in the signature, * compare it to the fingerprint of the returned key. */ @@ -2082,7 +2084,8 @@ check_sig_and_print (CTX c, kbnode_t node) free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; - res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, 1); + res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, + KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, diff --git a/g10/test-stubs.c b/g10/test-stubs.c index 913d49890..174af82f7 100644 --- a/g10/test-stubs.c +++ b/g10/test-stubs.c @@ -181,23 +181,23 @@ keyserver_any_configured (ctrl_t ctrl) } int -keyserver_import_keyid (u32 *keyid, void *dummy, int quick) +keyserver_import_keyid (u32 *keyid, void *dummy, unsigned int flags) { (void)keyid; (void)dummy; - (void)quick; + (void)flags; return -1; } int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len, - struct keyserver_spec *keyserver, int quick) + struct keyserver_spec *keyserver, unsigned int flags) { (void)ctrl; (void)fprint; (void)fprint_len; (void)keyserver; - (void)quick; + (void)flags; return -1; } @@ -209,12 +209,12 @@ keyserver_import_cert (const char *name) } gpg_error_t -keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, +keyserver_import_wkd (ctrl_t ctrl, const char *name, unsigned int flags, unsigned char **fpr, size_t *fpr_len) { (void)ctrl; (void)name; - (void)quick; + (void)flags; (void)fpr; (void)fpr_len; return GPG_ERR_BUG;