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