mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
dirmngr: Add option --standard-resolver.
* dirmngr/dirmngr.c (oStandardResolver): New constant. (opts): New option --standard-resolver. (parse_rereadable_options): Set option. * dirmngr/dns-stuff.c: Refactor all code to support the new option. (standard_resolver): New var. (enable_standard_resolver, standard_resolver_p): New func. * dirmngr/http.c (connect_server): Remove USE_DNS_SRV build conditional. * dirmngr/ks-engine-hkp.c (map_host): Ditto. * dirmngr/server.c (cmd_getinfo) <dnsinfo>: Take care of new option * configure.ac (HAVE_ADNS_IF_TORMODE): Remove var ADNSLIB. ac_define USE_ADNS in the adns checking code. Remove options --disable-dns-srv and --disable-dns-cert. Always look for the system resolver. Print warning if no system resolver was found. (USE_DNS_CERT, USE_DNS_SRV): Remove ac_defines. (HAVE_SYSTEM_RESOLVER): New ac_define. (USE_DNS_SRV): Remove am_conditional; not used anyway. -- This option allows for runtime switching to the system's standard resolver. This is mainly useful to work around possible bugs in the optional resolver libraries (as of now ADNS). Note that on Windows there is no code to use systems's resolver and thus for full functionality dirmngr must be build with a separate resolver. This patch also does way with configure options to disable the use of CERT and SRV records. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
86efc3ee53
commit
304566d332
118
configure.ac
118
configure.ac
@ -103,6 +103,7 @@ have_sqlite=no
|
|||||||
have_npth=no
|
have_npth=no
|
||||||
have_libusb=no
|
have_libusb=no
|
||||||
have_adns=no
|
have_adns=no
|
||||||
|
have_system_resolver=no
|
||||||
gnupg_have_ldap="n/a"
|
gnupg_have_ldap="n/a"
|
||||||
|
|
||||||
use_zip=yes
|
use_zip=yes
|
||||||
@ -1025,58 +1026,39 @@ fi
|
|||||||
CPPFLAGS=${_cppflags}
|
CPPFLAGS=${_cppflags}
|
||||||
LDFLAGS=${_ldflags}
|
LDFLAGS=${_ldflags}
|
||||||
if test "$have_adns" = "yes"; then
|
if test "$have_adns" = "yes"; then
|
||||||
ADNSLIBS="-ladns"
|
DNSLIBS="-ladns"
|
||||||
|
AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.])
|
||||||
|
else
|
||||||
|
DNSLIBS=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Now try for the resolver functions so we can use DNS for SRV, PA and CERT.
|
# Check standard resolver functions.
|
||||||
#
|
#
|
||||||
AC_ARG_ENABLE(dns-srv,
|
if test "$build_dirmngr" = "yes"; then
|
||||||
AC_HELP_STRING([--disable-dns-srv],
|
|
||||||
[disable the use of DNS SRV in HKP and HTTP]),
|
|
||||||
use_dns_srv=$enableval,use_dns_srv=yes)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(dns-cert,
|
|
||||||
AC_HELP_STRING([--disable-dns-cert],
|
|
||||||
[disable the use of CERT records in DNS]),
|
|
||||||
use_dns_cert=$enableval,use_dns_cert=yes)
|
|
||||||
|
|
||||||
if test x"$use_dns_srv" = xyes || test x"$use_dns_cert" = xyes; then
|
|
||||||
_dns_save_libs=$LIBS
|
_dns_save_libs=$LIBS
|
||||||
LIBS=""
|
LIBS=""
|
||||||
|
|
||||||
if test x"$have_adns" = xyes ; then
|
# Find the system resolver which can always be enabled with
|
||||||
# We prefer ADNS.
|
# the dirmngr option --standard-resolver.
|
||||||
DNSLIBS="$ADNSLIBS"
|
|
||||||
AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.])
|
|
||||||
|
|
||||||
if test x"$use_dns_srv" = xyes ; then
|
# the double underscore thing is a glibc-ism?
|
||||||
AC_DEFINE(USE_DNS_SRV,1)
|
AC_SEARCH_LIBS(res_query,resolv bind,,
|
||||||
fi
|
AC_SEARCH_LIBS(__res_query,resolv bind,,have_resolver=no))
|
||||||
|
AC_SEARCH_LIBS(dn_expand,resolv bind,,
|
||||||
|
AC_SEARCH_LIBS(__dn_expand,resolv bind,,have_resolver=no))
|
||||||
|
|
||||||
if test x"$use_dns_cert" = xyes ; then
|
# macOS renames dn_skipname into res_9_dn_skipname in <resolv.h>,
|
||||||
AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT])
|
# and for some reason fools us into believing we don't need
|
||||||
fi
|
# -lresolv even if we do. Since the test program checking for the
|
||||||
else
|
# symbol does not include <resolv.h>, we need to check for the
|
||||||
# With no ADNS find the system resolver.
|
# renamed symbol explicitly.
|
||||||
|
AC_SEARCH_LIBS(res_9_dn_skipname,resolv bind,,
|
||||||
|
AC_SEARCH_LIBS(dn_skipname,resolv bind,,
|
||||||
|
AC_SEARCH_LIBS(__dn_skipname,resolv bind,,have_resolver=no)))
|
||||||
|
|
||||||
# the double underscore thing is a glibc-ism?
|
if test x"$have_resolver" != xno ; then
|
||||||
AC_SEARCH_LIBS(res_query,resolv bind,,
|
|
||||||
AC_SEARCH_LIBS(__res_query,resolv bind,,have_resolver=no))
|
|
||||||
AC_SEARCH_LIBS(dn_expand,resolv bind,,
|
|
||||||
AC_SEARCH_LIBS(__dn_expand,resolv bind,,have_resolver=no))
|
|
||||||
|
|
||||||
# macOS renames dn_skipname into res_9_dn_skipname in <resolv.h>,
|
|
||||||
# and for some reason fools us into believing we don't need
|
|
||||||
# -lresolv even if we do. Since the test program checking for the
|
|
||||||
# symbol does not include <resolv.h>, we need to check for the
|
|
||||||
# renamed symbol explicitly.
|
|
||||||
AC_SEARCH_LIBS(res_9_dn_skipname,resolv bind,,
|
|
||||||
AC_SEARCH_LIBS(dn_skipname,resolv bind,,
|
|
||||||
AC_SEARCH_LIBS(__dn_skipname,resolv bind,,have_resolver=no)))
|
|
||||||
|
|
||||||
if test x"$have_resolver" != xno ; then
|
|
||||||
|
|
||||||
# Make sure that the BIND 4 resolver interface is workable before
|
# Make sure that the BIND 4 resolver interface is workable before
|
||||||
# enabling any code that calls it. At some point I'll rewrite the
|
# enabling any code that calls it. At some point I'll rewrite the
|
||||||
@ -1084,8 +1066,8 @@ if test x"$use_dns_srv" = xyes || test x"$use_dns_cert" = xyes; then
|
|||||||
# We might also want to use adns instead. Problem with ADNS is that
|
# We might also want to use adns instead. Problem with ADNS is that
|
||||||
# it does not support v6.
|
# it does not support v6.
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether the resolver is usable])
|
AC_MSG_CHECKING([whether the resolver is usable])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
#include <resolv.h>]],
|
#include <resolv.h>]],
|
||||||
@ -1094,15 +1076,15 @@ if test x"$use_dns_srv" = xyes || test x"$use_dns_cert" = xyes; then
|
|||||||
dn_skipname(0,0);
|
dn_skipname(0,0);
|
||||||
dn_expand(0,0,0,0,0);
|
dn_expand(0,0,0,0,0);
|
||||||
]])],have_resolver=yes,have_resolver=no)
|
]])],have_resolver=yes,have_resolver=no)
|
||||||
AC_MSG_RESULT($have_resolver)
|
AC_MSG_RESULT($have_resolver)
|
||||||
|
|
||||||
# This is Apple-specific and somewhat bizarre as they changed the
|
# This is Apple-specific and somewhat bizarre as they changed the
|
||||||
# define in bind 8 for some reason.
|
# define in bind 8 for some reason.
|
||||||
|
|
||||||
if test x"$have_resolver" != xyes ; then
|
if test x"$have_resolver" != xyes ; then
|
||||||
AC_MSG_CHECKING(
|
AC_MSG_CHECKING(
|
||||||
[whether I can make the resolver usable with BIND_8_COMPAT])
|
[whether I can make the resolver usable with BIND_8_COMPAT])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define BIND_8_COMPAT
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define BIND_8_COMPAT
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
@ -1111,28 +1093,23 @@ if test x"$use_dns_srv" = xyes || test x"$use_dns_cert" = xyes; then
|
|||||||
res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
|
res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
|
||||||
dn_skipname(0,0); dn_expand(0,0,0,0,0);
|
dn_skipname(0,0); dn_expand(0,0,0,0,0);
|
||||||
]])],[have_resolver=yes ; need_compat=yes])
|
]])],[have_resolver=yes ; need_compat=yes])
|
||||||
AC_MSG_RESULT($have_resolver)
|
AC_MSG_RESULT($have_resolver)
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if test x"$have_resolver" = xyes ; then
|
if test x"$have_resolver" = xyes ; then
|
||||||
DNSLIBS=$LIBS
|
AC_DEFINE(HAVE_SYSTEM_RESOLVER,1,[The system's resolver is usable.])
|
||||||
|
DNSLIBS="$DNSLIBS $LIBS"
|
||||||
if test x"$use_dns_srv" = xyes ; then
|
if test x"$need_compat" = xyes ; then
|
||||||
AC_DEFINE(USE_DNS_SRV,1,[define to use DNS SRV])
|
AC_DEFINE(BIND_8_COMPAT,1,[an Apple OSXism])
|
||||||
fi
|
|
||||||
|
|
||||||
if test x"$use_dns_cert" = xyes ; then
|
|
||||||
AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x"$need_compat" = xyes ; then
|
|
||||||
AC_DEFINE(BIND_8_COMPAT,1,[an Apple OSXism])
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
use_dns_srv=no
|
|
||||||
use_dns_cert=no
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_WARN([[
|
||||||
|
***
|
||||||
|
*** The system's DNS resolver is not usable.
|
||||||
|
*** Dirmngr functionality is limited.
|
||||||
|
***]])
|
||||||
|
show_tor_support="${show_tor_support} (no system resolver)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LIBS=$_dns_save_libs
|
LIBS=$_dns_save_libs
|
||||||
@ -1140,8 +1117,6 @@ fi
|
|||||||
|
|
||||||
AC_SUBST(DNSLIBS)
|
AC_SUBST(DNSLIBS)
|
||||||
|
|
||||||
AM_CONDITIONAL(USE_DNS_SRV, test x"$use_dns_srv" = xyes)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check for LDAP
|
# Check for LDAP
|
||||||
@ -1963,7 +1938,6 @@ echo "
|
|||||||
Dirmngr auto start: $dirmngr_auto_start
|
Dirmngr auto start: $dirmngr_auto_start
|
||||||
Readline support: $gnupg_cv_have_readline
|
Readline support: $gnupg_cv_have_readline
|
||||||
LDAP support: $gnupg_have_ldap
|
LDAP support: $gnupg_have_ldap
|
||||||
DNS SRV support: $use_dns_srv
|
|
||||||
TLS support: $use_tls_library
|
TLS support: $use_tls_library
|
||||||
TOFU support: $use_tofu
|
TOFU support: $use_tofu
|
||||||
Tor support: $show_tor_support
|
Tor support: $show_tor_support
|
||||||
|
@ -140,6 +140,7 @@ enum cmd_and_opt_values {
|
|||||||
oKeyServer,
|
oKeyServer,
|
||||||
oNameServer,
|
oNameServer,
|
||||||
oDisableCheckOwnSocket,
|
oDisableCheckOwnSocket,
|
||||||
|
oStandardResolver,
|
||||||
aTest
|
aTest
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -236,6 +237,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_s (oHTTPWrapperProgram, "http-wrapper-program", "@"),
|
ARGPARSE_s_s (oHTTPWrapperProgram, "http-wrapper-program", "@"),
|
||||||
ARGPARSE_s_n (oHonorHTTPProxy, "honor-http-proxy", "@"),
|
ARGPARSE_s_n (oHonorHTTPProxy, "honor-http-proxy", "@"),
|
||||||
ARGPARSE_s_s (oIgnoreCertExtension,"ignore-cert-extension", "@"),
|
ARGPARSE_s_s (oIgnoreCertExtension,"ignore-cert-extension", "@"),
|
||||||
|
ARGPARSE_s_n (oStandardResolver, "standard-resolver", "@"),
|
||||||
|
|
||||||
ARGPARSE_group (302,N_("@\n(See the \"info\" manual for a complete listing "
|
ARGPARSE_group (302,N_("@\n(See the \"info\" manual for a complete listing "
|
||||||
"of all commands and options)\n")),
|
"of all commands and options)\n")),
|
||||||
@ -543,6 +545,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
|
|||||||
FREE_STRLIST (opt.keyserver);
|
FREE_STRLIST (opt.keyserver);
|
||||||
/* Note: We do not allow resetting of opt.use_tor at runtime. */
|
/* Note: We do not allow resetting of opt.use_tor at runtime. */
|
||||||
disable_check_own_socket = 0;
|
disable_check_own_socket = 0;
|
||||||
|
enable_standard_resolver (0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,6 +620,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
|
|||||||
|
|
||||||
case oUseTor: opt.use_tor = 1; break;
|
case oUseTor: opt.use_tor = 1; break;
|
||||||
|
|
||||||
|
case oStandardResolver: enable_standard_resolver (1); break;
|
||||||
|
|
||||||
case oKeyServer:
|
case oKeyServer:
|
||||||
if (*pargs->r.ret_str)
|
if (*pargs->r.ret_str)
|
||||||
add_to_strlist (&opt.keyserver, pargs->r.ret_str);
|
add_to_strlist (&opt.keyserver, pargs->r.ret_str);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* dns-stuff.c - DNS related code including CERT RR (rfc-4398)
|
/* dns-stuff.c - DNS related code including CERT RR (rfc-4398)
|
||||||
* Copyright (C) 2003, 2005, 2006, 2009 Free Software Foundation, Inc.
|
* Copyright (C) 2003, 2005, 2006, 2009 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 2005, 2006, 2009, 2015 Werner Koch
|
* Copyright (C) 2005, 2006, 2009, 2015. 2016 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -36,9 +36,11 @@
|
|||||||
# endif
|
# endif
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#else
|
#else
|
||||||
# include <netinet/in.h>
|
# if HAVE_SYSTEM_RESOLVER
|
||||||
# include <arpa/nameser.h>
|
# include <netinet/in.h>
|
||||||
# include <resolv.h>
|
# include <arpa/nameser.h>
|
||||||
|
# include <resolv.h>
|
||||||
|
# endif
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -101,6 +103,8 @@
|
|||||||
/* The default nameserver used with ADNS in Tor mode. */
|
/* The default nameserver used with ADNS in Tor mode. */
|
||||||
#define DEFAULT_NAMESERVER "8.8.8.8"
|
#define DEFAULT_NAMESERVER "8.8.8.8"
|
||||||
|
|
||||||
|
/* If set force the use of the standard resolver. */
|
||||||
|
static int standard_resolver;
|
||||||
|
|
||||||
/* If set Tor mode shall be used. */
|
/* If set Tor mode shall be used. */
|
||||||
static int tor_mode;
|
static int tor_mode;
|
||||||
@ -114,6 +118,25 @@ static char tor_nameserver[40+20];
|
|||||||
static char tor_credentials[50];
|
static char tor_credentials[50];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
void
|
||||||
|
enable_standard_resolver (int yes)
|
||||||
|
{
|
||||||
|
standard_resolver = yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if the standard resolver is used. */
|
||||||
|
int
|
||||||
|
standard_resolver_p (void)
|
||||||
|
{
|
||||||
|
return standard_resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Sets the module in Tor mode. Returns 0 is this is possible or an
|
/* Sets the module in Tor mode. Returns 0 is this is possible or an
|
||||||
error code. */
|
error code. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
@ -121,7 +144,7 @@ enable_dns_tormode (int new_circuit)
|
|||||||
{
|
{
|
||||||
(void) new_circuit;
|
(void) new_circuit;
|
||||||
|
|
||||||
#if defined(USE_DNS_CERT) && defined(USE_ADNS)
|
#ifdef USE_ADNS
|
||||||
# if HAVE_ADNS_IF_TORMODE
|
# if HAVE_ADNS_IF_TORMODE
|
||||||
if (!*tor_credentials || new_circuit)
|
if (!*tor_credentials || new_circuit)
|
||||||
{
|
{
|
||||||
@ -367,7 +390,6 @@ resolve_name_adns (const char *name, unsigned short port,
|
|||||||
#endif /*USE_ADNS*/
|
#endif /*USE_ADNS*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef USE_ADNS
|
|
||||||
/* 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,
|
||||||
@ -472,7 +494,6 @@ resolve_name_standard (const char *name, unsigned short port,
|
|||||||
*r_dai = daihead;
|
*r_dai = daihead;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif /*!USE_ADNS*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Resolve an address using the standard system function. */
|
/* Resolve an address using the standard system function. */
|
||||||
@ -552,12 +573,12 @@ resolve_dns_name (const char *name, unsigned short port,
|
|||||||
dns_addrinfo_t *r_ai, char **r_canonname)
|
dns_addrinfo_t *r_ai, char **r_canonname)
|
||||||
{
|
{
|
||||||
#ifdef USE_ADNS
|
#ifdef USE_ADNS
|
||||||
return resolve_name_adns (name, port, want_family, want_socktype,
|
if (!standard_resolver)
|
||||||
r_ai, r_canonname);
|
return resolve_name_adns (name, port, want_family, want_socktype,
|
||||||
#else
|
r_ai, r_canonname);
|
||||||
|
#endif
|
||||||
return 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);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -565,11 +586,7 @@ gpg_error_t
|
|||||||
resolve_dns_addr (const struct sockaddr *addr, int addrlen,
|
resolve_dns_addr (const struct sockaddr *addr, int addrlen,
|
||||||
unsigned int flags, char **r_name)
|
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);
|
return resolve_addr_standard (addr, addrlen, flags, r_name);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -654,23 +671,13 @@ is_onion_address (const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns 0 on success or an error code. If a PGP CERT record was
|
|
||||||
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
|
|
||||||
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
|
|
||||||
supported certtypes only records with this certtype are considered
|
|
||||||
and the first found is returned. (R_KEY,R_KEYLEN) are optional. */
|
|
||||||
gpg_error_t
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
#ifdef USE_DNS_CERT
|
|
||||||
#ifdef USE_ADNS
|
#ifdef USE_ADNS
|
||||||
|
/* ADNS version of get_dns_cert. */
|
||||||
|
static gpg_error_t
|
||||||
|
get_dns_cert_adns (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;
|
gpg_error_t err;
|
||||||
int ret;
|
int ret;
|
||||||
adns_state state;
|
adns_state state;
|
||||||
@ -678,14 +685,6 @@ get_dns_cert (const char *name, int want_certtype,
|
|||||||
unsigned int ctype;
|
unsigned int ctype;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
if (r_key)
|
|
||||||
*r_key = NULL;
|
|
||||||
if (r_keylen)
|
|
||||||
*r_keylen = 0;
|
|
||||||
*r_fpr = NULL;
|
|
||||||
*r_fprlen = 0;
|
|
||||||
*r_url = NULL;
|
|
||||||
|
|
||||||
err = my_adns_init (&state);
|
err = my_adns_init (&state);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -812,22 +811,22 @@ get_dns_cert (const char *name, int want_certtype,
|
|||||||
adns_free (answer);
|
adns_free (answer);
|
||||||
adns_finish (state);
|
adns_finish (state);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
#endif /*!USE_ADNS */
|
||||||
|
|
||||||
#else /*!USE_ADNS*/
|
|
||||||
|
|
||||||
|
/* Standard resolver version of get_dns_cert. */
|
||||||
|
static gpg_error_t
|
||||||
|
get_dns_cert_standard (const char *name, int want_certtype,
|
||||||
|
void **r_key, size_t *r_keylen,
|
||||||
|
unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYSTEM_RESOLVER
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char *answer;
|
unsigned char *answer;
|
||||||
int r;
|
int r;
|
||||||
u16 count;
|
u16 count;
|
||||||
|
|
||||||
if (r_key)
|
|
||||||
*r_key = NULL;
|
|
||||||
if (r_keylen)
|
|
||||||
*r_keylen = 0;
|
|
||||||
*r_fpr = NULL;
|
|
||||||
*r_fprlen = 0;
|
|
||||||
*r_url = NULL;
|
|
||||||
|
|
||||||
/* Allocate a 64k buffer which is the limit for an DNS response. */
|
/* Allocate a 64k buffer which is the limit for an DNS response. */
|
||||||
answer = xtrymalloc (65536);
|
answer = xtrymalloc (65536);
|
||||||
if (!answer)
|
if (!answer)
|
||||||
@ -1004,9 +1003,36 @@ get_dns_cert (const char *name, int want_certtype,
|
|||||||
xfree (answer);
|
xfree (answer);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
#endif /*!USE_ADNS */
|
#else /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
#else /* !USE_DNS_CERT */
|
|
||||||
(void)name;
|
(void)name;
|
||||||
|
(void)want_certtype;
|
||||||
|
(void)r_key;
|
||||||
|
(void)r_keylen;
|
||||||
|
(void)r_fpr;
|
||||||
|
(void)r_fprlen;
|
||||||
|
(void)r_url;
|
||||||
|
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
#endif /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns 0 on success or an error code. If a PGP CERT record was
|
||||||
|
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
|
||||||
|
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
|
||||||
|
supported certtypes only records with this certtype are considered
|
||||||
|
and the first found is returned. (R_KEY,R_KEYLEN) are optional. */
|
||||||
|
gpg_error_t
|
||||||
|
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)
|
||||||
|
{
|
||||||
if (r_key)
|
if (r_key)
|
||||||
*r_key = NULL;
|
*r_key = NULL;
|
||||||
if (r_keylen)
|
if (r_keylen)
|
||||||
@ -1015,11 +1041,16 @@ get_dns_cert (const char *name, int want_certtype,
|
|||||||
*r_fprlen = 0;
|
*r_fprlen = 0;
|
||||||
*r_url = NULL;
|
*r_url = NULL;
|
||||||
|
|
||||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
#ifdef USE_ADNS
|
||||||
#endif
|
if (!standard_resolver)
|
||||||
|
return get_dns_cert_adns (name, want_certtype, r_key, r_keylen,
|
||||||
|
r_fpr, r_fprlen, r_url);
|
||||||
|
#endif /*!USE_ADNS */
|
||||||
|
return get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
|
||||||
|
r_fpr, r_fprlen, r_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DNS_SRV
|
|
||||||
static int
|
static int
|
||||||
priosort(const void *a,const void *b)
|
priosort(const void *a,const void *b)
|
||||||
{
|
{
|
||||||
@ -1033,170 +1064,215 @@ priosort(const void *a,const void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
getsrv (const char *name,struct srventry **list)
|
|
||||||
{
|
|
||||||
int srvcount=0;
|
|
||||||
u16 count;
|
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
*list = NULL;
|
|
||||||
|
|
||||||
#ifdef USE_ADNS
|
#ifdef USE_ADNS
|
||||||
{
|
/* ADNS based helper for getsrv. */
|
||||||
adns_state state;
|
static int
|
||||||
adns_answer *answer = NULL;
|
getsrv_adns (const char *name, struct srventry **list)
|
||||||
|
{
|
||||||
|
int srvcount = 0;
|
||||||
|
u16 count;
|
||||||
|
int rc;
|
||||||
|
adns_state state;
|
||||||
|
adns_answer *answer = NULL;
|
||||||
|
|
||||||
if (my_adns_init (&state))
|
if (my_adns_init (&state))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
my_unprotect ();
|
||||||
|
rc = adns_synchronous (state, name, adns_r_srv, adns_qf_quoteok_query,
|
||||||
|
&answer);
|
||||||
|
my_protect ();
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_error ("DNS query failed: %s\n", strerror (rc));
|
||||||
|
adns_finish (state);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
my_unprotect ();
|
if (answer->status != adns_s_ok
|
||||||
rc = adns_synchronous (state, name, adns_r_srv, adns_qf_quoteok_query,
|
|| answer->type != adns_r_srv || !answer->nrrs)
|
||||||
&answer);
|
{
|
||||||
my_protect ();
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("DNS query failed: %s\n", strerror (rc));
|
|
||||||
adns_finish (state);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (answer->status != adns_s_ok
|
|
||||||
|| answer->type != adns_r_srv || !answer->nrrs)
|
|
||||||
{
|
|
||||||
log_error ("DNS query returned an error or no records: %s (%s)\n",
|
log_error ("DNS query returned an error or no records: %s (%s)\n",
|
||||||
adns_strerror (answer->status),
|
adns_strerror (answer->status),
|
||||||
adns_errabbrev (answer->status));
|
adns_errabbrev (answer->status));
|
||||||
adns_free (answer);
|
adns_free (answer);
|
||||||
adns_finish (state);
|
adns_finish (state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (count = 0; count < answer->nrrs; count++)
|
for (count = 0; count < answer->nrrs; count++)
|
||||||
{
|
{
|
||||||
struct srventry *srv = NULL;
|
struct srventry *srv = NULL;
|
||||||
struct srventry *newlist;
|
struct srventry *newlist;
|
||||||
|
|
||||||
if (strlen (answer->rrs.srvha[count].ha.host) >= sizeof srv->target)
|
if (strlen (answer->rrs.srvha[count].ha.host) >= sizeof srv->target)
|
||||||
{
|
{
|
||||||
log_info ("hostname in SRV record too long - skipped\n");
|
log_info ("hostname in SRV record too long - skipped\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
|
newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
|
||||||
if (!newlist)
|
if (!newlist)
|
||||||
goto fail;
|
{
|
||||||
*list = newlist;
|
xfree (*list);
|
||||||
memset (&(*list)[srvcount], 0, sizeof(struct srventry));
|
*list = NULL;
|
||||||
srv = &(*list)[srvcount];
|
return -1;
|
||||||
srvcount++;
|
}
|
||||||
|
*list = newlist;
|
||||||
|
memset (&(*list)[srvcount], 0, sizeof(struct srventry));
|
||||||
|
srv = &(*list)[srvcount];
|
||||||
|
srvcount++;
|
||||||
|
|
||||||
srv->priority = answer->rrs.srvha[count].priority;
|
srv->priority = answer->rrs.srvha[count].priority;
|
||||||
srv->weight = answer->rrs.srvha[count].weight;
|
srv->weight = answer->rrs.srvha[count].weight;
|
||||||
srv->port = answer->rrs.srvha[count].port;
|
srv->port = answer->rrs.srvha[count].port;
|
||||||
strcpy (srv->target, answer->rrs.srvha[count].ha.host);
|
strcpy (srv->target, answer->rrs.srvha[count].ha.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
adns_free (answer);
|
adns_free (answer);
|
||||||
adns_finish (state);
|
adns_finish (state);
|
||||||
}
|
|
||||||
#else /*!USE_ADNS*/
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned char ans[2048];
|
|
||||||
HEADER header[1];
|
|
||||||
} res;
|
|
||||||
unsigned char *answer = res.ans;
|
|
||||||
HEADER *header = res.header;
|
|
||||||
unsigned char *pt, *emsg;
|
|
||||||
int r;
|
|
||||||
u16 dlen;
|
|
||||||
|
|
||||||
/* Do not allow a query using the standard resolver in Tor mode. */
|
return srvcount;
|
||||||
if (tor_mode)
|
}
|
||||||
return -1;
|
#endif /*USE_ADNS*/
|
||||||
|
|
||||||
my_unprotect ();
|
|
||||||
r = res_query (name, C_IN, T_SRV, answer, sizeof answer);
|
|
||||||
my_protect ();
|
|
||||||
if (r < sizeof (HEADER) || r > sizeof answer
|
|
||||||
|| header->rcode != NOERROR || !(count=ntohs (header->ancount)))
|
|
||||||
return 0; /* Error or no record found. */
|
|
||||||
|
|
||||||
emsg = &answer[r];
|
/* Standard resolver based helper for getsrv. */
|
||||||
pt = &answer[sizeof(HEADER)];
|
static int
|
||||||
|
getsrv_standard (const char *name, struct srventry **list)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYSTEM_RESOLVER
|
||||||
|
union {
|
||||||
|
unsigned char ans[2048];
|
||||||
|
HEADER header[1];
|
||||||
|
} res;
|
||||||
|
unsigned char *answer = res.ans;
|
||||||
|
HEADER *header = res.header;
|
||||||
|
unsigned char *pt, *emsg;
|
||||||
|
int r, rc;
|
||||||
|
u16 dlen;
|
||||||
|
int srvcount=0;
|
||||||
|
u16 count;
|
||||||
|
|
||||||
/* Skip over the query */
|
/* Do not allow a query using the standard resolver in Tor mode. */
|
||||||
rc = dn_skipname (pt, emsg);
|
if (tor_mode)
|
||||||
if (rc == -1)
|
return -1;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
pt += rc + QFIXEDSZ;
|
my_unprotect ();
|
||||||
|
r = res_query (name, C_IN, T_SRV, answer, sizeof answer);
|
||||||
|
my_protect ();
|
||||||
|
if (r < sizeof (HEADER) || r > sizeof answer
|
||||||
|
|| header->rcode != NOERROR || !(count=ntohs (header->ancount)))
|
||||||
|
return 0; /* Error or no record found. */
|
||||||
|
|
||||||
while (count-- > 0 && pt < emsg)
|
emsg = &answer[r];
|
||||||
{
|
pt = &answer[sizeof(HEADER)];
|
||||||
struct srventry *srv=NULL;
|
|
||||||
u16 type,class;
|
|
||||||
struct srventry *newlist;
|
|
||||||
|
|
||||||
newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
|
/* Skip over the query */
|
||||||
if (!newlist)
|
rc = dn_skipname (pt, emsg);
|
||||||
goto fail;
|
if (rc == -1)
|
||||||
*list = newlist;
|
goto fail;
|
||||||
memset(&(*list)[srvcount],0,sizeof(struct srventry));
|
|
||||||
srv=&(*list)[srvcount];
|
|
||||||
srvcount++;
|
|
||||||
|
|
||||||
rc = dn_skipname(pt,emsg); /* the name we just queried for */
|
pt += rc + QFIXEDSZ;
|
||||||
if (rc == -1)
|
|
||||||
goto fail;
|
|
||||||
pt+=rc;
|
|
||||||
|
|
||||||
/* Truncated message? */
|
while (count-- > 0 && pt < emsg)
|
||||||
if((emsg-pt)<16)
|
{
|
||||||
goto fail;
|
struct srventry *srv = NULL;
|
||||||
|
u16 type, class;
|
||||||
|
struct srventry *newlist;
|
||||||
|
|
||||||
type = buf16_to_u16 (pt);
|
newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
|
||||||
pt += 2;
|
if (!newlist)
|
||||||
/* We asked for SRV and got something else !? */
|
goto fail;
|
||||||
if(type!=T_SRV)
|
*list = newlist;
|
||||||
goto fail;
|
memset (&(*list)[srvcount], 0, sizeof(struct srventry));
|
||||||
|
srv = &(*list)[srvcount];
|
||||||
|
srvcount++;
|
||||||
|
|
||||||
class = buf16_to_u16 (pt);
|
rc = dn_skipname (pt, emsg); /* The name we just queried for. */
|
||||||
pt += 2;
|
if (rc == -1)
|
||||||
/* We asked for IN and got something else !? */
|
goto fail;
|
||||||
if(class!=C_IN)
|
pt += rc;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
pt += 4; /* ttl */
|
/* Truncated message? */
|
||||||
dlen = buf16_to_u16 (pt);
|
if ((emsg-pt) < 16)
|
||||||
pt += 2;
|
goto fail;
|
||||||
|
|
||||||
srv->priority = buf16_to_ushort (pt);
|
type = buf16_to_u16 (pt);
|
||||||
pt += 2;
|
pt += 2;
|
||||||
srv->weight = buf16_to_ushort (pt);
|
/* We asked for SRV and got something else !? */
|
||||||
pt += 2;
|
if (type != T_SRV)
|
||||||
srv->port = buf16_to_ushort (pt);
|
goto fail;
|
||||||
pt += 2;
|
|
||||||
|
|
||||||
/* Get the name. 2782 doesn't allow name compression, but
|
class = buf16_to_u16 (pt);
|
||||||
dn_expand still works to pull the name out of the
|
pt += 2;
|
||||||
packet. */
|
/* We asked for IN and got something else !? */
|
||||||
rc = dn_expand(answer,emsg,pt,srv->target, sizeof srv->target);
|
if (class != C_IN)
|
||||||
if (rc == 1 && srv->target[0] == 0) /* "." */
|
goto fail;
|
||||||
{
|
|
||||||
xfree(*list);
|
pt += 4; /* ttl */
|
||||||
*list = NULL;
|
dlen = buf16_to_u16 (pt);
|
||||||
return 0;
|
pt += 2;
|
||||||
}
|
|
||||||
if (rc == -1)
|
srv->priority = buf16_to_ushort (pt);
|
||||||
goto fail;
|
pt += 2;
|
||||||
pt += rc;
|
srv->weight = buf16_to_ushort (pt);
|
||||||
/* Corrupt packet? */
|
pt += 2;
|
||||||
if (dlen != rc+6)
|
srv->port = buf16_to_ushort (pt);
|
||||||
goto fail;
|
pt += 2;
|
||||||
}
|
|
||||||
}
|
/* Get the name. 2782 doesn't allow name compression, but
|
||||||
|
* dn_expand still works to pull the name out of the packet. */
|
||||||
|
rc = dn_expand (answer, emsg, pt, srv->target, sizeof srv->target);
|
||||||
|
if (rc == 1 && srv->target[0] == 0) /* "." */
|
||||||
|
{
|
||||||
|
xfree(*list);
|
||||||
|
*list = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (rc == -1)
|
||||||
|
goto fail;
|
||||||
|
pt += rc;
|
||||||
|
/* Corrupt packet? */
|
||||||
|
if (dlen != rc+6)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return srvcount;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
xfree (*list);
|
||||||
|
*list = NULL;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#else /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
|
|
||||||
|
(void)name;
|
||||||
|
(void)list;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#endif /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
getsrv (const char *name, struct srventry **list)
|
||||||
|
{
|
||||||
|
int srvcount;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
*list = NULL;
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
;
|
||||||
|
#ifdef USE_ADNS
|
||||||
|
else if (!standard_resolver)
|
||||||
|
srvcount = getsrv_adns (name, list);
|
||||||
#endif /*!USE_ADNS*/
|
#endif /*!USE_ADNS*/
|
||||||
|
else
|
||||||
|
srvcount = getsrv_standard (name, list);
|
||||||
|
|
||||||
|
if (srvcount <= 0)
|
||||||
|
return srvcount;
|
||||||
|
|
||||||
/* Now we have an array of all the srv records. */
|
/* Now we have an array of all the srv records. */
|
||||||
|
|
||||||
@ -1272,125 +1348,144 @@ getsrv (const char *name,struct srventry **list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return srvcount;
|
return srvcount;
|
||||||
|
|
||||||
fail:
|
|
||||||
xfree(*list);
|
|
||||||
*list=NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
#endif /*USE_DNS_SRV*/
|
|
||||||
|
|
||||||
|
#ifdef USE_ADNS
|
||||||
|
/* ADNS version of get_dns_cname. */
|
||||||
|
gpg_error_t
|
||||||
|
get_dns_cname_adns (const char *name, char **r_cname)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int rc;
|
||||||
|
adns_state state;
|
||||||
|
adns_answer *answer = NULL;
|
||||||
|
|
||||||
|
if (my_adns_init (&state))
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
|
my_unprotect ();
|
||||||
|
rc = adns_synchronous (state, name, adns_r_cname, adns_qf_quoteok_query,
|
||||||
|
&answer);
|
||||||
|
my_protect ();
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
err = gpg_error (gpg_err_code_from_errno (rc));
|
||||||
|
log_error ("DNS query failed: %s\n", gpg_strerror (err));
|
||||||
|
adns_finish (state);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (answer->status != adns_s_ok
|
||||||
|
|| answer->type != adns_r_cname || answer->nrrs != 1)
|
||||||
|
{
|
||||||
|
err = map_adns_status_to_gpg_error (answer->status);
|
||||||
|
log_error ("DNS query returned an error or no records: %s (%s)\n",
|
||||||
|
adns_strerror (answer->status),
|
||||||
|
adns_errabbrev (answer->status));
|
||||||
|
adns_free (answer);
|
||||||
|
adns_finish (state);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*r_cname = xtrystrdup (answer->rrs.str[0]);
|
||||||
|
if (!*r_cname)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
adns_free (answer);
|
||||||
|
adns_finish (state);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif /*USE_ADNS*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Standard resolver version of get_dns_cname. */
|
||||||
|
gpg_error_t
|
||||||
|
get_dns_cname_standard (const char *name, char **r_cname)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYSTEM_RESOLVER
|
||||||
|
gpg_error_t err;
|
||||||
|
int rc;
|
||||||
|
union {
|
||||||
|
unsigned char ans[2048];
|
||||||
|
HEADER header[1];
|
||||||
|
} res;
|
||||||
|
unsigned char *answer = res.ans;
|
||||||
|
HEADER *header = res.header;
|
||||||
|
unsigned char *pt, *emsg;
|
||||||
|
int r;
|
||||||
|
char *cname;
|
||||||
|
int cnamesize = 1025;
|
||||||
|
u16 count;
|
||||||
|
|
||||||
|
/* Do not allow a query using the standard resolver in Tor mode. */
|
||||||
|
if (tor_mode)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
r = res_query (name, C_IN, T_CERT, answer, sizeof answer);
|
||||||
|
if (r < sizeof (HEADER) || r > sizeof answer)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
|
||||||
|
return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found. */
|
||||||
|
if (count != 1)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
|
||||||
|
emsg = &answer[r];
|
||||||
|
pt = &answer[sizeof(HEADER)];
|
||||||
|
rc = dn_skipname (pt, emsg);
|
||||||
|
if (rc == -1)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
|
||||||
|
pt += rc + QFIXEDSZ;
|
||||||
|
if (pt >= emsg)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
|
||||||
|
rc = dn_skipname (pt, emsg);
|
||||||
|
if (rc == -1)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
pt += rc + 2 + 2 + 4;
|
||||||
|
if (pt+2 >= emsg)
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
pt += 2; /* Skip rdlen */
|
||||||
|
|
||||||
|
cname = xtrymalloc (cnamesize);
|
||||||
|
if (!cname)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
xfree (cname);
|
||||||
|
return gpg_error (GPG_ERR_SERVER_FAILED);
|
||||||
|
}
|
||||||
|
*r_cname = xtryrealloc (cname, strlen (cname)+1);
|
||||||
|
if (!*r_cname)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
xfree (cname);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
|
|
||||||
|
(void)name;
|
||||||
|
(void)r_cname;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#endif /*!HAVE_SYSTEM_RESOLVER*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
*r_cname = NULL;
|
*r_cname = NULL;
|
||||||
|
|
||||||
#ifdef USE_ADNS
|
#ifdef USE_ADNS
|
||||||
{
|
if (!standard_resolver)
|
||||||
adns_state state;
|
return get_dns_cname_adns (name, r_cname);
|
||||||
adns_answer *answer = NULL;
|
|
||||||
|
|
||||||
if (my_adns_init (&state))
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
|
|
||||||
my_unprotect ();
|
|
||||||
rc = adns_synchronous (state, name, adns_r_cname, adns_qf_quoteok_query,
|
|
||||||
&answer);
|
|
||||||
my_protect ();
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
err = gpg_error (gpg_err_code_from_errno (rc));
|
|
||||||
log_error ("DNS query failed: %s\n", gpg_strerror (err));
|
|
||||||
adns_finish (state);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (answer->status != adns_s_ok
|
|
||||||
|| answer->type != adns_r_cname || answer->nrrs != 1)
|
|
||||||
{
|
|
||||||
err = map_adns_status_to_gpg_error (answer->status);
|
|
||||||
log_error ("DNS query returned an error or no records: %s (%s)\n",
|
|
||||||
adns_strerror (answer->status),
|
|
||||||
adns_errabbrev (answer->status));
|
|
||||||
adns_free (answer);
|
|
||||||
adns_finish (state);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
*r_cname = xtrystrdup (answer->rrs.str[0]);
|
|
||||||
if (!*r_cname)
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
else
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
adns_free (answer);
|
|
||||||
adns_finish (state);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
#else /*!USE_ADNS*/
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned char ans[2048];
|
|
||||||
HEADER header[1];
|
|
||||||
} res;
|
|
||||||
unsigned char *answer = res.ans;
|
|
||||||
HEADER *header = res.header;
|
|
||||||
unsigned char *pt, *emsg;
|
|
||||||
int r;
|
|
||||||
char *cname;
|
|
||||||
int cnamesize = 1025;
|
|
||||||
u16 count;
|
|
||||||
|
|
||||||
/* Do not allow a query using the standard resolver in Tor mode. */
|
|
||||||
if (tor_mode)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
r = res_query (name, C_IN, T_CERT, answer, sizeof answer);
|
|
||||||
if (r < sizeof (HEADER) || r > sizeof answer)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
|
|
||||||
return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found. */
|
|
||||||
if (count != 1)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
|
|
||||||
emsg = &answer[r];
|
|
||||||
pt = &answer[sizeof(HEADER)];
|
|
||||||
rc = dn_skipname (pt, emsg);
|
|
||||||
if (rc == -1)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
|
|
||||||
pt += rc + QFIXEDSZ;
|
|
||||||
if (pt >= emsg)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
|
|
||||||
rc = dn_skipname (pt, emsg);
|
|
||||||
if (rc == -1)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
pt += rc + 2 + 2 + 4;
|
|
||||||
if (pt+2 >= emsg)
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
pt += 2; /* Skip rdlen */
|
|
||||||
|
|
||||||
cname = xtrymalloc (cnamesize);
|
|
||||||
if (!cname)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
|
|
||||||
rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
|
|
||||||
if (rc == -1)
|
|
||||||
{
|
|
||||||
xfree (cname);
|
|
||||||
return gpg_error (GPG_ERR_SERVER_FAILED);
|
|
||||||
}
|
|
||||||
*r_cname = xtryrealloc (cname, strlen (cname)+1);
|
|
||||||
if (!*r_cname)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
xfree (cname);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /*!USE_ADNS*/
|
#endif /*!USE_ADNS*/
|
||||||
|
|
||||||
|
return get_dns_cname_standard (name, r_cname);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,14 @@ struct srventry
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
void enable_standard_resolver (int yes);
|
||||||
|
|
||||||
|
/* Return true if the standard resolver is used. */
|
||||||
|
int standard_resolver_p (void);
|
||||||
|
|
||||||
/* Calling this function switches the DNS code into Tor mode if
|
/* Calling this function switches the DNS code into Tor mode if
|
||||||
possibe. Return 0 on success. */
|
possibe. Return 0 on success. */
|
||||||
gpg_error_t enable_dns_tormode (int new_circuit);
|
gpg_error_t enable_dns_tormode (int new_circuit);
|
||||||
|
@ -2323,7 +2323,6 @@ connect_server (const char *server, unsigned short port,
|
|||||||
#endif /*!HASSUAN_SOCK_TOR*/
|
#endif /*!HASSUAN_SOCK_TOR*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_DNS_SRV
|
|
||||||
/* Do the SRV thing */
|
/* Do the SRV thing */
|
||||||
if (srvtag)
|
if (srvtag)
|
||||||
{
|
{
|
||||||
@ -2347,10 +2346,6 @@ connect_server (const char *server, unsigned short port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
(void)flags;
|
|
||||||
(void)srvtag;
|
|
||||||
#endif /*USE_DNS_SRV*/
|
|
||||||
|
|
||||||
if (!serverlist)
|
if (!serverlist)
|
||||||
{
|
{
|
||||||
|
@ -426,11 +426,9 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
|
|||||||
int refidx;
|
int refidx;
|
||||||
int is_pool = 0;
|
int is_pool = 0;
|
||||||
char *cname;
|
char *cname;
|
||||||
#ifdef USE_DNS_SRV
|
|
||||||
char *srvrecord;
|
char *srvrecord;
|
||||||
struct srventry *srvs;
|
struct srventry *srvs;
|
||||||
int srvscount;
|
int srvscount;
|
||||||
#endif /* USE_DNS_SRV */
|
|
||||||
|
|
||||||
reftblsize = 100;
|
reftblsize = 100;
|
||||||
reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
|
reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
|
||||||
@ -447,7 +445,6 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
|
|||||||
}
|
}
|
||||||
hi = hosttable[idx];
|
hi = hosttable[idx];
|
||||||
|
|
||||||
#ifdef USE_DNS_SRV
|
|
||||||
if (!is_ip_address (name))
|
if (!is_ip_address (name))
|
||||||
{
|
{
|
||||||
/* Check for SRV records. */
|
/* Check for SRV records. */
|
||||||
@ -488,7 +485,6 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
|
|||||||
xfree (srvs);
|
xfree (srvs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* USE_DNS_SRV */
|
|
||||||
|
|
||||||
/* Find all A records for this entry and put them into the pool
|
/* Find all A records for this entry and put them into the pool
|
||||||
list - if any. */
|
list - if any. */
|
||||||
|
@ -2309,13 +2309,19 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
else if (!strcmp (line, "dnsinfo"))
|
else if (!strcmp (line, "dnsinfo"))
|
||||||
{
|
{
|
||||||
|
if (standard_resolver_p ())
|
||||||
|
assuan_set_okay_line
|
||||||
|
(ctx, "- Forced use of System resolver (w/o Tor support)");
|
||||||
|
else
|
||||||
|
{
|
||||||
#if USE_ADNS && HAVE_ADNS_IF_TORMODE
|
#if USE_ADNS && HAVE_ADNS_IF_TORMODE
|
||||||
assuan_set_okay_line (ctx, "- ADNS with Tor support");
|
assuan_set_okay_line (ctx, "- ADNS with Tor support");
|
||||||
#elif USE_ADNS
|
#elif USE_ADNS
|
||||||
assuan_set_okay_line (ctx, "- ADNS w/o Tor support");
|
assuan_set_okay_line (ctx, "- ADNS w/o Tor support");
|
||||||
#else
|
#else
|
||||||
assuan_set_okay_line (ctx, "- System resolver w/o Tor support");
|
assuan_set_okay_line (ctx, "- System resolver (w/o Tor support)");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -64,14 +64,15 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
fputs ("usage: " PGM " [HOST]\n"
|
fputs ("usage: " PGM " [HOST]\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --verbose print timings etc.\n"
|
" --verbose print timings etc.\n"
|
||||||
" --debug flyswatter\n"
|
" --debug flyswatter\n"
|
||||||
" --use-tor use Tor\n"
|
" --standard-resolver use the system's resolver\n"
|
||||||
" --new-circuit use a new Tor circuit\n"
|
" --use-tor use Tor\n"
|
||||||
" --bracket enclose v6 addresses in brackets\n"
|
" --new-circuit use a new Tor circuit\n"
|
||||||
" --cert lookup a CERT RR\n"
|
" --bracket enclose v6 addresses in brackets\n"
|
||||||
" --srv lookup a SRV RR\n"
|
" --cert lookup a CERT RR\n"
|
||||||
" --cname lookup a CNAME RR\n"
|
" --srv lookup a SRV RR\n"
|
||||||
|
" --cname lookup a CNAME RR\n"
|
||||||
, stdout);
|
, stdout);
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
@ -96,6 +97,11 @@ main (int argc, char **argv)
|
|||||||
opt_new_circuit = 1;
|
opt_new_circuit = 1;
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (*argv, "--standard-resolver"))
|
||||||
|
{
|
||||||
|
enable_standard_resolver (1);
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
else if (!strcmp (*argv, "--bracket"))
|
else if (!strcmp (*argv, "--bracket"))
|
||||||
{
|
{
|
||||||
opt_bracket = 1;
|
opt_bracket = 1;
|
||||||
|
@ -244,6 +244,13 @@ this still leaks the DNS queries; e.g. to lookup the hosts in a
|
|||||||
keyserver pool. Certain other features are disabled if this mode is
|
keyserver pool. Certain other features are disabled if this mode is
|
||||||
active.
|
active.
|
||||||
|
|
||||||
|
@item --standard-resolver
|
||||||
|
@opindex standard-resolver
|
||||||
|
This option forces the use of the system's standard DNS resolver code.
|
||||||
|
This is mainly used for debugging. Note that on Windows a standard
|
||||||
|
resolver is not used and all DNS access will return the error ``Not
|
||||||
|
Implemented'' if this function is used.
|
||||||
|
|
||||||
@item --allow-version-check
|
@item --allow-version-check
|
||||||
@opindex allow-version-check
|
@opindex allow-version-check
|
||||||
Allow Dirmngr to connect to @code{https://versions.gnupg.org} to get
|
Allow Dirmngr to connect to @code{https://versions.gnupg.org} to get
|
||||||
|
Loading…
x
Reference in New Issue
Block a user