diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index ef4ca7651..26955abbf 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -94,6 +94,9 @@ struct dirmngr_local_s /* The active Assuan context. */ assuan_context_t ctx; + /* Flag set when the keyserver names have been send. */ + int set_keyservers_done; + /* Flag set to true while an operation is running on CTX. */ int is_active; }; @@ -145,32 +148,9 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx) } else if (!err) { - keyserver_spec_t ksi; - /* Tell the dirmngr that we want to collect audit event. */ /* err = assuan_transact (agent_ctx, "OPTION audit-events=1", */ /* NULL, NULL, NULL, NULL, NULL, NULL); */ - - /* Set all configured keyservers. We clear existing keyservers - so that any keyserver configured in GPG overrides keyservers - possibly still configured in Dirmngr for the session (Note - that the keyserver list of a session in Dirmngr survives a - RESET. */ - for (ksi = opt.keyserver; !err && ksi; ksi = ksi->next) - { - char *line; - - line = xtryasprintf ("KEYSERVER%s %s", - ksi == opt.keyserver? " --clear":"", ksi->uri); - if (!line) - err = gpg_error_from_syserror (); - else - { - err = assuan_transact (ctx, line, - NULL, NULL, NULL, NULL, NULL, NULL); - xfree (line); - } - } } if (err) @@ -205,7 +185,42 @@ open_context (ctrl_t ctrl, assuan_context_t *r_ctx) { /* Found an inactive local session - return that. */ assert (!dml->is_active); + + /* But first do the per session init if not yet done. */ + if (!dml->set_keyservers_done) + { + keyserver_spec_t ksi; + + /* Set all configured keyservers. We clear existing + keyservers so that any keyserver configured in GPG + overrides keyservers possibly still configured in Dirmngr + for the session (Note that the keyserver list of a + session in Dirmngr survives a RESET. */ + for (ksi = opt.keyserver; ksi; ksi = ksi->next) + { + char *line; + + line = xtryasprintf + ("KEYSERVER%s %s", + ksi == opt.keyserver? " --clear":"", ksi->uri); + if (!line) + err = gpg_error_from_syserror (); + else + { + err = assuan_transact (dml->ctx, line, NULL, NULL, NULL, + NULL, NULL, NULL); + xfree (line); + } + + if (err) + return err; + } + + dml->set_keyservers_done = 1; + } + dml->is_active = 1; + *r_ctx = dml->ctx; return 0; } @@ -219,6 +234,7 @@ open_context (ctrl_t ctrl, assuan_context_t *r_ctx) xfree (dml); return err; } + /* To be on the nPth thread safe site we need to add it to a list; this is far easier than to have a lock for this function. It should not happen anyway but the code is free @@ -253,6 +269,29 @@ close_context (ctrl_t ctrl, assuan_context_t ctx) } +/* Clear the set_keyservers_done flag on context CTX. */ +static void +clear_context_flags (ctrl_t ctrl, assuan_context_t ctx) +{ + dirmngr_local_t dml; + + if (!ctx) + return; + + for (dml = ctrl->dirmngr_local; dml; dml = dml->next) + { + if (dml->ctx == ctx) + { + if (!dml->is_active) + log_fatal ("clear_context_flags on inactive dirmngr ctx %p\n", ctx); + dml->set_keyservers_done = 0; + return; + } + } + log_fatal ("clear_context_flags on unknown dirmngr ctx %p\n", ctx); +} + + /* Status callback for ks_get and ks_search. */ static gpg_error_t @@ -453,6 +492,7 @@ 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, estream_t *r_fp, char **r_source) { gpg_error_t err; @@ -475,6 +515,27 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, if (err) return err; + /* 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. */ + if (override_keyserver) + { + clear_context_flags (ctrl, ctx); + line = xtryasprintf ("KEYSERVER --clear %s", override_keyserver->uri); + if (!line) + { + err = gpg_error_from_syserror (); + goto leave; + } + err = assuan_transact (ctx, line, NULL, NULL, NULL, + NULL, NULL, NULL); + if (err) + goto leave; + + xfree (line); + line = NULL; + } + /* Lump all patterns into one string. */ init_membuf (&mb, 1024); put_membuf_str (&mb, "KS_GET --"); diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h index 481b948d9..bae11238c 100644 --- a/g10/call-dirmngr.h +++ b/g10/call-dirmngr.h @@ -25,6 +25,7 @@ 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, 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/keyserver.c b/g10/keyserver.c index 3aed54bc9..674eb8119 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -112,7 +112,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 *keyserver, + struct keyserver_spec *override_keyserver, unsigned char **r_fpr, size_t *r_fprlen); static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs, struct keyserver_spec *keyserver); @@ -1394,6 +1394,9 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) { struct keyserver_spec *keyserver=desc[i].skipfncvalue; + if (!opt.quiet) + log_info (_("refreshing 1 key from %s\n"), keyserver->uri); + /* We use the keyserver structure we parsed out before. Note that a preferred keyserver without a scheme:// will be interpreted as hkp:// */ @@ -1418,7 +1421,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) if(count>0) { - if(opt.keyserver) + if(opt.keyserver && !opt.quiet) { if(count==1) log_info(_("refreshing 1 key from %s\n"),opt.keyserver->uri); @@ -1556,7 +1559,7 @@ static gpg_error_t keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, int *r_ndesc_used, void *stats_handle, - struct keyserver_spec *keyserver, + struct keyserver_spec *override_keyserver, unsigned char **r_fpr, size_t *r_fprlen) { @@ -1672,15 +1675,15 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, return err; } - if (!quiet && keyserver) + if (!quiet && override_keyserver) { - if (keyserver->host) + if (override_keyserver->host) log_info (_("requesting key %s from %s server %s\n"), keystr_from_desc (&desc[idx]), - keyserver->scheme, keyserver->host); + override_keyserver->scheme, override_keyserver->host); else log_info (_("requesting key %s from %s\n"), - keystr_from_desc (&desc[idx]), keyserver->uri); + keystr_from_desc (&desc[idx]), override_keyserver->uri); } } @@ -1688,7 +1691,8 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, this is different from NPAT. */ *r_ndesc_used = idx; - err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream, &source); + err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, + &datastream, &source); for (idx=0; idx < npat; idx++) xfree (pattern[idx]); xfree (pattern); @@ -1728,12 +1732,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, /* Retrieve a key from a keyserver. The search pattern are in (DESC,NDESC). Allowed search modes are keyid, fingerprint, and - exact searches. KEYSERVER gives an optional override keyserver. If - (R_FPR,R_FPRLEN) are not NULL, they may return the fingerprint of a - single imported key. */ + 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. */ static gpg_error_t keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, - struct keyserver_spec *keyserver, + struct keyserver_spec *override_keyserver, unsigned char **r_fpr, size_t *r_fprlen) { gpg_error_t err; @@ -1746,7 +1750,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, for (;;) { err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle, - keyserver, r_fpr, r_fprlen); + override_keyserver, r_fpr, r_fprlen); if (!err) any_good = 1; if (err || ndesc_used >= ndesc)