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. */ return 0; /* Not handled. */
} }
set_dns_verbose (opt.verbose, !!DBG_DNS);
return 1; /* Handled. */ return 1; /* Handled. */
} }

View File

@ -108,6 +108,10 @@
/* The default nameserver used in Tor mode. */ /* The default nameserver used in Tor mode. */
#define DEFAULT_NAMESERVER "8.8.8.8" #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. */ /* If set force the use of the standard resolver. */
static int 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 /* 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 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. */ 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) && libdns_tor_port == TOR_PORT)
{ {
/* Switch port and try again. */ /* 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_tor_port = TOR_PORT2;
libdns_reinit_pending = 1; libdns_reinit_pending = 1;
return 1; return 1;
@ -906,22 +922,24 @@ resolve_dns_name (const char *name, unsigned short port,
int want_family, int want_socktype, int want_family, int want_socktype,
dns_addrinfo_t *r_ai, char **r_canonname) dns_addrinfo_t *r_ai, char **r_canonname)
{ {
gpg_error_t err;
#ifdef USE_LIBDNS #ifdef USE_LIBDNS
if (!standard_resolver) if (!standard_resolver)
{ {
gpg_error_t err;
err = resolve_name_libdns (name, port, want_family, want_socktype, err = resolve_name_libdns (name, port, want_family, want_socktype,
r_ai, r_canonname); r_ai, r_canonname);
if (err && libdns_switch_port_p (err)) if (err && libdns_switch_port_p (err))
err = resolve_name_libdns (name, port, want_family, want_socktype, err = resolve_name_libdns (name, port, want_family, want_socktype,
r_ai, r_canonname); r_ai, r_canonname);
return err;
} }
else
#endif /*USE_LIBDNS*/ #endif /*USE_LIBDNS*/
err = resolve_name_standard (name, port, want_family, want_socktype,
return resolve_name_standard (name, port, want_family, want_socktype, r_ai, r_canonname);
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, void **r_key, size_t *r_keylen,
unsigned char **r_fpr, size_t *r_fprlen, char **r_url) unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
{ {
gpg_error_t err;
if (r_key) if (r_key)
*r_key = NULL; *r_key = NULL;
if (r_keylen) if (r_keylen)
@ -1418,19 +1438,20 @@ get_dns_cert (const char *name, int want_certtype,
#ifdef USE_LIBDNS #ifdef USE_LIBDNS
if (!standard_resolver) if (!standard_resolver)
{ {
gpg_error_t err;
err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen, err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
r_fpr, r_fprlen, r_url); r_fpr, r_fprlen, r_url);
if (err && libdns_switch_port_p (err)) if (err && libdns_switch_port_p (err))
err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen, err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
r_fpr, r_fprlen, r_url); r_fpr, r_fprlen, r_url);
return err;
} }
else
#endif /*USE_LIBDNS*/ #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, if (opt_debug)
r_fpr, r_fprlen, r_url); 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. */ * R_COUNT. */
#ifdef USE_LIBDNS #ifdef USE_LIBDNS
static gpg_error_t 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; gpg_error_t err;
struct dns_resolver *res = NULL; 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; struct dns_rr_i rri;
char host[DNS_D_MAXNAME + 1]; char host[DNS_D_MAXNAME + 1];
int derr; int derr;
int srvcount=0; unsigned int srvcount = 0;
err = libdns_res_open (&res); err = libdns_res_open (&res);
if (err) 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 * expected that NULL is stored at the address of LIST and 0 is stored
* at the address of R_COUNT. */ * at the address of R_COUNT. */
static gpg_error_t 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 #ifdef HAVE_SYSTEM_RESOLVER
union { union {
@ -1561,7 +1583,7 @@ getsrv_standard (const char *name, struct srventry **list, int *r_count)
unsigned char *pt, *emsg; unsigned char *pt, *emsg;
int r, rc; int r, rc;
u16 dlen; u16 dlen;
int srvcount=0; unsigned int srvcount = 0;
u16 count; u16 count;
/* Do not allow a query using the standard resolver in Tor mode. */ /* 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 /* Note that we do not return NONAME but simply store 0 at R_COUNT. */
getsrv (const char *name, struct srventry **list) gpg_error_t
get_dns_srv (const char *name, struct srventry **list, unsigned int *r_count)
{ {
gpg_error_t err; gpg_error_t err;
int srvcount; unsigned int srvcount;
int i; int i;
*list = NULL; *list = NULL;
*r_count = 0;
srvcount = 0; srvcount = 0;
#ifdef USE_LIBDNS #ifdef USE_LIBDNS
if (!standard_resolver) if (!standard_resolver)
@ -1693,7 +1717,11 @@ getsrv (const char *name, struct srventry **list)
err = getsrv_standard (name, list, &srvcount); err = getsrv_standard (name, list, &srvcount);
if (err) 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. */ /* 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 gpg_error_t
get_dns_cname (const char *name, char **r_cname) get_dns_cname (const char *name, char **r_cname)
{ {
gpg_error_t err;
*r_cname = NULL; *r_cname = NULL;
#ifdef USE_LIBDNS #ifdef USE_LIBDNS
if (!standard_resolver) if (!standard_resolver)
{ {
gpg_error_t err;
err = get_dns_cname_libdns (name, r_cname); err = get_dns_cname_libdns (name, r_cname);
if (err && libdns_switch_port_p (err)) if (err && libdns_switch_port_p (err))
err = get_dns_cname_libdns (name, r_cname); err = get_dns_cname_libdns (name, r_cname);
@ -1938,5 +1976,10 @@ get_dns_cname (const char *name, char **r_cname)
} }
#endif /*USE_LIBDNS*/ #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 /* Calling this function with YES set to True forces the use of the
* standard resolver even if dirmngr has been built with support for * standard resolver even if dirmngr has been built with support for
* an alternative resolver. */ * 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, unsigned char **r_fpr, size_t *r_fprlen,
char **r_url); char **r_url);
/* Return an array of SRV records. */
int getsrv (const char *name,struct srventry **list); gpg_error_t get_dns_srv (const char *name,
struct srventry **list, unsigned int *r_count);
#endif /*GNUPG_DIRMNGR_DNS_STUFF_H*/ #endif /*GNUPG_DIRMNGR_DNS_STUFF_H*/

View File

@ -2321,7 +2321,7 @@ connect_server (const char *server, unsigned short port,
{ {
gpg_error_t err; gpg_error_t err;
assuan_fd_t sock = ASSUAN_INVALID_FD; assuan_fd_t sock = ASSUAN_INVALID_FD;
int srvcount = 0; unsigned int srvcount = 0;
int hostfound = 0; int hostfound = 0;
int anyhostaddr = 0; int anyhostaddr = 0;
int srv, connected; int srv, connected;
@ -2377,8 +2377,12 @@ connect_server (const char *server, unsigned short port,
{ {
stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag), stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
"._tcp."), server); "._tcp."), server);
srvcount = getsrv (srvname, &serverlist); err = get_dns_srv (srvname, &serverlist, &srvcount);
xfree (srvname); 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 *cname;
char *srvrecord; char *srvrecord;
struct srventry *srvs; struct srventry *srvs;
int srvscount; unsigned int srvscount;
reftblsize = 100; reftblsize = 100;
reftbl = xtrymalloc (reftblsize * sizeof *reftbl); reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
@ -456,11 +456,10 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
return err; return err;
} }
srvscount = getsrv (srvrecord, &srvs); err = get_dns_srv (srvrecord, &srvs, &srvscount);
xfree (srvrecord); xfree (srvrecord);
if (srvscount < 0) if (err)
{ {
err = gpg_error_from_syserror ();
xfree (reftbl); xfree (reftbl);
return err; return err;
} }

View File

@ -157,6 +157,7 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
set_dns_verbose (verbose, debug);
init_sockets (); init_sockets ();
if (opt_tor) if (opt_tor)
@ -234,19 +235,27 @@ main (int argc, char **argv)
else if (opt_srv) else if (opt_srv)
{ {
struct srventry *srv; struct srventry *srv;
int rc,i; unsigned int count;
int i;
rc=getsrv (name? name : "_hkp._tcp.wwwkeys.pgp.net", &srv); err = get_dns_srv (name? name : "_hkp._tcp.wwwkeys.pgp.net",
printf("Count=%d\n",rc); &srv, &count);
for(i=0;i<rc;i++) if (err)
printf ("get_dns_srv failed: %s <%s>\n",
gpg_strerror (err), gpg_strsource (err));
else
{ {
printf("priority=%-8hu ",srv[i].priority); printf ("count=%u\n",count);
printf("weight=%-8hu ",srv[i].weight); for (i=0; i < count; i++)
printf("port=%-5hu ",srv[i].port); {
printf("target=%s\n",srv[i].target); 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. */ else /* Standard lookup. */
{ {
@ -289,7 +298,7 @@ main (int argc, char **argv)
(opt_bracket? DNS_WITHBRACKET:0), (opt_bracket? DNS_WITHBRACKET:0),
&host); &host);
if (err) if (err)
printf ("[resolve_dns_addr failed (2): %s]", gpg_strerror (err)); printf (" [resolve_dns_addr failed (2): %s]", gpg_strerror (err));
else else
{ {
if (!is_ip_address (host)) if (!is_ip_address (host))