diff options
Diffstat (limited to 'dirmngr/dns-stuff.c')
-rw-r--r-- | dirmngr/dns-stuff.c | 81 |
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 |