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