LCOV - code coverage report
Current view: top level - dirmngr - dns-stuff.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 388 12.9 %
Date: 2015-11-05 17:10:59 Functions: 1 13 7.7 %

          Line data    Source code
       1             : /* dns-stuff.c - DNS related code including CERT RR (rfc-4398)
       2             :  * Copyright (C) 2003, 2005, 2006, 2009 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2005, 2006, 2009, 2015 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : #include <sys/types.h>
      33             : #ifdef HAVE_W32_SYSTEM
      34             : # ifdef HAVE_WINSOCK2_H
      35             : #  include <winsock2.h>
      36             : # endif
      37             : # include <windows.h>
      38             : #else
      39             : # include <netinet/in.h>
      40             : # include <arpa/nameser.h>
      41             : # include <resolv.h>
      42             : # include <netdb.h>
      43             : #endif
      44             : #include <string.h>
      45             : #include <unistd.h>
      46             : #ifdef USE_ADNS
      47             : # include <adns.h>
      48             : #endif
      49             : 
      50             : #if !defined(HAVE_GETADDRINFO) && !defined(USE_ADNS)
      51             : # error Either getaddrinfo or the ADNS libary is required.
      52             : #endif
      53             : 
      54             : #include "util.h"
      55             : #include "host2net.h"
      56             : #include "dns-stuff.h"
      57             : 
      58             : /* We allow the use of 0 instead of AF_UNSPEC - check this assumption.  */
      59             : #if AF_UNSPEC != 0
      60             : # error AF_UNSPEC does not have the value 0
      61             : #endif
      62             : 
      63             : /* Windows does not support the AI_ADDRCONFIG flag - use zero instead.  */
      64             : #ifndef AI_ADDRCONFIG
      65             : # define AI_ADDRCONFIG 0
      66             : #endif
      67             : 
      68             : /* Not every installation has gotten around to supporting SRVs or
      69             :    CERTs yet... */
      70             : #ifndef T_SRV
      71             : #define T_SRV 33
      72             : #endif
      73             : #ifndef T_CERT
      74             : # define T_CERT 37
      75             : #endif
      76             : 
      77             : /* ADNS has no support for CERT yet. */
      78             : #define my_adns_r_cert 37
      79             : 
      80             : /* If set Tor mode shall be used.  */
      81             : static int tor_mode;
      82             : 
      83             : /* Sets the module in Tor mode.  Returns 0 is this is possible or an
      84             :    error code.  */
      85             : gpg_error_t
      86           0 : enable_dns_tormode (void)
      87             : {
      88             : #if defined(USE_DNS_CERT) && defined(USE_ADNS)
      89             : # if HAVE_ADNS_IF_TORMODE
      90             :    tor_mode = 1;
      91             :    return 0;
      92             : # endif
      93             : #endif
      94           0 :   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
      95             : }
      96             : 
      97             : /* Free an addressinfo linked list as returned by resolve_dns_name.  */
      98             : void
      99           0 : free_dns_addrinfo (dns_addrinfo_t ai)
     100             : {
     101           0 :   while (ai)
     102             :     {
     103           0 :       dns_addrinfo_t next = ai->next;
     104           0 :       xfree (ai);
     105           0 :       ai = next;
     106             :     }
     107           0 : }
     108             : 
     109             : 
     110             : static gpg_error_t
     111           0 : map_eai_to_gpg_error (int ec)
     112             : {
     113             :   gpg_error_t err;
     114             : 
     115           0 :   switch (ec)
     116             :     {
     117           0 :     case EAI_AGAIN:     err = gpg_error (GPG_ERR_EAGAIN); break;
     118           0 :     case EAI_BADFLAGS:  err = gpg_error (GPG_ERR_INV_FLAG); break;
     119           0 :     case EAI_FAIL:      err = gpg_error (GPG_ERR_SERVER_FAILED); break;
     120           0 :     case EAI_MEMORY:    err = gpg_error (GPG_ERR_ENOMEM); break;
     121           0 :     case EAI_NODATA:    err = gpg_error (GPG_ERR_NO_DATA); break;
     122           0 :     case EAI_NONAME:    err = gpg_error (GPG_ERR_NO_NAME); break;
     123           0 :     case EAI_SERVICE:   err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
     124           0 :     case EAI_FAMILY:    err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
     125           0 :     case EAI_SOCKTYPE:  err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
     126             : #ifndef HAVE_W32_SYSTEM
     127           0 :     case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
     128           0 :     case EAI_SYSTEM:    err = gpg_error_from_syserror (); break;
     129             : #endif
     130           0 :     default:            err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
     131             :     }
     132           0 :   return err;
     133             : }
     134             : 
     135             : 
     136             : #ifdef USE_ADNS
     137             : /* Init ADNS and store the new state at R_STATE.  Returns 0 on
     138             :    success; prints an error message and returns an error code on
     139             :    failure.  */
     140             : static gpg_error_t
     141             : my_adns_init (adns_state *r_state)
     142             : {
     143             :   gpg_error_t err;
     144             : 
     145             :   if (tor_mode? adns_init_strcfg (r_state,
     146             :                                   adns_if_noerrprint|adns_if_tormode,
     147             :                                   NULL, "nameserver 8.8.8.8")
     148             :       /*    */: adns_init (r_state, adns_if_noerrprint, NULL))
     149             :     {
     150             :       err = gpg_error_from_syserror ();
     151             :       log_error ("error initializing adns: %s\n", gpg_strerror (err));
     152             :       return err;
     153             :     }
     154             :   return 0;
     155             : }
     156             : #endif /*USE_ADNS*/
     157             : 
     158             : 
     159             : #ifdef USE_ADNS
     160             : /* Resolve a name using the ADNS library.  See resolve_dns_name for
     161             :    the description.  */
     162             : static gpg_error_t
     163             : resolve_name_adns (const char *name, unsigned short port,
     164             :                    int want_family, int want_socktype,
     165             :                    dns_addrinfo_t *r_dai, char **r_canonname)
     166             : {
     167             :   gpg_error_t err = 0;
     168             :   dns_addrinfo_t daihead = NULL;
     169             :   dns_addrinfo_t dai;
     170             :   adns_state state;
     171             :   adns_answer *answer = NULL;
     172             :   int count;
     173             : 
     174             :   *r_dai = NULL;
     175             :   if (r_canonname)
     176             :     *r_canonname = NULL;
     177             : 
     178             :   if (want_socktype != SOCK_STREAM && want_socktype != SOCK_DGRAM)
     179             :     return gpg_error (GPG_ERR_ESOCKTNOSUPPORT);
     180             : 
     181             :   err = my_adns_init (&state);
     182             :   if (err)
     183             :     return err;
     184             : 
     185             :   if (adns_synchronous (state, name, adns_r_addr,
     186             :                         adns_qf_quoteok_query, &answer))
     187             :     {
     188             :       err = gpg_error_from_syserror ();
     189             :       log_error ("DNS query failed: %s\n", gpg_strerror (err));
     190             :       goto leave;
     191             :     }
     192             : 
     193             :   err = gpg_error (GPG_ERR_NOT_FOUND);
     194             :   if (answer->status != adns_s_ok || answer->type != adns_r_addr)
     195             :     {
     196             :       log_error ("DNS query returned an error: %s (%s)\n",
     197             :                  adns_strerror (answer->status),
     198             :                  adns_errabbrev (answer->status));
     199             :       goto leave;
     200             :     }
     201             : 
     202             :   if (r_canonname && answer->cname)
     203             :     {
     204             :       *r_canonname = xtrystrdup (answer->cname);
     205             :       if (!*r_canonname)
     206             :         {
     207             :           err = gpg_error_from_syserror ();
     208             :           goto leave;
     209             :         }
     210             :     }
     211             : 
     212             :   for (count = 0; count < answer->nrrs; count++)
     213             :     {
     214             :       int len;
     215             :       adns_rr_addr *addr;
     216             : 
     217             :       len  = answer->rrs.addr[count].len;
     218             :       addr = &answer->rrs.addr[count];
     219             :       if (addr->addr.sa.sa_family != AF_INET6
     220             :           && addr->addr.sa.sa_family != AF_INET)
     221             :         continue;
     222             : 
     223             :       dai = xtrymalloc (sizeof *dai + len - 1);
     224             :       if (!dai)
     225             :         {
     226             :           err = gpg_error_from_syserror ();
     227             :           goto leave;
     228             :         }
     229             :       dai->family = addr->addr.sa.sa_family;
     230             :       dai->socktype = want_socktype == SOCK_STREAM? SOCK_STREAM : SOCK_DGRAM;
     231             :       dai->protocol = want_socktype == SOCK_STREAM? IPPROTO_TCP : IPPROTO_UDP;
     232             :       dai->addrlen = len;
     233             :       memcpy (dai->addr, &addr->addr.sa, len);
     234             :       dai->next = daihead;
     235             :       daihead = dai;
     236             :       err = 0;
     237             :     }
     238             : 
     239             :  leave:
     240             :   adns_free (answer);
     241             :   adns_finish (state);
     242             :   if (err)
     243             :     {
     244             :       if (r_canonname)
     245             :         {
     246             :           xfree (*r_canonname);
     247             :           *r_canonname = NULL;
     248             :         }
     249             :       free_dns_addrinfo (daihead);
     250             :     }
     251             :   else
     252             :     *r_dai = daihead;
     253             :   return err;
     254             : }
     255             : #endif /*USE_ADNS*/
     256             : 
     257             : 
     258             : #ifndef USE_ADNS
     259             : /* Resolve a name using the standard system function.  */
     260             : static gpg_error_t
     261           0 : resolve_name_standard (const char *name, unsigned short port,
     262             :                        int want_family, int want_socktype,
     263             :                        dns_addrinfo_t *r_dai, char **r_canonname)
     264             : {
     265           0 :   gpg_error_t err = 0;
     266           0 :   dns_addrinfo_t daihead = NULL;
     267             :   dns_addrinfo_t dai;
     268           0 :   struct addrinfo *aibuf = NULL;
     269             :   struct addrinfo hints, *ai;
     270             :   char portstr[21];
     271             :   int ret;
     272             : 
     273           0 :   *r_dai = NULL;
     274           0 :   if (r_canonname)
     275           0 :     *r_canonname = NULL;
     276             : 
     277           0 :   memset (&hints, 0, sizeof hints);
     278           0 :   hints.ai_family = want_family;
     279           0 :   hints.ai_socktype = want_socktype;
     280           0 :   hints.ai_flags = AI_ADDRCONFIG;
     281           0 :   if (r_canonname)
     282           0 :     hints.ai_flags |= AI_CANONNAME;
     283             : 
     284           0 :   if (port)
     285           0 :     snprintf (portstr, sizeof portstr, "%hu", port);
     286             :   else
     287           0 :     *portstr = 0;
     288             : 
     289             :   /* We can't use the the AI_IDN flag because that does the conversion
     290             :      using the current locale.  However, GnuPG always used UTF-8.  To
     291             :      support IDN we would need to make use of the libidn API.  */
     292           0 :   ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
     293           0 :   if (ret)
     294             :     {
     295           0 :       aibuf = NULL;
     296           0 :       err = map_eai_to_gpg_error (ret);
     297           0 :       if (gpg_err_code (err) == GPG_ERR_NO_NAME)
     298             :         {
     299             :           /* There seems to be a bug in the glibc getaddrinfo function
     300             :              if the CNAME points to a long list of A and AAAA records
     301             :              in which case the function return NO_NAME.  Let's do the
     302             :              CNAME redirection again.  */
     303             :           char *cname;
     304             : 
     305           0 :           if (get_dns_cname (name, &cname))
     306           0 :             goto leave; /* Still no success.  */
     307             : 
     308           0 :           ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
     309           0 :           xfree (cname);
     310           0 :           if (ret)
     311             :             {
     312           0 :               aibuf = NULL;
     313           0 :               err = map_eai_to_gpg_error (ret);
     314           0 :               goto leave;
     315             :             }
     316           0 :           err = 0; /* Yep, now it worked.  */
     317             :         }
     318             :       else
     319           0 :         goto leave;
     320             :     }
     321             : 
     322           0 :   if (r_canonname && aibuf && aibuf->ai_canonname)
     323             :     {
     324           0 :       *r_canonname = xtrystrdup (aibuf->ai_canonname);
     325           0 :       if (!*r_canonname)
     326             :         {
     327           0 :           err = gpg_error_from_syserror ();
     328           0 :           goto leave;
     329             :         }
     330             :     }
     331             : 
     332           0 :   for (ai = aibuf; ai; ai = ai->ai_next)
     333             :     {
     334           0 :       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
     335           0 :         continue;
     336             : 
     337           0 :       dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
     338           0 :       dai->family = ai->ai_family;
     339           0 :       dai->socktype = ai->ai_socktype;
     340           0 :       dai->protocol = ai->ai_protocol;
     341           0 :       dai->addrlen = ai->ai_addrlen;
     342           0 :       memcpy (dai->addr, ai->ai_addr, ai->ai_addrlen);
     343           0 :       dai->next = daihead;
     344           0 :       daihead = dai;
     345             :     }
     346             : 
     347             :  leave:
     348           0 :   if (aibuf)
     349           0 :     freeaddrinfo (aibuf);
     350           0 :   if (err)
     351             :     {
     352           0 :       if (r_canonname)
     353             :         {
     354           0 :           xfree (*r_canonname);
     355           0 :           *r_canonname = NULL;
     356             :         }
     357           0 :       free_dns_addrinfo (daihead);
     358             :     }
     359             :   else
     360           0 :     *r_dai = daihead;
     361           0 :   return err;
     362             : }
     363             : #endif /*!USE_ADNS*/
     364             : 
     365             : 
     366             : /* Resolve an address using the standard system function.  */
     367             : static gpg_error_t
     368           0 : resolve_addr_standard (const struct sockaddr *addr, int addrlen,
     369             :                        unsigned int flags, char **r_name)
     370             : {
     371             :   gpg_error_t err;
     372             :   int ec;
     373             :   char *buffer, *p;
     374             :   int buflen;
     375             : 
     376           0 :   *r_name = NULL;
     377             : 
     378           0 :   buflen = NI_MAXHOST;
     379           0 :   buffer = xtrymalloc (buflen + 2 + 1);
     380           0 :   if (!buffer)
     381           0 :     return gpg_error_from_syserror ();
     382             : 
     383           0 :   if ((flags & DNS_NUMERICHOST) || tor_mode)
     384           0 :     ec = EAI_NONAME;
     385             :   else
     386           0 :     ec = getnameinfo (addr, addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
     387             : 
     388           0 :   if (!ec && *buffer == '[')
     389           0 :     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
     390           0 :   else if (ec == EAI_NONAME)
     391             :     {
     392           0 :       p = buffer;
     393           0 :       if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
     394             :         {
     395           0 :           *p++ = '[';
     396           0 :           buflen -= 2;
     397             :         }
     398           0 :       ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
     399           0 :       if (!ec && addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
     400           0 :         strcat (buffer, "]");
     401             :     }
     402             : 
     403           0 :   if (ec)
     404           0 :     err = map_eai_to_gpg_error (ec);
     405             :   else
     406             :     {
     407           0 :       p = xtryrealloc (buffer, strlen (buffer)+1);
     408           0 :       if (!p)
     409           0 :         err = gpg_error_from_syserror ();
     410             :       else
     411             :         {
     412           0 :           buffer = p;
     413           0 :           err = 0;
     414             :         }
     415             :     }
     416             : 
     417           0 :   if (err)
     418           0 :     xfree (buffer);
     419             :   else
     420           0 :     *r_name = buffer;
     421             : 
     422           0 :   return err;
     423             : }
     424             : 
     425             : 
     426             : /* This a wrapper around getaddrinfo with slighly different semantics.
     427             :    NAME is the name to resolve.
     428             :    PORT is the requested port or 0.
     429             :    WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
     430             :    WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
     431             : 
     432             :    On success the result is stored in a linked list with the head
     433             :    stored at the address R_AI; the caller must call gpg_addrinfo_free
     434             :    on this.  If R_CANONNAME is not NULL the official name of the host
     435             :    is stored there as a malloced string; if that name is not available
     436             :    NULL is stored.  */
     437             : gpg_error_t
     438           0 : resolve_dns_name (const char *name, unsigned short port,
     439             :                   int want_family, int want_socktype,
     440             :                   dns_addrinfo_t *r_ai, char **r_canonname)
     441             : {
     442             : #ifdef USE_ADNS
     443             :   return resolve_name_adns (name, port, want_family, want_socktype,
     444             :                             r_ai, r_canonname);
     445             : #else
     446           0 :   return resolve_name_standard (name, port, want_family, want_socktype,
     447             :                                 r_ai, r_canonname);
     448             : #endif
     449             : }
     450             : 
     451             : 
     452             : gpg_error_t
     453           0 : resolve_dns_addr (const struct sockaddr *addr, int addrlen,
     454             :                   unsigned int flags, char **r_name)
     455             : {
     456             : #ifdef USE_ADNS_disabled_for_now
     457             :   return resolve_addr_adns (addr, addrlen, flags, r_name);
     458             : #else
     459           0 :   return resolve_addr_standard (addr, addrlen, flags, r_name);
     460             : #endif
     461             : }
     462             : 
     463             : 
     464             : /* Check whether NAME is an IP address.  Returns true if it is either
     465             :    an IPv6 or IPv4 numerical address.  */
     466             : int
     467           0 : is_ip_address (const char *name)
     468             : {
     469             :   const char *s;
     470             :   int ndots, dblcol, n;
     471             : 
     472           0 :   if (*name == '[')
     473           0 :     return 1; /* yes: A legal DNS name may not contain this character;
     474             :                  this mut be bracketed v6 address.  */
     475           0 :   if (*name == '.')
     476           0 :     return 0; /* No.  A leading dot is not a valid IP address.  */
     477             : 
     478             :   /* Check whether this is a v6 address.  */
     479           0 :   ndots = n = dblcol = 0;
     480           0 :   for (s=name; *s; s++)
     481             :     {
     482           0 :       if (*s == ':')
     483             :         {
     484           0 :           ndots++;
     485           0 :           if (s[1] == ':')
     486             :             {
     487           0 :               ndots++;
     488           0 :               if (dblcol)
     489           0 :                 return 0; /* No: Only one "::" allowed.  */
     490           0 :               dblcol++;
     491           0 :               if (s[1])
     492           0 :                 s++;
     493             :             }
     494           0 :           n = 0;
     495             :         }
     496           0 :       else if (*s == '.')
     497           0 :         goto legacy;
     498           0 :       else if (!strchr ("0123456789abcdefABCDEF", *s))
     499           0 :         return 0; /* No: Not a hex digit.  */
     500           0 :       else if (++n > 4)
     501           0 :         return 0; /* To many digits in a group.  */
     502             :     }
     503           0 :   if (ndots > 7)
     504           0 :     return 0; /* No: Too many colons.  */
     505           0 :   else if (ndots > 1)
     506           0 :     return 1; /* Yes: At least 2 colons indicate an v6 address.  */
     507             : 
     508             :  legacy:
     509             :   /* Check whether it is legacy IP address.  */
     510           0 :   ndots = n = 0;
     511           0 :   for (s=name; *s; s++)
     512             :     {
     513           0 :       if (*s == '.')
     514             :         {
     515           0 :           if (s[1] == '.')
     516           0 :             return 0; /* No:  Douple dot. */
     517           0 :           if (atoi (s+1) > 255)
     518           0 :             return 0; /* No:  Ipv4 byte value too large.  */
     519           0 :           ndots++;
     520           0 :           n = 0;
     521             :         }
     522           0 :       else if (!strchr ("0123456789", *s))
     523           0 :         return 0; /* No: Not a digit.  */
     524           0 :       else if (++n > 3)
     525           0 :         return 0; /* No: More than 3 digits.  */
     526             :     }
     527           0 :   return !!(ndots == 3);
     528             : }
     529             : 
     530             : 
     531             : /* Return true if NAME is an onion address.  */
     532             : int
     533           0 : is_onion_address (const char *name)
     534             : {
     535             :   size_t len;
     536             : 
     537           0 :   len = name? strlen (name) : 0;
     538           0 :   if (len < 8 || strcmp (name + len - 6, ".onion"))
     539           0 :     return 0;
     540             :   /* Note that we require at least 2 characters before the suffix.  */
     541           0 :   return 1;  /* Yes.  */
     542             : }
     543             : 
     544             : 
     545             : /* Returns 0 on success or an error code.  If a PGP CERT record was
     546             :    found, the malloced data is returned at (R_KEY, R_KEYLEN) and
     547             :    the other return parameters are set to NULL/0.  If an IPGP CERT
     548             :    record was found the fingerprint is stored as an allocated block at
     549             :    R_FPR and its length at R_FPRLEN; an URL is is allocated as a
     550             :    string and returned at R_URL.  If WANT_CERTTYPE is 0 this function
     551             :    returns the first CERT found with a supported type; it is expected
     552             :    that only one CERT record is used.  If WANT_CERTTYPE is one of the
     553             :    supported certtypes only records with this certtype are considered
     554             :    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
     555             : gpg_error_t
     556           1 : get_dns_cert (const char *name, int want_certtype,
     557             :               void **r_key, size_t *r_keylen,
     558             :               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
     559             : {
     560             : #ifdef USE_DNS_CERT
     561             : #ifdef USE_ADNS
     562             :   gpg_error_t err;
     563             :   adns_state state;
     564             :   adns_answer *answer = NULL;
     565             :   unsigned int ctype;
     566             :   int count;
     567             : 
     568             :   if (r_key)
     569             :     *r_key = NULL;
     570             :   if (r_keylen)
     571             :     *r_keylen = 0;
     572             :   *r_fpr = NULL;
     573             :   *r_fprlen = 0;
     574             :   *r_url = NULL;
     575             : 
     576             :   err = my_adns_init (&state);
     577             :   if (err)
     578             :     return err;
     579             : 
     580             :   if (adns_synchronous (state, name,
     581             :                         (adns_r_unknown
     582             :                          | (want_certtype < DNS_CERTTYPE_RRBASE
     583             :                             ? my_adns_r_cert
     584             :                             : (want_certtype - DNS_CERTTYPE_RRBASE))),
     585             :                         adns_qf_quoteok_query, &answer))
     586             :     {
     587             :       err = gpg_error_from_syserror ();
     588             :       /* log_error ("DNS query failed: %s\n", strerror (errno)); */
     589             :       adns_finish (state);
     590             :       return err;
     591             :     }
     592             :   if (answer->status != adns_s_ok)
     593             :     {
     594             :       /* log_error ("DNS query returned an error: %s (%s)\n", */
     595             :       /*            adns_strerror (answer->status), */
     596             :       /*            adns_errabbrev (answer->status)); */
     597             :       err = gpg_error (GPG_ERR_NOT_FOUND);
     598             :       goto leave;
     599             :     }
     600             : 
     601             :   err = gpg_error (GPG_ERR_NOT_FOUND);
     602             :   for (count = 0; count < answer->nrrs; count++)
     603             :     {
     604             :       int datalen = answer->rrs.byteblock[count].len;
     605             :       const unsigned char *data = answer->rrs.byteblock[count].data;
     606             : 
     607             :       /* First check for our generic RR hack.  */
     608             :       if (datalen
     609             :           && want_certtype >= DNS_CERTTYPE_RRBASE
     610             :           && ((want_certtype - DNS_CERTTYPE_RRBASE)
     611             :               == (answer->type & ~adns_r_unknown)))
     612             :         {
     613             :           /* Found the requested record - return it.  */
     614             :           *r_key = xtrymalloc (datalen);
     615             :           if (!*r_key)
     616             :             err = gpg_error_from_syserror ();
     617             :           else
     618             :             {
     619             :               memcpy (*r_key, data, datalen);
     620             :               *r_keylen = datalen;
     621             :               err = 0;
     622             :             }
     623             :           goto leave;
     624             :         }
     625             : 
     626             :       if (datalen < 5)
     627             :         continue;  /* Truncated CERT record - skip.  */
     628             : 
     629             :       ctype = buf16_to_uint (data);
     630             :       /* (key tag and algorithm fields are not required.) */
     631             :       data += 5;
     632             :       datalen -= 5;
     633             : 
     634             :       if (want_certtype && want_certtype != ctype)
     635             :         ; /* Not of the requested certtype.  */
     636             :       else if (ctype == DNS_CERTTYPE_PGP && datalen >= 11 && r_key && r_keylen)
     637             :         {
     638             :           /* CERT type is PGP.  Gpg checks for a minimum length of 11,
     639             :              thus we do the same.  */
     640             :           *r_key = xtrymalloc (datalen);
     641             :           if (!*r_key)
     642             :             err = gpg_error_from_syserror ();
     643             :           else
     644             :             {
     645             :               memcpy (*r_key, data, datalen);
     646             :               *r_keylen = datalen;
     647             :               err = 0;
     648             :             }
     649             :           goto leave;
     650             :         }
     651             :       else if (ctype == DNS_CERTTYPE_IPGP && datalen && datalen < 1023
     652             :                && datalen >= data[0] + 1 && r_fpr && r_fprlen && r_url)
     653             :         {
     654             :           /* CERT type is IPGP.  We made sure that the data is
     655             :              plausible and that the caller requested this
     656             :              information.  */
     657             :           *r_fprlen = data[0];
     658             :           if (*r_fprlen)
     659             :             {
     660             :               *r_fpr = xtrymalloc (*r_fprlen);
     661             :               if (!*r_fpr)
     662             :                 {
     663             :                   err = gpg_error_from_syserror ();
     664             :                   goto leave;
     665             :                 }
     666             :               memcpy (*r_fpr, data + 1, *r_fprlen);
     667             :             }
     668             :           else
     669             :             *r_fpr = NULL;
     670             : 
     671             :           if (datalen > *r_fprlen + 1)
     672             :             {
     673             :               *r_url = xtrymalloc (datalen - (*r_fprlen + 1) + 1);
     674             :               if (!*r_url)
     675             :                 {
     676             :                   err = gpg_error_from_syserror ();
     677             :                   xfree (*r_fpr);
     678             :                   *r_fpr = NULL;
     679             :                   goto leave;
     680             :                 }
     681             :               memcpy (*r_url,
     682             :                       data + (*r_fprlen + 1), datalen - (*r_fprlen + 1));
     683             :               (*r_url)[datalen - (*r_fprlen + 1)] = '\0';
     684             :             }
     685             :           else
     686             :             *r_url = NULL;
     687             : 
     688             :           err = 0;
     689             :           goto leave;
     690             :         }
     691             :     }
     692             : 
     693             :  leave:
     694             :   adns_free (answer);
     695             :   adns_finish (state);
     696             :   return err;
     697             : 
     698             : #else /*!USE_ADNS*/
     699             : 
     700             :   gpg_error_t err;
     701             :   unsigned char *answer;
     702             :   int r;
     703             :   u16 count;
     704             : 
     705           1 :   if (r_key)
     706           1 :     *r_key = NULL;
     707           1 :   if (r_keylen)
     708           1 :     *r_keylen = 0;
     709           1 :   *r_fpr = NULL;
     710           1 :   *r_fprlen = 0;
     711           1 :   *r_url = NULL;
     712             : 
     713             :   /* Allocate a 64k buffer which is the limit for an DNS response.  */
     714           1 :   answer = xtrymalloc (65536);
     715           1 :   if (!answer)
     716           0 :     return gpg_error_from_syserror ();
     717             : 
     718           1 :   err = gpg_error (GPG_ERR_NOT_FOUND);
     719           1 :   r = res_query (name, C_IN,
     720             :                  (want_certtype < DNS_CERTTYPE_RRBASE
     721             :                   ? T_CERT
     722             :                   : (want_certtype - DNS_CERTTYPE_RRBASE)),
     723             :                  answer, 65536);
     724             :   /* Not too big, not too small, no errors and at least 1 answer. */
     725           1 :   if (r >= sizeof (HEADER) && r <= 65536
     726           1 :       && (((HEADER *) answer)->rcode) == NOERROR
     727           1 :       && (count = ntohs (((HEADER *) answer)->ancount)))
     728             :     {
     729             :       int rc;
     730             :       unsigned char *pt, *emsg;
     731             : 
     732           1 :       emsg = &answer[r];
     733             : 
     734           1 :       pt = &answer[sizeof (HEADER)];
     735             : 
     736             :       /* Skip over the query */
     737             : 
     738           1 :       rc = dn_skipname (pt, emsg);
     739           1 :       if (rc == -1)
     740             :         {
     741           0 :           err = gpg_error (GPG_ERR_INV_OBJ);
     742           0 :           goto leave;
     743             :         }
     744           1 :       pt += rc + QFIXEDSZ;
     745             : 
     746             :       /* There are several possible response types for a CERT request.
     747             :          We're interested in the PGP (a key) and IPGP (a URI) types.
     748             :          Skip all others.  TODO: A key is better than a URI since
     749             :          we've gone through all this bother to fetch it, so favor that
     750             :          if we have both PGP and IPGP? */
     751             : 
     752           2 :       while (count-- > 0 && pt < emsg)
     753             :         {
     754             :           u16 type, class, dlen, ctype;
     755             : 
     756           1 :           rc = dn_skipname (pt, emsg);  /* the name we just queried for */
     757           1 :           if (rc == -1)
     758             :             {
     759           0 :               err = gpg_error (GPG_ERR_INV_OBJ);
     760           0 :               goto leave;
     761             :             }
     762             : 
     763           1 :           pt += rc;
     764             : 
     765             :           /* Truncated message? 15 bytes takes us to the point where
     766             :              we start looking at the ctype. */
     767           1 :           if ((emsg - pt) < 15)
     768           0 :             break;
     769             : 
     770           1 :           type = buf16_to_u16 (pt);
     771           1 :           pt += 2;
     772             : 
     773           1 :           class = buf16_to_u16 (pt);
     774           1 :           pt += 2;
     775             : 
     776           1 :           if (class != C_IN)
     777           0 :             break;
     778             : 
     779             :           /* ttl */
     780           1 :           pt += 4;
     781             : 
     782             :           /* data length */
     783           1 :           dlen = buf16_to_u16 (pt);
     784           1 :           pt += 2;
     785             : 
     786             :           /* Check the type and parse.  */
     787           1 :           if (want_certtype >= DNS_CERTTYPE_RRBASE
     788           0 :               && type == (want_certtype - DNS_CERTTYPE_RRBASE)
     789           0 :               && r_key)
     790             :             {
     791           0 :               *r_key = xtrymalloc (dlen);
     792           0 :               if (!*r_key)
     793           0 :                 err = gpg_error_from_syserror ();
     794             :               else
     795             :                 {
     796           0 :                   memcpy (*r_key, pt, dlen);
     797           0 :                   *r_keylen = dlen;
     798           0 :                   err = 0;
     799             :                 }
     800           0 :               goto leave;
     801             :             }
     802           1 :           else if (want_certtype >= DNS_CERTTYPE_RRBASE)
     803             :             {
     804             :               /* We did not found the requested RR.  */
     805           0 :               pt += dlen;
     806             :             }
     807           1 :           else if (type == T_CERT)
     808             :             {
     809             :               /* We got a CERT type.   */
     810           1 :               ctype = buf16_to_u16 (pt);
     811           1 :               pt += 2;
     812             : 
     813             :               /* Skip the CERT key tag and algo which we don't need. */
     814           1 :               pt += 3;
     815             : 
     816           1 :               dlen -= 5;
     817             : 
     818             :               /* 15 bytes takes us to here */
     819           1 :               if (want_certtype && want_certtype != ctype)
     820             :                 ; /* Not of the requested certtype.  */
     821           1 :               else if (ctype == DNS_CERTTYPE_PGP && dlen && r_key && r_keylen)
     822             :                 {
     823             :                   /* PGP type */
     824           1 :                   *r_key = xtrymalloc (dlen);
     825           1 :                   if (!*r_key)
     826           0 :                     err = gpg_error_from_syserror ();
     827             :                   else
     828             :                     {
     829           1 :                       memcpy (*r_key, pt, dlen);
     830           1 :                       *r_keylen = dlen;
     831           1 :                       err = 0;
     832             :                     }
     833           1 :                   goto leave;
     834             :                 }
     835           0 :               else if (ctype == DNS_CERTTYPE_IPGP
     836           0 :                        && dlen && dlen < 1023 && dlen >= pt[0] + 1)
     837             :                 {
     838             :                   /* IPGP type */
     839           0 :                   *r_fprlen = pt[0];
     840           0 :                   if (*r_fprlen)
     841             :                     {
     842           0 :                       *r_fpr = xtrymalloc (*r_fprlen);
     843           0 :                       if (!*r_fpr)
     844             :                         {
     845           0 :                           err = gpg_error_from_syserror ();
     846           0 :                           goto leave;
     847             :                         }
     848           0 :                       memcpy (*r_fpr, &pt[1], *r_fprlen);
     849             :                     }
     850             :                   else
     851           0 :                     *r_fpr = NULL;
     852             : 
     853           0 :                   if (dlen > *r_fprlen + 1)
     854             :                     {
     855           0 :                       *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1);
     856           0 :                       if (!*r_fpr)
     857             :                         {
     858           0 :                           err = gpg_error_from_syserror ();
     859           0 :                           xfree (*r_fpr);
     860           0 :                           *r_fpr = NULL;
     861           0 :                           goto leave;
     862             :                         }
     863           0 :                       memcpy (*r_url, &pt[*r_fprlen + 1],
     864           0 :                               dlen - (*r_fprlen + 1));
     865           0 :                       (*r_url)[dlen - (*r_fprlen + 1)] = '\0';
     866             :                     }
     867             :                   else
     868           0 :                     *r_url = NULL;
     869             : 
     870           0 :                   err = 0;
     871           0 :                   goto leave;
     872             :                 }
     873             : 
     874             :               /* No subtype matches, so continue with the next answer. */
     875           0 :               pt += dlen;
     876             :             }
     877             :           else
     878             :             {
     879             :               /* Not a requested type - might be a CNAME. Try next item.  */
     880           0 :               pt += dlen;
     881             :             }
     882             :         }
     883             :     }
     884             : 
     885             :  leave:
     886           1 :   xfree (answer);
     887           1 :   return err;
     888             : 
     889             : #endif /*!USE_ADNS */
     890             : #else /* !USE_DNS_CERT */
     891             :   (void)name;
     892             :   if (r_key)
     893             :     *r_key = NULL;
     894             :   if (r_keylen)
     895             :     *r_keylen = NULL;
     896             :   *r_fpr = NULL;
     897             :   *r_fprlen = 0;
     898             :   *r_url = NULL;
     899             : 
     900             :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     901             : #endif
     902             : }
     903             : 
     904             : #ifdef USE_DNS_SRV
     905             : static int
     906           0 : priosort(const void *a,const void *b)
     907             : {
     908           0 :   const struct srventry *sa=a,*sb=b;
     909           0 :   if(sa->priority>sb->priority)
     910           0 :     return 1;
     911           0 :   else if(sa->priority<sb->priority)
     912           0 :     return -1;
     913             :   else
     914           0 :     return 0;
     915             : }
     916             : 
     917             : 
     918             : int
     919           0 : getsrv (const char *name,struct srventry **list)
     920             : {
     921           0 :   int srvcount=0;
     922             :   u16 count;
     923             :   int i, rc;
     924             : 
     925           0 :   *list = NULL;
     926             : 
     927             : #ifdef USE_ADNS
     928             :   {
     929             :     adns_state state;
     930             :     adns_answer *answer = NULL;
     931             : 
     932             :     if (my_adns_init (&state))
     933             :       return -1;
     934             : 
     935             :     rc = adns_synchronous (state, name, adns_r_srv, adns_qf_quoteok_query,
     936             :                            &answer);
     937             :     if (rc)
     938             :       {
     939             :         log_error ("DNS query failed: %s\n", strerror (errno));
     940             :         adns_finish (state);
     941             :         return -1;
     942             :       }
     943             :     if (answer->status != adns_s_ok
     944             :         || answer->type != adns_r_srv || !answer->nrrs)
     945             :       {
     946             :         log_error ("DNS query returned an error or no records: %s (%s)\n",
     947             :                    adns_strerror (answer->status),
     948             :                    adns_errabbrev (answer->status));
     949             :         adns_free (answer);
     950             :         adns_finish (state);
     951             :         return 0;
     952             :       }
     953             : 
     954             :     for (count = 0; count < answer->nrrs; count++)
     955             :       {
     956             :         struct srventry *srv = NULL;
     957             :         struct srventry *newlist;
     958             : 
     959             :         if (strlen (answer->rrs.srvha[count].ha.host) >= sizeof srv->target)
     960             :           {
     961             :             log_info ("hostname in SRV record too long - skipped\n");
     962             :             continue;
     963             :           }
     964             : 
     965             :         newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
     966             :         if (!newlist)
     967             :           goto fail;
     968             :         *list = newlist;
     969             :         memset (&(*list)[srvcount], 0, sizeof(struct srventry));
     970             :         srv = &(*list)[srvcount];
     971             :         srvcount++;
     972             : 
     973             :         srv->priority = answer->rrs.srvha[count].priority;
     974             :         srv->weight   = answer->rrs.srvha[count].weight;
     975             :         srv->port     = answer->rrs.srvha[count].port;
     976             :         strcpy (srv->target, answer->rrs.srvha[count].ha.host);
     977             :       }
     978             : 
     979             :     adns_free (answer);
     980             :     adns_finish (state);
     981             :   }
     982             : #else /*!USE_ADNS*/
     983             :   {
     984             :     unsigned char answer[2048];
     985           0 :     HEADER *header = (HEADER *)answer;
     986             :     unsigned char *pt, *emsg;
     987             :     int r;
     988             :     u16 dlen;
     989             : 
     990             :     /* Do not allow a query using the standard resolver in Tor mode.  */
     991           0 :     if (tor_mode)
     992           0 :       return -1;
     993             : 
     994           0 :     r = res_query (name, C_IN, T_SRV, answer, sizeof answer);
     995           0 :     if (r < sizeof (HEADER) || r > sizeof answer)
     996           0 :       return -1;
     997           0 :     if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
     998           0 :       return 0; /* Error or no record found.  */
     999             : 
    1000           0 :     emsg = &answer[r];
    1001           0 :     pt = &answer[sizeof(HEADER)];
    1002             : 
    1003             :     /* Skip over the query */
    1004           0 :     rc = dn_skipname (pt, emsg);
    1005           0 :     if (rc == -1)
    1006           0 :       goto fail;
    1007             : 
    1008           0 :     pt += rc + QFIXEDSZ;
    1009             : 
    1010           0 :     while (count-- > 0 && pt < emsg)
    1011             :       {
    1012           0 :         struct srventry *srv=NULL;
    1013             :         u16 type,class;
    1014             :         struct srventry *newlist;
    1015             : 
    1016           0 :         newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
    1017           0 :         if (!newlist)
    1018           0 :           goto fail;
    1019           0 :         *list = newlist;
    1020           0 :         memset(&(*list)[srvcount],0,sizeof(struct srventry));
    1021           0 :         srv=&(*list)[srvcount];
    1022           0 :         srvcount++;
    1023             : 
    1024           0 :         rc = dn_skipname(pt,emsg); /* the name we just queried for */
    1025           0 :         if (rc == -1)
    1026           0 :           goto fail;
    1027           0 :         pt+=rc;
    1028             : 
    1029             :         /* Truncated message? */
    1030           0 :         if((emsg-pt)<16)
    1031           0 :           goto fail;
    1032             : 
    1033           0 :         type = buf16_to_u16 (pt);
    1034           0 :         pt += 2;
    1035             :         /* We asked for SRV and got something else !? */
    1036           0 :         if(type!=T_SRV)
    1037           0 :           goto fail;
    1038             : 
    1039           0 :         class = buf16_to_u16 (pt);
    1040           0 :         pt += 2;
    1041             :         /* We asked for IN and got something else !? */
    1042           0 :         if(class!=C_IN)
    1043           0 :           goto fail;
    1044             : 
    1045           0 :         pt += 4; /* ttl */
    1046           0 :         dlen = buf16_to_u16 (pt);
    1047           0 :         pt += 2;
    1048             : 
    1049           0 :         srv->priority = buf16_to_ushort (pt);
    1050           0 :         pt += 2;
    1051           0 :         srv->weight = buf16_to_ushort (pt);
    1052           0 :         pt += 2;
    1053           0 :         srv->port = buf16_to_ushort (pt);
    1054           0 :         pt += 2;
    1055             : 
    1056             :         /* Get the name.  2782 doesn't allow name compression, but
    1057             :            dn_expand still works to pull the name out of the
    1058             :            packet. */
    1059           0 :         rc = dn_expand(answer,emsg,pt,srv->target, sizeof srv->target);
    1060           0 :         if (rc == 1 && srv->target[0] == 0) /* "." */
    1061             :           {
    1062           0 :             xfree(*list);
    1063           0 :             *list = NULL;
    1064           0 :             return 0;
    1065             :           }
    1066           0 :         if (rc == -1)
    1067           0 :           goto fail;
    1068           0 :         pt += rc;
    1069             :         /* Corrupt packet? */
    1070           0 :         if (dlen != rc+6)
    1071           0 :           goto fail;
    1072             :       }
    1073             :   }
    1074             : #endif /*!USE_ADNS*/
    1075             : 
    1076             :   /* Now we have an array of all the srv records. */
    1077             : 
    1078             :   /* Order by priority */
    1079           0 :   qsort(*list,srvcount,sizeof(struct srventry),priosort);
    1080             : 
    1081             :   /* For each priority, move the zero-weighted items first. */
    1082           0 :   for (i=0; i < srvcount; i++)
    1083             :     {
    1084             :       int j;
    1085             : 
    1086           0 :       for (j=i;j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
    1087             :         {
    1088           0 :           if((*list)[j].weight==0)
    1089             :             {
    1090             :               /* Swap j with i */
    1091           0 :               if(j!=i)
    1092             :                 {
    1093             :                   struct srventry temp;
    1094             : 
    1095           0 :                   memcpy (&temp,&(*list)[j],sizeof(struct srventry));
    1096           0 :                   memcpy (&(*list)[j],&(*list)[i],sizeof(struct srventry));
    1097           0 :                   memcpy (&(*list)[i],&temp,sizeof(struct srventry));
    1098             :                 }
    1099             : 
    1100           0 :               break;
    1101             :             }
    1102             :         }
    1103             :     }
    1104             : 
    1105             :   /* Run the RFC-2782 weighting algorithm.  We don't need very high
    1106             :      quality randomness for this, so regular libc srand/rand is
    1107             :      sufficient.  */
    1108             : 
    1109             :   {
    1110             :     static int done;
    1111           0 :     if (!done)
    1112             :       {
    1113           0 :         done = 1;
    1114           0 :         srand (time (NULL)*getpid());
    1115             :       }
    1116             :   }
    1117             : 
    1118           0 :   for (i=0; i < srvcount; i++)
    1119             :     {
    1120             :       int j;
    1121           0 :       float prio_count=0,chose;
    1122             : 
    1123           0 :       for (j=i; j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
    1124             :         {
    1125           0 :           prio_count+=(*list)[j].weight;
    1126           0 :           (*list)[j].run_count=prio_count;
    1127             :         }
    1128             : 
    1129           0 :       chose=prio_count*rand()/RAND_MAX;
    1130             : 
    1131           0 :       for (j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
    1132             :         {
    1133           0 :           if (chose<=(*list)[j].run_count)
    1134             :             {
    1135             :               /* Swap j with i */
    1136           0 :               if(j!=i)
    1137             :                 {
    1138             :                   struct srventry temp;
    1139             : 
    1140           0 :                   memcpy(&temp,&(*list)[j],sizeof(struct srventry));
    1141           0 :                   memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
    1142           0 :                   memcpy(&(*list)[i],&temp,sizeof(struct srventry));
    1143             :                 }
    1144           0 :               break;
    1145             :             }
    1146             :         }
    1147             :     }
    1148             : 
    1149           0 :   return srvcount;
    1150             : 
    1151             :  fail:
    1152           0 :   xfree(*list);
    1153           0 :   *list=NULL;
    1154           0 :   return -1;
    1155             : }
    1156             : #endif /*USE_DNS_SRV*/
    1157             : 
    1158             : 
    1159             : gpg_error_t
    1160           0 : get_dns_cname (const char *name, char **r_cname)
    1161             : {
    1162             :   gpg_error_t err;
    1163             :   int rc;
    1164             : 
    1165           0 :   *r_cname = NULL;
    1166             : 
    1167             : #ifdef USE_ADNS
    1168             :   {
    1169             :     adns_state state;
    1170             :     adns_answer *answer = NULL;
    1171             : 
    1172             :     if (my_adns_init (&state))
    1173             :       return gpg_error (GPG_ERR_GENERAL);
    1174             : 
    1175             :     rc = adns_synchronous (state, name, adns_r_cname, adns_qf_quoteok_query,
    1176             :                            &answer);
    1177             :     if (rc)
    1178             :       {
    1179             :         err = gpg_error_from_syserror ();
    1180             :         log_error ("DNS query failed: %s\n", gpg_strerror (err));
    1181             :         adns_finish (state);
    1182             :         return err;
    1183             :       }
    1184             :     if (answer->status != adns_s_ok
    1185             :         || answer->type != adns_r_cname || answer->nrrs != 1)
    1186             :       {
    1187             :         err = gpg_error (GPG_ERR_GENERAL);
    1188             :         log_error ("DNS query returned an error or no records: %s (%s)\n",
    1189             :                    adns_strerror (answer->status),
    1190             :                    adns_errabbrev (answer->status));
    1191             :         adns_free (answer);
    1192             :         adns_finish (state);
    1193             :         return err;
    1194             :       }
    1195             :     *r_cname = xtrystrdup (answer->rrs.str[0]);
    1196             :     if (!*r_cname)
    1197             :       err = gpg_error_from_syserror ();
    1198             :     else
    1199             :       err = 0;
    1200             : 
    1201             :     adns_free (answer);
    1202             :     adns_finish (state);
    1203             :     return err;
    1204             :   }
    1205             : #else /*!USE_ADNS*/
    1206             :   {
    1207             :     unsigned char answer[2048];
    1208           0 :     HEADER *header = (HEADER *)answer;
    1209             :     unsigned char *pt, *emsg;
    1210             :     int r;
    1211             :     char *cname;
    1212           0 :     int cnamesize = 1025;
    1213             :     u16 count;
    1214             : 
    1215             :     /* Do not allow a query using the standard resolver in Tor mode.  */
    1216           0 :     if (tor_mode)
    1217           0 :       return -1;
    1218             : 
    1219           0 :     r = res_query (name, C_IN, T_CERT, answer, sizeof answer);
    1220           0 :     if (r < sizeof (HEADER) || r > sizeof answer)
    1221           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1222           0 :     if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
    1223           0 :       return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
    1224           0 :     if (count != 1)
    1225           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1226             : 
    1227           0 :     emsg = &answer[r];
    1228           0 :     pt = &answer[sizeof(HEADER)];
    1229           0 :     rc = dn_skipname (pt, emsg);
    1230           0 :     if (rc == -1)
    1231           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1232             : 
    1233           0 :     pt += rc + QFIXEDSZ;
    1234           0 :     if (pt >= emsg)
    1235           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1236             : 
    1237           0 :     rc = dn_skipname (pt, emsg);
    1238           0 :     if (rc == -1)
    1239           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1240           0 :     pt += rc + 2 + 2 + 4;
    1241           0 :     if (pt+2 >= emsg)
    1242           0 :       return gpg_error (GPG_ERR_SERVER_FAILED);
    1243           0 :     pt += 2;  /* Skip rdlen */
    1244             : 
    1245           0 :     cname = xtrymalloc (cnamesize);
    1246           0 :     if (!cname)
    1247           0 :       return gpg_error_from_syserror ();
    1248             : 
    1249           0 :     rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
    1250           0 :     if (rc == -1)
    1251             :       {
    1252           0 :         xfree (cname);
    1253           0 :         return gpg_error (GPG_ERR_SERVER_FAILED);
    1254             :       }
    1255           0 :     *r_cname = xtryrealloc (cname, strlen (cname)+1);
    1256           0 :     if (!*r_cname)
    1257             :       {
    1258           0 :         err = gpg_error_from_syserror ();
    1259           0 :         xfree (cname);
    1260           0 :         return err;
    1261             :       }
    1262           0 :     return 0;
    1263             :   }
    1264             : #endif /*!USE_ADNS*/
    1265             : }

Generated by: LCOV version 1.11