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