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