dirmngr: Improve concurrency in the non-adns case.
authorWerner Koch <wk@gnupg.org>
Thu, 10 Nov 2016 10:38:42 +0000 (11:38 +0100)
committerWerner Koch <wk@gnupg.org>
Thu, 10 Nov 2016 10:41:53 +0000 (11:41 +0100)
* 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 <wk@gnupg.org>
dirmngr/dns-stuff.c
dirmngr/ks-engine-hkp.c

index 70554f6..6849af4 100644 (file)
@@ -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));
index 8530851..3b5e75d 100644 (file)
@@ -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)
-        {
-          err = gpg_error_from_syserror ();
-          xfree (reftbl);
-          return err;
-        }
-
-      srvscount = getsrv (srvrecord, &srvs);
-      xfree (srvrecord);
-      if (srvscount < 0)
+#ifdef USE_DNS_SRV
+      if (!is_ip_address (name))
         {
-          err = gpg_error_from_syserror ();
-          xfree (reftbl);
-          return err;
-        }
-
-      if (srvscount > 0)
-        {
-          int i;
-          is_pool = srvscount > 1;
+          /* Check for SRV records.  */
+          srvrecord = xtryasprintf ("_hkp._tcp.%s", name);
+          if (srvrecord == NULL)
+            {
+              err = gpg_error_from_syserror ();
+              xfree (reftbl);
+              return err;
+            }
 
-          for (i = 0; i < srvscount; i++)
+          srvscount = getsrv (srvrecord, &srvs);
+          xfree (srvrecord);
+          if (srvscount < 0)
             {
-              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);
+          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.  */