dirmngr: New configure option --disable-libdns.
[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 /* William Ahern's DNS library, included as a source copy.  */
50 #ifdef USE_LIBDNS
51 # include "dns.h"
52 #endif
53
54 /* dns.c has a dns_p_free but it is not exported.  We use our own
55  * wrapper here so that we do not accidentally use xfree which would
56  * be wrong for dns.c allocated data.  */
57 #define dns_free(a)  free ((a))
58
59
60 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
61 # undef USE_NPTH
62 #endif
63 #ifdef USE_NPTH
64 # include <npth.h>
65 #endif
66
67 #include "./dirmngr-err.h"
68 #include "util.h"
69 #include "host2net.h"
70 #include "dns-stuff.h"
71
72 #ifdef USE_NPTH
73 # define my_unprotect()        npth_unprotect ()
74 # define my_protect()          npth_protect ()
75 #else
76 # define my_unprotect()        do { } while(0)
77 # define my_protect()          do { } while(0)
78 #endif
79
80 /* We allow the use of 0 instead of AF_UNSPEC - check this assumption.  */
81 #if AF_UNSPEC != 0
82 # error AF_UNSPEC does not have the value 0
83 #endif
84
85 /* Windows does not support the AI_ADDRCONFIG flag - use zero instead.  */
86 #ifndef AI_ADDRCONFIG
87 # define AI_ADDRCONFIG 0
88 #endif
89
90 /* Not every installation has gotten around to supporting SRVs or
91    CERTs yet... */
92 #ifndef T_SRV
93 #define T_SRV 33
94 #endif
95 #ifndef T_CERT
96 # define T_CERT 37
97 #endif
98
99
100 /* The default nameserver used in Tor mode.  */
101 #define DEFAULT_NAMESERVER "8.8.8.8"
102
103 /* If set force the use of the standard resolver.  */
104 static int standard_resolver;
105
106 /* If set use recursive resolver when available. */
107 static int recursive_resolver;
108
109 /* If set Tor mode shall be used.  */
110 static int tor_mode;
111
112 /* A string with the nameserver IP address used with Tor.
113   (40 should be sufficient for v6 but we add some extra for a scope.) */
114 static char tor_nameserver[40+20];
115
116 /* A string to hold the credentials presented to Tor.  */
117 static char tor_credentials[50];
118
119 #ifdef USE_LIBDNS
120 /* Libdns gobal data.  */
121 struct
122 {
123   struct dns_resolv_conf *resolv_conf;
124   struct dns_hosts *hosts;
125   struct dns_hints *hints;
126
127   struct sockaddr_storage socks_host;
128 } libdns;
129 #endif /*USE_LIBDNS*/
130
131 /* Calling this function with YES set to True forces the use of the
132  * standard resolver even if dirmngr has been built with support for
133  * an alternative resolver.  */
134 void
135 enable_standard_resolver (int yes)
136 {
137   standard_resolver = yes;
138 }
139
140
141 /* Return true if the standard resolver is used.  */
142 int
143 standard_resolver_p (void)
144 {
145   return standard_resolver;
146 }
147
148
149 /* Calling this function with YES switches libdns into recursive mode.
150  * It has no effect on the standard resolver.  */
151 void
152 enable_recursive_resolver (int yes)
153 {
154   recursive_resolver = yes;
155 }
156
157
158 /* Return true iff the recursive resolver is used.  */
159 int
160 recursive_resolver_p (void)
161 {
162 #if USE_LIBDNS
163   return !standard_resolver && recursive_resolver;
164 #else
165   return 0;
166 #endif
167 }
168
169
170 /* Sets the module in Tor mode.  Returns 0 is this is possible or an
171    error code.  */
172 gpg_error_t
173 enable_dns_tormode (int new_circuit)
174 {
175   /* XXX: dns.c doesn't support SOCKS credentials.  */
176
177   if (!*tor_credentials || new_circuit)
178     {
179       static unsigned int counter;
180
181       gpgrt_snprintf (tor_credentials, sizeof tor_credentials,
182                       "dirmngr-%lu:p%u",
183                       (unsigned long)getpid (), counter);
184       counter++;
185     }
186   tor_mode = 1;
187   return 0;
188 }
189
190
191 /* Change the default IP address of the nameserver to IPADDR.  The
192    address needs to be a numerical IP address and will be used for the
193    next DNS query.  Note that this is only used in Tor mode.  */
194 void
195 set_dns_nameserver (const char *ipaddr)
196 {
197   strncpy (tor_nameserver, ipaddr? ipaddr : DEFAULT_NAMESERVER,
198            sizeof tor_nameserver -1);
199   tor_nameserver[sizeof tor_nameserver -1] = 0;
200 }
201
202
203 /* Free an addressinfo linked list as returned by resolve_dns_name.  */
204 void
205 free_dns_addrinfo (dns_addrinfo_t ai)
206 {
207   while (ai)
208     {
209       dns_addrinfo_t next = ai->next;
210       xfree (ai);
211       ai = next;
212     }
213 }
214
215 /* Return H_ERRNO mapped to a gpg-error code.  Will never return 0. */
216 static gpg_error_t
217 get_h_errno_as_gpg_error (void)
218 {
219   gpg_err_code_t ec;
220
221   switch (h_errno)
222     {
223     case HOST_NOT_FOUND: ec = GPG_ERR_UNKNOWN_HOST; break;
224     case TRY_AGAIN:      ec = GPG_ERR_TRY_LATER; break;
225     case NO_RECOVERY:    ec = GPG_ERR_SERVER_FAILED; break;
226     case NO_DATA:        ec = GPG_ERR_NO_DATA; break;
227     default:             ec = GPG_ERR_UNKNOWN_ERRNO; break;
228     }
229   return gpg_error (ec);
230 }
231
232
233 static gpg_error_t
234 map_eai_to_gpg_error (int ec)
235 {
236   gpg_error_t err;
237
238   switch (ec)
239     {
240     case EAI_AGAIN:     err = gpg_error (GPG_ERR_EAGAIN); break;
241     case EAI_BADFLAGS:  err = gpg_error (GPG_ERR_INV_FLAG); break;
242     case EAI_FAIL:      err = gpg_error (GPG_ERR_SERVER_FAILED); break;
243     case EAI_MEMORY:    err = gpg_error (GPG_ERR_ENOMEM); break;
244 #ifdef EAI_NODATA
245     case EAI_NODATA:    err = gpg_error (GPG_ERR_NO_DATA); break;
246 #endif
247     case EAI_NONAME:    err = gpg_error (GPG_ERR_NO_NAME); break;
248     case EAI_SERVICE:   err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
249     case EAI_FAMILY:    err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
250     case EAI_SOCKTYPE:  err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
251 #ifndef HAVE_W32_SYSTEM
252 # ifdef EAI_ADDRFAMILY
253     case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
254 # endif
255     case EAI_SYSTEM:    err = gpg_error_from_syserror (); break;
256 #endif
257     default:            err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
258     }
259   return err;
260 }
261
262
263 #ifdef USE_LIBDNS
264 static gpg_error_t
265 libdns_error_to_gpg_error (int serr)
266 {
267   gpg_err_code_t ec;
268
269   switch (serr)
270     {
271     case 0: ec = 0; break;
272
273     case DNS_ENOBUFS:  ec = GPG_ERR_BUFFER_TOO_SHORT; break;
274     case DNS_EILLEGAL: ec = GPG_ERR_INV_OBJ; break;
275     case DNS_EORDER:   ec = GPG_ERR_INV_ORDER; break;
276     case DNS_ESECTION: ec = GPG_ERR_DNS_SECTION; break;
277     case DNS_EUNKNOWN: ec = GPG_ERR_DNS_UNKNOWN; break;
278     case DNS_EADDRESS: ec = GPG_ERR_DNS_ADDRESS; break;
279     case DNS_ENOQUERY: ec = GPG_ERR_DNS_NO_QUERY; break;
280     case DNS_ENOANSWER:ec = GPG_ERR_DNS_NO_ANSWER; break;
281     case DNS_EFETCHED: ec = GPG_ERR_ALREADY_FETCHED; break;
282     case DNS_ESERVICE: ec = GPG_ERR_NOT_SUPPORTED; break;
283     case DNS_ENONAME:  ec = GPG_ERR_NO_NAME; break;
284     case DNS_EFAIL:    ec = GPG_ERR_SERVER_FAILED; break;
285     case DNS_ECONNFIN: ec = GPG_ERR_DNS_CLOSED; break;
286     case DNS_EVERIFY:  ec = GPG_ERR_DNS_VERIFY; break;
287
288     default:
289       if (serr >= 0)
290         ec = gpg_err_code_from_errno (serr);
291       else
292         ec = GPG_ERR_DNS_UNKNOWN;
293       break;
294     }
295   return gpg_error (ec);
296 }
297 #endif /*USE_LIBDNS*/
298
299
300 #ifdef USE_LIBDNS
301 static gpg_error_t
302 libdns_init (void)
303 {
304   int error;
305
306   libdns.resolv_conf = dns_resconf_open (&error);
307   if (! libdns.resolv_conf)
308     goto leave;
309
310 #if 0
311   error = dns_resconf_pton (&libdns.resolv_conf->nameserver[0],
312                             "[127.0.0.1]:53");
313   if (error)
314     goto leave;
315 #else
316   error = dns_resconf_loadpath (libdns.resolv_conf, "/etc/resolv.conf");
317   if (error)
318     goto leave;
319
320   error = dns_nssconf_loadpath (libdns.resolv_conf, "/etc/nsswitch.conf");
321   if (error)
322     goto leave;
323 #endif
324
325   libdns.hosts = dns_hosts_open (&error);
326   if (! libdns.hosts)
327     goto leave;
328
329   /* dns_hints_local for stub mode, dns_hints_root for recursive.  */
330   libdns.hints = (recursive_resolver
331                   ? dns_hints_root  (libdns.resolv_conf, &error)
332                   : dns_hints_local (libdns.resolv_conf, &error));
333   if (! libdns.hints)
334     goto leave;
335
336   /* XXX */
337  leave:
338   return libdns_error_to_gpg_error (error);
339 }
340 #endif /*USE_LIBDNS*/
341
342
343 #ifdef USE_LIBDNS
344 static gpg_error_t
345 resolve_name_libdns (const char *name, unsigned short port,
346                      int want_family, int want_socktype,
347                      dns_addrinfo_t *r_dai, char **r_canonname)
348 {
349   gpg_error_t err;
350   dns_addrinfo_t daihead = NULL;
351   dns_addrinfo_t dai;
352   struct dns_resolver *res = NULL;
353   struct dns_addrinfo *ai = NULL;
354   struct addrinfo hints;
355   struct addrinfo *ent;
356   char portstr_[21];
357   char *portstr = NULL;
358   int derr;
359
360   *r_dai = NULL;
361   if (r_canonname)
362     *r_canonname = NULL;
363
364   err = libdns_init ();
365   if (err)
366     goto leave;
367
368   memset (&hints, 0, sizeof hints);
369   hints.ai_family = want_family;
370   hints.ai_socktype = want_socktype;
371   hints.ai_flags = AI_ADDRCONFIG;
372   if (r_canonname)
373     hints.ai_flags |= AI_CANONNAME;
374
375   if (port)
376     {
377       snprintf (portstr_, sizeof portstr_, "%hu", port);
378       portstr = portstr_;
379     }
380
381   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
382                       dns_opts (/*.socks_host=&libdns.socks_host*/), &derr);
383   if (!res)
384     {
385       err = libdns_error_to_gpg_error (derr);
386       goto leave;
387     }
388
389   ai = dns_ai_open (name, portstr, 0, &hints, res, &derr);
390   if (!ai)
391     {
392       err = libdns_error_to_gpg_error (derr);
393       goto leave;
394     }
395
396   /* Loop over all records.  */
397   for (;;)
398     {
399       err = libdns_error_to_gpg_error (dns_ai_nextent (&ent, ai));
400       if (gpg_err_code (err) == GPG_ERR_ENOENT)
401         {
402           if (daihead)
403             err = 0; /* We got some results, we're good.  */
404           break; /* Ready.  */
405         }
406       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
407         {
408           if (dns_ai_elapsed (ai) > 30)
409             {
410               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
411               goto leave;
412             }
413
414           my_unprotect ();
415           dns_ai_poll (ai, 1);
416           my_protect ();
417           continue;
418         }
419       if (err)
420         goto leave;
421
422       if (r_canonname && ! *r_canonname && ent && ent->ai_canonname)
423         {
424           *r_canonname = xtrystrdup (ent->ai_canonname);
425           if (!*r_canonname)
426             {
427               err = gpg_error_from_syserror ();
428               goto leave;
429             }
430         }
431
432       dai = xtrymalloc (sizeof *dai + ent->ai_addrlen -1);
433       if (dai == NULL)
434         {
435           err = gpg_error_from_syserror ();
436           goto leave;
437         }
438
439       dai->family = ent->ai_family;
440       dai->socktype = ent->ai_socktype;
441       dai->protocol = ent->ai_protocol;
442       dai->addrlen = ent->ai_addrlen;
443       memcpy (dai->addr, ent->ai_addr, ent->ai_addrlen);
444       dai->next = daihead;
445       daihead = dai;
446
447       xfree (ent);
448   }
449
450  leave:
451   dns_ai_close (ai);
452   dns_res_close (res);
453
454   if (err)
455     {
456       if (r_canonname)
457         {
458           xfree (*r_canonname);
459           *r_canonname = NULL;
460         }
461       free_dns_addrinfo (daihead);
462     }
463   else
464     *r_dai = daihead;
465
466   return err;
467 }
468 #endif /*USE_LIBDNS*/
469
470
471 /* Resolve a name using the standard system function.  */
472 static gpg_error_t
473 resolve_name_standard (const char *name, unsigned short port,
474                        int want_family, int want_socktype,
475                        dns_addrinfo_t *r_dai, char **r_canonname)
476 {
477   gpg_error_t err = 0;
478   dns_addrinfo_t daihead = NULL;
479   dns_addrinfo_t dai;
480   struct addrinfo *aibuf = NULL;
481   struct addrinfo hints, *ai;
482   char portstr[21];
483   int ret;
484
485   *r_dai = NULL;
486   if (r_canonname)
487     *r_canonname = NULL;
488
489   memset (&hints, 0, sizeof hints);
490   hints.ai_family = want_family;
491   hints.ai_socktype = want_socktype;
492   hints.ai_flags = AI_ADDRCONFIG;
493   if (r_canonname)
494     hints.ai_flags |= AI_CANONNAME;
495
496   if (port)
497     snprintf (portstr, sizeof portstr, "%hu", port);
498   else
499     *portstr = 0;
500
501   /* We can't use the the AI_IDN flag because that does the conversion
502      using the current locale.  However, GnuPG always used UTF-8.  To
503      support IDN we would need to make use of the libidn API.  */
504   ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
505   if (ret)
506     {
507       aibuf = NULL;
508       err = map_eai_to_gpg_error (ret);
509       if (gpg_err_code (err) == GPG_ERR_NO_NAME)
510         {
511           /* There seems to be a bug in the glibc getaddrinfo function
512              if the CNAME points to a long list of A and AAAA records
513              in which case the function return NO_NAME.  Let's do the
514              CNAME redirection again.  */
515           char *cname;
516
517           if (get_dns_cname (name, &cname))
518             goto leave; /* Still no success.  */
519
520           ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
521           xfree (cname);
522           if (ret)
523             {
524               aibuf = NULL;
525               err = map_eai_to_gpg_error (ret);
526               goto leave;
527             }
528           err = 0; /* Yep, now it worked.  */
529         }
530       else
531         goto leave;
532     }
533
534   if (r_canonname && aibuf && aibuf->ai_canonname)
535     {
536       *r_canonname = xtrystrdup (aibuf->ai_canonname);
537       if (!*r_canonname)
538         {
539           err = gpg_error_from_syserror ();
540           goto leave;
541         }
542     }
543
544   for (ai = aibuf; ai; ai = ai->ai_next)
545     {
546       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
547         continue;
548
549       dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
550       dai->family = ai->ai_family;
551       dai->socktype = ai->ai_socktype;
552       dai->protocol = ai->ai_protocol;
553       dai->addrlen = ai->ai_addrlen;
554       memcpy (dai->addr, ai->ai_addr, ai->ai_addrlen);
555       dai->next = daihead;
556       daihead = dai;
557     }
558
559  leave:
560   if (aibuf)
561     freeaddrinfo (aibuf);
562   if (err)
563     {
564       if (r_canonname)
565         {
566           xfree (*r_canonname);
567           *r_canonname = NULL;
568         }
569       free_dns_addrinfo (daihead);
570     }
571   else
572     *r_dai = daihead;
573   return err;
574 }
575
576
577 /* Resolve an address using the standard system function.  */
578 static gpg_error_t
579 resolve_addr_standard (const struct sockaddr *addr, int addrlen,
580                        unsigned int flags, char **r_name)
581 {
582   gpg_error_t err;
583   int ec;
584   char *buffer, *p;
585   int buflen;
586
587   *r_name = NULL;
588
589   buflen = NI_MAXHOST;
590   buffer = xtrymalloc (buflen + 2 + 1);
591   if (!buffer)
592     return gpg_error_from_syserror ();
593
594   if ((flags & DNS_NUMERICHOST) || tor_mode)
595     ec = EAI_NONAME;
596   else
597     ec = getnameinfo (addr, addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
598
599   if (!ec && *buffer == '[')
600     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
601   else if (ec == EAI_NONAME)
602     {
603       p = buffer;
604       if (addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
605         {
606           *p++ = '[';
607           buflen -= 2;
608         }
609       ec = getnameinfo (addr, addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
610       if (!ec && addr->sa_family == AF_INET6 && (flags & DNS_WITHBRACKET))
611         strcat (buffer, "]");
612     }
613
614   if (ec)
615     err = map_eai_to_gpg_error (ec);
616   else
617     {
618       p = xtryrealloc (buffer, strlen (buffer)+1);
619       if (!p)
620         err = gpg_error_from_syserror ();
621       else
622         {
623           buffer = p;
624           err = 0;
625         }
626     }
627
628   if (err)
629     xfree (buffer);
630   else
631     *r_name = buffer;
632
633   return err;
634 }
635
636
637 /* This a wrapper around getaddrinfo with slightly different semantics.
638    NAME is the name to resolve.
639    PORT is the requested port or 0.
640    WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
641    WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
642
643    On success the result is stored in a linked list with the head
644    stored at the address R_AI; the caller must call gpg_addrinfo_free
645    on this.  If R_CANONNAME is not NULL the official name of the host
646    is stored there as a malloced string; if that name is not available
647    NULL is stored.  */
648 gpg_error_t
649 resolve_dns_name (const char *name, unsigned short port,
650                   int want_family, int want_socktype,
651                   dns_addrinfo_t *r_ai, char **r_canonname)
652 {
653 #ifdef USE_LIBDNS
654   if (!standard_resolver)
655     return resolve_name_libdns (name, port, want_family, want_socktype,
656                                 r_ai, r_canonname);
657 #endif /*USE_LIBDNS*/
658
659   return resolve_name_standard (name, port, want_family, want_socktype,
660                                 r_ai, r_canonname);
661 }
662
663
664 gpg_error_t
665 resolve_dns_addr (const struct sockaddr *addr, int addrlen,
666                   unsigned int flags, char **r_name)
667 {
668   return resolve_addr_standard (addr, addrlen, flags, r_name);
669 }
670
671
672 /* Check whether NAME is an IP address.  Returns true if it is either
673    an IPv6 or IPv4 numerical address.  */
674 int
675 is_ip_address (const char *name)
676 {
677   const char *s;
678   int ndots, dblcol, n;
679
680   if (*name == '[')
681     return 1; /* yes: A legal DNS name may not contain this character;
682                  this mut be bracketed v6 address.  */
683   if (*name == '.')
684     return 0; /* No.  A leading dot is not a valid IP address.  */
685
686   /* Check whether this is a v6 address.  */
687   ndots = n = dblcol = 0;
688   for (s=name; *s; s++)
689     {
690       if (*s == ':')
691         {
692           ndots++;
693           if (s[1] == ':')
694             {
695               ndots++;
696               if (dblcol)
697                 return 0; /* No: Only one "::" allowed.  */
698               dblcol++;
699               if (s[1])
700                 s++;
701             }
702           n = 0;
703         }
704       else if (*s == '.')
705         goto legacy;
706       else if (!strchr ("0123456789abcdefABCDEF", *s))
707         return 0; /* No: Not a hex digit.  */
708       else if (++n > 4)
709         return 0; /* To many digits in a group.  */
710     }
711   if (ndots > 7)
712     return 0; /* No: Too many colons.  */
713   else if (ndots > 1)
714     return 1; /* Yes: At least 2 colons indicate an v6 address.  */
715
716  legacy:
717   /* Check whether it is legacy IP address.  */
718   ndots = n = 0;
719   for (s=name; *s; s++)
720     {
721       if (*s == '.')
722         {
723           if (s[1] == '.')
724             return 0; /* No:  Douple dot. */
725           if (atoi (s+1) > 255)
726             return 0; /* No:  Ipv4 byte value too large.  */
727           ndots++;
728           n = 0;
729         }
730       else if (!strchr ("0123456789", *s))
731         return 0; /* No: Not a digit.  */
732       else if (++n > 3)
733         return 0; /* No: More than 3 digits.  */
734     }
735   return !!(ndots == 3);
736 }
737
738
739 /* Return true if NAME is an onion address.  */
740 int
741 is_onion_address (const char *name)
742 {
743   size_t len;
744
745   len = name? strlen (name) : 0;
746   if (len < 8 || strcmp (name + len - 6, ".onion"))
747     return 0;
748   /* Note that we require at least 2 characters before the suffix.  */
749   return 1;  /* Yes.  */
750 }
751
752
753 /* libdns version of get_dns_cert.  */
754 #ifdef USE_LIBDNS
755 static gpg_error_t
756 get_dns_cert_libdns (const char *name, int want_certtype,
757                      void **r_key, size_t *r_keylen,
758                      unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
759 {
760   gpg_error_t err;
761   struct dns_resolver *res = NULL;
762   struct dns_packet *ans = NULL;
763   struct dns_rr rr;
764   struct dns_rr_i rri;
765   char host[DNS_D_MAXNAME + 1];
766   int derr;
767   int qtype;
768
769   /* Gte the query type from WANT_CERTTYPE (which in general indicates
770    * the subtype we want). */
771   qtype = (want_certtype < DNS_CERTTYPE_RRBASE
772            ? T_CERT
773            : (want_certtype - DNS_CERTTYPE_RRBASE));
774
775
776   err = libdns_init ();
777   if (err)
778     goto leave;
779
780   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
781                       dns_opts (/*.socks_host=&libdns.socks_host*/), &derr);
782   if (!res)
783     {
784       err = libdns_error_to_gpg_error (derr);
785       goto leave;
786     }
787
788   if (dns_d_anchor (host, sizeof host, name, strlen (name)) >= sizeof host)
789     {
790       err = gpg_error (GPG_ERR_ENAMETOOLONG);
791       goto leave;
792     }
793
794   err = libdns_error_to_gpg_error (dns_res_submit (res, name, qtype, DNS_C_IN));
795   if (err)
796     goto leave;
797
798   /* Loop until we found a record.  */
799   while ((err = libdns_error_to_gpg_error (dns_res_check (res))))
800     {
801       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
802         {
803           if (dns_res_elapsed (res) > 30)
804             {
805               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
806               goto leave;
807             }
808
809           my_unprotect ();
810           dns_res_poll (res, 1);
811           my_protect ();
812         }
813       else if (err)
814         goto leave;
815     }
816   ans = dns_res_fetch (res, &derr);
817   if (!ans)
818     {
819       err = libdns_error_to_gpg_error (derr);
820       goto leave;
821     }
822
823   /* Check the rcode.  */
824   switch (dns_p_rcode (ans))
825     {
826     case DNS_RC_NOERROR: break;
827     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
828     default: err = GPG_ERR_SERVER_FAILED; break;
829     }
830   if (err)
831     goto leave;
832
833   memset (&rri, 0, sizeof rri);
834   dns_rr_i_init (&rri, ans);
835   rri.section = DNS_S_ALL & ~DNS_S_QD;
836   rri.name    = host;
837   rri.type    = qtype;
838
839   err = gpg_error (GPG_ERR_NOT_FOUND);
840   while (dns_rr_grep (&rr, 1, &rri, ans, &derr))
841     {
842       unsigned char *rp  = ans->data + rr.rd.p;
843       unsigned short len = rr.rd.len;
844       u16 subtype;
845
846        if (!len)
847         {
848           /* Definitely too short - skip.  */
849         }
850       else if (want_certtype >= DNS_CERTTYPE_RRBASE
851           && rr.type == (want_certtype - DNS_CERTTYPE_RRBASE)
852           && r_key)
853         {
854           *r_key = xtrymalloc (len);
855           if (!*r_key)
856             err = gpg_error_from_syserror ();
857           else
858             {
859               memcpy (*r_key, rp, len);
860               *r_keylen = len;
861               err = 0;
862             }
863           goto leave;
864         }
865       else if (want_certtype >= DNS_CERTTYPE_RRBASE)
866         {
867           /* We did not found the requested RR - skip. */
868         }
869       else if (rr.type == T_CERT && len > 5)
870         {
871           /* We got a CERT type.   */
872           subtype = buf16_to_u16 (rp);
873           rp += 2; len -= 2;
874
875           /* Skip the CERT key tag and algo which we don't need.  */
876           rp += 3; len -= 3;
877
878           if (want_certtype && want_certtype != subtype)
879             ; /* Not the requested subtype - skip.  */
880           else if (subtype == DNS_CERTTYPE_PGP && len && r_key && r_keylen)
881             {
882               /* PGP subtype */
883               *r_key = xtrymalloc (len);
884               if (!*r_key)
885                 err = gpg_error_from_syserror ();
886               else
887                 {
888                   memcpy (*r_key, rp, len);
889                   *r_keylen = len;
890                   err = 0;
891                 }
892               goto leave;
893             }
894           else if (subtype == DNS_CERTTYPE_IPGP
895                    && len && len < 1023 && len >= rp[0] + 1)
896             {
897               /* IPGP type */
898               *r_fprlen = rp[0];
899               if (*r_fprlen)
900                 {
901                   *r_fpr = xtrymalloc (*r_fprlen);
902                   if (!*r_fpr)
903                     {
904                       err = gpg_error_from_syserror ();
905                       goto leave;
906                     }
907                   memcpy (*r_fpr, rp+1, *r_fprlen);
908                 }
909               else
910                 *r_fpr = NULL;
911
912               if (len > *r_fprlen + 1)
913                 {
914                   *r_url = xtrymalloc (len - (*r_fprlen + 1) + 1);
915                   if (!*r_url)
916                     {
917                       err = gpg_error_from_syserror ();
918                       xfree (*r_fpr);
919                       *r_fpr = NULL;
920                       goto leave;
921                     }
922                   memcpy (*r_url, rp + *r_fprlen + 1, len - (*r_fprlen + 1));
923                   (*r_url)[len - (*r_fprlen + 1)] = 0;
924                 }
925               else
926                 *r_url = NULL;
927
928               err = 0;
929               goto leave;
930             }
931           else
932             {
933               /* Unknown subtype or record too short - skip.  */
934             }
935         }
936       else
937         {
938           /* Not a requested type - skip.  */
939         }
940     }
941
942  leave:
943   dns_free (ans);
944   dns_res_close (res);
945   return err;
946 }
947 #endif /*USE_LIBDNS*/
948
949
950 /* Standard resolver version of get_dns_cert.  */
951 static gpg_error_t
952 get_dns_cert_standard (const char *name, int want_certtype,
953                        void **r_key, size_t *r_keylen,
954                        unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
955 {
956 #ifdef HAVE_SYSTEM_RESOLVER
957   gpg_error_t err;
958   unsigned char *answer;
959   int r;
960   u16 count;
961
962   /* Allocate a 64k buffer which is the limit for an DNS response.  */
963   answer = xtrymalloc (65536);
964   if (!answer)
965     return gpg_error_from_syserror ();
966
967   err = gpg_error (GPG_ERR_NOT_FOUND);
968   r = res_query (name, C_IN,
969                  (want_certtype < DNS_CERTTYPE_RRBASE
970                   ? T_CERT
971                   : (want_certtype - DNS_CERTTYPE_RRBASE)),
972                  answer, 65536);
973   /* Not too big, not too small, no errors and at least 1 answer. */
974   if (r >= sizeof (HEADER) && r <= 65536
975       && (((HEADER *)(void *) answer)->rcode) == NOERROR
976       && (count = ntohs (((HEADER *)(void *) answer)->ancount)))
977     {
978       int rc;
979       unsigned char *pt, *emsg;
980
981       emsg = &answer[r];
982
983       pt = &answer[sizeof (HEADER)];
984
985       /* Skip over the query */
986
987       rc = dn_skipname (pt, emsg);
988       if (rc == -1)
989         {
990           err = gpg_error (GPG_ERR_INV_OBJ);
991           goto leave;
992         }
993       pt += rc + QFIXEDSZ;
994
995       /* There are several possible response types for a CERT request.
996          We're interested in the PGP (a key) and IPGP (a URI) types.
997          Skip all others.  TODO: A key is better than a URI since
998          we've gone through all this bother to fetch it, so favor that
999          if we have both PGP and IPGP? */
1000
1001       while (count-- > 0 && pt < emsg)
1002         {
1003           u16 type, class, dlen, ctype;
1004
1005           rc = dn_skipname (pt, emsg);  /* the name we just queried for */
1006           if (rc == -1)
1007             {
1008               err = gpg_error (GPG_ERR_INV_OBJ);
1009               goto leave;
1010             }
1011
1012           pt += rc;
1013
1014           /* Truncated message? 15 bytes takes us to the point where
1015              we start looking at the ctype. */
1016           if ((emsg - pt) < 15)
1017             break;
1018
1019           type = buf16_to_u16 (pt);
1020           pt += 2;
1021
1022           class = buf16_to_u16 (pt);
1023           pt += 2;
1024
1025           if (class != C_IN)
1026             break;
1027
1028           /* ttl */
1029           pt += 4;
1030
1031           /* data length */
1032           dlen = buf16_to_u16 (pt);
1033           pt += 2;
1034
1035           /* Check the type and parse.  */
1036           if (want_certtype >= DNS_CERTTYPE_RRBASE
1037               && type == (want_certtype - DNS_CERTTYPE_RRBASE)
1038               && r_key)
1039             {
1040               *r_key = xtrymalloc (dlen);
1041               if (!*r_key)
1042                 err = gpg_error_from_syserror ();
1043               else
1044                 {
1045                   memcpy (*r_key, pt, dlen);
1046                   *r_keylen = dlen;
1047                   err = 0;
1048                 }
1049               goto leave;
1050             }
1051           else if (want_certtype >= DNS_CERTTYPE_RRBASE)
1052             {
1053               /* We did not found the requested RR.  */
1054               pt += dlen;
1055             }
1056           else if (type == T_CERT)
1057             {
1058               /* We got a CERT type.   */
1059               ctype = buf16_to_u16 (pt);
1060               pt += 2;
1061
1062               /* Skip the CERT key tag and algo which we don't need. */
1063               pt += 3;
1064
1065               dlen -= 5;
1066
1067               /* 15 bytes takes us to here */
1068               if (want_certtype && want_certtype != ctype)
1069                 ; /* Not of the requested certtype.  */
1070               else if (ctype == DNS_CERTTYPE_PGP && dlen && r_key && r_keylen)
1071                 {
1072                   /* PGP type */
1073                   *r_key = xtrymalloc (dlen);
1074                   if (!*r_key)
1075                     err = gpg_error_from_syserror ();
1076                   else
1077                     {
1078                       memcpy (*r_key, pt, dlen);
1079                       *r_keylen = dlen;
1080                       err = 0;
1081                     }
1082                   goto leave;
1083                 }
1084               else if (ctype == DNS_CERTTYPE_IPGP
1085                        && dlen && dlen < 1023 && dlen >= pt[0] + 1)
1086                 {
1087                   /* IPGP type */
1088                   *r_fprlen = pt[0];
1089                   if (*r_fprlen)
1090                     {
1091                       *r_fpr = xtrymalloc (*r_fprlen);
1092                       if (!*r_fpr)
1093                         {
1094                           err = gpg_error_from_syserror ();
1095                           goto leave;
1096                         }
1097                       memcpy (*r_fpr, &pt[1], *r_fprlen);
1098                     }
1099                   else
1100                     *r_fpr = NULL;
1101
1102                   if (dlen > *r_fprlen + 1)
1103                     {
1104                       *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1);
1105                       if (!*r_url)
1106                         {
1107                           err = gpg_error_from_syserror ();
1108                           xfree (*r_fpr);
1109                           *r_fpr = NULL;
1110                           goto leave;
1111                         }
1112                       memcpy (*r_url, &pt[*r_fprlen + 1],
1113                               dlen - (*r_fprlen + 1));
1114                       (*r_url)[dlen - (*r_fprlen + 1)] = '\0';
1115                     }
1116                   else
1117                     *r_url = NULL;
1118
1119                   err = 0;
1120                   goto leave;
1121                 }
1122
1123               /* No subtype matches, so continue with the next answer. */
1124               pt += dlen;
1125             }
1126           else
1127             {
1128               /* Not a requested type - might be a CNAME. Try next item.  */
1129               pt += dlen;
1130             }
1131         }
1132     }
1133
1134  leave:
1135   xfree (answer);
1136   return err;
1137
1138 #else /*!HAVE_SYSTEM_RESOLVER*/
1139
1140   (void)name;
1141   (void)want_certtype;
1142   (void)r_key;
1143   (void)r_keylen;
1144   (void)r_fpr;
1145   (void)r_fprlen;
1146   (void)r_url;
1147   return gpg_error (GPG_ERR_NOT_SUPPORTED);
1148
1149 #endif /*!HAVE_SYSTEM_RESOLVER*/
1150 }
1151
1152
1153 /* Returns 0 on success or an error code.  If a PGP CERT record was
1154    found, the malloced data is returned at (R_KEY, R_KEYLEN) and
1155    the other return parameters are set to NULL/0.  If an IPGP CERT
1156    record was found the fingerprint is stored as an allocated block at
1157    R_FPR and its length at R_FPRLEN; an URL is is allocated as a
1158    string and returned at R_URL.  If WANT_CERTTYPE is 0 this function
1159    returns the first CERT found with a supported type; it is expected
1160    that only one CERT record is used.  If WANT_CERTTYPE is one of the
1161    supported certtypes only records with this certtype are considered
1162    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
1163 gpg_error_t
1164 get_dns_cert (const char *name, int want_certtype,
1165               void **r_key, size_t *r_keylen,
1166               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
1167 {
1168   if (r_key)
1169     *r_key = NULL;
1170   if (r_keylen)
1171     *r_keylen = 0;
1172   *r_fpr = NULL;
1173   *r_fprlen = 0;
1174   *r_url = NULL;
1175
1176 #ifdef USE_LIBDNS
1177   if (!standard_resolver)
1178     return get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
1179                                 r_fpr, r_fprlen, r_url);
1180 #endif /*USE_LIBDNS*/
1181
1182   return get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
1183                                 r_fpr, r_fprlen, r_url);
1184 }
1185
1186
1187 static int
1188 priosort(const void *a,const void *b)
1189 {
1190   const struct srventry *sa=a,*sb=b;
1191   if(sa->priority>sb->priority)
1192     return 1;
1193   else if(sa->priority<sb->priority)
1194     return -1;
1195   else
1196     return 0;
1197 }
1198
1199
1200 /* Libdns based helper for getsrv.  Note that it is expected that NULL
1201  * is stored at the address of LIST and 0 is stored at the address of
1202  * R_COUNT.  */
1203 #ifdef USE_LIBDNS
1204 static gpg_error_t
1205 getsrv_libdns (const char *name, struct srventry **list, int *r_count)
1206 {
1207   gpg_error_t err;
1208   struct dns_resolver *res = NULL;
1209   struct dns_packet *ans = NULL;
1210   struct dns_rr rr;
1211   struct dns_rr_i rri;
1212   char host[DNS_D_MAXNAME + 1];
1213   int derr;
1214   int srvcount=0;
1215
1216   err = libdns_init ();
1217   if (err)
1218     goto leave;
1219
1220   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
1221                       dns_opts (/*.socks_host=&libdns.socks_host*/), &derr);
1222   if (!res)
1223     {
1224       err = libdns_error_to_gpg_error (derr);
1225       goto leave;
1226     }
1227
1228   if (dns_d_anchor (host, sizeof host, name, strlen (name)) >= sizeof host)
1229     {
1230       err = gpg_error (GPG_ERR_ENAMETOOLONG);
1231       goto leave;
1232     }
1233
1234   err = libdns_error_to_gpg_error
1235     (dns_res_submit (res, name, DNS_T_SRV, DNS_C_IN));
1236   if (err)
1237     goto leave;
1238
1239   /* Loop until we found a record.  */
1240   while ((err = libdns_error_to_gpg_error (dns_res_check (res))))
1241     {
1242       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
1243         {
1244           if (dns_res_elapsed (res) > 30)
1245             {
1246               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
1247               goto leave;
1248             }
1249
1250           my_unprotect ();
1251           dns_res_poll (res, 1);
1252           my_protect ();
1253         }
1254       else if (err)
1255         goto leave;
1256     }
1257   ans = dns_res_fetch (res, &derr);
1258   if (!ans)
1259     {
1260       err = libdns_error_to_gpg_error (derr);
1261       goto leave;
1262     }
1263
1264   /* Check the rcode.  */
1265   switch (dns_p_rcode (ans))
1266     {
1267     case DNS_RC_NOERROR: break;
1268     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
1269     default: err = GPG_ERR_SERVER_FAILED; break;
1270     }
1271   if (err)
1272     goto leave;
1273
1274   memset (&rri, 0, sizeof rri);
1275   dns_rr_i_init (&rri, ans);
1276   rri.section = DNS_S_ALL & ~DNS_S_QD;
1277   rri.name        = host;
1278   rri.type        = DNS_T_SRV;
1279
1280   while (dns_rr_grep (&rr, 1, &rri, ans, &derr))
1281     {
1282       struct dns_srv dsrv;
1283       struct srventry *srv;
1284       struct srventry *newlist;
1285
1286       err = libdns_error_to_gpg_error (dns_srv_parse(&dsrv, &rr, ans));
1287       if (err)
1288         goto leave;
1289
1290       newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
1291       if (!newlist)
1292         {
1293           err = gpg_error_from_syserror ();
1294           goto leave;
1295         }
1296       *list = newlist;
1297       memset (&(*list)[srvcount], 0, sizeof(struct srventry));
1298       srv = &(*list)[srvcount];
1299       srvcount++;
1300       srv->priority = dsrv.priority;
1301       srv->weight   = dsrv.weight;
1302       srv->port     = dsrv.port;
1303       mem2str (srv->target, dsrv.target, sizeof srv->target);
1304     }
1305
1306   *r_count = srvcount;
1307
1308  leave:
1309   if (err)
1310     {
1311       xfree (*list);
1312       *list = NULL;
1313     }
1314   dns_free (ans);
1315   dns_res_close (res);
1316   return err;
1317 }
1318 #endif /*USE_LIBDNS*/
1319
1320
1321 /* Standard resolver based helper for getsrv.  Note that it is
1322  * expected that NULL is stored at the address of LIST and 0 is stored
1323  * at the address of R_COUNT.  */
1324 static gpg_error_t
1325 getsrv_standard (const char *name, struct srventry **list, int *r_count)
1326 {
1327 #ifdef HAVE_SYSTEM_RESOLVER
1328   union {
1329     unsigned char ans[2048];
1330     HEADER header[1];
1331   } res;
1332   unsigned char *answer = res.ans;
1333   HEADER *header = res.header;
1334   unsigned char *pt, *emsg;
1335   int r, rc;
1336   u16 dlen;
1337   int srvcount=0;
1338   u16 count;
1339
1340   /* Do not allow a query using the standard resolver in Tor mode.  */
1341   if (tor_mode)
1342     return gpg_error (GPG_ERR_NOT_ENABLED);
1343
1344   my_unprotect ();
1345   r = res_query (name, C_IN, T_SRV, answer, sizeof res.ans);
1346   my_protect ();
1347   if (r < 0)
1348     return get_h_errno_as_gpg_error ();
1349   if (r < sizeof (HEADER))
1350     return gpg_error (GPG_ERR_SERVER_FAILED);
1351   if (r > sizeof res.ans)
1352     return gpg_error (GPG_ERR_SYSTEM_BUG);
1353   if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
1354     return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
1355
1356   emsg = &answer[r];
1357   pt = &answer[sizeof(HEADER)];
1358
1359   /* Skip over the query */
1360   rc = dn_skipname (pt, emsg);
1361   if (rc == -1)
1362     goto fail;
1363
1364   pt += rc + QFIXEDSZ;
1365
1366   while (count-- > 0 && pt < emsg)
1367     {
1368       struct srventry *srv;
1369       u16 type, class;
1370       struct srventry *newlist;
1371
1372       newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
1373       if (!newlist)
1374         goto fail;
1375       *list = newlist;
1376       memset (&(*list)[srvcount], 0, sizeof(struct srventry));
1377       srv = &(*list)[srvcount];
1378       srvcount++;
1379
1380       rc = dn_skipname (pt, emsg); /* The name we just queried for.  */
1381       if (rc == -1)
1382         goto fail;
1383       pt += rc;
1384
1385       /* Truncated message? */
1386       if ((emsg-pt) < 16)
1387         goto fail;
1388
1389       type = buf16_to_u16 (pt);
1390       pt += 2;
1391       /* We asked for SRV and got something else !? */
1392       if (type != T_SRV)
1393         goto fail;
1394
1395       class = buf16_to_u16 (pt);
1396       pt += 2;
1397       /* We asked for IN and got something else !? */
1398       if (class != C_IN)
1399         goto fail;
1400
1401       pt += 4; /* ttl */
1402       dlen = buf16_to_u16 (pt);
1403       pt += 2;
1404
1405       srv->priority = buf16_to_ushort (pt);
1406       pt += 2;
1407       srv->weight = buf16_to_ushort (pt);
1408       pt += 2;
1409       srv->port = buf16_to_ushort (pt);
1410       pt += 2;
1411
1412       /* Get the name.  2782 doesn't allow name compression, but
1413        * dn_expand still works to pull the name out of the packet. */
1414       rc = dn_expand (answer, emsg, pt, srv->target, sizeof srv->target);
1415       if (rc == 1 && srv->target[0] == 0) /* "." */
1416         {
1417           xfree(*list);
1418           *list = NULL;
1419           return 0;
1420         }
1421       if (rc == -1)
1422         goto fail;
1423       pt += rc;
1424       /* Corrupt packet? */
1425       if (dlen != rc+6)
1426         goto fail;
1427     }
1428
1429   *r_count = srvcount;
1430   return 0;
1431
1432  fail:
1433   xfree (*list);
1434   *list = NULL;
1435   return gpg_error (GPG_ERR_GENERAL);
1436
1437 #else /*!HAVE_SYSTEM_RESOLVER*/
1438
1439   (void)name;
1440   (void)list;
1441   (void)r_count;
1442   return gpg_error (GPG_ERR_NOT_SUPPORTED);
1443
1444 #endif /*!HAVE_SYSTEM_RESOLVER*/
1445 }
1446
1447
1448 int
1449 getsrv (const char *name, struct srventry **list)
1450 {
1451   gpg_error_t err;
1452   int srvcount;
1453   int i;
1454
1455   *list = NULL;
1456   srvcount = 0;
1457 #ifdef USE_LIBDNS
1458   if (!standard_resolver)
1459     err = getsrv_libdns (name, list, &srvcount);
1460   else
1461 #endif /*USE_LIBDNS*/
1462     err = getsrv_standard (name, list, &srvcount);
1463
1464   if (err)
1465     return -1;  /* Ugly.  FIXME: Return an error code. */
1466
1467   /* Now we have an array of all the srv records. */
1468
1469   /* Order by priority */
1470   qsort(*list,srvcount,sizeof(struct srventry),priosort);
1471
1472   /* For each priority, move the zero-weighted items first. */
1473   for (i=0; i < srvcount; i++)
1474     {
1475       int j;
1476
1477       for (j=i;j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
1478         {
1479           if((*list)[j].weight==0)
1480             {
1481               /* Swap j with i */
1482               if(j!=i)
1483                 {
1484                   struct srventry temp;
1485
1486                   memcpy (&temp,&(*list)[j],sizeof(struct srventry));
1487                   memcpy (&(*list)[j],&(*list)[i],sizeof(struct srventry));
1488                   memcpy (&(*list)[i],&temp,sizeof(struct srventry));
1489                 }
1490
1491               break;
1492             }
1493         }
1494     }
1495
1496   /* Run the RFC-2782 weighting algorithm.  We don't need very high
1497      quality randomness for this, so regular libc srand/rand is
1498      sufficient.  */
1499
1500   {
1501     static int done;
1502     if (!done)
1503       {
1504         done = 1;
1505         srand (time (NULL)*getpid());
1506       }
1507   }
1508
1509   for (i=0; i < srvcount; i++)
1510     {
1511       int j;
1512       float prio_count=0,chose;
1513
1514       for (j=i; j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
1515         {
1516           prio_count+=(*list)[j].weight;
1517           (*list)[j].run_count=prio_count;
1518         }
1519
1520       chose=prio_count*rand()/RAND_MAX;
1521
1522       for (j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
1523         {
1524           if (chose<=(*list)[j].run_count)
1525             {
1526               /* Swap j with i */
1527               if(j!=i)
1528                 {
1529                   struct srventry temp;
1530
1531                   memcpy(&temp,&(*list)[j],sizeof(struct srventry));
1532                   memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
1533                   memcpy(&(*list)[i],&temp,sizeof(struct srventry));
1534                 }
1535               break;
1536             }
1537         }
1538     }
1539
1540   return srvcount;
1541 }
1542
1543
1544 \f
1545 #ifdef USE_LIBDNS
1546 /* libdns version of get_dns_cname.  */
1547 gpg_error_t
1548 get_dns_cname_libdns (const char *name, char **r_cname)
1549 {
1550   gpg_error_t err;
1551   struct dns_resolver *res = NULL;
1552   struct dns_packet *ans = NULL;
1553   struct dns_cname cname;
1554   int derr;
1555
1556   err = libdns_init ();
1557   if (err)
1558     goto leave;
1559
1560   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
1561                       dns_opts (/*.socks_host=&libdns.socks_host*/), &derr);
1562   if (!res)
1563     {
1564       err = libdns_error_to_gpg_error (derr);
1565       goto leave;
1566     }
1567
1568   err = libdns_error_to_gpg_error
1569     (dns_res_submit (res, name, DNS_T_CNAME, DNS_C_IN));
1570   if (err)
1571     goto leave;
1572
1573   /* Loop until we found a record.  */
1574   while ((err = libdns_error_to_gpg_error (dns_res_check (res))))
1575     {
1576       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
1577         {
1578           if (dns_res_elapsed (res) > 30)
1579             {
1580               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
1581               goto leave;
1582             }
1583
1584           my_unprotect ();
1585           dns_res_poll (res, 1);
1586           my_protect ();
1587         }
1588       else if (err)
1589         goto leave;
1590     }
1591   ans = dns_res_fetch (res, &derr);
1592   if (!ans)
1593     {
1594       err = libdns_error_to_gpg_error (derr);
1595       goto leave;
1596     }
1597
1598   /* Check the rcode.  */
1599   switch (dns_p_rcode (ans))
1600     {
1601     case DNS_RC_NOERROR: break;
1602     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
1603     default: err = GPG_ERR_SERVER_FAILED; break;
1604     }
1605   if (err)
1606     goto leave;
1607
1608   /* Parse the result into CNAME.  */
1609   err = libdns_error_to_gpg_error (dns_p_study (ans));
1610   if (err)
1611     goto leave;
1612
1613   if (!dns_d_cname (&cname, sizeof cname, name, strlen (name), ans, &derr))
1614     {
1615       err = libdns_error_to_gpg_error (derr);
1616       goto leave;
1617     }
1618
1619   /* Copy result.  */
1620   *r_cname = xtrystrdup (cname.host);
1621   if (!*r_cname)
1622     err = gpg_error_from_syserror ();
1623
1624  leave:
1625   dns_free (ans);
1626   dns_res_close (res);
1627   return err;
1628 }
1629 #endif /*USE_LIBDNS*/
1630
1631
1632 /* Standard resolver version of get_dns_cname.  */
1633 gpg_error_t
1634 get_dns_cname_standard (const char *name, char **r_cname)
1635 {
1636 #ifdef HAVE_SYSTEM_RESOLVER
1637   gpg_error_t err;
1638   int rc;
1639   union {
1640     unsigned char ans[2048];
1641     HEADER header[1];
1642   } res;
1643   unsigned char *answer = res.ans;
1644   HEADER *header = res.header;
1645   unsigned char *pt, *emsg;
1646   int r;
1647   char *cname;
1648   int cnamesize = 1025;
1649   u16 count;
1650
1651   /* Do not allow a query using the standard resolver in Tor mode.  */
1652   if (tor_mode)
1653     return -1;
1654
1655   my_unprotect ();
1656   r = res_query (name, C_IN, T_CERT, answer, sizeof res.ans);
1657   my_protect ();
1658   if (r < 0)
1659     return get_h_errno_as_gpg_error ();
1660   if (r < sizeof (HEADER))
1661     return gpg_error (GPG_ERR_SERVER_FAILED);
1662   if (r > sizeof res.ans)
1663     return gpg_error (GPG_ERR_SYSTEM_BUG);
1664   if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
1665     return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
1666   if (count != 1)
1667     return gpg_error (GPG_ERR_SERVER_FAILED);
1668
1669   emsg = &answer[r];
1670   pt = &answer[sizeof(HEADER)];
1671   rc = dn_skipname (pt, emsg);
1672   if (rc == -1)
1673     return gpg_error (GPG_ERR_SERVER_FAILED);
1674
1675   pt += rc + QFIXEDSZ;
1676   if (pt >= emsg)
1677     return gpg_error (GPG_ERR_SERVER_FAILED);
1678
1679   rc = dn_skipname (pt, emsg);
1680   if (rc == -1)
1681     return gpg_error (GPG_ERR_SERVER_FAILED);
1682   pt += rc + 2 + 2 + 4;
1683   if (pt+2 >= emsg)
1684     return gpg_error (GPG_ERR_SERVER_FAILED);
1685   pt += 2;  /* Skip rdlen */
1686
1687   cname = xtrymalloc (cnamesize);
1688   if (!cname)
1689     return gpg_error_from_syserror ();
1690
1691   rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
1692   if (rc == -1)
1693     {
1694       xfree (cname);
1695       return gpg_error (GPG_ERR_SERVER_FAILED);
1696     }
1697   *r_cname = xtryrealloc (cname, strlen (cname)+1);
1698   if (!*r_cname)
1699     {
1700       err = gpg_error_from_syserror ();
1701       xfree (cname);
1702       return err;
1703     }
1704   return 0;
1705
1706 #else /*!HAVE_SYSTEM_RESOLVER*/
1707
1708   (void)name;
1709   (void)r_cname;
1710   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1711
1712 #endif /*!HAVE_SYSTEM_RESOLVER*/
1713 }
1714
1715
1716 gpg_error_t
1717 get_dns_cname (const char *name, char **r_cname)
1718 {
1719   *r_cname = NULL;
1720
1721 #ifdef USE_LIBDNS
1722   if (!standard_resolver)
1723     return get_dns_cname_libdns (name, r_cname);
1724 #endif /*USE_LIBDNS*/
1725
1726   return get_dns_cname_standard (name, r_cname);
1727 }