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