summaryrefslogtreecommitdiff
path: root/dirmngr/dns-stuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'dirmngr/dns-stuff.c')
-rw-r--r--dirmngr/dns-stuff.c81
1 files changed, 69 insertions, 12 deletions
diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c
index 9347196..d72d1c7 100644
--- a/dirmngr/dns-stuff.c
+++ b/dirmngr/dns-stuff.c
@@ -119,6 +119,10 @@ static int opt_debug;
/* The timeout in seconds for libdns requests. */
static int opt_timeout;
+/* The flag to disable IPv4 access - right now this only skips
+ * returned A records. */
+static int opt_disable_ipv4;
+
/* If set force the use of the standard resolver. */
static int standard_resolver;
@@ -218,6 +222,14 @@ enable_dns_tormode (int new_circuit)
}
+/* Disable tor mode. */
+void
+disable_dns_tormode (void)
+{
+ tor_mode = 0;
+}
+
+
/* Set verbosity and debug mode for this module. */
void
set_dns_verbose (int verbose, int debug)
@@ -227,6 +239,15 @@ set_dns_verbose (int verbose, int debug)
}
+/* Set the Disable-IPv4 flag so that the name resolver does not return
+ * A addresses. */
+void
+set_dns_disable_ipv4 (int yes)
+{
+ opt_disable_ipv4 = !!yes;
+}
+
+
/* Set the timeout for libdns requests to SECONDS. A value of 0 sets
* the default timeout and values are capped at 10 minutes. */
void
@@ -477,12 +498,10 @@ libdns_init (void)
(dns_nssconf_loadpath (ld.resolv_conf, fname));
if (err)
{
- log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
- /* not fatal, nsswitch.conf is not used on all systems; assume
- * classic behavior instead. Our dns library states "bf" which tries
- * DNS then Files, which is not classic; FreeBSD
- * /usr/src/lib/libc/net/gethostnamadr.c defines default_src[] which
- * is Files then DNS, which is. */
+ /* This is not a fatal error: nsswitch.conf is not used on
+ * all systems; assume classic behavior instead. */
+ if (gpg_err_code (err) != GPG_ERR_ENOENT)
+ log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
if (opt_debug)
log_debug ("dns: fallback resolution order, files then DNS\n");
ld.resolv_conf->lookup[0] = 'f';
@@ -490,6 +509,23 @@ libdns_init (void)
ld.resolv_conf->lookup[2] = '\0';
err = GPG_ERR_NO_ERROR;
}
+ else if (!strchr (ld.resolv_conf->lookup, 'b'))
+ {
+ /* No DNS resulution type found in the list. This might be
+ * due to systemd based systems which allow for custom
+ * keywords which are not known to us and thus we do not
+ * know whether DNS is wanted or not. Becuase DNS is
+ * important for our infrastructure, we forcefully append
+ * DNS to the end of the list. */
+ if (strlen (ld.resolv_conf->lookup)+2 < sizeof ld.resolv_conf->lookup)
+ {
+ if (opt_debug)
+ log_debug ("dns: appending DNS to resolution order\n");
+ strcat (ld.resolv_conf->lookup, "b");
+ }
+ else
+ log_error ("failed to append DNS to resolution order\n");
+ }
#endif /* Unix */
}
@@ -683,6 +719,7 @@ resolve_name_libdns (const char *name, unsigned short port,
struct addrinfo *ent;
char portstr_[21];
char *portstr = NULL;
+ char *namebuf = NULL;
int derr;
*r_dai = NULL;
@@ -695,8 +732,6 @@ resolve_name_libdns (const char *name, unsigned short port,
hints.ai_flags = AI_ADDRCONFIG;
if (r_canonname)
hints.ai_flags |= AI_CANONNAME;
- if (is_ip_address (name))
- hints.ai_flags |= AI_NUMERICHOST;
if (port)
{
@@ -708,6 +743,25 @@ resolve_name_libdns (const char *name, unsigned short port,
if (err)
goto leave;
+
+ if (is_ip_address (name))
+ {
+ hints.ai_flags |= AI_NUMERICHOST;
+ /* libdns does not grok brackets - remove them. */
+ if (*name == '[' && name[strlen(name)-1] == ']')
+ {
+ namebuf = xtrymalloc (strlen (name));
+ if (!namebuf)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ strcpy (namebuf, name+1);
+ namebuf[strlen (namebuf)-1] = 0;
+ name = namebuf;
+ }
+ }
+
ai = dns_ai_open (name, portstr, 0, &hints, res, &derr);
if (!ai)
{
@@ -789,6 +843,7 @@ resolve_name_libdns (const char *name, unsigned short port,
else
*r_dai = daihead;
+ xfree (namebuf);
return err;
}
#endif /*USE_LIBDNS*/
@@ -826,7 +881,7 @@ resolve_name_standard (const char *name, unsigned short port,
else
*portstr = 0;
- /* We can't use the the AI_IDN flag because that does the conversion
+ /* We can't use the AI_IDN flag because that does the conversion
using the current locale. However, GnuPG always used UTF-8. To
support IDN we would need to make use of the libidn API. */
ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
@@ -873,6 +928,8 @@ resolve_name_standard (const char *name, unsigned short port,
{
if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
continue;
+ if (opt_disable_ipv4 && ai->ai_family == AF_INET)
+ continue;
dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
dai->family = ai->ai_family;
@@ -1170,7 +1227,7 @@ is_ip_address (const char *name)
if (*name == '[')
return 6; /* yes: A legal DNS name may not contain this character;
- this mut be bracketed v6 address. */
+ this must be bracketed v6 address. */
if (*name == '.')
return 0; /* No. A leading dot is not a valid IP address. */
@@ -1212,7 +1269,7 @@ is_ip_address (const char *name)
if (*s == '.')
{
if (s[1] == '.')
- return 0; /* No: Douple dot. */
+ return 0; /* No: Double dot. */
if (atoi (s+1) > 255)
return 0; /* No: Ipv4 byte value too large. */
ndots++;
@@ -1623,7 +1680,7 @@ get_dns_cert_standard (const char *name, int want_certtype,
found, the malloced data is returned at (R_KEY, R_KEYLEN) and
the other return parameters are set to NULL/0. If an IPGP CERT
record was found the fingerprint is stored as an allocated block at
- R_FPR and its length at R_FPRLEN; an URL is is allocated as a
+ R_FPR and its length at R_FPRLEN; an URL is allocated as a
string and returned at R_URL. If WANT_CERTTYPE is 0 this function
returns the first CERT found with a supported type; it is expected
that only one CERT record is used. If WANT_CERTTYPE is one of the