dirmngr: New option --resolver-timeout.
authorWerner Koch <wk@gnupg.org>
Tue, 20 Dec 2016 08:53:58 +0000 (09:53 +0100)
committerWerner Koch <wk@gnupg.org>
Tue, 20 Dec 2016 08:53:58 +0000 (09:53 +0100)
* dirmngr/dns-stuff.c (DEFAULT_TIMEOUT): New.
(opt_timeout): New var.
(set_dns_timeout): New.
(libdns_res_open): Set the default timeout.
(libdns_res_wait): Use configurable timeout.
(resolve_name_libdns): Ditto.

* dirmngr/dirmngr.c (oResolverTimeout): New const.
(opts): New option --resolver-timeout.
(parse_rereadable_options): Set that option.
(main) <aGPGConfList>: Add --nameserver and --resolver-timeout.
* tools/gpgconf-comp.c (gc_options_dirmngr): Add --resolver-timeout
and --nameserver.

* dirmngr/http.c (connect_server): Fix yesterday introduced bug in
error diagnostic.
--

This timeout is a pretty crude thing because libdns has a few other
internal timeouts as well.

Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/dirmngr.c
dirmngr/dns-stuff.c
dirmngr/dns-stuff.h
dirmngr/http.c
dirmngr/t-dns-stuff.c
doc/dirmngr.texi
tools/gpgconf-comp.c

index bb4d9f3..5ee589e 100644 (file)
@@ -142,6 +142,7 @@ enum cmd_and_opt_values {
   oDisableCheckOwnSocket,
   oStandardResolver,
   oRecursiveResolver,
+  oResolverTimeout,
   aTest
 };
 
@@ -240,6 +241,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oIgnoreCertExtension,"ignore-cert-extension", "@"),
   ARGPARSE_s_n (oStandardResolver, "standard-resolver", "@"),
   ARGPARSE_s_n (oRecursiveResolver, "recursive-resolver", "@"),
+  ARGPARSE_s_i (oResolverTimeout, "resolver-timeout", "@"),
 
   ARGPARSE_group (302,N_("@\n(See the \"info\" manual for a complete listing "
                          "of all commands and options)\n")),
@@ -550,6 +552,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       /* Note: We do not allow resetting of opt.use_tor at runtime.  */
       disable_check_own_socket = 0;
       enable_standard_resolver (0);
+      set_dns_timeout (0);
       return 1;
     }
 
@@ -636,6 +639,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       set_dns_nameserver (pargs->r.ret_str);
       break;
 
+    case oResolverTimeout:
+      set_dns_timeout (pargs->r.ret_int);
+      break;
+
     default:
       return 0; /* Not handled. */
     }
@@ -1376,6 +1383,9 @@ main (int argc, char **argv)
 
       es_printf ("use-tor:%lu:\n", flags | GC_OPT_FLAG_NONE);
       es_printf ("keyserver:%lu:\n", flags | GC_OPT_FLAG_NONE);
+      es_printf ("nameserver:%lu:\n", flags | GC_OPT_FLAG_NONE);
+      es_printf ("resolver-timeout:%lu:%u\n",
+                 flags | GC_OPT_FLAG_DEFAULT, 0);
     }
   cleanup ();
   return !!rc;
index 08270a6..491fcce 100644 (file)
 /* The default nameserver used in Tor mode.  */
 #define DEFAULT_NAMESERVER "8.8.8.8"
 
+/* The default timeout in seconds for libdns requests.  */
+#define DEFAULT_TIMEOUT 30
+
+
 /* Two flags to enable verbose and debug mode.  */
 static int opt_verbose;
 static int opt_debug;
 
+/* The timeout in seconds for libdns requests.  */
+static int opt_timeout;
+
 /* If set force the use of the standard resolver.  */
 static int standard_resolver;
 
@@ -219,6 +226,22 @@ set_dns_verbose (int verbose, int debug)
 }
 
 
+/* Set the timeout for libdns requests to SECONDS.  A value of 0 sets
+ * the default timeout and values are capped at 10 minutes.  */
+void
+set_dns_timeout (int seconds)
+{
+  if (!seconds)
+    seconds = DEFAULT_TIMEOUT;
+  else if (seconds < 1)
+    seconds = 1;
+  else if (seconds > 600)
+    seconds = 600;
+
+  opt_timeout = seconds;
+}
+
+
 /* 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.  */
@@ -421,7 +444,8 @@ libdns_init (void)
            pip && idx < DIM (ld.resolv_conf->nameserver);
            pip = pip->Next)
         {
-          log_debug ("ninfo->dnsserver[%d] '%s'\n", idx, pip->IpAddress.String);
+          if (opt_debug)
+            log_debug ("dns: dnsserver[%d] '%s'\n", idx, pip->IpAddress.String);
           err = libdns_error_to_gpg_error
             (dns_resconf_pton (&ld.resolv_conf->nameserver[idx],
                                pip->IpAddress.String));
@@ -547,6 +571,9 @@ libdns_res_open (struct dns_resolver **r_res)
   if (err)
     return err;
 
+  if (!opt_timeout)
+    set_dns_timeout (0);
+
   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
                       dns_opts (.socks_host     = &libdns.socks_host,
                                 .socks_user     = tor_socks_user,
@@ -604,7 +631,7 @@ libdns_res_wait (struct dns_resolver *res)
   while ((err = libdns_error_to_gpg_error (dns_res_check (res)))
          && gpg_err_code (err) == GPG_ERR_EAGAIN)
     {
-      if (dns_res_elapsed (res) > 30)
+      if (dns_res_elapsed (res) > opt_timeout)
         {
           err = gpg_error (GPG_ERR_DNS_TIMEOUT);
           break;
@@ -677,7 +704,7 @@ resolve_name_libdns (const char *name, unsigned short port,
         }
       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
         {
-          if (dns_ai_elapsed (ai) > 30)
+          if (dns_ai_elapsed (ai) > opt_timeout)
             {
               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
               goto leave;
index 075aeaf..0a4a4de 100644 (file)
@@ -95,6 +95,9 @@ struct srventry
 /* Set verbosity and debug mode for this module. */
 void set_dns_verbose (int verbose, int debug);
 
+/* Set the timeout for libdns requests to SECONDS.  */
+void set_dns_timeout (int seconds);
+
 /* 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.  */
index 619f2f1..14d60df 100644 (file)
@@ -2378,10 +2378,10 @@ connect_server (const char *server, unsigned short port,
               stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
                               "._tcp."), server);
               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));
+                          srvname, gpg_strerror (err));
+              xfree (srvname);
               /* Note that on error SRVCOUNT is zero.  */
             }
        }
index f58f323..b087b5e 100644 (file)
@@ -83,6 +83,7 @@ main (int argc, char **argv)
                  "  --cert              lookup a CERT RR\n"
                  "  --srv               lookup a SRV RR\n"
                  "  --cname             lookup a CNAME RR\n"
+                 "  --timeout SECONDS   timeout after SECONDS\n"
                  , stdout);
           exit (0);
         }
@@ -137,6 +138,15 @@ main (int argc, char **argv)
           any_options = opt_cname = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--timeout"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              set_dns_timeout (atoi (*argv));
+              argc--; argv++;
+            }
+        }
       else if (!strncmp (*argv, "--", 2))
         {
           fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
index 94ef35d..5b4e68b 100644 (file)
@@ -255,6 +255,10 @@ Implemented'' if this function is used.
 @opindex recursive-resolver
 When possible use a recursive resolver instead of a stub resolver.
 
+@item --resolver-timeout @var{n}
+Set the timeout for the DNS resolver to N seconds.  The default are 30
+seconds.
+
 @item --allow-version-check
 @opindex allow-version-check
 Allow Dirmngr to connect to @code{https://versions.gnupg.org} to get
index e45857d..925f1cf 100644 (file)
@@ -889,6 +889,12 @@ static gc_option_t gc_options_dirmngr[] =
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "dirmngr", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
+   { "resolver-timeout", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL,
+     GC_ARG_TYPE_INT32, GC_BACKEND_DIRMNGR },
+   { "nameserver", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL,
+     GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,