dirmngr: Fix problems with the getsrv function.

* 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>
This commit is contained in:
Werner Koch 2016-12-19 23:27:02 +01:00
parent 284ec54495
commit af8b68fae3
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 103 additions and 42 deletions

View 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. */
}

View File

@ -108,6 +108,10 @@
/* 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;
}

View 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*/

View 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. */
}
}
}

View 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;
}

View 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))