dirmngr: Print a WARNING status for DNS config problems.
[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. 2016 Werner Koch
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * This file is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <https://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <sys/types.h>
33 #ifdef HAVE_W32_SYSTEM
34 # define WIN32_LEAN_AND_MEAN
35 # ifdef HAVE_WINSOCK2_H
36 #  include <winsock2.h>
37 # endif
38 # include <windows.h>
39 # include <iphlpapi.h>
40 #else
41 # if HAVE_SYSTEM_RESOLVER
42 #  include <netinet/in.h>
43 #  include <arpa/nameser.h>
44 #  include <resolv.h>
45 # endif
46 # include <netdb.h>
47 #endif
48 #ifdef HAVE_STAT
49 # include <sys/stat.h>
50 #endif
51 #include <string.h>
52 #include <unistd.h>
53
54
55 /* William Ahern's DNS library, included as a source copy.  */
56 #ifdef USE_LIBDNS
57 # include "dns.h"
58 #endif
59
60 /* dns.c has a dns_p_free but it is not exported.  We use our own
61  * wrapper here so that we do not accidentally use xfree which would
62  * be wrong for dns.c allocated data.  */
63 #define dns_free(a)  free ((a))
64
65
66 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
67 # undef USE_NPTH
68 #endif
69 #ifdef USE_NPTH
70 # include <npth.h>
71 #endif
72
73 #include "./dirmngr-err.h"
74 #include "../common/util.h"
75 #include "../common/host2net.h"
76 #include "dirmngr-status.h"
77 #include "dns-stuff.h"
78
79 #ifdef USE_NPTH
80 # define my_unprotect()        npth_unprotect ()
81 # define my_protect()          npth_protect ()
82 #else
83 # define my_unprotect()        do { } while(0)
84 # define my_protect()          do { } while(0)
85 #endif
86
87 /* We allow the use of 0 instead of AF_UNSPEC - check this assumption.  */
88 #if AF_UNSPEC != 0
89 # error AF_UNSPEC does not have the value 0
90 #endif
91
92 /* Windows does not support the AI_ADDRCONFIG flag - use zero instead.  */
93 #ifndef AI_ADDRCONFIG
94 # define AI_ADDRCONFIG 0
95 #endif
96
97 /* Not every installation has gotten around to supporting SRVs or
98    CERTs yet... */
99 #ifndef T_SRV
100 #define T_SRV 33
101 #endif
102 #undef T_CERT
103 #define T_CERT 37
104
105 /* The standard SOCKS and TOR ports.  */
106 #define SOCKS_PORT 1080
107 #define TOR_PORT   9050
108 #define TOR_PORT2  9150   /* (Used by the Tor browser) */
109
110
111 /* The default nameserver used in Tor mode.  */
112 #define DEFAULT_NAMESERVER "8.8.8.8"
113
114 /* The default timeout in seconds for libdns requests.  */
115 #define DEFAULT_TIMEOUT 30
116
117
118 #define RESOLV_CONF_NAME "/etc/resolv.conf"
119
120 /* Two flags to enable verbose and debug mode.  */
121 static int opt_verbose;
122 static int opt_debug;
123
124 /* The timeout in seconds for libdns requests.  */
125 static int opt_timeout;
126
127 /* The flag to disable IPv4 access - right now this only skips
128  * returned A records.  */
129 static int opt_disable_ipv4;
130
131 /* The flag to disable IPv6 access - right now this only skips
132  * returned AAAA records.  */
133 static int opt_disable_ipv6;
134
135 /* If set force the use of the standard resolver.  */
136 static int standard_resolver;
137
138 /* If set use recursive resolver when available. */
139 static int recursive_resolver;
140
141 /* If set Tor mode shall be used.  */
142 static int tor_mode;
143
144 /* A string with the nameserver IP address used with Tor.
145   (40 should be sufficient for v6 but we add some extra for a scope.) */
146 static char tor_nameserver[40+20];
147
148 /* Two strings to hold the credentials presented to Tor.  */
149 static char tor_socks_user[30];
150 static char tor_socks_password[20];
151
152
153 #ifdef USE_LIBDNS
154 /* Libdns gobal data.  */
155 struct libdns_s
156 {
157   struct dns_resolv_conf *resolv_conf;
158   struct dns_hosts *hosts;
159   struct dns_hints *hints;
160
161   struct sockaddr_storage socks_host;
162 } libdns;
163
164 /* If this flag is set, libdns shall be reinited for the next use.  */
165 static int libdns_reinit_pending;
166
167 /* The Tor port to be used.  */
168 static int libdns_tor_port;
169
170 #endif /*USE_LIBDNS*/
171
172
173 /* Calling this function with YES set to True forces the use of the
174  * standard resolver even if dirmngr has been built with support for
175  * an alternative resolver.  */
176 void
177 enable_standard_resolver (int yes)
178 {
179   standard_resolver = yes;
180 }
181
182
183 /* Return true if the standard resolver is used.  */
184 int
185 standard_resolver_p (void)
186 {
187   return standard_resolver;
188 }
189
190
191 /* Calling this function with YES switches libdns into recursive mode.
192  * It has no effect on the standard resolver.  */
193 void
194 enable_recursive_resolver (int yes)
195 {
196   recursive_resolver = yes;
197 #ifdef USE_LIBDNS
198   libdns_reinit_pending = 1;
199 #endif
200 }
201
202
203 /* Return true iff the recursive resolver is used.  */
204 int
205 recursive_resolver_p (void)
206 {
207 #if USE_LIBDNS
208   return !standard_resolver && recursive_resolver;
209 #else
210   return 0;
211 #endif
212 }
213
214
215 /* Puts this module eternally into Tor mode.  When called agained with
216  * NEW_CIRCUIT request a new TOR circuit for the next DNS query.  */
217 void
218 enable_dns_tormode (int new_circuit)
219 {
220   if (!*tor_socks_user || new_circuit)
221     {
222       static unsigned int counter;
223
224       gpgrt_snprintf (tor_socks_user, sizeof tor_socks_user,
225                       "dirmngr-%lu", (unsigned long)getpid ());
226       gpgrt_snprintf (tor_socks_password, sizeof tor_socks_password,
227                       "p%u", counter);
228       counter++;
229     }
230   tor_mode = 1;
231 }
232
233
234 /* Disable tor mode.  */
235 void
236 disable_dns_tormode (void)
237 {
238   tor_mode = 0;
239 }
240
241
242 /* Set verbosity and debug mode for this module. */
243 void
244 set_dns_verbose (int verbose, int debug)
245 {
246   opt_verbose = verbose;
247   opt_debug = debug;
248 }
249
250
251 /* Set the Disable-IPv4 flag so that the name resolver does not return
252  * A addresses.  */
253 void
254 set_dns_disable_ipv4 (int yes)
255 {
256   opt_disable_ipv4 = !!yes;
257 }
258
259
260 /* Set the Disable-IPv6 flag so that the name resolver does not return
261  * AAAA addresses.  */
262 void
263 set_dns_disable_ipv6 (int yes)
264 {
265   opt_disable_ipv6 = !!yes;
266 }
267
268
269 /* Set the timeout for libdns requests to SECONDS.  A value of 0 sets
270  * the default timeout and values are capped at 10 minutes.  */
271 void
272 set_dns_timeout (int seconds)
273 {
274   if (!seconds)
275     seconds = DEFAULT_TIMEOUT;
276   else if (seconds < 1)
277     seconds = 1;
278   else if (seconds > 600)
279     seconds = 600;
280
281   opt_timeout = seconds;
282 }
283
284
285 /* Change the default IP address of the nameserver to IPADDR.  The
286    address needs to be a numerical IP address and will be used for the
287    next DNS query.  Note that this is only used in Tor mode.  */
288 void
289 set_dns_nameserver (const char *ipaddr)
290 {
291   strncpy (tor_nameserver, ipaddr? ipaddr : DEFAULT_NAMESERVER,
292            sizeof tor_nameserver -1);
293   tor_nameserver[sizeof tor_nameserver -1] = 0;
294 #ifdef USE_LIBDNS
295   libdns_reinit_pending = 1;
296   libdns_tor_port = 0;  /* Start again with the default port.  */
297 #endif
298 }
299
300
301 /* Free an addressinfo linked list as returned by resolve_dns_name.  */
302 void
303 free_dns_addrinfo (dns_addrinfo_t ai)
304 {
305   while (ai)
306     {
307       dns_addrinfo_t next = ai->next;
308       xfree (ai);
309       ai = next;
310     }
311 }
312
313
314 #ifndef HAVE_W32_SYSTEM
315 /* Return H_ERRNO mapped to a gpg-error code.  Will never return 0. */
316 static gpg_error_t
317 get_h_errno_as_gpg_error (void)
318 {
319   gpg_err_code_t ec;
320
321   switch (h_errno)
322     {
323     case HOST_NOT_FOUND: ec = GPG_ERR_NO_NAME; break;
324     case TRY_AGAIN:      ec = GPG_ERR_TRY_LATER; break;
325     case NO_RECOVERY:    ec = GPG_ERR_SERVER_FAILED; break;
326     case NO_DATA:        ec = GPG_ERR_NO_DATA; break;
327     default:             ec = GPG_ERR_UNKNOWN_ERRNO; break;
328     }
329   return gpg_error (ec);
330 }
331 #endif /*!HAVE_W32_SYSTEM*/
332
333 static gpg_error_t
334 map_eai_to_gpg_error (int ec)
335 {
336   gpg_error_t err;
337
338   switch (ec)
339     {
340     case EAI_AGAIN:     err = gpg_error (GPG_ERR_EAGAIN); break;
341     case EAI_BADFLAGS:  err = gpg_error (GPG_ERR_INV_FLAG); break;
342     case EAI_FAIL:      err = gpg_error (GPG_ERR_SERVER_FAILED); break;
343     case EAI_MEMORY:    err = gpg_error (GPG_ERR_ENOMEM); break;
344 #ifdef EAI_NODATA
345     case EAI_NODATA:    err = gpg_error (GPG_ERR_NO_DATA); break;
346 #endif
347     case EAI_NONAME:    err = gpg_error (GPG_ERR_NO_NAME); break;
348     case EAI_SERVICE:   err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
349     case EAI_FAMILY:    err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
350     case EAI_SOCKTYPE:  err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
351 #ifndef HAVE_W32_SYSTEM
352 # ifdef EAI_ADDRFAMILY
353     case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
354 # endif
355     case EAI_SYSTEM:    err = gpg_error_from_syserror (); break;
356 #endif
357     default:            err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
358     }
359   return err;
360 }
361
362
363 #ifdef USE_LIBDNS
364 static gpg_error_t
365 libdns_error_to_gpg_error (int serr)
366 {
367   gpg_err_code_t ec;
368
369   switch (serr)
370     {
371     case 0: ec = 0; break;
372
373     case DNS_ENOBUFS:  ec = GPG_ERR_BUFFER_TOO_SHORT; break;
374     case DNS_EILLEGAL: ec = GPG_ERR_INV_OBJ; break;
375     case DNS_EORDER:   ec = GPG_ERR_INV_ORDER; break;
376     case DNS_ESECTION: ec = GPG_ERR_DNS_SECTION; break;
377     case DNS_EUNKNOWN: ec = GPG_ERR_DNS_UNKNOWN; break;
378     case DNS_EADDRESS: ec = GPG_ERR_DNS_ADDRESS; break;
379     case DNS_ENOQUERY: ec = GPG_ERR_DNS_NO_QUERY; break;
380     case DNS_ENOANSWER:ec = GPG_ERR_DNS_NO_ANSWER; break;
381     case DNS_EFETCHED: ec = GPG_ERR_ALREADY_FETCHED; break;
382     case DNS_ESERVICE: ec = GPG_ERR_NOT_SUPPORTED; break;
383     case DNS_ENONAME:  ec = GPG_ERR_NO_NAME; break;
384     case DNS_EFAIL:    ec = GPG_ERR_SERVER_FAILED; break;
385     case DNS_ECONNFIN: ec = GPG_ERR_DNS_CLOSED; break;
386     case DNS_EVERIFY:  ec = GPG_ERR_DNS_VERIFY; break;
387
388     default:
389       if (serr >= 0)
390         ec = gpg_err_code_from_errno (serr);
391       else
392         ec = GPG_ERR_DNS_UNKNOWN;
393       break;
394     }
395   return gpg_error (ec);
396 }
397 #endif /*USE_LIBDNS*/
398
399
400 /* Return true if resolve.conf changed since it was last loaded.  */
401 #ifdef USE_LIBDNS
402 static int
403 resolv_conf_changed_p (void)
404 {
405 #if defined(HAVE_W32_SYSTEM) || !defined(HAVE_STAT)
406   return 0;
407 #else
408   static time_t last_mtime;
409   const char *fname = RESOLV_CONF_NAME;
410   struct stat statbuf;
411   int changed = 0;
412
413   if (stat (fname, &statbuf))
414     {
415       log_error ("stat'ing '%s' failed: %s\n",
416                  fname, gpg_strerror (gpg_error_from_syserror ()));
417       last_mtime = 1; /* Force a "changed" result the next time stat
418                        * works.  */
419     }
420   else if (!last_mtime)
421     last_mtime = statbuf.st_mtime;
422   else if (last_mtime != statbuf.st_mtime)
423     {
424       changed = 1;
425       last_mtime = statbuf.st_mtime;
426     }
427
428   return changed;
429 #endif
430 }
431 #endif /*USE_LIBDNS*/
432
433 #ifdef USE_LIBDNS
434 /* Initialize libdns.  Returns 0 on success; prints a diagnostic and
435  * returns an error code on failure.  */
436 static gpg_error_t
437 libdns_init (ctrl_t ctrl)
438 {
439   gpg_error_t err;
440   struct libdns_s ld;
441   int derr;
442   char *cfgstr = NULL;
443   const char *fname = NULL;
444
445   if (libdns.resolv_conf)
446     return 0; /* Already initialized.  */
447
448   memset (&ld, 0, sizeof ld);
449
450   ld.resolv_conf = dns_resconf_open (&derr);
451   if (!ld.resolv_conf)
452     {
453       err = libdns_error_to_gpg_error (derr);
454       log_error ("failed to allocate DNS resconf object: %s\n",
455                  gpg_strerror (err));
456       goto leave;
457     }
458
459   if (tor_mode)
460     {
461       if (!*tor_nameserver)
462         set_dns_nameserver (NULL);
463
464       if (!libdns_tor_port)
465         libdns_tor_port = TOR_PORT;
466
467       cfgstr = xtryasprintf ("[%s]:53", tor_nameserver);
468       if (!cfgstr)
469         err = gpg_error_from_syserror ();
470       else
471         err = libdns_error_to_gpg_error
472           (dns_resconf_pton (&ld.resolv_conf->nameserver[0], cfgstr));
473       if (err)
474         log_error ("failed to set nameserver '%s': %s\n",
475                    cfgstr, gpg_strerror (err));
476       if (err)
477         goto leave;
478
479       ld.resolv_conf->options.tcp = DNS_RESCONF_TCP_SOCKS;
480
481       xfree (cfgstr);
482       cfgstr = xtryasprintf ("[%s]:%d", "127.0.0.1", libdns_tor_port);
483       if (!cfgstr)
484         err = gpg_error_from_syserror ();
485       else
486         err = libdns_error_to_gpg_error
487           (dns_resconf_pton (&ld.socks_host, cfgstr));
488       if (err)
489         {
490           log_error ("failed to set socks server '%s': %s\n",
491                      cfgstr, gpg_strerror (err));
492           goto leave;
493         }
494     }
495   else
496     {
497 #ifdef HAVE_W32_SYSTEM
498       ULONG ninfo_len;
499       PFIXED_INFO ninfo;
500       PIP_ADDR_STRING pip;
501       int idx;
502
503       ninfo_len = 2048;
504       ninfo = xtrymalloc (ninfo_len);
505       if (!ninfo)
506         {
507           err = gpg_error_from_syserror ();
508           goto leave;
509         }
510
511       if (GetNetworkParams (ninfo, &ninfo_len))
512         {
513           log_error ("GetNetworkParms failed: %s\n", w32_strerror (-1));
514           err = gpg_error (GPG_ERR_GENERAL);
515           xfree (ninfo);
516           goto leave;
517         }
518
519       for (idx=0, pip = &(ninfo->DnsServerList);
520            pip && idx < DIM (ld.resolv_conf->nameserver);
521            pip = pip->Next)
522         {
523           if (opt_debug)
524             log_debug ("dns: dnsserver[%d] '%s'\n", idx, pip->IpAddress.String);
525           err = libdns_error_to_gpg_error
526             (dns_resconf_pton (&ld.resolv_conf->nameserver[idx],
527                                pip->IpAddress.String));
528           if (err)
529             log_error ("failed to set nameserver[%d] '%s': %s\n",
530                        idx, pip->IpAddress.String, gpg_strerror (err));
531           else
532             idx++;
533         }
534       xfree (ninfo);
535
536 #else /* Unix */
537
538       fname = RESOLV_CONF_NAME;
539       resolv_conf_changed_p (); /* Reset timestamp.  */
540       err = libdns_error_to_gpg_error
541         (dns_resconf_loadpath (ld.resolv_conf, fname));
542       if (err)
543         {
544           log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
545           goto leave;
546         }
547
548       fname = "/etc/nsswitch.conf";
549       err = libdns_error_to_gpg_error
550         (dns_nssconf_loadpath (ld.resolv_conf, fname));
551       if (err)
552         {
553           /* This is not a fatal error: nsswitch.conf is not used on
554            * all systems; assume classic behavior instead.  */
555           if (gpg_err_code (err) != GPG_ERR_ENOENT)
556             log_error ("failed to load '%s': %s\n", fname, gpg_strerror (err));
557           if (opt_debug)
558             log_debug ("dns: fallback resolution order, files then DNS\n");
559           ld.resolv_conf->lookup[0] = 'f';
560           ld.resolv_conf->lookup[1] = 'b';
561           ld.resolv_conf->lookup[2] = '\0';
562           err = GPG_ERR_NO_ERROR;
563         }
564       else if (!strchr (ld.resolv_conf->lookup, 'b'))
565         {
566           /* No DNS resolution type found in the list.  This might be
567            * due to systemd based systems which allow for custom
568            * keywords which are not known to us and thus we do not
569            * know whether DNS is wanted or not.  Because DNS is
570            * important for our infrastructure, we forcefully append
571            * DNS to the end of the list.  */
572           if (strlen (ld.resolv_conf->lookup)+2 < sizeof ld.resolv_conf->lookup)
573             {
574               if (opt_debug)
575                 log_debug ("dns: appending DNS to resolution order\n");
576               strcat (ld.resolv_conf->lookup, "b");
577             }
578           else
579             log_error ("failed to append DNS to resolution order\n");
580         }
581
582 #endif /* Unix */
583     }
584
585   ld.hosts = dns_hosts_open (&derr);
586   if (!ld.hosts)
587     {
588       err = libdns_error_to_gpg_error (derr);
589       log_error ("failed to initialize hosts file: %s\n", gpg_strerror (err));
590       goto leave;
591     }
592
593   {
594 #if HAVE_W32_SYSTEM
595     char *hosts_path = xtryasprintf ("%s\\System32\\drivers\\etc\\hosts",
596                                      getenv ("SystemRoot"));
597     if (! hosts_path)
598       {
599         err = gpg_error_from_syserror ();
600         goto leave;
601       }
602
603     derr = dns_hosts_loadpath (ld.hosts, hosts_path);
604     xfree (hosts_path);
605 #else
606     derr = dns_hosts_loadpath (ld.hosts, "/etc/hosts");
607 #endif
608     if (derr)
609       {
610         err = libdns_error_to_gpg_error (derr);
611         log_error ("failed to load hosts file: %s\n", gpg_strerror (err));
612         err = 0; /* Do not bail out - having no /etc/hosts is legal.  */
613       }
614   }
615
616   ld.resolv_conf->options.recurse = recursive_resolver_p ();
617
618   /* dns_hints_local for stub mode, dns_hints_root for recursive.  */
619   ld.hints = (recursive_resolver
620               ? dns_hints_root  (ld.resolv_conf, &derr)
621               : dns_hints_local (ld.resolv_conf, &derr));
622   if (!ld.hints)
623     {
624       err = libdns_error_to_gpg_error (derr);
625       log_error ("failed to load DNS hints: %s\n", gpg_strerror (err));
626       fname = "[dns hints]";
627       goto leave;
628     }
629
630   /* All fine.  Make the data global.  */
631   libdns = ld;
632
633   if (opt_debug)
634     log_debug ("dns: libdns initialized%s\n", tor_mode?" (tor mode)":"");
635
636  leave:
637   if (!fname)
638     fname = cfgstr;
639   if (err && fname)
640     dirmngr_status_printf (ctrl, "WARNING",
641                            "dns_config_problem %u"
642                            " error accessing '%s': %s <%s>",
643                            err, fname, gpg_strerror (err), gpg_strsource (err));
644
645   xfree (cfgstr);
646   return err;
647 }
648 #endif /*USE_LIBDNS*/
649
650
651 #ifdef USE_LIBDNS
652 /* Deinitialize libdns.  */
653 static void
654 libdns_deinit (void)
655 {
656   struct libdns_s ld;
657
658   if (!libdns.resolv_conf)
659     return; /* Not initialized.  */
660
661   ld = libdns;
662   memset (&libdns, 0, sizeof libdns);
663   dns_hints_close (ld.hints);
664   dns_hosts_close (ld.hosts);
665   dns_resconf_close (ld.resolv_conf);
666 }
667 #endif /*USE_LIBDNS*/
668
669
670 /* SIGHUP action handler for this module.  With FORCE set objects are
671  * all immediately released. */
672 void
673 reload_dns_stuff (int force)
674 {
675 #ifdef USE_LIBDNS
676   if (force)
677     {
678       libdns_deinit ();
679       libdns_reinit_pending = 0;
680     }
681   else
682     {
683       libdns_reinit_pending = 1;
684       libdns_tor_port = 0;  /* Start again with the default port.  */
685     }
686 #else
687   (void)force;
688 #endif
689 }
690
691
692 #ifdef USE_LIBDNS
693 /*
694  * Initialize libdns if needed and open a dns_resolver context.
695  * Returns 0 on success and stores the new context at R_RES.  On
696  * failure an error code is returned and NULL stored at R_RES.
697  */
698 static gpg_error_t
699 libdns_res_open (ctrl_t ctrl, struct dns_resolver **r_res)
700 {
701   gpg_error_t err;
702   struct dns_resolver *res;
703   int derr;
704
705   *r_res = NULL;
706
707   /* Force a reload if resolv.conf has changed.  */
708   if (resolv_conf_changed_p ())
709     {
710       if (opt_debug)
711         log_debug ("dns: resolv.conf changed - forcing reload\n");
712       libdns_reinit_pending = 1;
713     }
714
715   if (libdns_reinit_pending)
716     {
717       libdns_reinit_pending = 0;
718       libdns_deinit ();
719     }
720
721   err = libdns_init (ctrl);
722   if (err)
723     return err;
724
725   if (!opt_timeout)
726     set_dns_timeout (0);
727
728   res = dns_res_open (libdns.resolv_conf, libdns.hosts, libdns.hints, NULL,
729                       dns_opts (.socks_host     = &libdns.socks_host,
730                                 .socks_user     = tor_socks_user,
731                                 .socks_password = tor_socks_password ),
732                       &derr);
733   if (!res)
734     return libdns_error_to_gpg_error (derr);
735
736   *r_res = res;
737   return 0;
738 }
739 #endif /*USE_LIBDNS*/
740
741
742 #ifdef USE_LIBDNS
743 /* Helper to test whether we need to try again after having switched
744  * the Tor port.  */
745 static int
746 libdns_switch_port_p (gpg_error_t err)
747 {
748   if (tor_mode && gpg_err_code (err) == GPG_ERR_ECONNREFUSED
749       && libdns_tor_port == TOR_PORT)
750     {
751       /* Switch port and try again.  */
752       if (opt_debug)
753         log_debug ("dns: switching from SOCKS port %d to %d\n",
754                    TOR_PORT, TOR_PORT2);
755       libdns_tor_port = TOR_PORT2;
756       libdns_reinit_pending = 1;
757       return 1;
758     }
759   return 0;
760 }
761 #endif /*USE_LIBDNS*/
762
763
764 #ifdef USE_LIBDNS
765 /* Wrapper around dns_res_submit.  */
766 static gpg_error_t
767 libdns_res_submit (struct dns_resolver *res, const char *qname,
768                    enum dns_type qtype, enum dns_class qclass)
769 {
770   return libdns_error_to_gpg_error (dns_res_submit (res, qname, qtype, qclass));
771 }
772 #endif /*USE_LIBDNS*/
773
774
775 #ifdef USE_LIBDNS
776 /* Standard event handling loop.  */
777 gpg_error_t
778 libdns_res_wait (struct dns_resolver *res)
779 {
780   gpg_error_t err;
781
782   while ((err = libdns_error_to_gpg_error (dns_res_check (res)))
783          && gpg_err_code (err) == GPG_ERR_EAGAIN)
784     {
785       if (dns_res_elapsed (res) > opt_timeout)
786         {
787           err = gpg_error (GPG_ERR_DNS_TIMEOUT);
788           break;
789         }
790
791       my_unprotect ();
792       dns_res_poll (res, 1);
793       my_protect ();
794     }
795
796   return err;
797 }
798 #endif /*USE_LIBDNS*/
799
800
801 #ifdef USE_LIBDNS
802 static gpg_error_t
803 resolve_name_libdns (ctrl_t ctrl, const char *name, unsigned short port,
804                      int want_family, int want_socktype,
805                      dns_addrinfo_t *r_dai, char **r_canonname)
806 {
807   gpg_error_t err;
808   dns_addrinfo_t daihead = NULL;
809   dns_addrinfo_t dai;
810   struct dns_resolver *res = NULL;
811   struct dns_addrinfo *ai = NULL;
812   struct addrinfo hints;
813   struct addrinfo *ent;
814   char portstr_[21];
815   char *portstr = NULL;
816   char *namebuf = NULL;
817   int derr;
818
819   *r_dai = NULL;
820   if (r_canonname)
821     *r_canonname = NULL;
822
823   memset (&hints, 0, sizeof hints);
824   hints.ai_family = want_family;
825   hints.ai_socktype = want_socktype;
826   hints.ai_flags = AI_ADDRCONFIG;
827   if (r_canonname)
828     hints.ai_flags |= AI_CANONNAME;
829
830   if (port)
831     {
832       snprintf (portstr_, sizeof portstr_, "%hu", port);
833       portstr = portstr_;
834     }
835
836   err = libdns_res_open (ctrl, &res);
837   if (err)
838     goto leave;
839
840
841   if (is_ip_address (name))
842     {
843       hints.ai_flags |= AI_NUMERICHOST;
844       /* libdns does not grok brackets - remove them.  */
845       if (*name == '[' && name[strlen(name)-1] == ']')
846         {
847           namebuf = xtrymalloc (strlen (name));
848           if (!namebuf)
849             {
850               err = gpg_error_from_syserror ();
851               goto leave;
852             }
853           strcpy (namebuf, name+1);
854           namebuf[strlen (namebuf)-1] = 0;
855           name = namebuf;
856         }
857     }
858
859   ai = dns_ai_open (name, portstr, 0, &hints, res, &derr);
860   if (!ai)
861     {
862       err = libdns_error_to_gpg_error (derr);
863       goto leave;
864     }
865
866   /* Loop over all records.  */
867   for (;;)
868     {
869       err = libdns_error_to_gpg_error (dns_ai_nextent (&ent, ai));
870       if (gpg_err_code (err) == GPG_ERR_ENOENT)
871         {
872           if (daihead)
873             err = 0; /* We got some results, we're good.  */
874           break; /* Ready.  */
875         }
876       if (gpg_err_code (err) == GPG_ERR_EAGAIN)
877         {
878           if (dns_ai_elapsed (ai) > opt_timeout)
879             {
880               err = gpg_error (GPG_ERR_DNS_TIMEOUT);
881               goto leave;
882             }
883
884           my_unprotect ();
885           dns_ai_poll (ai, 1);
886           my_protect ();
887           continue;
888         }
889       if (err)
890         goto leave;
891
892       if (r_canonname && ! *r_canonname && ent && ent->ai_canonname)
893         {
894           *r_canonname = xtrystrdup (ent->ai_canonname);
895           if (!*r_canonname)
896             {
897               err = gpg_error_from_syserror ();
898               goto leave;
899             }
900           /* Libdns appends the root zone part which is problematic
901            * for most other functions - strip it.  */
902           if (**r_canonname && (*r_canonname)[strlen (*r_canonname)-1] == '.')
903             (*r_canonname)[strlen (*r_canonname)-1] = 0;
904         }
905
906       dai = xtrymalloc (sizeof *dai);
907       if (dai == NULL)
908         {
909           err = gpg_error_from_syserror ();
910           goto leave;
911         }
912
913       dai->family = ent->ai_family;
914       dai->socktype = ent->ai_socktype;
915       dai->protocol = ent->ai_protocol;
916       dai->addrlen = ent->ai_addrlen;
917       memcpy (dai->addr, ent->ai_addr, ent->ai_addrlen);
918       dai->next = daihead;
919       daihead = dai;
920
921       xfree (ent);
922   }
923
924  leave:
925   dns_ai_close (ai);
926   dns_res_close (res);
927
928   if (err)
929     {
930       if (r_canonname)
931         {
932           xfree (*r_canonname);
933           *r_canonname = NULL;
934         }
935       free_dns_addrinfo (daihead);
936     }
937   else
938     *r_dai = daihead;
939
940   xfree (namebuf);
941   return err;
942 }
943 #endif /*USE_LIBDNS*/
944
945
946 /* Resolve a name using the standard system function.  */
947 static gpg_error_t
948 resolve_name_standard (ctrl_t ctrl, const char *name, unsigned short port,
949                        int want_family, int want_socktype,
950                        dns_addrinfo_t *r_dai, char **r_canonname)
951 {
952   gpg_error_t err = 0;
953   dns_addrinfo_t daihead = NULL;
954   dns_addrinfo_t dai;
955   struct addrinfo *aibuf = NULL;
956   struct addrinfo hints, *ai;
957   char portstr[21];
958   int ret;
959
960   *r_dai = NULL;
961   if (r_canonname)
962     *r_canonname = NULL;
963
964   memset (&hints, 0, sizeof hints);
965   hints.ai_family = want_family;
966   hints.ai_socktype = want_socktype;
967   hints.ai_flags = AI_ADDRCONFIG;
968   if (r_canonname)
969     hints.ai_flags |= AI_CANONNAME;
970   if (is_ip_address (name))
971     hints.ai_flags |= AI_NUMERICHOST;
972
973   if (port)
974     snprintf (portstr, sizeof portstr, "%hu", port);
975   else
976     *portstr = 0;
977
978   /* We can't use the AI_IDN flag because that does the conversion
979      using the current locale.  However, GnuPG always used UTF-8.  To
980      support IDN we would need to make use of the libidn API.  */
981   ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
982   if (ret)
983     {
984       aibuf = NULL;
985       err = map_eai_to_gpg_error (ret);
986       if (gpg_err_code (err) == GPG_ERR_NO_NAME)
987         {
988           /* There seems to be a bug in the glibc getaddrinfo function
989              if the CNAME points to a long list of A and AAAA records
990              in which case the function return NO_NAME.  Let's do the
991              CNAME redirection again.  */
992           char *cname;
993
994           if (get_dns_cname (ctrl, name, &cname))
995             goto leave; /* Still no success.  */
996
997           ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
998           xfree (cname);
999           if (ret)
1000             {
1001               aibuf = NULL;
1002               err = map_eai_to_gpg_error (ret);
1003               goto leave;
1004             }
1005           err = 0; /* Yep, now it worked.  */
1006         }
1007       else
1008         goto leave;
1009     }
1010
1011   if (r_canonname && aibuf && aibuf->ai_canonname)
1012     {
1013       *r_canonname = xtrystrdup (aibuf->ai_canonname);
1014       if (!*r_canonname)
1015         {
1016           err = gpg_error_from_syserror ();
1017           goto leave;
1018         }
1019     }
1020
1021   for (ai = aibuf; ai; ai = ai->ai_next)
1022     {
1023       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
1024         continue;
1025       if (opt_disable_ipv4 && ai->ai_family == AF_INET)
1026         continue;
1027       if (opt_disable_ipv6 && ai->ai_family == AF_INET6)
1028         continue;
1029
1030       dai = xtrymalloc (sizeof *dai);
1031       dai->family = ai->ai_family;
1032       dai->socktype = ai->ai_socktype;
1033       dai->protocol = ai->ai_protocol;
1034       dai->addrlen = ai->ai_addrlen;
1035       memcpy (dai->addr, ai->ai_addr, ai->ai_addrlen);
1036       dai->next = daihead;
1037       daihead = dai;
1038     }
1039
1040  leave:
1041   if (aibuf)
1042     freeaddrinfo (aibuf);
1043   if (err)
1044     {
1045       if (r_canonname)
1046         {
1047           xfree (*r_canonname);
1048           *r_canonname = NULL;
1049         }
1050       free_dns_addrinfo (daihead);
1051     }
1052   else
1053     *r_dai = daihead;
1054   return err;
1055 }
1056
1057
1058 /* This a wrapper around getaddrinfo with slightly different semantics.
1059    NAME is the name to resolve.
1060    PORT is the requested port or 0.
1061    WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
1062    WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
1063
1064    On success the result is stored in a linked list with the head
1065    stored at the address R_AI; the caller must call gpg_addrinfo_free
1066    on this.  If R_CANONNAME is not NULL the official name of the host
1067    is stored there as a malloced string; if that name is not available
1068    NULL is stored.  */
1069 gpg_error_t
1070 resolve_dns_name (ctrl_t ctrl, const char *name, unsigned short port,
1071                   int want_family, int want_socktype,
1072                   dns_addrinfo_t *r_ai, char **r_canonname)
1073 {
1074   gpg_error_t err;
1075
1076 #ifdef USE_LIBDNS
1077   if (!standard_resolver)
1078     {
1079       err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
1080                                   r_ai, r_canonname);
1081       if (err && libdns_switch_port_p (err))
1082         err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
1083                                    r_ai, r_canonname);
1084     }
1085   else
1086 #endif /*USE_LIBDNS*/
1087     err = resolve_name_standard (ctrl, name, port, want_family, want_socktype,
1088                                  r_ai, r_canonname);
1089   if (opt_debug)
1090     log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
1091   return err;
1092 }
1093
1094
1095 #ifdef USE_LIBDNS
1096 /* Resolve an address using libdns.  */
1097 static gpg_error_t
1098 resolve_addr_libdns (ctrl_t ctrl,
1099                      const struct sockaddr_storage *addr, int addrlen,
1100                      unsigned int flags, char **r_name)
1101 {
1102   gpg_error_t err;
1103   char host[DNS_D_MAXNAME + 1];
1104   struct dns_resolver *res = NULL;
1105   struct dns_packet *ans = NULL;
1106   struct dns_ptr ptr;
1107   int derr;
1108
1109   *r_name = NULL;
1110
1111   /* First we turn ADDR into a DNS name (with ".arpa" suffix).  */
1112   err = 0;
1113   if (addr->ss_family == AF_INET6)
1114     {
1115       const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)addr;
1116       if (!dns_aaaa_arpa (host, sizeof host, (void*)&a6->sin6_addr))
1117         err = gpg_error (GPG_ERR_INV_OBJ);
1118     }
1119   else if (addr->ss_family == AF_INET)
1120     {
1121       const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
1122       if (!dns_a_arpa (host, sizeof host, (void*)&a4->sin_addr))
1123         err = gpg_error (GPG_ERR_INV_OBJ);
1124     }
1125   else
1126     err = gpg_error (GPG_ERR_EAFNOSUPPORT);
1127   if (err)
1128     goto leave;
1129
1130
1131   err = libdns_res_open (ctrl, &res);
1132   if (err)
1133     goto leave;
1134
1135   err = libdns_res_submit (res, host, DNS_T_PTR, DNS_C_IN);
1136   if (err)
1137     goto leave;
1138
1139   err = libdns_res_wait (res);
1140   if (err)
1141     goto leave;
1142
1143   ans = dns_res_fetch (res, &derr);
1144   if (!ans)
1145     {
1146       err = libdns_error_to_gpg_error (derr);
1147       goto leave;
1148     }
1149
1150   /* Check the rcode.  */
1151   switch (dns_p_rcode (ans))
1152     {
1153     case DNS_RC_NOERROR:
1154       break;
1155     case DNS_RC_NXDOMAIN:
1156       err = gpg_error (GPG_ERR_NO_NAME);
1157       break;
1158     default:
1159       err = GPG_ERR_SERVER_FAILED;
1160       goto leave;
1161     }
1162
1163   /* Parse the result.  */
1164   if (!err)
1165     {
1166       struct dns_rr rr;
1167       struct dns_rr_i rri;
1168
1169       memset (&rri, 0, sizeof rri);
1170       dns_rr_i_init (&rri, ans);
1171       rri.section = DNS_S_ALL & ~DNS_S_QD;
1172       rri.name    = host;
1173       rri.type    = DNS_T_PTR;
1174
1175       if (!dns_rr_grep (&rr, 1, &rri, ans, &derr))
1176         {
1177           err = gpg_error (GPG_ERR_NOT_FOUND);
1178           goto leave;
1179         }
1180
1181       err = libdns_error_to_gpg_error (dns_ptr_parse (&ptr, &rr, ans));
1182       if (err)
1183         goto leave;
1184
1185       /* Copy result.  */
1186       *r_name = xtrystrdup (ptr.host);
1187       if (!*r_name)
1188         {
1189           err = gpg_error_from_syserror ();
1190           goto leave;
1191         }
1192       /* Libdns appends the root zone part which is problematic
1193        * for most other functions - strip it.  */
1194       if (**r_name && (*r_name)[strlen (*r_name)-1] == '.')
1195         (*r_name)[strlen (*r_name)-1] = 0;
1196     }
1197   else /* GPG_ERR_NO_NAME */
1198     {
1199       char *buffer, *p;
1200       int buflen;
1201       int ec;
1202
1203       buffer = ptr.host;
1204       buflen = sizeof ptr.host;
1205
1206       p = buffer;
1207       if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
1208         {
1209           *p++ = '[';
1210           buflen -= 2;
1211         }
1212       ec = getnameinfo ((const struct sockaddr *)addr,
1213                         addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
1214       if (ec)
1215         {
1216           err = map_eai_to_gpg_error (ec);
1217           goto leave;
1218         }
1219       if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
1220         strcat (buffer, "]");
1221     }
1222
1223  leave:
1224   dns_free (ans);
1225   dns_res_close (res);
1226   return err;
1227 }
1228 #endif /*USE_LIBDNS*/
1229
1230
1231 /* Resolve an address using the standard system function.  */
1232 static gpg_error_t
1233 resolve_addr_standard (const struct sockaddr_storage *addr, int addrlen,
1234                        unsigned int flags, char **r_name)
1235 {
1236   gpg_error_t err;
1237   int ec;
1238   char *buffer, *p;
1239   int buflen;
1240
1241   *r_name = NULL;
1242
1243   buflen = NI_MAXHOST;
1244   buffer = xtrymalloc (buflen + 2 + 1);
1245   if (!buffer)
1246     return gpg_error_from_syserror ();
1247
1248   if ((flags & DNS_NUMERICHOST) || tor_mode)
1249     ec = EAI_NONAME;
1250   else
1251     ec = getnameinfo ((const struct sockaddr *)addr,
1252                       addrlen, buffer, buflen, NULL, 0, NI_NAMEREQD);
1253
1254   if (!ec && *buffer == '[')
1255     ec = EAI_FAIL;  /* A name may never start with a bracket.  */
1256   else if (ec == EAI_NONAME)
1257     {
1258       p = buffer;
1259       if (addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
1260         {
1261           *p++ = '[';
1262           buflen -= 2;
1263         }
1264       ec = getnameinfo ((const struct sockaddr *)addr,
1265                         addrlen, p, buflen, NULL, 0, NI_NUMERICHOST);
1266       if (!ec && addr->ss_family == AF_INET6 && (flags & DNS_WITHBRACKET))
1267         strcat (buffer, "]");
1268     }
1269
1270   if (ec)
1271     err = map_eai_to_gpg_error (ec);
1272   else
1273     {
1274       p = xtryrealloc (buffer, strlen (buffer)+1);
1275       if (!p)
1276         err = gpg_error_from_syserror ();
1277       else
1278         {
1279           buffer = p;
1280           err = 0;
1281         }
1282     }
1283
1284   if (err)
1285     xfree (buffer);
1286   else
1287     *r_name = buffer;
1288
1289   return err;
1290 }
1291
1292
1293 /* A wrapper around getnameinfo.  */
1294 gpg_error_t
1295 resolve_dns_addr (ctrl_t ctrl,
1296                   const struct sockaddr_storage *addr, int addrlen,
1297                   unsigned int flags, char **r_name)
1298 {
1299   gpg_error_t err;
1300
1301 #ifdef USE_LIBDNS
1302   /* Note that we divert to the standard resolver for NUMERICHOST.  */
1303   if (!standard_resolver && !(flags & DNS_NUMERICHOST))
1304     {
1305       err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
1306       if (err && libdns_switch_port_p (err))
1307         err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
1308     }
1309   else
1310 #endif /*USE_LIBDNS*/
1311     err = resolve_addr_standard (addr, addrlen, flags, r_name);
1312
1313   if (opt_debug)
1314     log_debug ("dns: resolve_dns_addr(): %s\n", gpg_strerror (err));
1315   return err;
1316 }
1317
1318
1319 /* Check whether NAME is an IP address.  Returns a true if it is
1320  * either an IPv6 or a IPv4 numerical address.  The actual return
1321  * values can also be used to identify whether it is v4 or v6: The
1322  * true value will surprisingly be 4 for IPv4 and 6 for IPv6.  */
1323 int
1324 is_ip_address (const char *name)
1325 {
1326   const char *s;
1327   int ndots, dblcol, n;
1328
1329   if (*name == '[')
1330     return 6; /* yes: A legal DNS name may not contain this character;
1331                  this must be bracketed v6 address.  */
1332   if (*name == '.')
1333     return 0; /* No.  A leading dot is not a valid IP address.  */
1334
1335   /* Check whether this is a v6 address.  */
1336   ndots = n = dblcol = 0;
1337   for (s=name; *s; s++)
1338     {
1339       if (*s == ':')
1340         {
1341           ndots++;
1342           if (s[1] == ':')
1343             {
1344               ndots++;
1345               if (dblcol)
1346                 return 0; /* No: Only one "::" allowed.  */
1347               dblcol++;
1348               if (s[1])
1349                 s++;
1350             }
1351           n = 0;
1352         }
1353       else if (*s == '.')
1354         goto legacy;
1355       else if (!strchr ("0123456789abcdefABCDEF", *s))
1356         return 0; /* No: Not a hex digit.  */
1357       else if (++n > 4)
1358         return 0; /* To many digits in a group.  */
1359     }
1360   if (ndots > 7)
1361     return 0; /* No: Too many colons.  */
1362   else if (ndots > 1)
1363     return 6; /* Yes: At least 2 colons indicate an v6 address.  */
1364
1365  legacy:
1366   /* Check whether it is legacy IP address.  */
1367   ndots = n = 0;
1368   for (s=name; *s; s++)
1369     {
1370       if (*s == '.')
1371         {
1372           if (s[1] == '.')
1373             return 0; /* No:  Double dot. */
1374           if (atoi (s+1) > 255)
1375             return 0; /* No:  Ipv4 byte value too large.  */
1376           ndots++;
1377           n = 0;
1378         }
1379       else if (!strchr ("0123456789", *s))
1380         return 0; /* No: Not a digit.  */
1381       else if (++n > 3)
1382         return 0; /* No: More than 3 digits.  */
1383     }
1384   return (ndots == 3)? 4 : 0;
1385 }
1386
1387
1388 /* Return true if NAME is an onion address.  */
1389 int
1390 is_onion_address (const char *name)
1391 {
1392   size_t len;
1393
1394   len = name? strlen (name) : 0;
1395   if (len < 8 || strcmp (name + len - 6, ".onion"))
1396     return 0;
1397   /* Note that we require at least 2 characters before the suffix.  */
1398   return 1;  /* Yes.  */
1399 }
1400
1401
1402 /* libdns version of get_dns_cert.  */
1403 #ifdef USE_LIBDNS
1404 static gpg_error_t
1405 get_dns_cert_libdns (ctrl_t ctrl, const char *name, int want_certtype,
1406                      void **r_key, size_t *r_keylen,
1407                      unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
1408 {
1409   gpg_error_t err;
1410   struct dns_resolver *res = NULL;
1411   struct dns_packet *ans = NULL;
1412   struct dns_rr rr;
1413   struct dns_rr_i rri;
1414   char host[DNS_D_MAXNAME + 1];
1415   int derr;
1416   int qtype;
1417
1418   /* Get the query type from WANT_CERTTYPE (which in general indicates
1419    * the subtype we want). */
1420   qtype = (want_certtype < DNS_CERTTYPE_RRBASE
1421            ? T_CERT
1422            : (want_certtype - DNS_CERTTYPE_RRBASE));
1423
1424
1425   err = libdns_res_open (ctrl, &res);
1426   if (err)
1427     goto leave;
1428
1429   if (dns_d_anchor (host, sizeof host, name, strlen (name)) >= sizeof host)
1430     {
1431       err = gpg_error (GPG_ERR_ENAMETOOLONG);
1432       goto leave;
1433     }
1434
1435   err = libdns_res_submit (res, name, qtype, DNS_C_IN);
1436   if (err)
1437     goto leave;
1438
1439   err = libdns_res_wait (res);
1440   if (err)
1441     goto leave;
1442
1443   ans = dns_res_fetch (res, &derr);
1444   if (!ans)
1445     {
1446       err = libdns_error_to_gpg_error (derr);
1447       goto leave;
1448     }
1449
1450   /* Check the rcode.  */
1451   switch (dns_p_rcode (ans))
1452     {
1453     case DNS_RC_NOERROR: break;
1454     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
1455     default: err = GPG_ERR_SERVER_FAILED; break;
1456     }
1457   if (err)
1458     goto leave;
1459
1460   memset (&rri, 0, sizeof rri);
1461   dns_rr_i_init (&rri, ans);
1462   rri.section = DNS_S_ALL & ~DNS_S_QD;
1463   rri.name    = host;
1464   rri.type    = qtype;
1465
1466   err = gpg_error (GPG_ERR_NOT_FOUND);
1467   while (dns_rr_grep (&rr, 1, &rri, ans, &derr))
1468     {
1469       unsigned char *rp  = ans->data + rr.rd.p;
1470       unsigned short len = rr.rd.len;
1471       u16 subtype;
1472
1473        if (!len)
1474         {
1475           /* Definitely too short - skip.  */
1476         }
1477       else if (want_certtype >= DNS_CERTTYPE_RRBASE
1478           && rr.type == (want_certtype - DNS_CERTTYPE_RRBASE)
1479           && r_key)
1480         {
1481           *r_key = xtrymalloc (len);
1482           if (!*r_key)
1483             err = gpg_error_from_syserror ();
1484           else
1485             {
1486               memcpy (*r_key, rp, len);
1487               *r_keylen = len;
1488               err = 0;
1489             }
1490           goto leave;
1491         }
1492       else if (want_certtype >= DNS_CERTTYPE_RRBASE)
1493         {
1494           /* We did not found the requested RR - skip. */
1495         }
1496       else if (rr.type == T_CERT && len > 5)
1497         {
1498           /* We got a CERT type.   */
1499           subtype = buf16_to_u16 (rp);
1500           rp += 2; len -= 2;
1501
1502           /* Skip the CERT key tag and algo which we don't need.  */
1503           rp += 3; len -= 3;
1504
1505           if (want_certtype && want_certtype != subtype)
1506             ; /* Not the requested subtype - skip.  */
1507           else if (subtype == DNS_CERTTYPE_PGP && len && r_key && r_keylen)
1508             {
1509               /* PGP subtype */
1510               *r_key = xtrymalloc (len);
1511               if (!*r_key)
1512                 err = gpg_error_from_syserror ();
1513               else
1514                 {
1515                   memcpy (*r_key, rp, len);
1516                   *r_keylen = len;
1517                   err = 0;
1518                 }
1519               goto leave;
1520             }
1521           else if (subtype == DNS_CERTTYPE_IPGP
1522                    && len && len < 1023 && len >= rp[0] + 1)
1523             {
1524               /* IPGP type */
1525               *r_fprlen = rp[0];
1526               if (*r_fprlen)
1527                 {
1528                   *r_fpr = xtrymalloc (*r_fprlen);
1529                   if (!*r_fpr)
1530                     {
1531                       err = gpg_error_from_syserror ();
1532                       goto leave;
1533                     }
1534                   memcpy (*r_fpr, rp+1, *r_fprlen);
1535                 }
1536               else
1537                 *r_fpr = NULL;
1538
1539               if (len > *r_fprlen + 1)
1540                 {
1541                   *r_url = xtrymalloc (len - (*r_fprlen + 1) + 1);
1542                   if (!*r_url)
1543                     {
1544                       err = gpg_error_from_syserror ();
1545                       xfree (*r_fpr);
1546                       *r_fpr = NULL;
1547                       goto leave;
1548                     }
1549                   memcpy (*r_url, rp + *r_fprlen + 1, len - (*r_fprlen + 1));
1550                   (*r_url)[len - (*r_fprlen + 1)] = 0;
1551                 }
1552               else
1553                 *r_url = NULL;
1554
1555               err = 0;
1556               goto leave;
1557             }
1558           else
1559             {
1560               /* Unknown subtype or record too short - skip.  */
1561             }
1562         }
1563       else
1564         {
1565           /* Not a requested type - skip.  */
1566         }
1567     }
1568
1569  leave:
1570   dns_free (ans);
1571   dns_res_close (res);
1572   return err;
1573 }
1574 #endif /*USE_LIBDNS*/
1575
1576
1577 /* Standard resolver version of get_dns_cert.  */
1578 static gpg_error_t
1579 get_dns_cert_standard (const char *name, int want_certtype,
1580                        void **r_key, size_t *r_keylen,
1581                        unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
1582 {
1583 #ifdef HAVE_SYSTEM_RESOLVER
1584   gpg_error_t err;
1585   unsigned char *answer;
1586   int r;
1587   u16 count;
1588
1589   /* Allocate a 64k buffer which is the limit for an DNS response.  */
1590   answer = xtrymalloc (65536);
1591   if (!answer)
1592     return gpg_error_from_syserror ();
1593
1594   err = gpg_error (GPG_ERR_NOT_FOUND);
1595   r = res_query (name, C_IN,
1596                  (want_certtype < DNS_CERTTYPE_RRBASE
1597                   ? T_CERT
1598                   : (want_certtype - DNS_CERTTYPE_RRBASE)),
1599                  answer, 65536);
1600   /* Not too big, not too small, no errors and at least 1 answer. */
1601   if (r >= sizeof (HEADER) && r <= 65536
1602       && (((HEADER *)(void *) answer)->rcode) == NOERROR
1603       && (count = ntohs (((HEADER *)(void *) answer)->ancount)))
1604     {
1605       int rc;
1606       unsigned char *pt, *emsg;
1607
1608       emsg = &answer[r];
1609
1610       pt = &answer[sizeof (HEADER)];
1611
1612       /* Skip over the query */
1613
1614       rc = dn_skipname (pt, emsg);
1615       if (rc == -1)
1616         {
1617           err = gpg_error (GPG_ERR_INV_OBJ);
1618           goto leave;
1619         }
1620       pt += rc + QFIXEDSZ;
1621
1622       /* There are several possible response types for a CERT request.
1623          We're interested in the PGP (a key) and IPGP (a URI) types.
1624          Skip all others.  TODO: A key is better than a URI since
1625          we've gone through all this bother to fetch it, so favor that
1626          if we have both PGP and IPGP? */
1627
1628       while (count-- > 0 && pt < emsg)
1629         {
1630           u16 type, class, dlen, ctype;
1631
1632           rc = dn_skipname (pt, emsg);  /* the name we just queried for */
1633           if (rc == -1)
1634             {
1635               err = gpg_error (GPG_ERR_INV_OBJ);
1636               goto leave;
1637             }
1638
1639           pt += rc;
1640
1641           /* Truncated message? 15 bytes takes us to the point where
1642              we start looking at the ctype. */
1643           if ((emsg - pt) < 15)
1644             break;
1645
1646           type = buf16_to_u16 (pt);
1647           pt += 2;
1648
1649           class = buf16_to_u16 (pt);
1650           pt += 2;
1651
1652           if (class != C_IN)
1653             break;
1654
1655           /* ttl */
1656           pt += 4;
1657
1658           /* data length */
1659           dlen = buf16_to_u16 (pt);
1660           pt += 2;
1661
1662           /* Check the type and parse.  */
1663           if (want_certtype >= DNS_CERTTYPE_RRBASE
1664               && type == (want_certtype - DNS_CERTTYPE_RRBASE)
1665               && r_key)
1666             {
1667               *r_key = xtrymalloc (dlen);
1668               if (!*r_key)
1669                 err = gpg_error_from_syserror ();
1670               else
1671                 {
1672                   memcpy (*r_key, pt, dlen);
1673                   *r_keylen = dlen;
1674                   err = 0;
1675                 }
1676               goto leave;
1677             }
1678           else if (want_certtype >= DNS_CERTTYPE_RRBASE)
1679             {
1680               /* We did not found the requested RR.  */
1681               pt += dlen;
1682             }
1683           else if (type == T_CERT)
1684             {
1685               /* We got a CERT type.   */
1686               ctype = buf16_to_u16 (pt);
1687               pt += 2;
1688
1689               /* Skip the CERT key tag and algo which we don't need. */
1690               pt += 3;
1691
1692               dlen -= 5;
1693
1694               /* 15 bytes takes us to here */
1695               if (want_certtype && want_certtype != ctype)
1696                 ; /* Not of the requested certtype.  */
1697               else if (ctype == DNS_CERTTYPE_PGP && dlen && r_key && r_keylen)
1698                 {
1699                   /* PGP type */
1700                   *r_key = xtrymalloc (dlen);
1701                   if (!*r_key)
1702                     err = gpg_error_from_syserror ();
1703                   else
1704                     {
1705                       memcpy (*r_key, pt, dlen);
1706                       *r_keylen = dlen;
1707                       err = 0;
1708                     }
1709                   goto leave;
1710                 }
1711               else if (ctype == DNS_CERTTYPE_IPGP
1712                        && dlen && dlen < 1023 && dlen >= pt[0] + 1)
1713                 {
1714                   /* IPGP type */
1715                   *r_fprlen = pt[0];
1716                   if (*r_fprlen)
1717                     {
1718                       *r_fpr = xtrymalloc (*r_fprlen);
1719                       if (!*r_fpr)
1720                         {
1721                           err = gpg_error_from_syserror ();
1722                           goto leave;
1723                         }
1724                       memcpy (*r_fpr, &pt[1], *r_fprlen);
1725                     }
1726                   else
1727                     *r_fpr = NULL;
1728
1729                   if (dlen > *r_fprlen + 1)
1730                     {
1731                       *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1);
1732                       if (!*r_url)
1733                         {
1734                           err = gpg_error_from_syserror ();
1735                           xfree (*r_fpr);
1736                           *r_fpr = NULL;
1737                           goto leave;
1738                         }
1739                       memcpy (*r_url, &pt[*r_fprlen + 1],
1740                               dlen - (*r_fprlen + 1));
1741                       (*r_url)[dlen - (*r_fprlen + 1)] = '\0';
1742                     }
1743                   else
1744                     *r_url = NULL;
1745
1746                   err = 0;
1747                   goto leave;
1748                 }
1749
1750               /* No subtype matches, so continue with the next answer. */
1751               pt += dlen;
1752             }
1753           else
1754             {
1755               /* Not a requested type - might be a CNAME. Try next item.  */
1756               pt += dlen;
1757             }
1758         }
1759     }
1760
1761  leave:
1762   xfree (answer);
1763   return err;
1764
1765 #else /*!HAVE_SYSTEM_RESOLVER*/
1766
1767   (void)name;
1768   (void)want_certtype;
1769   (void)r_key;
1770   (void)r_keylen;
1771   (void)r_fpr;
1772   (void)r_fprlen;
1773   (void)r_url;
1774   return gpg_error (GPG_ERR_NOT_SUPPORTED);
1775
1776 #endif /*!HAVE_SYSTEM_RESOLVER*/
1777 }
1778
1779
1780 /* Returns 0 on success or an error code.  If a PGP CERT record was
1781    found, the malloced data is returned at (R_KEY, R_KEYLEN) and
1782    the other return parameters are set to NULL/0.  If an IPGP CERT
1783    record was found the fingerprint is stored as an allocated block at
1784    R_FPR and its length at R_FPRLEN; an URL is allocated as a
1785    string and returned at R_URL.  If WANT_CERTTYPE is 0 this function
1786    returns the first CERT found with a supported type; it is expected
1787    that only one CERT record is used.  If WANT_CERTTYPE is one of the
1788    supported certtypes only records with this certtype are considered
1789    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
1790 gpg_error_t
1791 get_dns_cert (ctrl_t ctrl, const char *name, int want_certtype,
1792               void **r_key, size_t *r_keylen,
1793               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
1794 {
1795   gpg_error_t err;
1796
1797   if (r_key)
1798     *r_key = NULL;
1799   if (r_keylen)
1800     *r_keylen = 0;
1801   *r_fpr = NULL;
1802   *r_fprlen = 0;
1803   *r_url = NULL;
1804
1805 #ifdef USE_LIBDNS
1806   if (!standard_resolver)
1807     {
1808       err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
1809                                  r_fpr, r_fprlen, r_url);
1810       if (err && libdns_switch_port_p (err))
1811         err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
1812                                    r_fpr, r_fprlen, r_url);
1813     }
1814   else
1815 #endif /*USE_LIBDNS*/
1816     err = get_dns_cert_standard (name, want_certtype, r_key, r_keylen,
1817                                  r_fpr, r_fprlen, r_url);
1818
1819   if (opt_debug)
1820     log_debug ("dns: get_dns_cert(%s): %s\n", name, gpg_strerror (err));
1821   return err;
1822 }
1823
1824
1825 static int
1826 priosort(const void *a,const void *b)
1827 {
1828   const struct srventry *sa=a,*sb=b;
1829   if(sa->priority>sb->priority)
1830     return 1;
1831   else if(sa->priority<sb->priority)
1832     return -1;
1833   else
1834     return 0;
1835 }
1836
1837
1838 /* Libdns based helper for getsrv.  Note that it is expected that NULL
1839  * is stored at the address of LIST and 0 is stored at the address of
1840  * R_COUNT.  */
1841 #ifdef USE_LIBDNS
1842 static gpg_error_t
1843 getsrv_libdns (ctrl_t ctrl,
1844                const char *name, struct srventry **list, unsigned int *r_count)
1845 {
1846   gpg_error_t err;
1847   struct dns_resolver *res = NULL;
1848   struct dns_packet *ans = NULL;
1849   struct dns_rr rr;
1850   struct dns_rr_i rri;
1851   char host[DNS_D_MAXNAME + 1];
1852   int derr;
1853   unsigned int srvcount = 0;
1854
1855   err = libdns_res_open (ctrl, &res);
1856   if (err)
1857     goto leave;
1858
1859   if (dns_d_anchor (host, sizeof host, name, strlen (name)) >= sizeof host)
1860     {
1861       err = gpg_error (GPG_ERR_ENAMETOOLONG);
1862       goto leave;
1863     }
1864
1865   err = libdns_res_submit (res, name, DNS_T_SRV, DNS_C_IN);
1866   if (err)
1867     goto leave;
1868
1869   err = libdns_res_wait (res);
1870   if (err)
1871     goto leave;
1872
1873   ans = dns_res_fetch (res, &derr);
1874   if (!ans)
1875     {
1876       err = libdns_error_to_gpg_error (derr);
1877       goto leave;
1878     }
1879
1880   /* Check the rcode.  */
1881   switch (dns_p_rcode (ans))
1882     {
1883     case DNS_RC_NOERROR: break;
1884     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
1885     default: err = GPG_ERR_SERVER_FAILED; break;
1886     }
1887   if (err)
1888     goto leave;
1889
1890   memset (&rri, 0, sizeof rri);
1891   dns_rr_i_init (&rri, ans);
1892   rri.section = DNS_S_ALL & ~DNS_S_QD;
1893   rri.name        = host;
1894   rri.type        = DNS_T_SRV;
1895
1896   while (dns_rr_grep (&rr, 1, &rri, ans, &derr))
1897     {
1898       struct dns_srv dsrv;
1899       struct srventry *srv;
1900       struct srventry *newlist;
1901
1902       err = libdns_error_to_gpg_error (dns_srv_parse(&dsrv, &rr, ans));
1903       if (err)
1904         goto leave;
1905
1906       newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
1907       if (!newlist)
1908         {
1909           err = gpg_error_from_syserror ();
1910           goto leave;
1911         }
1912       *list = newlist;
1913       memset (&(*list)[srvcount], 0, sizeof(struct srventry));
1914       srv = &(*list)[srvcount];
1915       srvcount++;
1916       srv->priority = dsrv.priority;
1917       srv->weight   = dsrv.weight;
1918       srv->port     = dsrv.port;
1919       mem2str (srv->target, dsrv.target, sizeof srv->target);
1920       /* Libdns appends the root zone part which is problematic for
1921        * most other functions - strip it.  */
1922       if (*srv->target && (srv->target)[strlen (srv->target)-1] == '.')
1923         (srv->target)[strlen (srv->target)-1] = 0;
1924     }
1925
1926   *r_count = srvcount;
1927
1928  leave:
1929   if (err)
1930     {
1931       xfree (*list);
1932       *list = NULL;
1933     }
1934   dns_free (ans);
1935   dns_res_close (res);
1936   return err;
1937 }
1938 #endif /*USE_LIBDNS*/
1939
1940
1941 /* Standard resolver based helper for getsrv.  Note that it is
1942  * expected that NULL is stored at the address of LIST and 0 is stored
1943  * at the address of R_COUNT.  */
1944 static gpg_error_t
1945 getsrv_standard (const char *name,
1946                  struct srventry **list, unsigned int *r_count)
1947 {
1948 #ifdef HAVE_SYSTEM_RESOLVER
1949   union {
1950     unsigned char ans[2048];
1951     HEADER header[1];
1952   } res;
1953   unsigned char *answer = res.ans;
1954   HEADER *header = res.header;
1955   unsigned char *pt, *emsg;
1956   int r, rc;
1957   u16 dlen;
1958   unsigned int srvcount = 0;
1959   u16 count;
1960
1961   /* Do not allow a query using the standard resolver in Tor mode.  */
1962   if (tor_mode)
1963     return gpg_error (GPG_ERR_NOT_ENABLED);
1964
1965   my_unprotect ();
1966   r = res_query (name, C_IN, T_SRV, answer, sizeof res.ans);
1967   my_protect ();
1968   if (r < 0)
1969     return get_h_errno_as_gpg_error ();
1970   if (r < sizeof (HEADER))
1971     return gpg_error (GPG_ERR_SERVER_FAILED);
1972   if (r > sizeof res.ans)
1973     return gpg_error (GPG_ERR_SYSTEM_BUG);
1974   if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
1975     return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
1976
1977   emsg = &answer[r];
1978   pt = &answer[sizeof(HEADER)];
1979
1980   /* Skip over the query */
1981   rc = dn_skipname (pt, emsg);
1982   if (rc == -1)
1983     goto fail;
1984
1985   pt += rc + QFIXEDSZ;
1986
1987   while (count-- > 0 && pt < emsg)
1988     {
1989       struct srventry *srv;
1990       u16 type, class;
1991       struct srventry *newlist;
1992
1993       newlist = xtryrealloc (*list, (srvcount+1)*sizeof(struct srventry));
1994       if (!newlist)
1995         goto fail;
1996       *list = newlist;
1997       memset (&(*list)[srvcount], 0, sizeof(struct srventry));
1998       srv = &(*list)[srvcount];
1999       srvcount++;
2000
2001       rc = dn_skipname (pt, emsg); /* The name we just queried for.  */
2002       if (rc == -1)
2003         goto fail;
2004       pt += rc;
2005
2006       /* Truncated message? */
2007       if ((emsg-pt) < 16)
2008         goto fail;
2009
2010       type = buf16_to_u16 (pt);
2011       pt += 2;
2012       /* We asked for SRV and got something else !? */
2013       if (type != T_SRV)
2014         goto fail;
2015
2016       class = buf16_to_u16 (pt);
2017       pt += 2;
2018       /* We asked for IN and got something else !? */
2019       if (class != C_IN)
2020         goto fail;
2021
2022       pt += 4; /* ttl */
2023       dlen = buf16_to_u16 (pt);
2024       pt += 2;
2025
2026       srv->priority = buf16_to_ushort (pt);
2027       pt += 2;
2028       srv->weight = buf16_to_ushort (pt);
2029       pt += 2;
2030       srv->port = buf16_to_ushort (pt);
2031       pt += 2;
2032
2033       /* Get the name.  2782 doesn't allow name compression, but
2034        * dn_expand still works to pull the name out of the packet. */
2035       rc = dn_expand (answer, emsg, pt, srv->target, sizeof srv->target);
2036       if (rc == 1 && srv->target[0] == 0) /* "." */
2037         {
2038           xfree(*list);
2039           *list = NULL;
2040           return 0;
2041         }
2042       if (rc == -1)
2043         goto fail;
2044       pt += rc;
2045       /* Corrupt packet? */
2046       if (dlen != rc+6)
2047         goto fail;
2048     }
2049
2050   *r_count = srvcount;
2051   return 0;
2052
2053  fail:
2054   xfree (*list);
2055   *list = NULL;
2056   return gpg_error (GPG_ERR_GENERAL);
2057
2058 #else /*!HAVE_SYSTEM_RESOLVER*/
2059
2060   (void)name;
2061   (void)list;
2062   (void)r_count;
2063   return gpg_error (GPG_ERR_NOT_SUPPORTED);
2064
2065 #endif /*!HAVE_SYSTEM_RESOLVER*/
2066 }
2067
2068
2069 /* Query a SRV record for SERVICE and PROTO for NAME.  If SERVICE is
2070  * NULL, NAME is expected to contain the full query name.  Note that
2071  * we do not return NONAME but simply store 0 at R_COUNT.  On error an
2072  * error code is returned and 0 stored at R_COUNT.  */
2073 gpg_error_t
2074 get_dns_srv (ctrl_t ctrl,
2075              const char *name, const char *service, const char *proto,
2076              struct srventry **list, unsigned int *r_count)
2077 {
2078   gpg_error_t err;
2079   char *namebuffer = NULL;
2080   unsigned int srvcount;
2081   int i;
2082
2083   *list = NULL;
2084   *r_count = 0;
2085   srvcount = 0;
2086
2087   /* If SERVICE is given construct the query from it and PROTO.  */
2088   if (service)
2089     {
2090       namebuffer = xtryasprintf ("_%s._%s.%s",
2091                                  service, proto? proto:"tcp", name);
2092       if (!namebuffer)
2093         {
2094           err = gpg_error_from_syserror ();
2095           goto leave;
2096         }
2097       name = namebuffer;
2098     }
2099
2100
2101 #ifdef USE_LIBDNS
2102   if (!standard_resolver)
2103     {
2104       err = getsrv_libdns (ctrl, name, list, &srvcount);
2105       if (err && libdns_switch_port_p (err))
2106         err = getsrv_libdns (ctrl, name, list, &srvcount);
2107     }
2108   else
2109 #endif /*USE_LIBDNS*/
2110     err = getsrv_standard (name, list, &srvcount);
2111
2112   if (err)
2113     {
2114       if (gpg_err_code (err) == GPG_ERR_NO_NAME)
2115         err = 0;
2116       goto leave;
2117     }
2118
2119   /* Now we have an array of all the srv records. */
2120
2121   /* Order by priority */
2122   qsort(*list,srvcount,sizeof(struct srventry),priosort);
2123
2124   /* For each priority, move the zero-weighted items first. */
2125   for (i=0; i < srvcount; i++)
2126     {
2127       int j;
2128
2129       for (j=i;j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
2130         {
2131           if((*list)[j].weight==0)
2132             {
2133               /* Swap j with i */
2134               if(j!=i)
2135                 {
2136                   struct srventry temp;
2137
2138                   memcpy (&temp,&(*list)[j],sizeof(struct srventry));
2139                   memcpy (&(*list)[j],&(*list)[i],sizeof(struct srventry));
2140                   memcpy (&(*list)[i],&temp,sizeof(struct srventry));
2141                 }
2142
2143               break;
2144             }
2145         }
2146     }
2147
2148   /* Run the RFC-2782 weighting algorithm.  We don't need very high
2149      quality randomness for this, so regular libc srand/rand is
2150      sufficient.  */
2151
2152   {
2153     static int done;
2154     if (!done)
2155       {
2156         done = 1;
2157         srand (time (NULL)*getpid());
2158       }
2159   }
2160
2161   for (i=0; i < srvcount; i++)
2162     {
2163       int j;
2164       float prio_count=0,chose;
2165
2166       for (j=i; j < srvcount && (*list)[i].priority == (*list)[j].priority; j++)
2167         {
2168           prio_count+=(*list)[j].weight;
2169           (*list)[j].run_count=prio_count;
2170         }
2171
2172       chose=prio_count*rand()/RAND_MAX;
2173
2174       for (j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
2175         {
2176           if (chose<=(*list)[j].run_count)
2177             {
2178               /* Swap j with i */
2179               if(j!=i)
2180                 {
2181                   struct srventry temp;
2182
2183                   memcpy(&temp,&(*list)[j],sizeof(struct srventry));
2184                   memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
2185                   memcpy(&(*list)[i],&temp,sizeof(struct srventry));
2186                 }
2187               break;
2188             }
2189         }
2190     }
2191
2192  leave:
2193   if (opt_debug)
2194     {
2195       if (err)
2196         log_debug ("dns: getsrv(%s): %s\n", name, gpg_strerror (err));
2197       else
2198         log_debug ("dns: getsrv(%s) -> %u records\n", name, srvcount);
2199     }
2200   if (!err)
2201     *r_count = srvcount;
2202   xfree (namebuffer);
2203   return err;
2204 }
2205
2206
2207 \f
2208 #ifdef USE_LIBDNS
2209 /* libdns version of get_dns_cname.  */
2210 gpg_error_t
2211 get_dns_cname_libdns (ctrl_t ctrl, const char *name, char **r_cname)
2212 {
2213   gpg_error_t err;
2214   struct dns_resolver *res;
2215   struct dns_packet *ans = NULL;
2216   struct dns_cname cname;
2217   int derr;
2218
2219   err = libdns_res_open (ctrl, &res);
2220   if (err)
2221     goto leave;
2222
2223   err = libdns_res_submit (res, name, DNS_T_CNAME, DNS_C_IN);
2224   if (err)
2225     goto leave;
2226
2227   err = libdns_res_wait (res);
2228   if (err)
2229     goto leave;
2230
2231   ans = dns_res_fetch (res, &derr);
2232   if (!ans)
2233     {
2234       err = libdns_error_to_gpg_error (derr);
2235       goto leave;
2236     }
2237
2238   /* Check the rcode.  */
2239   switch (dns_p_rcode (ans))
2240     {
2241     case DNS_RC_NOERROR: break;
2242     case DNS_RC_NXDOMAIN: err = gpg_error (GPG_ERR_NO_NAME); break;
2243     default: err = GPG_ERR_SERVER_FAILED; break;
2244     }
2245   if (err)
2246     goto leave;
2247
2248   /* Parse the result into CNAME.  */
2249   err = libdns_error_to_gpg_error (dns_p_study (ans));
2250   if (err)
2251     goto leave;
2252
2253   if (!dns_d_cname (&cname, sizeof cname, name, strlen (name), ans, &derr))
2254     {
2255       err = libdns_error_to_gpg_error (derr);
2256       goto leave;
2257     }
2258
2259   /* Copy result.  */
2260   *r_cname = xtrystrdup (cname.host);
2261   if (!*r_cname)
2262     err = gpg_error_from_syserror ();
2263   else
2264     {
2265       /* Libdns appends the root zone part which is problematic
2266        * for most other functions - strip it.  */
2267       if (**r_cname && (*r_cname)[strlen (*r_cname)-1] == '.')
2268         (*r_cname)[strlen (*r_cname)-1] = 0;
2269     }
2270
2271  leave:
2272   dns_free (ans);
2273   dns_res_close (res);
2274   return err;
2275 }
2276 #endif /*USE_LIBDNS*/
2277
2278
2279 /* Standard resolver version of get_dns_cname.  */
2280 gpg_error_t
2281 get_dns_cname_standard (const char *name, char **r_cname)
2282 {
2283 #ifdef HAVE_SYSTEM_RESOLVER
2284   gpg_error_t err;
2285   int rc;
2286   union {
2287     unsigned char ans[2048];
2288     HEADER header[1];
2289   } res;
2290   unsigned char *answer = res.ans;
2291   HEADER *header = res.header;
2292   unsigned char *pt, *emsg;
2293   int r;
2294   char *cname;
2295   int cnamesize = 1025;
2296   u16 count;
2297
2298   /* Do not allow a query using the standard resolver in Tor mode.  */
2299   if (tor_mode)
2300     return -1;
2301
2302   my_unprotect ();
2303   r = res_query (name, C_IN, T_CERT, answer, sizeof res.ans);
2304   my_protect ();
2305   if (r < 0)
2306     return get_h_errno_as_gpg_error ();
2307   if (r < sizeof (HEADER))
2308     return gpg_error (GPG_ERR_SERVER_FAILED);
2309   if (r > sizeof res.ans)
2310     return gpg_error (GPG_ERR_SYSTEM_BUG);
2311   if (header->rcode != NOERROR || !(count=ntohs (header->ancount)))
2312     return gpg_error (GPG_ERR_NO_NAME); /* Error or no record found.  */
2313   if (count != 1)
2314     return gpg_error (GPG_ERR_SERVER_FAILED);
2315
2316   emsg = &answer[r];
2317   pt = &answer[sizeof(HEADER)];
2318   rc = dn_skipname (pt, emsg);
2319   if (rc == -1)
2320     return gpg_error (GPG_ERR_SERVER_FAILED);
2321
2322   pt += rc + QFIXEDSZ;
2323   if (pt >= emsg)
2324     return gpg_error (GPG_ERR_SERVER_FAILED);
2325
2326   rc = dn_skipname (pt, emsg);
2327   if (rc == -1)
2328     return gpg_error (GPG_ERR_SERVER_FAILED);
2329   pt += rc + 2 + 2 + 4;
2330   if (pt+2 >= emsg)
2331     return gpg_error (GPG_ERR_SERVER_FAILED);
2332   pt += 2;  /* Skip rdlen */
2333
2334   cname = xtrymalloc (cnamesize);
2335   if (!cname)
2336     return gpg_error_from_syserror ();
2337
2338   rc = dn_expand (answer, emsg, pt, cname, cnamesize -1);
2339   if (rc == -1)
2340     {
2341       xfree (cname);
2342       return gpg_error (GPG_ERR_SERVER_FAILED);
2343     }
2344   *r_cname = xtryrealloc (cname, strlen (cname)+1);
2345   if (!*r_cname)
2346     {
2347       err = gpg_error_from_syserror ();
2348       xfree (cname);
2349       return err;
2350     }
2351   return 0;
2352
2353 #else /*!HAVE_SYSTEM_RESOLVER*/
2354
2355   (void)name;
2356   (void)r_cname;
2357   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2358
2359 #endif /*!HAVE_SYSTEM_RESOLVER*/
2360 }
2361
2362
2363 gpg_error_t
2364 get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname)
2365 {
2366   gpg_error_t err;
2367
2368   *r_cname = NULL;
2369
2370 #ifdef USE_LIBDNS
2371   if (!standard_resolver)
2372     {
2373       err = get_dns_cname_libdns (ctrl, name, r_cname);
2374       if (err && libdns_switch_port_p (err))
2375         err = get_dns_cname_libdns (ctrl, name, r_cname);
2376       return err;
2377     }
2378 #endif /*USE_LIBDNS*/
2379
2380   err = get_dns_cname_standard (name, r_cname);
2381   if (opt_debug)
2382     log_debug ("get_dns_cname(%s)%s%s\n", name,
2383                err ? ": " : " -> ",
2384                err ? gpg_strerror (err) : *r_cname);
2385   return err;
2386 }