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