LCOV - code coverage report
Current view: top level - dirmngr - dns-stuff.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 31 375 8.3 %
Date: 2016-11-29 15:00:56 Functions: 3 16 18.8 %

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

Generated by: LCOV version 1.11