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