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