ba4ab8fd0eeb9f04777cb8230ebd94477d47e061
[gnupg.git] / dirmngr / dns-stuff.c
1 /* dns-stuff.c - DNS related code including CERT RR (rfc-4398)
2  * Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
3  * Copyright (C) 2005, 2006, 2009, 2015 Werner Koch
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * This file is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <http://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <sys/types.h>
33 #ifdef HAVE_W32_SYSTEM
34 # ifdef HAVE_WINSOCK2_H
35 #  include <winsock2.h>
36 # endif
37 # include <windows.h>
38 #else
39 # include <netinet/in.h>
40 # include <arpa/nameser.h>
41 # include <resolv.h>
42 # include <netdb.h>
43 #endif
44 #include <string.h>
45 #ifdef USE_ADNS
46 # include <adns.h>
47 #endif
48
49 #include "util.h"
50 #include "host2net.h"
51 #include "dns-stuff.h"
52
53 /* Not every installation has gotten around to supporting CERTs
54    yet... */
55 #ifndef T_CERT
56 # define T_CERT 37
57 #endif
58
59 /* ADNS has no support for CERT yet. */
60 #define my_adns_r_cert 37
61
62 /* If set Tor mode shall be used.  */
63 static int tor_mode;
64
65 /* Sets the module in TOR mode.  Returns 0 is this is possible or an
66    error code.  */
67 gpg_error_t
68 enable_dns_tormode (void)
69 {
70 #if defined(USE_DNS_CERT) && defined(USE_ADNS)
71 # if HAVE_ADNS_IF_TORMODE
72    tor_mode = 1;
73    return 0;
74 # endif
75 #endif
76   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
77 }
78
79 /* Free an addressinfo linked list as returned by resolve_dns_name.  */
80 void
81 free_dns_addrinfo (dns_addrinfo_t ai)
82 {
83   while (ai)
84     {
85       dns_addrinfo_t next = ai->next;
86       xfree (ai);
87       ai = next;
88     }
89 }
90
91
92 /* Resolve a name using the standard system function.  */
93 static gpg_error_t
94 resolve_name_standard (const char *name, unsigned short port,
95                        int want_family, int want_socktype,
96                        dns_addrinfo_t *r_dai, char **r_canonname)
97 {
98   gpg_error_t err = 0;
99   dns_addrinfo_t daihead = NULL;
100   dns_addrinfo_t dai;
101   struct addrinfo *aibuf = NULL;
102   struct addrinfo hints, *ai;
103   char portstr[21];
104   int ret;
105
106   *r_dai = NULL;
107   if (r_canonname)
108     *r_canonname = NULL;
109
110   memset (&hints, 0, sizeof hints);
111   hints.ai_family = want_family;
112   hints.ai_socktype = want_socktype;
113   if (r_canonname)
114     hints.ai_flags = AI_CANONNAME;
115
116   if (port)
117     snprintf (portstr, sizeof portstr, "%hu", port);
118   else
119     *portstr = 0;
120
121   /* We can't use the the AI_IDN flag because that does the conversion
122      using the current locale.  However, GnuPG always used UTF-8.  To
123      support IDN we would need to make use of the libidn API.  */
124   ret = getaddrinfo (name, *portstr? portstr : NULL, &hints, &aibuf);
125   if (ret)
126     {
127       aibuf = NULL;
128       switch (ret)
129         {
130         case EAI_AGAIN:     err = gpg_error (GPG_ERR_EAGAIN); break;
131         case EAI_BADFLAGS:  err = gpg_error (GPG_ERR_INV_FLAG); break;
132         case EAI_FAIL:      err = gpg_error (GPG_ERR_SERVER_FAILED); break;
133         case EAI_MEMORY:    err = gpg_error (GPG_ERR_ENOMEM); break;
134         case EAI_NODATA:    err = gpg_error (GPG_ERR_NO_DATA); break;
135         case EAI_NONAME:    err = gpg_error (GPG_ERR_NO_NAME); break;
136         case EAI_SERVICE:   err = gpg_error (GPG_ERR_NOT_SUPPORTED); break;
137         case EAI_ADDRFAMILY:err = gpg_error (GPG_ERR_EADDRNOTAVAIL); break;
138         case EAI_FAMILY:    err = gpg_error (GPG_ERR_EAFNOSUPPORT); break;
139         case EAI_SOCKTYPE:  err = gpg_error (GPG_ERR_ESOCKTNOSUPPORT); break;
140         case EAI_SYSTEM:    err = gpg_error_from_syserror (); break;
141         default:            err = gpg_error (GPG_ERR_UNKNOWN_ERRNO); break;
142         }
143       goto leave;
144     }
145
146   if (r_canonname && aibuf && aibuf->ai_canonname)
147     {
148       *r_canonname = xtrystrdup (aibuf->ai_canonname);
149       if (!*r_canonname)
150         {
151           err = gpg_error_from_syserror ();
152           goto leave;
153         }
154     }
155
156   for (ai = aibuf; ai; ai = ai->ai_next)
157     {
158       if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET)
159         continue;
160
161       dai = xtrymalloc (sizeof *dai + ai->ai_addrlen - 1);
162       dai->family = ai->ai_family;
163       dai->socktype = ai->ai_socktype;
164       dai->protocol = ai->ai_protocol;
165       dai->addrlen = ai->ai_addrlen;
166       memcpy (dai->addr, ai->ai_addr, ai->ai_addrlen);
167       dai->next = daihead;
168       daihead = dai;
169     }
170
171  leave:
172   if (aibuf)
173     freeaddrinfo (aibuf);
174   if (err)
175     {
176       if (r_canonname)
177         {
178           xfree (*r_canonname);
179           *r_canonname = NULL;
180         }
181       free_dns_addrinfo (daihead);
182     }
183   else
184     *r_dai = daihead;
185   return err;
186 }
187
188
189 /* This a wrapper around getaddrinfo with slighly different semantics.
190    NAME is the name to resolve.
191    PORT is the requested port or 0.
192    WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
193    WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
194
195    On success the result is stored in a linked list with the head
196    stored at the address R_AI; the caller must call gpg_addrinfo_free
197    on this.  If R_CANONNAME is not NULL the official name of the host
198    is stored there as a malloced string; if that name is not available
199    NULL is stored.  */
200 gpg_error_t
201 resolve_dns_name (const char *name, unsigned short port,
202                   int want_family, int want_socktype,
203                   dns_addrinfo_t *r_ai, char **r_canonname)
204 {
205 #ifdef USE_ADNS_disabled_for_now
206   return resolve_name_adns (name, port, want_family, want_socktype,
207                             r_ai, r_canonname);
208 #else
209   return resolve_name_standard (name, port, want_family, want_socktype,
210                                 r_ai, r_canonname);
211 #endif
212 }
213
214
215 /* Returns 0 on success or an error code.  If a PGP CERT record was
216    found, the malloced data is returned at (R_KEY, R_KEYLEN) and
217    the other return parameters are set to NULL/0.  If an IPGP CERT
218    record was found the fingerprint is stored as an allocated block at
219    R_FPR and its length at R_FPRLEN; an URL is is allocated as a
220    string and returned at R_URL.  If WANT_CERTTYPE is 0 this function
221    returns the first CERT found with a supported type; it is expected
222    that only one CERT record is used.  If WANT_CERTTYPE is one of the
223    supported certtypes only records with this certtype are considered
224    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
225 gpg_error_t
226 get_dns_cert (const char *name, int want_certtype,
227               void **r_key, size_t *r_keylen,
228               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
229 {
230 #ifdef USE_DNS_CERT
231 #ifdef USE_ADNS
232   gpg_error_t err;
233   adns_state state;
234   adns_answer *answer = NULL;
235   unsigned int ctype;
236   int count;
237
238   if (r_key)
239     *r_key = NULL;
240   if (r_keylen)
241     *r_keylen = 0;
242   *r_fpr = NULL;
243   *r_fprlen = 0;
244   *r_url = NULL;
245
246   if (tor_mode? adns_init_strcfg (&state, adns_if_noerrprint|adns_if_tormode,
247                                   NULL, "nameserver 8.8.8.8")
248       /*    */: adns_init (&state, adns_if_noerrprint, NULL))
249     {
250       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
251       log_error ("error initializing adns: %s\n", strerror (errno));
252       return err;
253     }
254
255   if (adns_synchronous (state, name,
256                         (adns_r_unknown
257                          | (want_certtype < DNS_CERTTYPE_RRBASE
258                             ? my_adns_r_cert
259                             : (want_certtype - DNS_CERTTYPE_RRBASE))),
260                         adns_qf_quoteok_query, &answer))
261     {
262       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
263       /* log_error ("DNS query failed: %s\n", strerror (errno)); */
264       adns_finish (state);
265       return err;
266     }
267   if (answer->status != adns_s_ok)
268     {
269       /* log_error ("DNS query returned an error: %s (%s)\n", */
270       /*            adns_strerror (answer->status), */
271       /*            adns_errabbrev (answer->status)); */
272       err = gpg_err_make (default_errsource, GPG_ERR_NOT_FOUND);
273       goto leave;
274     }
275
276   err = gpg_err_make (default_errsource, GPG_ERR_NOT_FOUND);
277   for (count = 0; count < answer->nrrs; count++)
278     {
279       int datalen = answer->rrs.byteblock[count].len;
280       const unsigned char *data = answer->rrs.byteblock[count].data;
281
282       /* First check for our generic RR hack.  */
283       if (datalen
284           && want_certtype >= DNS_CERTTYPE_RRBASE
285           && ((want_certtype - DNS_CERTTYPE_RRBASE)
286               == (answer->type & ~adns_r_unknown)))
287         {
288           /* Found the requested record - return it.  */
289           *r_key = xtrymalloc (datalen);
290           if (!*r_key)
291             err = gpg_err_make (default_errsource,
292                                 gpg_err_code_from_syserror ());
293           else
294             {
295               memcpy (*r_key, data, datalen);
296               *r_keylen = datalen;
297               err = 0;
298             }
299           goto leave;
300         }
301
302       if (datalen < 5)
303         continue;  /* Truncated CERT record - skip.  */
304
305       ctype = buf16_to_uint (data);
306       /* (key tag and algorithm fields are not required.) */
307       data += 5;
308       datalen -= 5;
309
310       if (want_certtype && want_certtype != ctype)
311         ; /* Not of the requested certtype.  */
312       else if (ctype == DNS_CERTTYPE_PGP && datalen >= 11 && r_key && r_keylen)
313         {
314           /* CERT type is PGP.  Gpg checks for a minimum length of 11,
315              thus we do the same.  */
316           *r_key = xtrymalloc (datalen);
317           if (!*r_key)
318             err = gpg_err_make (default_errsource,
319                                 gpg_err_code_from_syserror ());
320           else
321             {
322               memcpy (*r_key, data, datalen);
323               *r_keylen = datalen;
324               err = 0;
325             }
326           goto leave;
327         }
328       else if (ctype == DNS_CERTTYPE_IPGP && datalen && datalen < 1023
329                && datalen >= data[0] + 1 && r_fpr && r_fprlen && r_url)
330         {
331           /* CERT type is IPGP.  We made sure that the data is
332              plausible and that the caller requested this
333              information.  */
334           *r_fprlen = data[0];
335           if (*r_fprlen)
336             {
337               *r_fpr = xtrymalloc (*r_fprlen);
338               if (!*r_fpr)
339                 {
340                   err = gpg_err_make (default_errsource,
341                                       gpg_err_code_from_syserror ());
342                   goto leave;
343                 }
344               memcpy (*r_fpr, data + 1, *r_fprlen);
345             }
346           else
347             *r_fpr = NULL;
348
349           if (datalen > *r_fprlen + 1)
350             {
351               *r_url = xtrymalloc (datalen - (*r_fprlen + 1) + 1);
352               if (!*r_url)
353                 {
354                   err = gpg_err_make (default_errsource,
355                                       gpg_err_code_from_syserror ());
356                   xfree (*r_fpr);
357                   *r_fpr = NULL;
358                   goto leave;
359                 }
360               memcpy (*r_url,
361                       data + (*r_fprlen + 1), datalen - (*r_fprlen + 1));
362               (*r_url)[datalen - (*r_fprlen + 1)] = '\0';
363             }
364           else
365             *r_url = NULL;
366
367           err = 0;
368           goto leave;
369         }
370     }
371
372  leave:
373   adns_free (answer);
374   adns_finish (state);
375   return err;
376
377 #else /*!USE_ADNS*/
378
379   gpg_error_t err;
380   unsigned char *answer;
381   int r;
382   u16 count;
383
384   if (r_key)
385     *r_key = NULL;
386   if (r_keylen)
387     *r_keylen = 0;
388   *r_fpr = NULL;
389   *r_fprlen = 0;
390   *r_url = NULL;
391
392   /* Allocate a 64k buffer which is the limit for an DNS response.  */
393   answer = xtrymalloc (65536);
394   if (!answer)
395     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
396
397   err = gpg_err_make (default_errsource, GPG_ERR_NOT_FOUND);
398
399   r = res_query (name, C_IN,
400                  (want_certtype < DNS_CERTTYPE_RRBASE
401                   ? T_CERT
402                   : (want_certtype - DNS_CERTTYPE_RRBASE)),
403                  answer, 65536);
404   /* Not too big, not too small, no errors and at least 1 answer. */
405   if (r >= sizeof (HEADER) && r <= 65536
406       && (((HEADER *) answer)->rcode) == NOERROR
407       && (count = ntohs (((HEADER *) answer)->ancount)))
408     {
409       int rc;
410       unsigned char *pt, *emsg;
411
412       emsg = &answer[r];
413
414       pt = &answer[sizeof (HEADER)];
415
416       /* Skip over the query */
417
418       rc = dn_skipname (pt, emsg);
419       if (rc == -1)
420         {
421           err = gpg_err_make (default_errsource, GPG_ERR_INV_OBJ);
422           goto leave;
423         }
424       pt += rc + QFIXEDSZ;
425
426       /* There are several possible response types for a CERT request.
427          We're interested in the PGP (a key) and IPGP (a URI) types.
428          Skip all others.  TODO: A key is better than a URI since
429          we've gone through all this bother to fetch it, so favor that
430          if we have both PGP and IPGP? */
431
432       while (count-- > 0 && pt < emsg)
433         {
434           u16 type, class, dlen, ctype;
435
436           rc = dn_skipname (pt, emsg);  /* the name we just queried for */
437           if (rc == -1)
438             {
439               err = gpg_err_make (default_errsource, GPG_ERR_INV_OBJ);
440               goto leave;
441             }
442
443           pt += rc;
444
445           /* Truncated message? 15 bytes takes us to the point where
446              we start looking at the ctype. */
447           if ((emsg - pt) < 15)
448             break;
449
450           type = buf16_to_u16 (pt);
451           pt += 2;
452
453           class = buf16_to_u16 (pt);
454           pt += 2;
455
456           if (class != C_IN)
457             break;
458
459           /* ttl */
460           pt += 4;
461
462           /* data length */
463           dlen = buf16_to_u16 (pt);
464           pt += 2;
465
466           /* Check the type and parse.  */
467           if (want_certtype >= DNS_CERTTYPE_RRBASE
468               && type == (want_certtype - DNS_CERTTYPE_RRBASE)
469               && r_key)
470             {
471               *r_key = xtrymalloc (dlen);
472               if (!*r_key)
473                 err = gpg_err_make (default_errsource,
474                                     gpg_err_code_from_syserror ());
475               else
476                 {
477                   memcpy (*r_key, pt, dlen);
478                   *r_keylen = dlen;
479                   err = 0;
480                 }
481               goto leave;
482             }
483           else if (want_certtype >= DNS_CERTTYPE_RRBASE)
484             {
485               /* We did not found the requested RR.  */
486               pt += dlen;
487             }
488           else if (type == T_CERT)
489             {
490               /* We got a CERT type.   */
491               ctype = buf16_to_u16 (pt);
492               pt += 2;
493
494               /* Skip the CERT key tag and algo which we don't need. */
495               pt += 3;
496
497               dlen -= 5;
498
499               /* 15 bytes takes us to here */
500               if (want_certtype && want_certtype != ctype)
501                 ; /* Not of the requested certtype.  */
502               else if (ctype == DNS_CERTTYPE_PGP && dlen && r_key && r_keylen)
503                 {
504                   /* PGP type */
505                   *r_key = xtrymalloc (dlen);
506                   if (!*r_key)
507                     err = gpg_err_make (default_errsource,
508                                         gpg_err_code_from_syserror ());
509                   else
510                     {
511                       memcpy (*r_key, pt, dlen);
512                       *r_keylen = dlen;
513                       err = 0;
514                     }
515                   goto leave;
516                 }
517               else if (ctype == DNS_CERTTYPE_IPGP
518                        && dlen && dlen < 1023 && dlen >= pt[0] + 1)
519                 {
520                   /* IPGP type */
521                   *r_fprlen = pt[0];
522                   if (*r_fprlen)
523                     {
524                       *r_fpr = xtrymalloc (*r_fprlen);
525                       if (!*r_fpr)
526                         {
527                           err = gpg_err_make (default_errsource,
528                                               gpg_err_code_from_syserror ());
529                           goto leave;
530                         }
531                       memcpy (*r_fpr, &pt[1], *r_fprlen);
532                     }
533                   else
534                     *r_fpr = NULL;
535
536                   if (dlen > *r_fprlen + 1)
537                     {
538                       *r_url = xtrymalloc (dlen - (*r_fprlen + 1) + 1);
539                       if (!*r_fpr)
540                         {
541                           err = gpg_err_make (default_errsource,
542                                               gpg_err_code_from_syserror ());
543                           xfree (*r_fpr);
544                           *r_fpr = NULL;
545                           goto leave;
546                         }
547                       memcpy (*r_url, &pt[*r_fprlen + 1],
548                               dlen - (*r_fprlen + 1));
549                       (*r_url)[dlen - (*r_fprlen + 1)] = '\0';
550                     }
551                   else
552                     *r_url = NULL;
553
554                   err = 0;
555                   goto leave;
556                 }
557
558               /* No subtype matches, so continue with the next answer. */
559               pt += dlen;
560             }
561           else
562             {
563               /* Not a requested type - might be a CNAME. Try next item.  */
564               pt += dlen;
565             }
566         }
567     }
568
569  leave:
570   xfree (answer);
571   return err;
572
573 #endif /*!USE_ADNS */
574 #else /* !USE_DNS_CERT */
575   (void)name;
576   if (r_key)
577     *r_key = NULL;
578   if (r_keylen)
579     *r_keylen = NULL;
580   *r_fpr = NULL;
581   *r_fprlen = 0;
582   *r_url = NULL;
583
584   return gpg_err_make (default_errsource, GPG_ERR_NOT_SUPPORTED);
585 #endif
586 }