From d4e2302d8f4a1ff52d56da4f8e3a5d1c6303822d Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 14 Nov 2017 16:24:12 +0100 Subject: [PATCH] dirmngr: Check for WKD support at session end * dirmngr/domaininfo.c (insert_or_update): Copy the name. * dirmngr/misc.c (copy_stream): Allow arg OUT to be NULL. * dirmngr/server.c (set_error): Protect CTX. (dirmngr_status): Protect against missing ASSUAN_CTX. (dirmngr_status_help): Ditto. (dirmngr_status_printf): Ditto. (cmd_wkd_get): Factor code out to ... (proc_wkd_get): new func. Support silent operation with no CTX. (task_check_wkd_support): New. -- This finalizes the feature to efficiently cache WKD checks. If a standard WKD query returns no data, we queue a test to be run after the end of the session (so that we do not delay the calling client). This check tests whether the server responsible for the queried address has WKD at all enabled. The test is done by checking whether the "policy" file exists. We do not check the "submission-address" file because that is not necessary for the web key operation. The policy file is now required. Signed-off-by: Werner Koch --- dirmngr/domaininfo.c | 1 + dirmngr/ks-action.c | 3 +- dirmngr/misc.c | 7 ++-- dirmngr/server.c | 79 +++++++++++++++++++++++++++++++------------- 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/dirmngr/domaininfo.c b/dirmngr/domaininfo.c index 90cdb856c..a2effffef 100644 --- a/dirmngr/domaininfo.c +++ b/dirmngr/domaininfo.c @@ -158,6 +158,7 @@ insert_or_update (const char *domain, di_new = xtrycalloc (1, sizeof *di + strlen (domain)); if (!di_new) return; /* Out of core - we ignore this. */ + strcpy (di_new->name, domain); /* Need to do another lookup because the malloc is a system call and * thus the hash array may have been changed by another thread. */ diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c index 857aab166..38cd02feb 100644 --- a/dirmngr/ks-action.c +++ b/dirmngr/ks-action.c @@ -296,7 +296,8 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers, /* Retrieve keys from URL and write the result to the provided output - stream OUTFP. */ + * stream OUTFP. If OUTFP is NULL the data is written to the bit + * bucket. */ gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp) { diff --git a/dirmngr/misc.c b/dirmngr/misc.c index 1716141a6..6291a9a35 100644 --- a/dirmngr/misc.c +++ b/dirmngr/misc.c @@ -636,7 +636,9 @@ armor_data (char **r_string, const void *data, size_t datalen) return 0; } -/* Copy all data from IN to OUT. */ + +/* Copy all data from IN to OUT. OUT may be NULL to use this fucntion + * as a dummy reader. */ gpg_error_t copy_stream (estream_t in, estream_t out) { @@ -647,9 +649,8 @@ copy_stream (estream_t in, estream_t out) { if (!nread) return 0; /* EOF */ - if (es_write (out, buffer, nread, NULL)) + if (out && es_write (out, buffer, nread, NULL)) break; - } return gpg_error_from_syserror (); } diff --git a/dirmngr/server.c b/dirmngr/server.c index 1fbd007a0..3d0768b2a 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -80,7 +80,8 @@ #define PARM_ERROR(t) assuan_set_error (ctx, \ gpg_error (GPG_ERR_ASS_PARAMETER), (t)) -#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t)) +#define set_error(e,t) (ctx ? assuan_set_error (ctx, gpg_error (e), (t)) \ + /**/: gpg_error (e)) @@ -828,15 +829,11 @@ cmd_dns_cert (assuan_context_t ctx, char *line) -static const char hlp_wkd_get[] = - "WKD_GET [--submission-address|--policy-flags] \n" - "\n" - "Return the key or other info for \n" - "from the Web Key Directory."; +/* Core of cmd_wkd_get and task_check_wkd_support. If CTX is NULL + * this function will not write anything to the assuan output. */ static gpg_error_t -cmd_wkd_get (assuan_context_t ctx, char *line) +proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) { - ctrl_t ctrl = assuan_get_pointer (ctx); gpg_error_t err = 0; char *mbox = NULL; char *domainbuf = NULL; @@ -895,7 +892,8 @@ cmd_wkd_get (assuan_context_t ctx, char *line) domainlen = strlen (domain); for (i = 0; i < srvscount; i++) { - log_debug ("srv: trying '%s:%hu'\n", srvs[i].target, srvs[i].port); + if (DBG_DNS) + log_debug ("srv: trying '%s:%hu'\n", srvs[i].target, srvs[i].port); targetlen = strlen (srvs[i].target); if ((targetlen > domainlen + 1 && srvs[i].target[targetlen - domainlen - 1] == '.' @@ -972,19 +970,24 @@ cmd_wkd_get (assuan_context_t ctx, char *line) { estream_t outfp; - outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); - if (!outfp) + outfp = ctx? es_fopencookie (ctx, "w", data_line_cookie_functions) : NULL; + if (!outfp && ctx) err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream"); else { - if (no_log) - ctrl->server_local->inhibit_data_logging = 1; - ctrl->server_local->inhibit_data_logging_now = 0; - ctrl->server_local->inhibit_data_logging_count = 0; + if (ctrl->server_local) + { + if (no_log) + 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_fetch (ctrl, uri, outfp); es_fclose (outfp); - ctrl->server_local->inhibit_data_logging = 0; + if (ctrl->server_local) + ctrl->server_local->inhibit_data_logging = 0; + /* Register the result under the domain name of MBOX. */ switch (gpg_err_code (err)) { @@ -998,8 +1001,9 @@ cmd_wkd_get (assuan_context_t ctx, char *line) break; case GPG_ERR_NO_DATA: - if (is_wkd_query) /* Mark that and schedule a check. */ + if (is_wkd_query && ctrl->server_local) { + /* Mark that and schedule a check. */ domaininfo_set_wkd_not_found (domain_orig); workqueue_add_task (task_check_wkd_support, domain_orig, ctrl->server_local->session_id, 1); @@ -1020,6 +1024,23 @@ cmd_wkd_get (assuan_context_t ctx, char *line) xfree (encodedhash); xfree (mbox); xfree (domainbuf); + return err; +} + + +static const char hlp_wkd_get[] = + "WKD_GET [--submission-address|--policy-flags] \n" + "\n" + "Return the key or other info for \n" + "from the Web Key Directory."; +static gpg_error_t +cmd_wkd_get (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err; + + err = proc_wkd_get (ctrl, ctx, line); + return leave_cmd (ctx, err); } @@ -1029,10 +1050,19 @@ cmd_wkd_get (assuan_context_t ctx, char *line) static const char * task_check_wkd_support (ctrl_t ctrl, const char *domain) { + char *string; + if (!ctrl || !domain) return "check_wkd_support"; - log_debug ("FIXME: Implement %s\n", __func__); + string = strconcat ("--policy-flags foo@", domain, NULL); + if (!string) + log_error ("%s: %s\n", __func__, gpg_strerror (gpg_error_from_syserror ())); + else + { + proc_wkd_get (ctrl, NULL, string); + xfree (string); + } return NULL; } @@ -2800,12 +2830,12 @@ dirmngr_status (ctrl_t ctrl, const char *keyword, ...) gpg_error_t err = 0; va_list arg_ptr; const char *text; + assuan_context_t ctx; va_start (arg_ptr, keyword); - if (ctrl->server_local) + if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx)) { - assuan_context_t ctx = ctrl->server_local->assuan_ctx; char buf[950], *p; size_t n; @@ -2835,10 +2865,10 @@ gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text) { gpg_error_t err = 0; + assuan_context_t ctx; - if (ctrl->server_local) + if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx)) { - assuan_context_t ctx = ctrl->server_local->assuan_ctx; char buf[950], *p; size_t n; @@ -2888,7 +2918,10 @@ dirmngr_status_printf (ctrl_t ctrl, const char *keyword, { gpg_error_t err; va_list arg_ptr; - assuan_context_t ctx = ctrl->server_local->assuan_ctx; + assuan_context_t ctx; + + if (!ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx)) + return 0; va_start (arg_ptr, format); err = vprint_assuan_status (ctx, keyword, format, arg_ptr);