gpg: Make preferred keyservers work.

* g10/call-dirmngr.c (dirmngr_local_s): Add field set_keyservers_done.
(create_context): Move keyserver setting to ...
(open_context): here.
(clear_context_flags): New.
(gpg_dirmngr_ks_get): Add arg override_keyserver.
* g10/keyserver.c (keyserver_refresh): Improve diagnostics.
(keyserver_get_chunk): Ditto.  Pass OVERRIDE_KEYSERVER to ks_get.
--

It used to ignore the given server but showed a diagnostics that it
will be used.
This commit is contained in:
Werner Koch 2015-04-21 15:36:30 +02:00
parent da1990bac7
commit ae0d65f864
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 102 additions and 36 deletions

View File

@ -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 --");

View File

@ -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);

View File

@ -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)