From c7ea98cd3d44abf00e32c081e5049ad1d0b1f12c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 10 Nov 2016 11:38:42 +0100 Subject: [PATCH] dirmngr: Improve concurrency in the non-adns case. * dirmngr/dns-stuff.c (map_adns_status_to_gpg_error): New. (resolve_name_adns, get_dns_cert, get_dns_cname): Use that function. (getsrv) [!USE_ADNS]: Call res_query outside of nPth. Signed-off-by: Werner Koch --- dirmngr/dns-stuff.c | 26 +++++++++++++-- dirmngr/ks-engine-hkp.c | 71 +++++++++++++++++++++-------------------- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c index 70554f6f3..6849af4be 100644 --- a/dirmngr/dns-stuff.c +++ b/dirmngr/dns-stuff.c @@ -195,6 +195,21 @@ map_eai_to_gpg_error (int ec) return err; } +#ifdef USE_ADNS +static gpg_error_t +map_adns_status_to_gpg_error (adns_status status) +{ + gpg_err_code_t ec; + + switch (status) + { + /* case adns_s_netunreach: ec = GPG_ERR_ENETUNREACH; break; */ + default: ec = GPG_ERR_GENERAL; break; + } + return gpg_error (ec); +} +#endif /*USE_ADNS*/ + #ifdef USE_ADNS /* Init ADNS and store the new state at R_STATE. Returns 0 on @@ -286,6 +301,9 @@ resolve_name_adns (const char *name, unsigned short port, err = gpg_error (GPG_ERR_NOT_FOUND); if (answer->status != adns_s_ok || answer->type != adns_r_addr) { + err = map_adns_status_to_gpg_error (answer->status); + if (gpg_err_code (err) == GPG_ERR_GENERAL) + err = gpg_error (GPG_ERR_NOT_FOUND); log_error ("DNS query returned an error: %s (%s)\n", adns_strerror (answer->status), adns_errabbrev (answer->status)); @@ -692,7 +710,9 @@ get_dns_cert (const char *name, int want_certtype, /* log_error ("DNS query returned an error: %s (%s)\n", */ /* adns_strerror (answer->status), */ /* adns_errabbrev (answer->status)); */ - err = gpg_error (GPG_ERR_NOT_FOUND); + err = map_adns_status_to_gpg_error (answer->status); + if (gpg_err_code (err) == GPG_ERR_GENERAL) + err = gpg_error (GPG_ERR_NOT_FOUND); goto leave; } @@ -1095,7 +1115,9 @@ getsrv (const char *name,struct srventry **list) if (tor_mode) return -1; + my_unprotect (); r = res_query (name, C_IN, T_SRV, answer, sizeof answer); + my_protect (); if (r < sizeof (HEADER) || r > sizeof answer || header->rcode != NOERROR || !(count=ntohs (header->ancount))) return 0; /* Error or no record found. */ @@ -1289,7 +1311,7 @@ get_dns_cname (const char *name, char **r_cname) if (answer->status != adns_s_ok || answer->type != adns_r_cname || answer->nrrs != 1) { - err = gpg_error (GPG_ERR_GENERAL); + err = map_adns_status_to_gpg_error (answer->status); log_error ("DNS query returned an error or no records: %s (%s)\n", adns_strerror (answer->status), adns_errabbrev (answer->status)); diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 853085163..3b5e75d62 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -447,45 +447,48 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, } hi = hosttable[idx]; -#ifdef USE_DNS_SRV - /* Check for SRV records. */ - srvrecord = xtryasprintf ("_hkp._tcp.%s", name); - if (srvrecord == NULL) +#ifdef USE_DNS_SRV + if (!is_ip_address (name)) { - err = gpg_error_from_syserror (); - xfree (reftbl); - return err; - } - - srvscount = getsrv (srvrecord, &srvs); - xfree (srvrecord); - if (srvscount < 0) - { - err = gpg_error_from_syserror (); - xfree (reftbl); - return err; - } - - if (srvscount > 0) - { - int i; - is_pool = srvscount > 1; - - for (i = 0; i < srvscount; i++) + /* Check for SRV records. */ + srvrecord = xtryasprintf ("_hkp._tcp.%s", name); + if (srvrecord == NULL) { - err = resolve_dns_name (srvs[i].target, 0, - AF_UNSPEC, SOCK_STREAM, - &ai, &cname); - if (err) - continue; - dirmngr_tick (ctrl); - add_host (name, is_pool, ai, srvs[i].port, - reftbl, reftblsize, &refidx); + err = gpg_error_from_syserror (); + xfree (reftbl); + return err; } - xfree (srvs); + srvscount = getsrv (srvrecord, &srvs); + xfree (srvrecord); + if (srvscount < 0) + { + err = gpg_error_from_syserror (); + xfree (reftbl); + return err; + } + + if (srvscount > 0) + { + int i; + is_pool = srvscount > 1; + + for (i = 0; i < srvscount; i++) + { + err = resolve_dns_name (srvs[i].target, 0, + AF_UNSPEC, SOCK_STREAM, + &ai, &cname); + if (err) + continue; + dirmngr_tick (ctrl); + add_host (name, is_pool, ai, srvs[i].port, + reftbl, reftblsize, &refidx); + } + + xfree (srvs); + } } -#endif /* USE_DNS_SRV */ +#endif /* USE_DNS_SRV */ /* Find all A records for this entry and put them into the pool list - if any. */