dirmngr,build: Remove support for ADNS.
[gnupg.git] / dirmngr / dns-stuff.c
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. 2016 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 # if HAVE_SYSTEM_RESOLVER
40 #  include <netinet/in.h>
41 #  include <arpa/nameser.h>
42 #  include <resolv.h>
43 # endif
44 # include <netdb.h>
45 #endif
46 #include <string.h>
47 #include <unistd.h>
48
49 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
50 # undef USE_NPTH
51 #endif
52 #ifdef USE_NPTH
53 # include <npth.h>
54 #endif
55
56 #include "util.h"
57 #include "host2net.h"
58 #include "dns-stuff.h"
59
60 #ifdef USE_NPTH
61 # define my_unprotect()        npth_unprotect ()
62 # define my_protect()          npth_protect ()
63 #else
64 # define my_unprotect()        do { } while(0)
65 # define my_protect()          do { } while(0)
66 #endif
67
68 /* We allow the use of 0 instead of AF_UNSPEC - check this assumption.  */
69 #if AF_UNSPEC != 0
70 # error AF_UNSPEC does not have the value 0
71 #endif
72
73 /* Windows does not support the AI_ADDRCONFIG flag - use zero instead.  */
74 #ifndef AI_ADDRCONFIG
75 # define AI_ADDRCONFIG 0
76 #endif
77
78 /* Not every installation has gotten around to supporting SRVs or
79    CERTs yet... */
80 #ifndef T_SRV
81 #define T_SRV 33
82 #endif
83 #ifndef T_CERT
84 # define T_CERT 37
85 #endif
86
87
88 /* The default nameserver used in Tor mode.  */
89 #define DEFAULT_NAMESERVER "8.8.8.8"
90
91 /* If set force the use of the standard resolver.  */
92 static int standard_resolver;
93
94 /* If set Tor mode shall be used.  */
95 static int tor_mode;
96
97 /* A string with the nameserver IP address used with Tor.
98   (40 should be sufficient for v6 but we add some extra for a scope.) */
99 static char tor_nameserver[40+20];
100
101 /* A string to hold the credentials presented to Tor.  */
102 static char tor_credentials[50];
103
104
105 /* Calling this function with YES set to True forces the use of the
106  * standard resolver even if dirmngr has been built with support for
107  * an alternative resolver.  */
108 void
109 enable_standard_resolver (int yes)
110 {
111   standard_resolver = yes;
112 }
113
114
115 /* Return true if the standard resolver is used.  */
116 int
117 standard_resolver_p (void)
118 {
119   return standard_resolver;
120 }
121
122
123 /* Sets the module in Tor mode.  Returns 0 is this is possible or an
124    error code.  */
125 gpg_error_t
126 enable_dns_tormode (int new_circuit)
127 {
128   if (!*tor_credentials || new_circuit)
129     {
130       static unsigned int counter;
131
132       gpgrt_snprintf (tor_credentials, sizeof tor_credentials,
133                       "dirmngr-%lu:p%u",
134                       (unsigned long)getpid (), counter);
135       counter++;
136     }
137   tor_mode = 1;
138   return 0;
139 }
140
141
142 /* Change the default IP address of the nameserver to IPADDR.  The
143    address needs to be a numerical IP address and will be used for the
144    next DNS query.  Note that this is only used in Tor mode.  */
145 void
146 set_dns_nameserver (const char *ipaddr)
147 {
148   strncpy (tor_nameserver, ipaddr? ipaddr : DEFAULT_NAMESERVER,
149            sizeof tor_nameserver -1);
150   tor_nameserver[sizeof tor_nameserver -1] = 0;
151 }
152
153
154 /* Free an addressinfo linked list as returned by resolve_dns_name.  */
155 void
156 free_dns_addrinfo (dns_addrinfo_t ai)
157 {
158   while (ai)
159     {
160       dns_addrinfo_t next = ai->next;
161       xfree (ai);
162       ai = next;
163     }
164 }
165
166
167 static gpg_error_t
168 map_eai_to_gpg_error (int ec)
169 {
170   gpg_error_t err;
171
172   switch (ec)
173     {
174     case EAI_AGAIN:     err = gpg_error (GPG_ERR_EAGAIN); break;
175     case EAI_BADFLAGS:  err = gpg_error (GPG_ERR_INV_FLAG); break;
176     case EAI_FAIL:      err = gpg_error (GPG_ERR_SERVER_FAILED); break;
177     case EAI_MEMORY:    err = gpg_error (GPG_ERR_ENOMEM); break;
178 #ifdef EAI_NODATA
179     case EAI_NODATA:    err = gpg_error (GPG_ERR_NO_DATA); break;
180 #endif
181     case EAI_NONAME:    err = gpg_error (GPG_ERR_NO_NAME); break;
182     case EAI_SERVICE:   err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
183     case EAI_FAMILY:    err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
184     case EAI_SOCKTYPE:  err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
185 #ifndef HAVE_W32_SYSTEM
186 # ifdef EAI_ADDRFAMILY
187     case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
188 # endif
189     case EAI_SYSTEM:    err = gpg_error_from_syserror (); break;
190 #endif
191     default:            err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
192     }
193   return err;
194 }
195
196
197 /* Resolve a name using the standard system function.  */
198 static gpg_error_t
199 resolve_name_standard (const char *name, unsigned short port,
200                        int want_family, int want_socktype,
201                        dns_addrinfo_t *r_dai, char **r_canonname)
202 {
203   gpg_error_t err = 0;
204   dns_addrinfo_t daihead = NULL;
205   dns_addrinfo_t dai;
206   struct addrinfo *aibuf = NULL;
207   struct addrinfo hints, *ai;
208   char portstr[21];
209   int ret;
210
211   *r_dai = NULL;
212   if (r_canonname)
213     *r_canonname = NULL;
214
215   memset (&hints, 0, sizeof hints);
216   hints.ai_family = want_family;
217   hints.ai_socktype = want_socktype;
218   hints.ai_flags = AI_ADDRCONFIG;
219   if (r_canonname)
220     hints.ai_flags |= AI_CANONNAME;
221
222   if (port)
223     snprintf (portstr, sizeof portstr, "%hu", port);
224   else
225     *portstr = 0;
226
227   /* We can't use the the AI_IDN flag because that does the conversion
228      using the current locale.  However, GnuPG always used UTF-8.  To
229      support IDN we would need to make use of the libidn API.  */
230   ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
231   if (ret)
232     {
233       aibuf = NULL;
234       err = map_eai_to_gpg_error (ret);
235       if (gpg_err_code (err) == GPG_ERR_NO_NAME)
236         {
237           /* There seems to be a bug in the glibc getaddrinfo function
238              if the CNAME points to a long list of A and AAAA records
239              in which case the function return NO_NAME.  Let's do the
240              CNAME redirection again.  */
241           char *cname;
242
243           if (get_dns_cname (name, &cname))
244             goto leave; /* Still no success.  */
245
246           ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
247           xfree (cname);
248           if (ret)
249             {
250               aibuf = NULL;
251               err = map_eai_to_gpg_error (ret);
252               goto leave;
253             }
254           err = 0; /* Yep, now it worked.  */
255         }
256       else
257         goto leave;
258     }
259
260   if (r_canonname && aibuf && aibuf->ai_canonname)
261     {
262       *r_canonname = xtrystrdup (aibuf->ai_canonname);
263       if (!*r_canonname)
264         {
265           err = gpg_error_from_syserror ();
266           goto leave;
267         }
268     }
269
270   for (ai = aibuf; ai; ai = ai->ai_next)
271     {
272       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
273         continue;
274
275       dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
276       dai->family = ai->ai_family;
277       dai->socktype = ai->ai_socktype;
278       dai->protocol = ai->ai_protocol;
279       dai->addrlen = ai->ai_addrlen;
280       memcpy (dai->addr, ai->ai_addr, ai->ai_addrlen);
281       dai->next = daihead;
282       daihead = dai;
283     }
284
285  leave:
286   if (aibuf)
287     freeaddrinfo (aibuf);
288   if (err)
289     {
290       if (r_canonname)
291         {
292           xfree (*r_canonname);
293           *r_canonname = NULL;
294         }
295       free_dns_addrinfo (daihead);
296     }
297   else
298     *r_dai = daihead;
299   return err;
300 }
301
302
303 /* Resolve an address using the standard system function.  */
304 static gpg_error_t
305 resolve_addr_standard (const struct sockaddr *addr, int addrlen,
306                        unsigned int flags, char **r_name)
307 {
308   gpg_error_t err;
309   int ec;
310   char *buffer, *p;
311   int buflen;
312
313   *r_name = NULL;
314
315   buflen = NI_MAXHOST;
316   buffer = xtrymalloc (buflen + 2 + 1);
317   if (!buffer)
318     return gpg_error_from_syserror ();
319
320   if ((flags & DNS_NUMERICHOST) || tor_mode)
321     ec = EAI_NONAME;
322   else
323     ec = getnameinfo (addr, addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
324
325   if (!ec && *buffer == '[')
326     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
327   else if (ec == EAI_NONAME)
328     {
329       p = buffer;
330       if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
331         {
332           *p++ = '[';
333           buflen -= 2;
334         }
335       ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
336       if (!ec && addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
337         strcat (buffer, "]");
338     }
339
340   if (ec)
341     err = map_eai_to_gpg_error (ec);
342   else
343     {
344       p = xtryrealloc (buffer, strlen (buffer)+1);
345       if (!p)
346         err = gpg_error_from_syserror ();
347       else
348         {
349           buffer = p;
350           err = 0;
351         }
352     }
353
354   if (err)
355     xfree (buffer);
356   else
357     *r_name = buffer;
358
359   return err;
360 }
361
362
363 /* This a wrapper around getaddrinfo with slightly different semantics.
364    NAME is the name to resolve.
365    PORT is the requested port or 0.
366    WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
367    WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
368
369    On success the result is stored in a linked list with the head
370    stored at the address R_AI; the caller must call gpg_addrinfo_free
371    on this.  If R_CANONNAME is not NULL the official name of the host
372    is stored there as a malloced string; if that name is not available
373    NULL is stored.  */
374 gpg_error_t
375 resolve_dns_name (const char *name, unsigned short port,
376                   int want_family, int want_socktype,
377                   dns_addrinfo_t *r_ai, char **r_canonname)
378 {
379 #ifdef NOTYET
380   if (!standard_resolver)
381     return resolve_name_libdns (name, port, want_family, want_socktype,
382                                 r_ai, r_canonname);
383 #endif
384   return resolve_name_standard (name, port, want_family, want_socktype,
385                                 r_ai, r_canonname);
386 }
387
388
389 gpg_error_t
390 resolve_dns_addr (const struct sockaddr *addr, int addrlen,
391                   unsigned int flags, char **r_name)
392 {
393   return resolve_addr_standard (addr, addrlen, flags, r_name);
394 }
395
396
397 /* Check whether NAME is an IP address.  Returns true if it is either
398    an IPv6 or IPv4 numerical address.  */
399 int
400 is_ip_address (const char *name)
401 {
402   const char *s;
403   int ndots, dblcol, n;
404
405   if (*name == '[')
406     return 1; /* yes: A legal DNS name may not contain this character;
407                  this mut be bracketed v6 address.  */
408   if (*name == '.')
409     return 0; /* No.  A leading dot is not a valid IP address.  */
410
411   /* Check whether this is a v6 address.  */
412   ndots = n = dblcol = 0;
413   for (s=name; *s; s++)
414     {
415       if (*s == ':')
416         {
417           ndots++;
418           if (s[1] == ':')
419             {
420               ndots++;
421               if (dblcol)
422                 return 0; /* No: Only one "::" allowed.  */
423               dblcol++;
424               if (s[1])
425                 s++;
426             }
427           n = 0;
428         }
429       else if (*s == '.')
430         goto legacy;
431       else if (!strchr ("0123456789abcdefABCDEF", *s))
432         return 0; /* No: Not a hex digit.  */
433       else if (++n > 4)
434         return 0; /* To many digits in a group.  */
435     }
436   if (ndots > 7)
437     return 0; /* No: Too many colons.  */
438   else if (ndots > 1)
439     return 1; /* Yes: At least 2 colons indicate an v6 address.  */
440
441  legacy:
442   /* Check whether it is legacy IP address.  */
443   ndots = n = 0;
444   for (s=name; *s; s++)
445     {
446       if (*s == '.')
447         {
448           if (s[1] == '.')
449             return 0; /* No:  Douple dot. */
450           if (atoi (s+1) > 255)
451             return 0; /* No:  Ipv4 byte value too large.  */
452           ndots++;
453           n = 0;
454         }
455       else if (!strchr ("0123456789", *s))
456         return 0; /* No: Not a digit.  */
457       else if (++n > 3)
458         return 0; /* No: More than 3 digits.  */
459     }
460   return !!(ndots == 3);
461 }
462
463
464 /* Return true if NAME is an onion address.  */
465 int
466 is_onion_address (const char *name)
467 {
468   size_t len;
469
470   len = name? strlen (name) : 0;
471   if (len < 8 || strcmp (name + len - 6, ".onion"))
472     return 0;
473   /* Note that we require at least 2 characters before the suffix.  */
474   return 1;  /* Yes.  */
475 }
476
477
478 /* Standard resolver version of get_dns_cert.  */
479 static gpg_error_t
480 get_dns_cert_standard (const char *name, int want_certtype,
481                        void **r_key, size_t *r_keylen,
482                        unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
483 {
484 #ifdef HAVE_SYSTEM_RESOLVER
485   gpg_error_t err;
486   unsigned char *answer;
487   int r;
488   u16 count;
489
490   /* Allocate a 64k buffer which is the limit for an DNS response.  */
491   answer = xtrymalloc (65536);
492   if (!answer)
493     return gpg_error_from_syserror ();
494
495   err = gpg_error (GPG_ERR_NOT_FOUND);
496   r = res_query (name, C_IN,
497                  (want_certtype < DNS_CERTTYPE_RRBASE
498                   ? T_CERT
499                   : (want_certtype - DNS_CERTTYPE_RRBASE)),
500                  answer, 65536);
501   /* Not too big, not too small, no errors and at least 1 answer. */
502   if (r >= sizeof (HEADER) && r <= 65536
503       && (((HEADER *)(void *) answer)->rcode) == NOERROR
504       && (count = ntohs (((HEADER *)(void *) answer)->ancount)))
505     {
506       int rc;
507       unsigned char *pt, *emsg;
508
509       emsg = &answer[r];
510
511       pt = &answer[sizeof (HEADER)];
512
513       /* Skip over the query */
514
515       rc = dn_skipname (pt, emsg);
516       if (rc == -1)
517         {
518           err = gpg_error (GPG_ERR_INV_OBJ);
519           goto leave;
520         }
521       pt += rc + QFIXEDSZ;
522
523       /* There are several possible response types for a CERT request.
524          We're interested in the PGP (a key) and IPGP (a URI) types.
525          Skip all others.  TODO: A key is better than a URI since
526          we've gone through all this bother to fetch it, so favor that
527          if we have both PGP and IPGP? */
528
529       while (count-- > 0 && pt < emsg)
530         {
531           u16 type, class, dlen, ctype;
532
533           rc = dn_skipname (pt, emsg);  /* the name we just queried for */
534           if (rc == -1)
535             {
536               err = gpg_error (GPG_ERR_INV_OBJ);
537               goto leave;
538             }
539
540           pt += rc;
541
542           /* Truncated message? 15 bytes takes us to the point where
543              we start looking at the ctype. */
544           if ((emsg - pt) < 15)
545             break;
546
547           type = buf16_to_u16 (pt);
548           pt += 2;
549
550           class = buf16_to_u16 (pt);
551           pt += 2;
552
553           if (class != C_IN)
554             break;
555
556           /* ttl */
557           pt += 4;
558
559           /* data length */
560           dlen = buf16_to_u16 (pt);
561           pt += 2;
562
563           /* Check the type and parse.  */
564           if (want_certtype >= DNS_CERTTYPE_RRBASE
565               && type == (want_certtype - DNS_CERTTYPE_RRBASE)
566               && r_key)
567             {
568               *r_key = xtrymalloc (dlen);
569               if (!*r_key)
570                 err = gpg_error_from_syserror ();
571               else
572                 {
573                   memcpy (*r_key, pt, dlen);
574                   *r_keylen = dlen;
575                   err = 0;
576                 }
577               goto leave;
578             }
579           else if (want_certtype >= DNS_CERTTYPE_RRBASE)
580             {
581               /* We did not found the requested RR.  */
582               pt += dlen;
583             }
584           else if (type == T_CERT)
585             {
586               /* We got a CERT type.   */
587               ctype = buf16_to_u16 (pt);
588               pt += 2;
589
590               /* Skip the CERT key tag and algo which we don't need. */
591               pt += 3;
592
593               dlen -= 5;
594
595               /* 15 bytes takes us to here */
596               if (want_certtype && want_certtype != ctype)
597                 ; /* Not of the requested certtype.  */
598               else if (ctype == DNS_CERTTYPE_PGP && dlen && r_key && r_keylen)
599                 {
600                   /* PGP type */
601                   *r_key = xtrymalloc (dlen);
602                   if (!*r_key)
603                     err = gpg_error_from_syserror ();
604                   else
605                     {
606                       memcpy (*r_key, pt, dlen);
607                       *r_keylen = dlen;
608                       err = 0;
609                     }
610                   goto leave;
611                 }
612               else if (ctype == DNS_CERTTYPE_IPGP
613                        && dlen && dlen < 1023 && dlen >= pt[0] + 1)
614                 {
615                   /* IPGP type */
616                   *r_fprlen = pt[0];
617                   if (*r_fprlen)
618                     {
619                       *r_fpr = xtrymalloc (*r_fprlen);
620                       if (!*r_fpr)
621                         {
622                           err = gpg_error_from_syserror ();
623                           goto leave;
624                         }
625                       memcpy (*r_fpr, &pt[1], *r_fprlen);
626                     }
627                   else
628                     *r_fpr = NULL;
629
630                   if (dlen > *r_fprlen + 1)
631                     {
632                       *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1);
633                       if (!*r_fpr)
634                         {
635                           err = gpg_error_from_syserror ();
636                           xfree (*r_fpr);
637                           *r_fpr = NULL;
638                           goto leave;
639                         }
640                       memcpy (*r_url, &pt[*r_fprlen + 1],
641                               dlen - (*r_fprlen + 1));
642                       (*r_url)[dlen - (*r_fprlen + 1)] = '\0';
643                     }
644                   else
645                     *r_url = NULL;
646
647                   err = 0;
648                   goto leave;
649                 }
650
651               /* No subtype matches, so continue with the next answer. */
652               pt += dlen;
653             }
654           else
655             {
656               /* Not a requested type - might be a CNAME. Try next item.  */
657               pt += dlen;
658             }
659         }
660     }
661
662  leave:
663   xfree (answer);
664   return err;
665
666 #else /*!HAVE_SYSTEM_RESOLVER*/
667
668   (void)name;
669   (void)want_certtype;
670   (void)r_key;
671   (void)r_keylen;
672   (void)r_fpr;
673   (void)r_fprlen;
674   (void)r_url;
675   return gpg_error (GPG_ERR_NOT_SUPPORTED);
676
677 #endif /*!HAVE_SYSTEM_RESOLVER*/
678 }
679
680
681 /* Returns 0 on success or an error code.  If a PGP CERT record was
682    found, the malloced data is returned at (R_KEY, R_KEYLEN) and
683    the other return parameters are set to NULL/0.  If an IPGP CERT
684    record was found the fingerprint is stored as an allocated block at
685    R_FPR and its length at R_FPRLEN; an URL is is allocated as a
686    string and returned at R_URL.  If WANT_CERTTYPE is 0 this function
687    returns the first CERT found with a supported type; it is expected
688    that only one CERT record is used.  If WANT_CERTTYPE is one of the
689    supported certtypes only records with this certtype are considered
690    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
691 gpg_error_t
692 get_dns_cert (const char *name, int want_certtype,
693               void **r_key, size_t *r_keylen,
694               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
695 {
696   if (r_key)
697     *r_key = NULL;
698   if (r_keylen)
699     *r_keylen = 0;
700   *r_fpr = NULL;
701   *r_fprlen = 0;
702   *r_url = NULL;
703
704 #ifdef NOTYET
705   if (!standard_resolver)
706     return get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
707                                 r_fpr, r_fprlen, r_url);
708 #endif
709   return get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
710                                 r_fpr, r_fprlen, r_url);
711 }
712
713
714 static int
715 priosort(const void *a,const void *b)
716 {
717   const struct srventry *sa=a,*sb=b;
718   if(sa->priority>sb->priority)
719     return 1;
720   else if(sa->priority<sb->priority)
721     return -1;
722   else
723     return 0;
724 }
725
726
727 /* Standard resolver based helper for getsrv.  */
728 static int
729 getsrv_standard (const char *name, struct srventry **list)
730 {
731 #ifdef HAVE_SYSTEM_RESOLVER
732   union {
733     unsigned char ans[2048];
734     HEADER header[1];
735   } res;
736   unsigned char *answer = res.ans;
737   HEADER *header = res.header;
738   unsigned char *pt, *emsg;
739   int r, rc;
740   u16 dlen;
741   int srvcount=0;
742   u16 count;
743
744   /* Do not allow a query using the standard resolver in Tor mode.  */
745   if (tor_mode)
746     return -1;
747
748   my_unprotect ();
749   r = res_query (name, C_IN, T_SRV, answer, sizeof answer);
750   my_protect ();
751   if (r < sizeof (HEADER) || r > sizeof answer
752       || header->rcode != NOERROR || !(count=ntohs (header->ancount)))
753     return 0; /* Error or no record found.  */
754
755   emsg = &answer[r];
756   pt = &answer[sizeof(HEADER)];
757
758   /* Skip over the query */
759   rc = dn_skipname (pt, emsg);
760   if (rc == -1)
761     goto fail;
762
763   pt += rc + QFIXEDSZ;
764
765   while (count-- > 0 && pt < emsg)
766     {
767       struct srventry *srv = NULL;
768       u16 type, class;
769       struct srventry *newlist;
770
771       newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
772       if (!newlist)
773         goto fail;
774       *list = newlist;
775       memset (&(*list)[srvcount], 0, sizeof(struct srventry));
776       srv = &(*list)[srvcount];
777       srvcount++;
778
779       rc = dn_skipname (pt, emsg); /* The name we just queried for.  */
780       if (rc == -1)
781         goto fail;
782       pt += rc;
783
784       /* Truncated message? */
785       if ((emsg-pt) < 16)
786         goto fail;
787
788       type = buf16_to_u16 (pt);
789       pt += 2;
790       /* We asked for SRV and got something else !? */
791       if (type != T_SRV)
792         goto fail;
793
794       class = buf16_to_u16 (pt);
795       pt += 2;
796       /* We asked for IN and got something else !? */
797       if (class != C_IN)
798         goto fail;
799
800       pt += 4; /* ttl */
801       dlen = buf16_to_u16 (pt);
802       pt += 2;
803
804       srv->priority = buf16_to_ushort (pt);
805       pt += 2;
806       srv->weight = buf16_to_ushort (pt);
807       pt += 2;
808       srv->port = buf16_to_ushort (pt);
809       pt += 2;
810
811       /* Get the name.  2782 doesn't allow name compression, but
812        * dn_expand still works to pull the name out of the packet. */
813       rc = dn_expand (answer, emsg, pt, srv->target, sizeof srv->target);
814       if (rc == 1 && srv->target[0] == 0) /* "." */
815         {
816           xfree(*list);
817           *list = NULL;
818           return 0;
819         }
820       if (rc == -1)
821         goto fail;
822       pt += rc;
823       /* Corrupt packet? */
824       if (dlen != rc+6)
825         goto fail;
826     }
827
828   return srvcount;
829
830  fail:
831   xfree (*list);
832   *list = NULL;
833   return -1;
834
835 #else /*!HAVE_SYSTEM_RESOLVER*/
836
837   (void)name;
838   (void)list;
839   return -1;
840
841 #endif /*!HAVE_SYSTEM_RESOLVER*/
842 }
843
844
845 int
846 getsrv (const char *name, struct srventry **list)
847 {
848   int srvcount;
849   int i;
850
851   *list = NULL;
852
853   if (0)
854     ;
855 #ifdef NOTYET
856   else if (!standard_resolver)
857     srvcount = getsrv_libdns (name, list);
858 #endif
859   else
860     srvcount = getsrv_standard (name, list);
861
862   if (srvcount <= 0)
863     return srvcount;
864
865   /* Now we have an array of all the srv records. */
866
867   /* Order by priority */
868   qsort(*list,srvcount,sizeof(struct srventry),priosort);
869
870   /* For each priority, move the zero-weighted items first. */
871   for (i=0; i < srvcount; i++)
872     {
873       int j;
874
875       for (j=i;j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
876         {
877           if((*list)[j].weight==0)
878             {
879               /* Swap j with i */
880               if(j!=i)
881                 {
882                   struct srventry temp;
883
884                   memcpy (&temp,&(*list)[j],sizeof(struct srventry));
885                   memcpy (&(*list)[j],&(*list)[i],sizeof(struct srventry));
886                   memcpy (&(*list)[i],&temp,sizeof(struct srventry));
887                 }
888
889               break;
890             }
891         }
892     }
893
894   /* Run the RFC-2782 weighting algorithm.  We don't need very high
895      quality randomness for this, so regular libc srand/rand is
896      sufficient.  */
897
898   {
899     static int done;
900     if (!done)
901       {
902         done = 1;
903         srand (time (NULL)*getpid());
904       }
905   }
906
907   for (i=0; i < srvcount; i++)
908     {
909       int j;
910       float prio_count=0,chose;
911
912       for (j=i; j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
913         {
914           prio_count+=(*list)[j].weight;
915           (*list)[j].run_count=prio_count;
916         }
917
918       chose=prio_count*rand()/RAND_MAX;
919
920       for (j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
921         {
922           if (chose<=(*list)[j].run_count)
923             {
924               /* Swap j with i */
925               if(j!=i)
926                 {
927                   struct srventry temp;
928
929                   memcpy(&temp,&(*list)[j],sizeof(struct srventry));
930                   memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
931                   memcpy(&(*list)[i],&temp,sizeof(struct srventry));
932                 }
933               break;
934             }
935         }
936     }
937
938   return srvcount;
939 }
940
941
942 /* Standard resolver version of get_dns_cname.  */
943 gpg_error_t
944 get_dns_cname_standard (const char *name, char **r_cname)
945 {
946 #ifdef HAVE_SYSTEM_RESOLVER
947   gpg_error_t err;
948   int rc;
949   union {
950     unsigned char ans[2048];
951     HEADER header[1];
952   } res;
953   unsigned char *answer = res.ans;
954   HEADER *header = res.header;
955   unsigned char *pt, *emsg;
956   int r;
957   char *cname;
958   int cnamesize = 1025;
959   u16 count;
960
961   /* Do not allow a query using the standard resolver in Tor mode.  */
962   if (tor_mode)
963     return -1;
964
965   r = res_query (name, C_IN, T_CERT, answer, sizeof answer);
966   if (r < sizeof (HEADER) || r > sizeof answer)
967     return gpg_error (GPG_ERR_SERVER_FAILED);
968   if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
969     return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
970   if (count != 1)
971     return gpg_error (GPG_ERR_SERVER_FAILED);
972
973   emsg = &answer[r];
974   pt = &answer[sizeof(HEADER)];
975   rc = dn_skipname (pt, emsg);
976   if (rc == -1)
977     return gpg_error (GPG_ERR_SERVER_FAILED);
978
979   pt += rc + QFIXEDSZ;
980   if (pt >= emsg)
981     return gpg_error (GPG_ERR_SERVER_FAILED);
982
983   rc = dn_skipname (pt, emsg);
984   if (rc == -1)
985     return gpg_error (GPG_ERR_SERVER_FAILED);
986   pt += rc + 2 + 2 + 4;
987   if (pt+2 >= emsg)
988     return gpg_error (GPG_ERR_SERVER_FAILED);
989   pt += 2;  /* Skip rdlen */
990
991   cname = xtrymalloc (cnamesize);
992   if (!cname)
993     return gpg_error_from_syserror ();
994
995   rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
996   if (rc == -1)
997     {
998       xfree (cname);
999       return gpg_error (GPG_ERR_SERVER_FAILED);
1000     }
1001   *r_cname = xtryrealloc (cname, strlen (cname)+1);
1002   if (!*r_cname)
1003     {
1004       err = gpg_error_from_syserror ();
1005       xfree (cname);
1006       return err;
1007     }
1008   return 0;
1009
1010 #else /*!HAVE_SYSTEM_RESOLVER*/
1011
1012   (void)name;
1013   (void)r_cname;
1014   return -1;
1015
1016 #endif /*!HAVE_SYSTEM_RESOLVER*/
1017 }
1018
1019
1020 gpg_error_t
1021 get_dns_cname (const char *name, char **r_cname)
1022 {
1023   *r_cname = NULL;
1024
1025 #ifdef NOTYET
1026   if (!standard_resolver)
1027     return get_dns_cname_libdns (name, r_cname);
1028 #endif
1029
1030   return get_dns_cname_standard (name, r_cname);
1031 }