mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
dirmngr: Implement a getnameinfo wrapper.
* dirmngr/dns-stuff.h (DNS_NUMERICHOST): New. (DNS_WITHBRACKET): New. * dirmngr/dns-stuff.c (resolve_name_standard): Factor code out to... (map_eai_to_gpg_error): new. (resolve_addr_standard): New. (resolve_dns_addr): New. * dirmngr/ks-engine-hkp.c (is_ip_address): Move to ... * dirmngr/dns-stuff.c (is_ip_address): here. Add support for non bracketed v6 addresses. * dirmngr/t-dns-stuff.c: Remove header netdb.h. (main): Add option --bracket. Use resolve_dns_name instead of getnameinfo. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
7f65e84ac0
commit
816505958a
@ -54,6 +54,11 @@
|
|||||||
#include "host2net.h"
|
#include "host2net.h"
|
||||||
#include "dns-stuff.h"
|
#include "dns-stuff.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if AF_UNSPEC != 0
|
||||||
|
# error AF_UNSPEC does not have the value 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Not every installation has gotten around to supporting SRVs or
|
/* Not every installation has gotten around to supporting SRVs or
|
||||||
CERTs yet... */
|
CERTs yet... */
|
||||||
#ifndef T_SRV
|
#ifndef T_SRV
|
||||||
@ -96,6 +101,30 @@ free_dns_addrinfo (dns_addrinfo_t ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
map_eai_to_gpg_error (int ec)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
switch (ec)
|
||||||
|
{
|
||||||
|
case EAI_AGAIN: err = gpg_error (GPG_ERR_EAGAIN); break;
|
||||||
|
case EAI_BADFLAGS: err = gpg_error (GPG_ERR_INV_FLAG); break;
|
||||||
|
case EAI_FAIL: err = gpg_error (GPG_ERR_SERVER_FAILED); break;
|
||||||
|
case EAI_MEMORY: err = gpg_error (GPG_ERR_ENOMEM); break;
|
||||||
|
case EAI_NODATA: err = gpg_error (GPG_ERR_NO_DATA); break;
|
||||||
|
case EAI_NONAME: err = gpg_error (GPG_ERR_NO_NAME); break;
|
||||||
|
case EAI_SERVICE: err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
|
||||||
|
case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
|
||||||
|
case EAI_FAMILY: err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
|
||||||
|
case EAI_SOCKTYPE: err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
|
||||||
|
case EAI_SYSTEM: err = gpg_error_from_syserror (); break;
|
||||||
|
default: err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Resolve a name using the standard system function. */
|
/* Resolve a name using the standard system function. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
resolve_name_standard (const char *name, unsigned short port,
|
resolve_name_standard (const char *name, unsigned short port,
|
||||||
@ -132,21 +161,7 @@ resolve_name_standard (const char *name, unsigned short port,
|
|||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
aibuf = NULL;
|
aibuf = NULL;
|
||||||
switch (ret)
|
err = map_eai_to_gpg_error (ret);
|
||||||
{
|
|
||||||
case EAI_AGAIN: err = gpg_error (GPG_ERR_EAGAIN); break;
|
|
||||||
case EAI_BADFLAGS: err = gpg_error (GPG_ERR_INV_FLAG); break;
|
|
||||||
case EAI_FAIL: err = gpg_error (GPG_ERR_SERVER_FAILED); break;
|
|
||||||
case EAI_MEMORY: err = gpg_error (GPG_ERR_ENOMEM); break;
|
|
||||||
case EAI_NODATA: err = gpg_error (GPG_ERR_NO_DATA); break;
|
|
||||||
case EAI_NONAME: err = gpg_error (GPG_ERR_NO_NAME); break;
|
|
||||||
case EAI_SERVICE: err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
|
|
||||||
case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
|
|
||||||
case EAI_FAMILY: err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
|
|
||||||
case EAI_SOCKTYPE: err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
|
|
||||||
case EAI_SYSTEM: err = gpg_error_from_syserror (); break;
|
|
||||||
default: err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
|
|
||||||
}
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +208,66 @@ resolve_name_standard (const char *name, unsigned short port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Resolve an address using the standard system function. */
|
||||||
|
static gpg_error_t
|
||||||
|
resolve_addr_standard (const struct sockaddr *addr, int addrlen,
|
||||||
|
unsigned int flags, char **r_name)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int ec;
|
||||||
|
char *buffer, *p;
|
||||||
|
int buflen;
|
||||||
|
|
||||||
|
*r_name = NULL;
|
||||||
|
|
||||||
|
buflen = NI_MAXHOST;
|
||||||
|
buffer = xtrymalloc (buflen + 2 + 1);
|
||||||
|
if (!buffer)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
if ((flags & DNS_NUMERICHOST) || tor_mode)
|
||||||
|
ec = EAI_NONAME;
|
||||||
|
else
|
||||||
|
ec = getnameinfo (addr, addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
|
||||||
|
|
||||||
|
if (!ec && *buffer == '[')
|
||||||
|
ec = EAI_FAIL; /* A name may never start with a bracket. */
|
||||||
|
else if (ec == EAI_NONAME)
|
||||||
|
{
|
||||||
|
p = buffer;
|
||||||
|
if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
|
||||||
|
{
|
||||||
|
*p++ = '[';
|
||||||
|
buflen -= 2;
|
||||||
|
}
|
||||||
|
ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
|
||||||
|
if (!ec && addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
|
||||||
|
strcat (buffer, "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
err = map_eai_to_gpg_error (ec);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = xtryrealloc (buffer, strlen (buffer)+1);
|
||||||
|
if (!p)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = p;
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
xfree (buffer);
|
||||||
|
else
|
||||||
|
*r_name = buffer;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This a wrapper around getaddrinfo with slighly different semantics.
|
/* This a wrapper around getaddrinfo with slighly different semantics.
|
||||||
NAME is the name to resolve.
|
NAME is the name to resolve.
|
||||||
PORT is the requested port or 0.
|
PORT is the requested port or 0.
|
||||||
@ -219,6 +294,85 @@ resolve_dns_name (const char *name, unsigned short port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpg_error_t
|
||||||
|
resolve_dns_addr (const struct sockaddr *addr, int addrlen,
|
||||||
|
unsigned int flags, char **r_name)
|
||||||
|
{
|
||||||
|
#ifdef USE_ADNS_disabled_for_now
|
||||||
|
return resolve_addr_adns (addr, addrlen, flags, r_name);
|
||||||
|
#else
|
||||||
|
return resolve_addr_standard (addr, addrlen, flags, r_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether NAME is an IP address. Returns true if it is either
|
||||||
|
an IPv6 or IPv4 numerical address. */
|
||||||
|
int
|
||||||
|
is_ip_address (const char *name)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int ndots, dblcol, n;
|
||||||
|
|
||||||
|
if (*name == '[')
|
||||||
|
return 1; /* yes: A legal DNS name may not contain this character;
|
||||||
|
this mut be bracketed v6 address. */
|
||||||
|
if (*name == '.')
|
||||||
|
return 0; /* No. A leading dot is not a valid IP address. */
|
||||||
|
|
||||||
|
/* Check whether this is a v6 address. */
|
||||||
|
ndots = n = dblcol = 0;
|
||||||
|
for (s=name; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == ':')
|
||||||
|
{
|
||||||
|
ndots++;
|
||||||
|
if (s[1] == ':')
|
||||||
|
{
|
||||||
|
ndots++;
|
||||||
|
if (dblcol)
|
||||||
|
return 0; /* No: Only one "::" allowed. */
|
||||||
|
dblcol++;
|
||||||
|
if (s[1])
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
else if (*s == '.')
|
||||||
|
goto legacy;
|
||||||
|
else if (!strchr ("0123456789abcdefABCDEF", *s))
|
||||||
|
return 0; /* No: Not a hex digit. */
|
||||||
|
else if (++n > 4)
|
||||||
|
return 0; /* To many digits in a group. */
|
||||||
|
}
|
||||||
|
if (ndots > 7)
|
||||||
|
return 0; /* No: Too many colons. */
|
||||||
|
else if (ndots > 1)
|
||||||
|
return 1; /* Yes: At least 2 colons indicate an v6 address. */
|
||||||
|
|
||||||
|
legacy:
|
||||||
|
/* Check whether it is legacy IP address. */
|
||||||
|
ndots = n = 0;
|
||||||
|
for (s=name; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == '.')
|
||||||
|
{
|
||||||
|
if (s[1] == '.')
|
||||||
|
return 0; /* No: Douple dot. */
|
||||||
|
if (atoi (s+1) > 255)
|
||||||
|
return 0; /* No: Ipv4 byte value too large. */
|
||||||
|
ndots++;
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
else if (!strchr ("0123456789", *s))
|
||||||
|
return 0; /* No: Not a digit. */
|
||||||
|
else if (++n > 3)
|
||||||
|
return 0; /* No: More than 3 digits. */
|
||||||
|
}
|
||||||
|
return !!(ndots == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_ADNS
|
#ifdef USE_ADNS
|
||||||
/* Init ADNS and store the new state at R_STATE. Returns 0 on
|
/* Init ADNS and store the new state at R_STATE. Returns 0 on
|
||||||
success; prints an error message and returns an error code on
|
success; prints an error message and returns an error code on
|
||||||
|
@ -40,7 +40,16 @@
|
|||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags used with resolve_dns_addr.
|
||||||
|
*/
|
||||||
|
#define DNS_NUMERICHOST 1 /* Force numeric output format. */
|
||||||
|
#define DNS_WITHBRACKET 2 /* Put brackets around numeric v6
|
||||||
|
addresses. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants for use with get_dns_cert.
|
||||||
|
*/
|
||||||
#define DNS_CERTTYPE_ANY 0 /* Internal catch all type. */
|
#define DNS_CERTTYPE_ANY 0 /* Internal catch all type. */
|
||||||
/* Certificate types according to RFC-4398: */
|
/* Certificate types according to RFC-4398: */
|
||||||
#define DNS_CERTTYPE_PKIX 1 /* X.509 as per PKIX. */
|
#define DNS_CERTTYPE_PKIX 1 /* X.509 as per PKIX. */
|
||||||
@ -58,6 +67,8 @@
|
|||||||
#define DNS_CERTTYPE_RRBASE 1024 /* Base of special constants. */
|
#define DNS_CERTTYPE_RRBASE 1024 /* Base of special constants. */
|
||||||
#define DNS_CERTTYPE_RR61 (DNS_CERTTYPE_RRBASE + 61)
|
#define DNS_CERTTYPE_RR61 (DNS_CERTTYPE_RRBASE + 61)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct dns_addrinfo_s;
|
struct dns_addrinfo_s;
|
||||||
typedef struct dns_addrinfo_s *dns_addrinfo_t;
|
typedef struct dns_addrinfo_s *dns_addrinfo_t;
|
||||||
struct dns_addrinfo_s
|
struct dns_addrinfo_s
|
||||||
@ -87,17 +98,25 @@ gpg_error_t enable_dns_tormode (void);
|
|||||||
|
|
||||||
void free_dns_addrinfo (dns_addrinfo_t ai);
|
void free_dns_addrinfo (dns_addrinfo_t ai);
|
||||||
|
|
||||||
/* Provide function similar to getaddrinfo. */
|
/* Function similar to getaddrinfo. */
|
||||||
gpg_error_t resolve_dns_name (const char *name, unsigned short port,
|
gpg_error_t 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_dai, char **r_canonname);
|
dns_addrinfo_t *r_dai, char **r_canonname);
|
||||||
|
|
||||||
|
/* Function similar to getnameinfo. */
|
||||||
|
gpg_error_t resolve_dns_addr (const struct sockaddr *addr, int addrlen,
|
||||||
|
unsigned int flags, char **r_name);
|
||||||
|
|
||||||
|
/* Return true if NAME is a numerical IP address. */
|
||||||
|
int is_ip_address (const char *name);
|
||||||
|
|
||||||
/* Return a CERT record or an arbitray RR. */
|
/* Return a CERT record or an arbitray RR. */
|
||||||
gpg_error_t get_dns_cert (const char *name, int want_certtype,
|
gpg_error_t 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,
|
unsigned char **r_fpr, size_t *r_fprlen,
|
||||||
char **r_url);
|
char **r_url);
|
||||||
|
|
||||||
|
|
||||||
int getsrv (const char *name,struct srventry **list);
|
int getsrv (const char *name,struct srventry **list);
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,38 +280,6 @@ my_getnameinfo (dns_addrinfo_t ai, char *host, size_t hostlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether NAME is an IP address. */
|
|
||||||
static int
|
|
||||||
is_ip_address (const char *name)
|
|
||||||
{
|
|
||||||
int ndots, n;
|
|
||||||
|
|
||||||
if (*name == '[')
|
|
||||||
return 1;
|
|
||||||
/* Check whether it is legacy IP address. */
|
|
||||||
if (*name == '.')
|
|
||||||
return 0; /* No. */
|
|
||||||
ndots = n = 0;
|
|
||||||
for (; *name; name++)
|
|
||||||
{
|
|
||||||
if (*name == '.')
|
|
||||||
{
|
|
||||||
if (name[1] == '.')
|
|
||||||
return 0; /* No. */
|
|
||||||
if (atoi (name+1) > 255)
|
|
||||||
return 0; /* Value too large. */
|
|
||||||
ndots++;
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
else if (!strchr ("012345678", *name))
|
|
||||||
return 0; /* Not a digit. */
|
|
||||||
else if (++n > 3)
|
|
||||||
return 0; /* More than 3 digits. */
|
|
||||||
}
|
|
||||||
return !!(ndots == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Map the host name NAME to the actual to be used host name. This
|
/* Map the host name NAME to the actual to be used host name. This
|
||||||
allows us to manage round robin DNS names. We use our own strategy
|
allows us to manage round robin DNS names. We use our own strategy
|
||||||
to choose one of the hosts. For example we skip those hosts which
|
to choose one of the hosts. For example we skip those hosts which
|
||||||
|
@ -22,9 +22,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
# include <netdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "dns-stuff.h"
|
#include "dns-stuff.h"
|
||||||
@ -45,6 +43,7 @@ main (int argc, char **argv)
|
|||||||
int opt_tor = 0;
|
int opt_tor = 0;
|
||||||
int opt_cert = 0;
|
int opt_cert = 0;
|
||||||
int opt_srv = 0;
|
int opt_srv = 0;
|
||||||
|
int opt_bracket = 0;
|
||||||
char const *name = NULL;
|
char const *name = NULL;
|
||||||
|
|
||||||
gpgrt_init ();
|
gpgrt_init ();
|
||||||
@ -66,6 +65,7 @@ main (int argc, char **argv)
|
|||||||
" --verbose print timings etc.\n"
|
" --verbose print timings etc.\n"
|
||||||
" --debug flyswatter\n"
|
" --debug flyswatter\n"
|
||||||
" --use-tor use Tor\n"
|
" --use-tor use Tor\n"
|
||||||
|
" --bracket enclose v6 addresses in brackets\n"
|
||||||
" --cert lookup a CERT RR\n"
|
" --cert lookup a CERT RR\n"
|
||||||
" --srv lookup a SRV RR\n"
|
" --srv lookup a SRV RR\n"
|
||||||
, stdout);
|
, stdout);
|
||||||
@ -87,6 +87,11 @@ main (int argc, char **argv)
|
|||||||
opt_tor = 1;
|
opt_tor = 1;
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (*argv, "--bracket"))
|
||||||
|
{
|
||||||
|
opt_bracket = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
else if (!strcmp (*argv, "--cert"))
|
else if (!strcmp (*argv, "--cert"))
|
||||||
{
|
{
|
||||||
any_options = opt_cert = 1;
|
any_options = opt_cert = 1;
|
||||||
@ -194,8 +199,7 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
char *cname;
|
char *cname;
|
||||||
dns_addrinfo_t aibuf, ai;
|
dns_addrinfo_t aibuf, ai;
|
||||||
int ret;
|
char *host;
|
||||||
char hostbuf[1025];
|
|
||||||
|
|
||||||
printf ("Lookup on '%s'\n", name);
|
printf ("Lookup on '%s'\n", name);
|
||||||
|
|
||||||
@ -216,14 +220,30 @@ main (int argc, char **argv)
|
|||||||
ai->family == AF_INET? "inet4" : "? ",
|
ai->family == AF_INET? "inet4" : "? ",
|
||||||
ai->socktype, ai->protocol);
|
ai->socktype, ai->protocol);
|
||||||
|
|
||||||
ret = getnameinfo (ai->addr, ai->addrlen,
|
err = resolve_dns_addr (ai->addr, ai->addrlen,
|
||||||
hostbuf, sizeof hostbuf,
|
(DNS_NUMERICHOST
|
||||||
NULL, 0,
|
| (opt_bracket? DNS_WITHBRACKET:0)),
|
||||||
NI_NUMERICHOST);
|
&host);
|
||||||
if (ret)
|
if (err)
|
||||||
printf ("[getnameinfo failed: %s]\n", gai_strerror (ret));
|
printf ("[getnameinfo failed: %s]", gpg_strerror (err));
|
||||||
else
|
else
|
||||||
printf ("%s\n", hostbuf);
|
{
|
||||||
|
printf ("%s", host);
|
||||||
|
xfree (host);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resolve_dns_addr (ai->addr, ai->addrlen,
|
||||||
|
(opt_bracket? DNS_WITHBRACKET:0),
|
||||||
|
&host);
|
||||||
|
if (err)
|
||||||
|
printf ("[getnameinfo failed (2): %s]", gpg_strerror (err));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!is_ip_address (host))
|
||||||
|
printf (" (%s)", host);
|
||||||
|
xfree (host);
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
xfree (cname);
|
xfree (cname);
|
||||||
free_dns_addrinfo (aibuf);
|
free_dns_addrinfo (aibuf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user