dirmngr: Fix problems with the getsrv function.
authorWerner Koch <wk@gnupg.org>
Mon, 19 Dec 2016 22:27:02 +0000 (23:27 +0100)
committerWerner Koch <wk@gnupg.org>
Mon, 19 Dec 2016 22:27:02 +0000 (23:27 +0100)
* dirmngr/dns-stuff.c (opt_debug, opt_verbose): New vars.
(set_dns_verbose): New func.
(libdns_switch_port_p): Add debug output.
(resolve_dns_name): Ditto.
(get_dns_cert): Ditto.
(get_dns_cname): Ditto.
(getsrv_libdns, getsrv_standard): Change SRVCOUNT to an unsigend int.
(getsrv): Rename to ...
((get_dns_srv): this.  Add arg R_COUNT and return an error.  Add debug
output.
* dirmngr/http.c: Adjust for chnaged getsrv().
* dirmngr/ks-engine-hkp.c (map_host): Ditto.
* dirmngr/t-dns-stuff.c (main): Ditto.  Call set_dns_verbose.
* dirmngr/dirmngr.c (parse_rereadable_options): Call set_dns_verbose.
--

Due to our switch to Libdns getsrv didn't worked correctly because it
returned -1 for an NXDOMAIN.  However, it is perfectly okay to have no
SRV record and thus we change the way this function is called to be
aligned with the other functions and also map NXDOMAIN to a zero SRV
record count.

Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/dirmngr.c
dirmngr/dns-stuff.c
dirmngr/dns-stuff.h
dirmngr/http.c
dirmngr/ks-engine-hkp.c
dirmngr/t-dns-stuff.c

index 0d896f1..bb4d9f3 100644 (file)
@@ -640,6 +640,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       return 0; /* Not handled. */
     }
 
+  set_dns_verbose (opt.verbose, !!DBG_DNS);
+
   return 1; /* Handled. */
 }
 
index eae674f..08270a6 100644 (file)
 /* The default nameserver used in Tor mode.  */
 #define DEFAULT_NAMESERVER "8.8.8.8"
 
+/* Two flags to enable verbose and debug mode.  */
+static int opt_verbose;
+static int opt_debug;
+
 /* If set force the use of the standard resolver.  */
 static int standard_resolver;
 
@@ -206,6 +210,15 @@ enable_dns_tormode (int new_circuit)
 }
 
 
+/* Set verbosity and debug mode for this module. */
+void
+set_dns_verbose (int verbose, int debug)
+{
+  opt_verbose = verbose;
+  opt_debug = debug;
+}
+
+
 /* Change the default IP address of the nameserver to IPADDR.  The
    address needs to be a numerical IP address and will be used for the
    next DNS query.  Note that this is only used in Tor mode.  */
@@ -558,6 +571,9 @@ libdns_switch_port_p (gpg_error_t err)
       && libdns_tor_port == TOR_PORT)
     {
       /* Switch port and try again.  */
+      if (opt_debug)
+        log_debug ("dns: switching from SOCKS port %d to %d\n",
+                   TOR_PORT, TOR_PORT2);
       libdns_tor_port = TOR_PORT2;
       libdns_reinit_pending = 1;
       return 1;
@@ -906,22 +922,24 @@ resolve_dns_name (const char *name, unsigned short port,
                   int want_family, int want_socktype,
                   dns_addrinfo_t *r_ai, char **r_canonname)
 {
+  gpg_error_t err;
+
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      gpg_error_t err;
-
       err = resolve_name_libdns (name, port, want_family, want_socktype,
                                   r_ai, r_canonname);
       if (err && libdns_switch_port_p (err))
         err = resolve_name_libdns (name, port, want_family, want_socktype,
                                    r_ai, r_canonname);
-      return err;
     }
+  else
 #endif /*USE_LIBDNS*/
-
-  return resolve_name_standard (name, port, want_family, want_socktype,
-                                r_ai, r_canonname);
+    err = resolve_name_standard (name, port, want_family, want_socktype,
+                                 r_ai, r_canonname);
+  if (opt_debug)
+    log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
+  return err;
 }
 
 
@@ -1407,6 +1425,8 @@ get_dns_cert (const char *name, int want_certtype,
               void **r_key, size_t *r_keylen,
               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
 {
+  gpg_error_t err;
+
   if (r_key)
     *r_key = NULL;
   if (r_keylen)
@@ -1418,19 +1438,20 @@ get_dns_cert (const char *name, int want_certtype,
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      gpg_error_t err;
-
       err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
                                  r_fpr, r_fprlen, r_url);
       if (err && libdns_switch_port_p (err))
         err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
                                    r_fpr, r_fprlen, r_url);
-      return err;
     }
+  else
 #endif /*USE_LIBDNS*/
+    err = get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
+                                 r_fpr, r_fprlen, r_url);
 
-  return get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
-                                r_fpr, r_fprlen, r_url);
+  if (opt_debug)
+    log_debug ("dns: get_dns_cert(%s): %s\n", name, gpg_strerror (err));
+  return err;
 }
 
 
@@ -1452,7 +1473,7 @@ priosort(const void *a,const void *b)
  * R_COUNT.  */
 #ifdef USE_LIBDNS
 static gpg_error_t
-getsrv_libdns (const char *name, struct srventry **list, int *r_count)
+getsrv_libdns (const char *name, struct srventry **list, unsigned int *r_count)
 {
   gpg_error_t err;
   struct dns_resolver *res = NULL;
@@ -1461,7 +1482,7 @@ getsrv_libdns (const char *name, struct srventry **list, int *r_count)
   struct dns_rr_i rri;
   char host[DNS_D_MAXNAME + 1];
   int derr;
-  int srvcount=0;
+  unsigned int srvcount = 0;
 
   err = libdns_res_open (&res);
   if (err)
@@ -1549,7 +1570,8 @@ getsrv_libdns (const char *name, struct srventry **list, int *r_count)
  * expected that NULL is stored at the address of LIST and 0 is stored
  * at the address of R_COUNT.  */
 static gpg_error_t
-getsrv_standard (const char *name, struct srventry **list, int *r_count)
+getsrv_standard (const char *name,
+                 struct srventry **list, unsigned int *r_count)
 {
 #ifdef HAVE_SYSTEM_RESOLVER
   union {
@@ -1561,7 +1583,7 @@ getsrv_standard (const char *name, struct srventry **list, int *r_count)
   unsigned char *pt, *emsg;
   int r, rc;
   u16 dlen;
-  int srvcount=0;
+  unsigned int srvcount = 0;
   u16 count;
 
   /* Do not allow a query using the standard resolver in Tor mode.  */
@@ -1672,14 +1694,16 @@ getsrv_standard (const char *name, struct srventry **list, int *r_count)
 }
 
 
-int
-getsrv (const char *name, struct srventry **list)
+/* Note that we do not return NONAME but simply store 0 at R_COUNT.  */
+gpg_error_t
+get_dns_srv (const char *name, struct srventry **list, unsigned int *r_count)
 {
   gpg_error_t err;
-  int srvcount;
+  unsigned int srvcount;
   int i;
 
   *list = NULL;
+  *r_count = 0;
   srvcount = 0;
 #ifdef USE_LIBDNS
   if (!standard_resolver)
@@ -1693,7 +1717,11 @@ getsrv (const char *name, struct srventry **list)
     err = getsrv_standard (name, list, &srvcount);
 
   if (err)
-    return -1;  /* Ugly.  FIXME: Return an error code. */
+    {
+      if (gpg_err_code (err) == GPG_ERR_NO_NAME)
+        err = 0;
+      goto leave;
+    }
 
   /* Now we have an array of all the srv records. */
 
@@ -1768,7 +1796,17 @@ getsrv (const char *name, struct srventry **list)
         }
     }
 
-  return srvcount;
+ leave:
+  if (opt_debug)
+    {
+      if (err)
+        log_debug ("dns: getsrv(%s): %s\n", name, gpg_strerror (err));
+      else
+        log_debug ("dns: getsrv(%s) -> %u records\n", name, srvcount);
+    }
+  if (!err)
+    *r_count = srvcount;
+  return err;
 }
 
 
@@ -1924,13 +1962,13 @@ get_dns_cname_standard (const char *name, char **r_cname)
 gpg_error_t
 get_dns_cname (const char *name, char **r_cname)
 {
+  gpg_error_t err;
+
   *r_cname = NULL;
 
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      gpg_error_t err;
-
       err = get_dns_cname_libdns (name, r_cname);
       if (err && libdns_switch_port_p (err))
         err = get_dns_cname_libdns (name, r_cname);
@@ -1938,5 +1976,10 @@ get_dns_cname (const char *name, char **r_cname)
     }
 #endif /*USE_LIBDNS*/
 
-  return get_dns_cname_standard (name, r_cname);
+  err = get_dns_cname_standard (name, r_cname);
+  if (opt_debug)
+    log_debug ("get_dns_cname(%s)%s%s\n", name,
+               err ? ": " : " -> ",
+               err ? gpg_strerror (err) : *r_cname);
+  return err;
 }
index 2be972a..075aeaf 100644 (file)
@@ -92,6 +92,9 @@ struct srventry
 };
 
 
+/* Set verbosity and debug mode for this module. */
+void set_dns_verbose (int verbose, int debug);
+
 /* Calling this function with YES set to True forces the use of the
  * standard resolver even if dirmngr has been built with support for
  * an alternative resolver.  */
@@ -145,8 +148,9 @@ gpg_error_t get_dns_cert (const char *name, int want_certtype,
                           unsigned char **r_fpr, size_t *r_fprlen,
                           char **r_url);
 
-
-int getsrv (const char *name,struct srventry **list);
+/* Return an array of SRV records.  */
+gpg_error_t get_dns_srv (const char *name,
+                         struct srventry **list, unsigned int *r_count);
 
 
 #endif /*GNUPG_DIRMNGR_DNS_STUFF_H*/
index ebf80b1..619f2f1 100644 (file)
@@ -2321,7 +2321,7 @@ connect_server (const char *server, unsigned short port,
 {
   gpg_error_t err;
   assuan_fd_t sock = ASSUAN_INVALID_FD;
-  int srvcount = 0;
+  unsigned int srvcount = 0;
   int hostfound = 0;
   int anyhostaddr = 0;
   int srv, connected;
@@ -2377,8 +2377,12 @@ connect_server (const char *server, unsigned short port,
             {
               stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
                               "._tcp."), server);
-              srvcount = getsrv (srvname, &serverlist);
+              err = get_dns_srv (srvname, &serverlist, &srvcount);
               xfree (srvname);
+              if (err)
+                log_info ("getting SRV '%s' failed: %s\n",
+                          serverlist[srv].target, gpg_strerror (err));
+              /* Note that on error SRVCOUNT is zero.  */
             }
        }
     }
index 8f53432..a6c22f8 100644 (file)
@@ -428,7 +428,7 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
       char *cname;
       char *srvrecord;
       struct srventry *srvs;
-      int srvscount;
+      unsigned int srvscount;
 
       reftblsize = 100;
       reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
@@ -456,11 +456,10 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
               return err;
             }
 
-          srvscount = getsrv (srvrecord, &srvs);
+          err = get_dns_srv (srvrecord, &srvs, &srvscount);
           xfree (srvrecord);
-          if (srvscount < 0)
+          if (err)
             {
-              err = gpg_error_from_syserror ();
               xfree (reftbl);
               return err;
             }
index dd8e21e..f58f323 100644 (file)
@@ -157,6 +157,7 @@ main (int argc, char **argv)
       exit (1);
     }
 
+  set_dns_verbose (verbose, debug);
   init_sockets ();
 
   if (opt_tor)
@@ -234,19 +235,27 @@ main (int argc, char **argv)
   else if (opt_srv)
     {
       struct srventry *srv;
-      int rc,i;
+      unsigned int count;
+      int i;
 
-      rc=getsrv (name? name : "_hkp._tcp.wwwkeys.pgp.net", &srv);
-      printf("Count=%d\n",rc);
-      for(i=0;i<rc;i++)
+      err = get_dns_srv (name? name : "_hkp._tcp.wwwkeys.pgp.net",
+                         &srv, &count);
+      if (err)
+        printf ("get_dns_srv failed: %s <%s>\n",
+                gpg_strerror (err), gpg_strsource (err));
+      else
         {
-          printf("priority=%-8hu  ",srv[i].priority);
-          printf("weight=%-8hu  ",srv[i].weight);
-          printf("port=%-5hu  ",srv[i].port);
-          printf("target=%s\n",srv[i].target);
-        }
+          printf ("count=%u\n",count);
+          for (i=0; i < count; i++)
+            {
+              printf("priority=%-8hu  ",srv[i].priority);
+              printf("weight=%-8hu  ",srv[i].weight);
+              printf("port=%-5hu  ",srv[i].port);
+              printf("target=%s\n",srv[i].target);
+            }
 
-      xfree(srv);
+          xfree(srv);
+        }
     }
   else /* Standard lookup.  */
     {
@@ -289,7 +298,7 @@ main (int argc, char **argv)
                                   (opt_bracket? DNS_WITHBRACKET:0),
                                   &host);
           if (err)
-            printf ("[resolve_dns_addr failed (2): %s]", gpg_strerror (err));
+            printf ("  [resolve_dns_addr failed (2): %s]", gpg_strerror (err));
           else
             {
               if (!is_ip_address (host))