From a48e6de603c3a312f02b1b5fdb813032eeae9074 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 5 Oct 2015 17:44:20 +0200 Subject: [PATCH] dirmngr: Add option --keyserver. * dirmngr/dirmngr.c (oKeyServer): New. (opts): Add "keyserver". (parse_rereadable_options): Parse that options (main): Add option to the gpgconf list. * dirmngr/dirmngr.h (opt): Add field "keyserver". * dirmngr/server.c (ensure_keyserver): New. (make_keyserver_item): New. Factored out from (cmd_keyserver): here. Call ensure_keyserver. (cmd_ks_search): Call ensure_keyserver. (cmd_ks_get): Ditto. (cmd_ks_fetch): Ditto. (cmd_ks_put): Ditto. -- This option specifies the keyserver to be used if the client does not set another keyserver. We want to fade out the use of --keyserver in gpg.conf in favor of specifying it here. Signed-off-by: Werner Koch --- dirmngr/dirmngr.c | 13 +++++- dirmngr/dirmngr.h | 2 + dirmngr/server.c | 115 ++++++++++++++++++++++++++++++++++++---------- doc/dirmngr.texi | 19 ++++++++ 4 files changed, 124 insertions(+), 25 deletions(-) diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 31833ebd6..847a65d51 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -141,6 +141,7 @@ enum cmd_and_opt_values { oHTTPWrapperProgram, oIgnoreCertExtension, oUseTor, + oKeyServer, aTest }; @@ -213,6 +214,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_i (oMaxReplies, "max-replies", N_("|N|do not return more than N items in one query")), + ARGPARSE_s_s (oKeyServer, "keyserver", "@"), ARGPARSE_s_s (oHkpCaCert, "hkp-cacert", N_("|FILE|use the CA certificates in FILE for HKP over TLS")), @@ -520,7 +522,9 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) } FREE_STRLIST (opt.ignored_cert_extensions); http_register_tls_ca (NULL); - /* We do not allow resetting of opt.use_tor at runtime. */ + xfree (opt.keyserver); + opt.keyserver = NULL; + /* Note: We do not allow resetting of opt.use_tor at runtime. */ return 1; } @@ -585,6 +589,11 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oUseTor: opt.use_tor = 1; break; + case oKeyServer: + xfree (opt.keyserver); + opt.keyserver = *pargs->r.ret_str? xtrystrdup (pargs->r.ret_str) : NULL; + break; + default: return 0; /* Not handled. */ } @@ -1418,7 +1427,9 @@ main (int argc, char **argv) /* Note: The next one is to fix a typo in gpgconf - should be removed eventually. */ es_printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("use-tor:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("keyserver:%lu:\n", flags | GC_OPT_FLAG_NONE); } cleanup (); return !!rc; diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h index a2db62755..b2b94f9c8 100644 --- a/dirmngr/dirmngr.h +++ b/dirmngr/dirmngr.h @@ -130,6 +130,8 @@ struct considered valid after thisUpdate. */ unsigned int ocsp_current_period; /* Seconds a response is considered current after nextUpdate. */ + + char *keyserver; /* Malloced string with the default keyserver. */ } opt; diff --git a/dirmngr/server.c b/dirmngr/server.c index 694a881cc..5400a9876 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -1626,7 +1626,65 @@ cmd_validate (assuan_context_t ctx, char *line) return leave_cmd (ctx, err); } + +/* Parse an keyserver URI and store it in a new uri item which is + returned at R_ITEM. On error return an error code. */ +static gpg_error_t +make_keyserver_item (const char *uri, uri_item_t *r_item) +{ + gpg_error_t err; + uri_item_t item; + + *r_item = NULL; + item = xtrymalloc (sizeof *item + strlen (uri)); + if (!item) + return gpg_error_from_syserror (); + + item->next = NULL; + item->parsed_uri = NULL; + strcpy (item->uri, uri); + +#if USE_LDAP + if (ldap_uri_p (item->uri)) + err = ldap_parse_uri (&item->parsed_uri, uri); + else +#endif + { + err = http_parse_uri (&item->parsed_uri, uri, 1); + } + + if (err) + xfree (item); + else + *r_item = item; + return err; +} + + +/* If no keyserver is stored in CTRL but a global keyserver has been + set, put that global keyserver into CTRL. We need use this + function to help migrate from the old gpg based keyserver + configuration to the new dirmngr based configuration. */ +static gpg_error_t +ensure_keyserver (ctrl_t ctrl) +{ + gpg_error_t err; + uri_item_t item; + + if (ctrl->server_local->keyservers) + return 0; /* Already set for this session. */ + if (!opt.keyserver) + return 0; /* No global option set. */ + + err = make_keyserver_item (opt.keyserver, &item); + if (!err) + ctrl->server_local->keyservers = item; + + return err; +} + + static const char hlp_keyserver[] = "KEYSERVER [] [|]\n" "Options are:\n" @@ -1671,7 +1729,9 @@ cmd_keyserver (assuan_context_t ctx, char *line) if (resolve_flag) { - err = ks_action_resolve (ctrl, ctrl->server_local->keyservers); + err = ensure_keyserver (ctrl); + if (!err) + err = ks_action_resolve (ctrl, ctrl->server_local->keyservers); if (err) goto leave; } @@ -1711,29 +1771,9 @@ cmd_keyserver (assuan_context_t ctx, char *line) if (add_flag) { - item = xtrymalloc (sizeof *item + strlen (line)); - if (!item) - { - err = gpg_error_from_syserror (); - goto leave; - } - item->next = NULL; - item->parsed_uri = NULL; - strcpy (item->uri, line); - -#if USE_LDAP - if (ldap_uri_p (item->uri)) - err = ldap_parse_uri (&item->parsed_uri, line); - else -#endif - { - err = http_parse_uri (&item->parsed_uri, line, 1); - } + err = make_keyserver_item (line, &item); if (err) - { - xfree (item); - goto leave; - } + goto leave; } if (clear_flag) release_ctrl_keyservers (ctrl); @@ -1743,10 +1783,20 @@ cmd_keyserver (assuan_context_t ctx, char *line) ctrl->server_local->keyservers = item; } - if (!add_flag && !clear_flag && !help_flag) /* List configured keyservers. */ + if (!add_flag && !clear_flag && !help_flag) { + /* List configured keyservers. However, we first add a global + keyserver. */ uri_item_t u; + err = ensure_keyserver (ctrl); + if (err) + { + assuan_set_error (ctx, err, + "Bad keyserver configuration in dirmngr.conf"); + goto leave; + } + for (u=ctrl->server_local->keyservers; u; u = u->next) dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL); } @@ -1799,6 +1849,10 @@ cmd_ks_search (assuan_context_t ctx, char *line) } } + err = ensure_keyserver (ctrl); + if (err) + goto leave; + /* Setup an output stream and perform the search. */ outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); if (!outfp) @@ -1861,6 +1915,10 @@ cmd_ks_get (assuan_context_t ctx, char *line) } } + err = ensure_keyserver (ctrl); + if (err) + goto leave; + /* Setup an output stream and perform the get. */ outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); if (!outfp) @@ -1891,6 +1949,10 @@ cmd_ks_fetch (assuan_context_t ctx, char *line) /* No options for now. */ line = skip_options (line); + err = ensure_keyserver (ctrl); + if (err) + goto leave; + /* Setup an output stream and perform the get. */ outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); if (!outfp) @@ -1901,6 +1963,7 @@ cmd_ks_fetch (assuan_context_t ctx, char *line) es_fclose (outfp); } + leave: return leave_cmd (ctx, err); } @@ -1936,6 +1999,10 @@ cmd_ks_put (assuan_context_t ctx, char *line) /* No options for now. */ line = skip_options (line); + err = ensure_keyserver (ctrl); + if (err) + goto leave; + /* Ask for the key material. */ err = assuan_inquire (ctx, "KEYBLOCK", &value, &valuelen, MAX_KEYBLOCK_LENGTH); diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index 7757acf10..a5bcc73d9 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -242,6 +242,25 @@ This options is not yet functional! It will eventually switch GnuPG into a TOR mode to route all network access via TOR (an anonymity network). +@item --keyserver @code{name} +@opindex keyserver +Use @code{name} as your keyserver. This is the server that @command{gpg} +communicates with to receive keys, send keys, and search for +keys. The format of the @code{name} is a URI: +`scheme:[//]keyservername[:port]' The scheme is the type of keyserver: +"hkp" for the HTTP (or compatible) keyservers, "ldap" for the LDAP +keyservers, or "mailto" for the Graff email keyserver. Note that your +particular installation of GnuPG may have other keyserver types +available as well. Keyserver schemes are case-insensitive. After the +keyserver name, optional keyserver configuration options may be +provided. These are the same as the global @option{--keyserver-options} +from below, but apply only to this particular keyserver. + +Most keyservers synchronize with each other, so there is generally no +need to send keys to more than one server. The keyserver +@code{hkp://keys.gnupg.net} uses round robin DNS to give a different +keyserver each time you use it. + @item --disable-ldap @opindex disable-ldap Entirely disables the use of LDAP.