diff options
author | Werner Koch <[email protected]> | 2016-12-01 14:45:51 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2016-12-01 15:40:32 +0000 |
commit | 304566d3327ef0a85188cce3109d46d5ff47177a (patch) | |
tree | c352a95f0b6bdbe6fca8d4aec1bfea9a7418f388 /dirmngr/dns-stuff.c | |
parent | gpg: Let only Dirmngr decide whether CERT is supported. (diff) | |
download | gnupg-304566d3327ef0a85188cce3109d46d5ff47177a.tar.gz gnupg-304566d3327ef0a85188cce3109d46d5ff47177a.zip |
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 <[email protected]>
Diffstat (limited to '')
-rw-r--r-- | dirmngr/dns-stuff.c | 693 |
1 files changed, 394 insertions, 299 deletions
diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c index 6849af4be..7924fd333 100644 --- a/dirmngr/dns-stuff.c +++ b/dirmngr/dns-stuff.c @@ -1,6 +1,6 @@ /* dns-stuff.c - DNS related code including CERT RR (rfc-4398) * 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. * @@ -36,9 +36,11 @@ # endif # include <windows.h> #else -# include <netinet/in.h> -# include <arpa/nameser.h> -# include <resolv.h> +# if HAVE_SYSTEM_RESOLVER +# include <netinet/in.h> +# include <arpa/nameser.h> +# include <resolv.h> +# endif # include <netdb.h> #endif #include <string.h> @@ -101,6 +103,8 @@ /* The default nameserver used with ADNS in Tor mode. */ #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. */ static int tor_mode; @@ -114,6 +118,25 @@ static char tor_nameserver[40+20]; static char tor_credentials[50]; #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 error code. */ gpg_error_t @@ -121,7 +144,7 @@ enable_dns_tormode (int new_circuit) { (void) new_circuit; -#if defined(USE_DNS_CERT) && defined(USE_ADNS) +#ifdef USE_ADNS # if HAVE_ADNS_IF_TORMODE if (!*tor_credentials || new_circuit) { @@ -367,7 +390,6 @@ resolve_name_adns (const char *name, unsigned short port, #endif /*USE_ADNS*/ -#ifndef USE_ADNS /* Resolve a name using the standard system function. */ static gpg_error_t 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; return err; } -#endif /*!USE_ADNS*/ /* 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) { #ifdef USE_ADNS - return resolve_name_adns (name, port, want_family, want_socktype, - r_ai, r_canonname); -#else + if (!standard_resolver) + return resolve_name_adns (name, port, want_family, want_socktype, + r_ai, r_canonname); +#endif return resolve_name_standard (name, port, want_family, want_socktype, r_ai, r_canonname); -#endif } @@ -565,11 +586,7 @@ 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 } @@ -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 +/* 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; int ret; adns_state state; @@ -678,14 +685,6 @@ get_dns_cert (const char *name, int want_certtype, unsigned int ctype; 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); if (err) return err; @@ -812,22 +811,22 @@ get_dns_cert (const char *name, int want_certtype, adns_free (answer); adns_finish (state); 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; unsigned char *answer; int r; 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. */ answer = xtrymalloc (65536); if (!answer) @@ -1004,9 +1003,36 @@ get_dns_cert (const char *name, int want_certtype, xfree (answer); return err; -#endif /*!USE_ADNS */ -#else /* !USE_DNS_CERT */ +#else /*!HAVE_SYSTEM_RESOLVER*/ + (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) *r_key = NULL; if (r_keylen) @@ -1015,11 +1041,16 @@ get_dns_cert (const char *name, int want_certtype, *r_fprlen = 0; *r_url = NULL; - return gpg_error (GPG_ERR_NOT_SUPPORTED); -#endif +#ifdef USE_ADNS + 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 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) +#ifdef USE_ADNS +/* ADNS based helper for getsrv. */ +static int +getsrv_adns (const char *name, struct srventry **list) { - int srvcount=0; + int srvcount = 0; u16 count; - int i, rc; - - *list = NULL; + int rc; + adns_state state; + adns_answer *answer = NULL; -#ifdef USE_ADNS - { - adns_state state; - adns_answer *answer = NULL; + if (my_adns_init (&state)) + return -1; - if (my_adns_init (&state)) + 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; - - 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; - } - if (answer->status != adns_s_ok - || answer->type != adns_r_srv || !answer->nrrs) - { + } + 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", adns_strerror (answer->status), adns_errabbrev (answer->status)); adns_free (answer); adns_finish (state); return 0; - } + } - for (count = 0; count < answer->nrrs; count++) - { - struct srventry *srv = NULL; - struct srventry *newlist; - - if (strlen (answer->rrs.srvha[count].ha.host) >= sizeof srv->target) - { - log_info ("hostname in SRV record too long - skipped\n"); - continue; - } - - newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry)); - if (!newlist) - goto fail; - *list = newlist; - memset (&(*list)[srvcount], 0, sizeof(struct srventry)); - srv = &(*list)[srvcount]; - srvcount++; - - srv->priority = answer->rrs.srvha[count].priority; - srv->weight = answer->rrs.srvha[count].weight; - srv->port = answer->rrs.srvha[count].port; - strcpy (srv->target, answer->rrs.srvha[count].ha.host); - } + for (count = 0; count < answer->nrrs; count++) + { + struct srventry *srv = NULL; + struct srventry *newlist; - adns_free (answer); - 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. */ - if (tor_mode) - return -1; + if (strlen (answer->rrs.srvha[count].ha.host) >= sizeof srv->target) + { + log_info ("hostname in SRV record too long - skipped\n"); + continue; + } - 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. */ + newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry)); + if (!newlist) + { + xfree (*list); + *list = NULL; + return -1; + } + *list = newlist; + memset (&(*list)[srvcount], 0, sizeof(struct srventry)); + srv = &(*list)[srvcount]; + srvcount++; + + srv->priority = answer->rrs.srvha[count].priority; + srv->weight = answer->rrs.srvha[count].weight; + srv->port = answer->rrs.srvha[count].port; + strcpy (srv->target, answer->rrs.srvha[count].ha.host); + } - emsg = &answer[r]; - pt = &answer[sizeof(HEADER)]; + adns_free (answer); + adns_finish (state); - /* Skip over the query */ - rc = dn_skipname (pt, emsg); - if (rc == -1) - goto fail; + return srvcount; +} +#endif /*USE_ADNS*/ - pt += rc + QFIXEDSZ; - while (count-- > 0 && pt < emsg) - { - struct srventry *srv=NULL; - u16 type,class; - struct srventry *newlist; - - newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry)); - if (!newlist) - goto fail; - *list = newlist; - memset(&(*list)[srvcount],0,sizeof(struct srventry)); - srv=&(*list)[srvcount]; - srvcount++; - - rc = dn_skipname(pt,emsg); /* the name we just queried for */ - if (rc == -1) - goto fail; - pt+=rc; - - /* Truncated message? */ - if((emsg-pt)<16) - goto fail; - - type = buf16_to_u16 (pt); - pt += 2; - /* We asked for SRV and got something else !? */ - if(type!=T_SRV) - goto fail; - - class = buf16_to_u16 (pt); - pt += 2; - /* We asked for IN and got something else !? */ - if(class!=C_IN) - goto fail; - - pt += 4; /* ttl */ - dlen = buf16_to_u16 (pt); - pt += 2; - - srv->priority = buf16_to_ushort (pt); - pt += 2; - srv->weight = buf16_to_ushort (pt); - pt += 2; - srv->port = buf16_to_ushort (pt); - 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; - } - } +/* Standard resolver based helper for getsrv. */ +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; + + /* Do not allow a query using the standard resolver in Tor mode. */ + if (tor_mode) + return -1; + + 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]; + pt = &answer[sizeof(HEADER)]; + + /* Skip over the query */ + rc = dn_skipname (pt, emsg); + if (rc == -1) + goto fail; + + pt += rc + QFIXEDSZ; + + while (count-- > 0 && pt < emsg) + { + struct srventry *srv = NULL; + u16 type, class; + struct srventry *newlist; + + newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry)); + if (!newlist) + goto fail; + *list = newlist; + memset (&(*list)[srvcount], 0, sizeof(struct srventry)); + srv = &(*list)[srvcount]; + srvcount++; + + rc = dn_skipname (pt, emsg); /* The name we just queried for. */ + if (rc == -1) + goto fail; + pt += rc; + + /* Truncated message? */ + if ((emsg-pt) < 16) + goto fail; + + type = buf16_to_u16 (pt); + pt += 2; + /* We asked for SRV and got something else !? */ + if (type != T_SRV) + goto fail; + + class = buf16_to_u16 (pt); + pt += 2; + /* We asked for IN and got something else !? */ + if (class != C_IN) + goto fail; + + pt += 4; /* ttl */ + dlen = buf16_to_u16 (pt); + pt += 2; + + srv->priority = buf16_to_ushort (pt); + pt += 2; + srv->weight = buf16_to_ushort (pt); + pt += 2; + srv->port = buf16_to_ushort (pt); + 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*/ + else + srvcount = getsrv_standard (name, list); + + if (srvcount <= 0) + return srvcount; /* Now we have an array of all the srv records. */ @@ -1272,125 +1348,144 @@ getsrv (const char *name,struct srventry **list) } 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 (const char *name, char **r_cname) +get_dns_cname_adns (const char *name, char **r_cname) { gpg_error_t err; int rc; + adns_state state; + adns_answer *answer = NULL; - *r_cname = NULL; + if (my_adns_init (&state)) + return gpg_error (GPG_ERR_GENERAL); -#ifdef USE_ADNS - { - adns_state state; - adns_answer *answer = NULL; + 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; - if (my_adns_init (&state)) - return gpg_error (GPG_ERR_GENERAL); + adns_free (answer); + adns_finish (state); + return err; +} +#endif /*USE_ADNS*/ - 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; +/* 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; - 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); + /* Do not allow a query using the standard resolver in Tor mode. */ + if (tor_mode) + return -1; - emsg = &answer[r]; - pt = &answer[sizeof(HEADER)]; - rc = dn_skipname (pt, emsg); - if (rc == -1) - return gpg_error (GPG_ERR_SERVER_FAILED); + 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 (); - pt += rc + QFIXEDSZ; - if (pt >= emsg) + 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; - 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 */ +#else /*!HAVE_SYSTEM_RESOLVER*/ - cname = xtrymalloc (cnamesize); - if (!cname) - return gpg_error_from_syserror (); + (void)name; + (void)r_cname; + return -1; - 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 /*!HAVE_SYSTEM_RESOLVER*/ +} + + +gpg_error_t +get_dns_cname (const char *name, char **r_cname) +{ + *r_cname = NULL; + +#ifdef USE_ADNS + if (!standard_resolver) + return get_dns_cname_adns (name, r_cname); #endif /*!USE_ADNS*/ + + return get_dns_cname_standard (name, r_cname); } |