diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index bb4d9f3ef..5ee589e93 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -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; diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c index 08270a617..491fccefd 100644 --- a/dirmngr/dns-stuff.c +++ b/dirmngr/dns-stuff.c @@ -108,10 +108,17 @@ /* 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; diff --git a/dirmngr/dns-stuff.h b/dirmngr/dns-stuff.h index 075aeafab..0a4a4de2f 100644 --- a/dirmngr/dns-stuff.h +++ b/dirmngr/dns-stuff.h @@ -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. */ diff --git a/dirmngr/http.c b/dirmngr/http.c index 619f2f1b4..14d60df4b 100644 --- a/dirmngr/http.c +++ b/dirmngr/http.c @@ -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. */ } } diff --git a/dirmngr/t-dns-stuff.c b/dirmngr/t-dns-stuff.c index f58f3235a..b087b5ead 100644 --- a/dirmngr/t-dns-stuff.c +++ b/dirmngr/t-dns-stuff.c @@ -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); diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index 94ef35dd1..5b4e68bc8 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -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 diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e45857dab..925f1cf2d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -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,