1 /**
2 *
3 * /brief functions for DNSSEC
4 *
5 * In this file, the "dnssec_return_validation_chain" extension is implemented
6 * (with the _getdns_get_validation_chain() function)
7 * Also the function getdns_validate_dnssec is implemented.
8 * DNSSEC validation as a stub combines those two functionalities, by first
9 * fetching all the records that are necessary to be able to validate a
10 * request (i.e. the "dnssec_return_validation_chain" extension) and then
11 * performing DNSSEC validation for a request with those support records
12 * (and a trust anchor of course).
13 */
14
15 /*
16 * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are met:
21 * * Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * * Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * * Neither the names of the copyright holders nor the
27 * names of its contributors may be used to endorse or promote products
28 * derived from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 /*
43 * From the API:
44 *
45 * The "dnssec_return_validation_chain" extension as explained in section 3.1:
46 *
47 * Applications that want to do their own validation will want to have the
48 * DNSSEC-related records for a particular response. Use the
49 * dnssec_return_validation_chain extension. The extension's value
50 * (an int) is set to GETDNS_EXTENSION_TRUE to cause a set of additional
51 * DNSSEC-related records needed for validation to be returned in the
52 * response object. This set comes as validation_chain (a list) at the top
53 * level of the response object. This list includes all resource record
54 * dicts for all the resource records (DS, DNSKEY and their RRSIGs) that
55 * are needed to perform the validation from the root up.
56 *
57 *
58 * The getdns_validate_dnssec() function as explained in section 7:
59 *
60 * If an application wants the API do perform DNSSEC validation without
61 * using the extensions, it can use the getdns_validate_dnssec() helper
62 * function.
63 *
64 * getdns_return_t
65 * getdns_validate_dnssec(
66 * getdns_list *record_to_validate,
67 * getdns_list *bundle_of_support_records,
68 * getdns_list *trust_anchor_records
69 * );
70 *
71 * The record_to_validate is the resource record being validated together
72 * with the associated signatures. The API will use the resource records
73 * in bundle_of_support_records to construct the validation chain and the
74 * DNSKEY or DS records in trust_anchor_records as trust anchors. The
75 * function returns one of GETDNS_DNSSEC_SECURE, GETDNS_DNSSEC_BOGUS,
76 * GETDNS_DNSSEC_INDETERMINATE, or GETDNS_DNSSEC_INSECURE.
77 */
78
79 /* Outline of operations in this file
80 * ==================================
81 *
82 * Data structure to represent the delegation/referral hierarchy
83 * -------------------------------------------------------------
84 * Both the "dnssec_return_validation_chain" extension, and the
85 * getdns_validate_dnssec() function use the same structs to represent the
86 * involved pieces of the DNS in a hierarchical manner.
87 *
88 * However, the tree is not represented from the root, but from the RRsets that
89 * need to be validated. The RRset to validate is a member of the chain_head
90 * struct for this. The chain_head struct has a "next" member to form a linked
91 * list of RRsets to validate.
92 *
93 * The chain_head struct also has a "parent" member to a linked list of
94 * chain_node structs (linked with the "parent" member of those chain_nodes).
95 * For each label in the name of the rrset in a chain_head, is a chain_node,
96 * all the way to the root. The last chain_node is thus always the root, for
97 * every chain_head.
98 *
99 * The construction functions for this datastructure make sure there is always
100 * a single chain_node representing the same name. They also make sure space
101 * for chain_head + the number of extra chain_nodes needed is allocated in a
102 * single region, so that on destruction one only has to free the chain_heads.
103 *
104 * A chain_node contains two RRset members, "dnskey" and "ds" which represent
105 * the potential client side DNSKEYs and the parent side DS records of a
106 * potential zonecut at this point. Whether or not there is an actual zone
107 * cut is determined separately. With the "dnssec_return_validation_chain"
108 * extension by scheduling queries, and with the getdns_validation_dnssec()
109 * function by provisioning the support records at the chain nodes.
110 *
111 * In the construction functions a chain_head is created for every RRset in
112 * the answer and authority section of a given packet (except for synthesized
113 * CNAMEs). Furthermore, if the queries for name/class/type is not in the
114 * packet, a chain_head for the non-existent rrset is created too, to that
115 * it will be evaluated for non-existence later in the validation process.
116 *
117 * The chain_head and chain_node structs are defined in section:
118 * "Validation Chain Data Structs". The functions to construct the hierarchy
119 * are defined in section "Validation Chain Construction". When the
120 * construction functions are called for the purpose of the
121 * "dnssec_return_validation_chain" extension, queries to provision the
122 * chain_nodes are scheduled. Function theretofore are in section:
123 * "Schedule Queries to Provision Validation Chain"
124 *
125 *
126 * _getdns_rrset
127 * ------------
128 * RRsets used in the structure described above are represented by the
129 * _getdns_rrset struct. They consist of name/rr_class and rr_type members
130 * plus a reference to the wireformat packet that should contain the RRset.
131 *
132 * The actual RR's in the rrset and the signatures are only accessed via
133 * iterators; substantiated with the rrtype_iter struct to iterate over RRs
134 * in a _getdns_rrset, and the rrsig_iter to iterate over the RRSIGs covering
135 * the RRs in the _getdns_rrset.
136 *
137 * The _getdns_rrsets are already equipped with name/rr_class and rr_type when
138 * constructing the linked list of chain_nodes up to the root for a chain_head.
139 * They are substantiated with the wireformat packets that are returned with
140 * the queries that were sheduled in the context of the
141 * "dnssec_return_validation_chain" extension.
142 *
143 * Note that the NSEC(3) RRsets proving the non-existance of a _getdns_rrset
144 * can be found by processing that _getdns_rrset, as it contains the pointer
145 * to the wireformat data that should either contain the RRset or the proof
146 * of non-existance.
147 *
148 * The getdns_validate_dnssec() function, after it constructed the chain_heads
149 * hierarchy, creates an artificial packet for the support records and equips
150 * all the ds and dnskey _getdns_rrsets on the chain_nodes with this packet.
151 *
152 * The _getdns_rrset + support function and data types are defined in section:
153 * "_getdns_rrset + Support Iterators"
154 *
155 *
156 * Validation
157 * ----------
158 * Validation of a constructed chain is done by the
159 * chain_set_netreq_dnssec_status() function when validating in stub mode.
160 * And with the chain_validate_dnssec() function when using the
161 * getdns_validate_dnssec() function. They are the same, except that
162 * chain_set_netreq_dnssec_status() evaluates DNSSEC status per network
163 * request and chain_validate_dnssec() does it for the whole chain.
164 *
165 * They both evaluate the DNSSEC status for each head in turn. The worst
166 * DNSSEC status determines the status of all heads evaluated. Where
167 * INSECURE is worse than SECURE, and BOGUS is worse than INSECURE.
168 *
169 * For each head, the closest (most labels still a parent of the head's name)
170 * trust anchor is tried. Without fitting trust anchors, DNSSEC_INDETERMINATE
171 * is returned.
172 *
173 * Security status for a head (with a specific trust anchor) is evaluated by
174 * first finding a authenticated keyset from the parent chain_nodes, and then
175 * evaluating the rrset of the head (existent or not) with that keyset.
176 *
177 * Functions that implement DNSSEC validation are in section:
178 * "DNSSEC Validation".
179 *
180 * Many functions are of key verification boolean return type; e.g.
181 * key_proves_nonexistance(), ds_authenticates_keys(), a_key_signed_rrset()
182 * These will return the keytag identifying the key that was used to
183 * authenticate + 0x10000 to allow keytag 0.
184 *
185 * These returned keytag's are used later with function
186 * append_rrs2val_chain_list() to return a "dnssec_validation_chain" that
187 * enumerates a single RRSIG per RRset. This can be found in section:
188 * "dnssec_return_validation_chain Extension".
189 */
190
191 #include "config.h"
192 #include "debug.h"
193 #include <sys/types.h>
194 #include <sys/stat.h>
195 #include <unistd.h>
196 #include <ctype.h>
197 #include "getdns/getdns.h"
198 #include "context.h"
199 #include "util-internal.h"
200 #include "types-internal.h"
201 #include "dnssec.h"
202 #include "rr-dict.h"
203 #include "gldns/str2wire.h"
204 #include "gldns/wire2str.h"
205 #include "gldns/keyraw.h"
206 #include "gldns/parseutil.h"
207 #include "general.h"
208 #include "dict.h"
209 #include "list.h"
210 #include "util/val_secalgo.h"
211 #include "anchor.h"
212 #include "tls.h"
213
214 #define SIGNATURE_VERIFIED 0x10000
215 #define NSEC3_ITERATION_COUNT_HIGH 0x20000
216 #define NO_SUPPORTED_ALGORITHMS 0x40000
217
218 /******************* Frequently Used Utility Functions *********************
219 *****************************************************************************/
220
_dname_len(const uint8_t * name)221 static inline size_t _dname_len(const uint8_t *name)
222 {
223 const uint8_t *p;
224 for (p = name; *p; p += *p + 1)
225 /* pass */
226 ;
227 return p - name + 1;
228 }
229
_dname_label_count(const uint8_t * name)230 static inline size_t _dname_label_count(const uint8_t *name)
231 {
232 size_t c;
233 for (c = 0; *name; name += *name + 1, c++)
234 /* pass */
235 ;
236 return c;
237 }
238
_dname_equal(const uint8_t * left,const uint8_t * right)239 static inline int _dname_equal(const uint8_t *left, const uint8_t *right)
240 {
241 return _getdns_dname_equal(left, right);
242 }
243
_dname_is_parent(const uint8_t * const parent,const uint8_t * subdomain)244 static int _dname_is_parent(
245 const uint8_t * const parent, const uint8_t *subdomain)
246 {
247 if (*parent == 0)
248 return 1;
249
250 else while (*subdomain) {
251 if (_dname_equal(parent, subdomain))
252 return 1;
253
254 subdomain += *subdomain + 1;
255 }
256 return 0;
257 }
258
_dname_label_copy(uint8_t * dst,const uint8_t * src,size_t dst_len)259 static uint8_t *_dname_label_copy(uint8_t *dst, const uint8_t *src, size_t dst_len)
260 {
261 uint8_t *r = dst, i;
262
263 if (!src || (size_t)*src + 1 > dst_len)
264 return NULL;
265
266 for (i = (*dst++ = *src++); i ; i--)
267 *dst++ = tolower(*src++);
268
269 return r;
270 }
271
272
273 /* Fills the array pointed to by labels (of at least 128 uint8_t * pointers)
274 * with pointers to labels in given dname in reversed order. So that
275 * labels[0] will point to the root.
276 * labels[1] will point to the tld etc.
277 * A pointer just past the last assigned array element will be returned.
278 *
279 * So if dname would be "www.getdnsapi.net"
280 * labels[0] will be "."
281 * labels[1] will be "net."
282 * labels[2] will be "getdnsapi.net."
283 * labels[3] will be "www.getdnsapi.net."
284 * The returned value will be &labels[4]
285 */
reverse_labels(const uint8_t * dname,const uint8_t ** labels)286 static const uint8_t **reverse_labels(
287 const uint8_t *dname, const uint8_t **labels)
288 {
289 if (*dname)
290 labels = reverse_labels(dname + *dname + 1, labels);
291 *labels = dname;
292 return labels + 1;
293 }
294
dname_shared_parent(const uint8_t * left,const uint8_t * right)295 static const uint8_t *dname_shared_parent(
296 const uint8_t *left, const uint8_t *right)
297 {
298 const uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
299 **llabel, **rlabel, *l, *r;
300 uint8_t sz;
301
302 last_llabel = reverse_labels(left, llabels);
303 last_rlabel = reverse_labels(right, rlabels);
304
305 /* Always at least one label (the root) */
306 assert(last_llabel > llabels);
307 assert(last_rlabel > rlabels);
308 assert(*llabels[0] == 0);
309 assert(*rlabels[0] == 0);
310
311 for ( llabel = &llabels[1], rlabel = &rlabels[1]
312 ; llabel < last_llabel
313 ; llabel++, rlabel++ ) {
314
315 sz = **llabel;
316 if ( rlabel == last_rlabel
317 || **llabel != **rlabel)
318 return llabel[-1];
319
320 for (l = *llabel+1, r = *rlabel+1; sz; l++, r++, sz-- )
321 if (*l != *r && tolower((unsigned char)*l) !=
322 tolower((unsigned char)*r))
323 return llabel[-1];
324 }
325 return llabel[-1];
326 }
327
dname_compare(const uint8_t * left,const uint8_t * right)328 static int dname_compare(const uint8_t *left, const uint8_t *right)
329 {
330 const uint8_t *llabels[128], *rlabels[128], **last_llabel, **last_rlabel,
331 **llabel, **rlabel, *l, *r;
332 uint8_t lsz, rsz;
333
334 last_llabel = reverse_labels(left, llabels);
335 last_rlabel = reverse_labels(right, rlabels);
336
337 for ( llabel = llabels, rlabel = rlabels
338 ; llabel < last_llabel
339 ; llabel++, rlabel++ ) {
340
341 if (rlabel == last_rlabel)
342 return 1;
343
344 for ( l = *llabel, lsz = *l++, r = *rlabel, rsz = *r++
345 ; lsz; l++, r++, lsz--, rsz-- ) {
346
347 /* No compression pointers here */
348 assert(lsz <= 63);
349 assert(rsz <= 63);
350
351 if (!rsz)
352 return 1;
353 if (*l != *r && tolower((unsigned char)*l) !=
354 tolower((unsigned char)*r)) {
355 if (tolower((unsigned char)*l) <
356 tolower((unsigned char)*r))
357 return -1;
358 return 1;
359 }
360 }
361 if (rsz)
362 return -1;
363 }
364 return rlabel == last_rlabel ? 0 : -1;
365 }
366
bitmap_has_type(_getdns_rdf_iter * bitmap,uint16_t rr_type)367 static int bitmap_has_type(_getdns_rdf_iter *bitmap, uint16_t rr_type)
368 {
369 const uint8_t *dptr, *dend;
370 uint8_t window = rr_type >> 8;
371 uint8_t subtype = rr_type & 0xFF;
372
373 if (!bitmap || (dptr = bitmap->pos) == (dend = bitmap->nxt))
374 return 0;
375
376 /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
377 * dptr[0] dptr[1] dptr[2:]
378 */
379 while (dptr < dend && dptr[0] <= window) {
380 if (dptr[0] == window && subtype / 8 < dptr[1] &&
381 dptr + dptr[1] + 2 <= dend)
382 return dptr[2 + subtype / 8] & (0x80 >> (subtype % 8));
383 dptr += dptr[1] + 2; /* next window */
384 }
385 return 0;
386 }
387
388 #if defined(SEC_DEBUG) && SEC_DEBUG
debug_sec_print_rr(const char * msg,_getdns_rr_iter * rr)389 static inline void debug_sec_print_rr(const char *msg, _getdns_rr_iter *rr)
390 {
391 char str_spc[8192], *str = str_spc;
392 size_t str_len = sizeof(str_spc);
393 const uint8_t *data = rr->pos;
394 size_t data_len = rr->nxt - rr->pos;
395
396 if (!rr || !rr->pos) {
397 DEBUG_SEC("%s<nil>\n", msg);
398 return;
399 }
400 (void) gldns_wire2str_rr_scan(
401 (UNCONST_UINT8_p *) &data, &data_len, &str, &str_len,
402 (UNCONST_UINT8_p) rr->pkt, rr->pkt_end - rr->pkt);
403 DEBUG_SEC("%s%s", msg, str_spc);
404 }
debug_sec_print_dname(const char * msg,const uint8_t * label)405 static inline void debug_sec_print_dname(const char *msg, const uint8_t *label)
406 {
407 char str[1024];
408
409 if (label && gldns_wire2str_dname_buf(
410 (UNCONST_UINT8_p)label, 256, str, sizeof(str)))
411 DEBUG_SEC("%s%s\n", msg, str);
412 else
413 DEBUG_SEC("%s<nil>\n", msg);
414 }
415 #else
416 #define debug_sec_print_rr(...) DEBUG_OFF(__VA_ARGS__)
417 #define debug_sec_print_dname(...) DEBUG_OFF(__VA_ARGS__)
418 #define debug_sec_print_pkt(...) DEBUG_OFF(__VA_ARGS__)
419 #endif
420
421
422 /******************* _getdns_rrset + Support Iterators **********************
423 *****************************************************************************/
424
425
426 #if defined(SEC_DEBUG) && SEC_DEBUG
debug_sec_print_rrset(const char * msg,_getdns_rrset * rrset)427 static void debug_sec_print_rrset(const char *msg, _getdns_rrset *rrset)
428 {
429 char owner[1024];
430 char buf_space[2048];
431 gldns_buffer buf;
432 _getdns_rrtype_iter *rr, rr_space;
433 _getdns_rrsig_iter *rrsig, rrsig_space;
434 size_t i;
435
436 if (!rrset) {
437 DEBUG_SEC("<nil>");
438 return;
439 }
440 gldns_buffer_init_frm_data(&buf, buf_space, sizeof(buf_space));
441 if (gldns_wire2str_dname_buf(
442 (UNCONST_UINT8_p)rrset->name, 256, owner, sizeof(owner)))
443 gldns_buffer_printf(&buf, "%s ", owner);
444 else gldns_buffer_printf(&buf, "<nil> ");
445
446 switch (rrset->rr_class) {
447 case GETDNS_RRCLASS_IN : gldns_buffer_printf(&buf, "IN ") ; break;
448 case GETDNS_RRCLASS_CH : gldns_buffer_printf(&buf, "CH ") ; break;
449 case GETDNS_RRCLASS_HS : gldns_buffer_printf(&buf, "HS ") ; break;
450 case GETDNS_RRCLASS_NONE: gldns_buffer_printf(&buf, "NONE "); break;
451 case GETDNS_RRCLASS_ANY : gldns_buffer_printf(&buf, "ANY ") ; break;
452 default : gldns_buffer_printf(&buf, "CLASS%d "
453 , rrset->rr_class);
454 break;
455 }
456 gldns_buffer_printf(&buf, "%s", _getdns_rr_type_name(rrset->rr_type));
457
458 gldns_buffer_printf(&buf, ", rrs:");
459 for ( rr = _getdns_rrtype_iter_init(&rr_space, rrset), i = 1
460 ; rr
461 ; rr = _getdns_rrtype_iter_next(rr), i++)
462 gldns_buffer_printf(&buf, " %d", (int)i);
463
464 gldns_buffer_printf(&buf, ", rrsigs:");
465 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_space, rrset), i = 1
466 ; rrsig
467 ; rrsig = _getdns_rrsig_iter_next(rrsig), i++)
468 gldns_buffer_printf(&buf, " %d", (int)i);
469
470 DEBUG_SEC("%s%s\n", msg, buf_space);
471 }
472 #else
473 #define debug_sec_print_rrset(...) DEBUG_OFF(__VA_ARGS__)
474 #endif
475
476
477 /********************* Validation Chain Data Structs ***********************
478 *****************************************************************************/
479
480 typedef struct chain_head chain_head;
481 typedef struct chain_node chain_node;
482
483 struct chain_head {
484 struct mem_funcs my_mf;
485
486 size_t lock;
487
488 chain_head *next;
489 chain_node *parent;
490 size_t node_count; /* Number of nodes attached directly
491 * to this head. For cleaning. */
492 _getdns_rrset rrset;
493 getdns_network_req *netreq;
494 int signer;
495
496 uint8_t name_spc[];
497 };
498
499 struct chain_node {
500 chain_node *parent;
501
502 size_t lock;
503
504 _getdns_rrset dnskey;
505 getdns_network_req *dnskey_req;
506 int dnskey_signer;
507
508 _getdns_rrset ds;
509 getdns_network_req *ds_req;
510 int ds_signer;
511
512 chain_head *chains;
513 };
514
515 /********************* Validation Chain Construction ***********************
516 *****************************************************************************/
517
518 /* When construction is done in the context of stub validation, the requests
519 * to equip the chain nodes with their RR sets are done alongside construction.
520 * Hence they need to be enumerated before the construction functions.
521 */
522 static void val_chain_sched(chain_head *head, const uint8_t *dname);
523 static void val_chain_sched_ds(chain_head *head, const uint8_t *dname);
524 static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig);
525
add_rrset2val_chain(const struct mem_funcs * mf,chain_head ** chain_p,_getdns_rrset * rrset,getdns_network_req * netreq)526 static chain_head *add_rrset2val_chain(const struct mem_funcs *mf,
527 chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq)
528 {
529 chain_head *head;
530 const uint8_t *labels[128], **last_label, **label;
531
532 ssize_t max_labels; /* max labels in common */
533 chain_head *max_head;
534 chain_node *max_node;
535
536 size_t dname_len, head_sz, node_count, n;
537 const uint8_t *dname;
538 uint8_t *region;
539 chain_node *node;
540
541 last_label = reverse_labels(rrset->name, labels);
542
543 /* Try to find a chain with the most overlapping labels.
544 * max_labels will be the number of labels in common from the root
545 * (so at least one; the root)
546 * max_head will be the head of the chain with max # labels in common
547 */
548 max_head = NULL;
549 max_labels = 0;
550 for (head = *chain_p; head; head = head->next) {
551 /* Also, try to prevent adding double rrsets */
552 if ( rrset->rr_class == head->rrset.rr_class
553 && rrset->rr_type == head->rrset.rr_type
554 && _dname_equal(rrset->name, head->rrset.name)) {
555
556 if (rrset->pkt == head->rrset.pkt &&
557 rrset->pkt_len == head->rrset.pkt_len)
558 return NULL;
559 else {
560 /* Anticipate resubmissions due to
561 * roadblock avoidance */
562 head->rrset.pkt = rrset->pkt;
563 head->rrset.pkt_len = rrset->pkt_len;
564 return head;
565 }
566 }
567
568 if ( rrset->rr_class == head->rrset.rr_class
569 && rrset->rr_type == head->rrset.rr_type
570 && rrset->pkt != head->rrset.pkt
571 && _dname_equal(rrset->name, head->rrset.name)) {
572 return NULL;
573 }
574 for (label = labels; label < last_label; label++) {
575 if (! _dname_is_parent(*label, head->rrset.name))
576 break;
577 }
578 if ((ssize_t)(label - labels) > max_labels) {
579 max_labels = label - labels;
580 max_head = head;
581 }
582 }
583 /* Chain found. Now set max_node to the point in the chain where nodes
584 * will be common.
585 */
586 if (max_head) {
587 for ( node = max_head->parent, n = 0
588 ; node
589 ; node = node->parent, n++);
590
591 for ( n -= max_labels, node = max_head->parent
592 ; n && node
593 ; n--, node = node->parent);
594
595 max_node = node;
596 } else
597 max_node = NULL;
598
599 /* node_count is the amount of nodes to still allocate.
600 * the last one's parent has to hook into the max_node.
601 */
602 dname_len = *labels - last_label[-1] + 1;
603 head_sz = (sizeof(chain_head) + dname_len + 7) / 8 * 8;
604 node_count = last_label - labels - max_labels;
605 DEBUG_SEC( "%"PRIsz" labels in common. %"PRIsz" labels to allocate\n"
606 , max_labels, node_count);
607
608 if (! (region = GETDNS_XMALLOC(*mf, uint8_t, head_sz +
609 node_count * sizeof(chain_node))))
610 return NULL;
611
612 /* Append the head on the linked list of heads */
613 for (head = *chain_p; head && head->next; head = head->next)
614 ;
615 if (head)
616 head = head->next = (chain_head *)region;
617 else
618 head = *chain_p = (chain_head *)region;
619
620 head->my_mf = *mf;
621 head->lock = 1;
622 head->next = NULL;
623 head->rrset.name = head->name_spc;
624 memcpy(head->name_spc, rrset->name, dname_len);
625 head->rrset.rr_class = rrset->rr_class;
626 head->rrset.rr_type = rrset->rr_type;
627 head->rrset.pkt = rrset->pkt;
628 head->rrset.pkt_len = rrset->pkt_len;
629 head->rrset.sections = rrset->sections;
630 head->netreq = netreq;
631 head->signer = -1;
632 head->node_count = node_count;
633
634 if (!node_count) {
635 /* When this head has no nodes of itself, it must have found
636 * another head which has nodes for its labels (i.e. max_head)
637 */
638 assert(max_head != NULL);
639
640 head->parent = max_head->parent;
641 return head;
642 }
643
644 /* Initialize the nodes */
645
646 for ( head->parent = node = (chain_node *)(region + head_sz),
647 dname = head->rrset.name
648 ; node_count
649 ; node_count--, node = node->parent =&node[1], dname += *dname + 1) {
650
651 node->lock = 0;
652 node->ds.name = dname;
653 node->dnskey.name = dname;
654 node->ds.rr_class = head->rrset.rr_class;
655 node->dnskey.rr_class = head->rrset.rr_class;
656 node->ds.rr_type = GETDNS_RRTYPE_DS;
657 node->dnskey.rr_type = GETDNS_RRTYPE_DNSKEY;
658 node->ds.pkt = NULL;
659 node->ds.pkt_len = 0;
660 node->ds.sections = head->rrset.sections;
661 node->dnskey.pkt = NULL;
662 node->dnskey.pkt_len = 0;
663 node->dnskey.sections = head->rrset.sections;
664 node->ds_req = NULL;
665 node->dnskey_req = NULL;
666 node->ds_signer = -1;
667 node->dnskey_signer = -1;
668
669 node->chains = *chain_p;
670 }
671 /* On the first chain, max_node == NULL.
672 * Schedule a root DNSKEY query, we always need that.
673 */
674 if (!(node[-1].parent = max_node))
675 val_chain_sched(head, (uint8_t *)"\0");
676
677 /* For an NSEC or NSEC3 query, stop at that. If it is valid it will
678 * have a signature which will be chased.
679 */
680 if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC ||
681 head->rrset.rr_type == GETDNS_RRTYPE_NSEC3)
682 return head;
683
684 /* Otherwise, schedule key lookups for the tld and sld too. */
685 if (!max_node) {
686 if (head->node_count > 1)
687 val_chain_sched(head, node[-2].ds.name);
688 if (head->node_count > 2)
689 val_chain_sched(head, node[-3].ds.name);
690 } else if ((max_labels == 1 || max_labels == 2) && head->node_count > 0)
691 val_chain_sched(head, node[-1].ds.name);
692 if (max_labels == 1 && head->node_count > 1)
693 val_chain_sched(head, node[-2].ds.name);
694
695 return head;
696 }
697
is_synthesized_cname(_getdns_rrset * cname)698 static int is_synthesized_cname(_getdns_rrset *cname)
699 {
700 _getdns_rrset_iter *i, i_spc;
701 _getdns_rrset *dname;
702 _getdns_rrtype_iter rr_spc, *rr;
703 _getdns_rdf_iter rdf_spc, *rdf;
704 _getdns_rrtype_iter drr_spc, *drr;
705 _getdns_rdf_iter drdf_spc, *drdf;
706 uint8_t cname_rdata_spc[256],
707 dname_rdata_spc[256],
708 synth_name[256],
709 *synth_name_end = synth_name + sizeof(synth_name) - 1, *s;
710 const uint8_t *cname_rdata, *dname_rdata, *c;
711 size_t cname_rdata_len = sizeof(cname_rdata_spc),
712 dname_rdata_len = sizeof(dname_rdata_len),
713 cname_labels, dname_labels;
714
715 /* Synthesized CNAMEs don't have RRSIGs */
716 if ( cname->rr_type != GETDNS_RRTYPE_CNAME
717 || _getdns_rrset_has_rrsigs(cname))
718 return 0;
719
720 /* Get canonical name rdata field */
721 if ( !(rr = _getdns_rrtype_iter_init(&rr_spc, cname))
722 || !(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))
723 || !(cname_rdata = _getdns_rdf_if_or_as_decompressed(
724 rdf, cname_rdata_spc, &cname_rdata_len)))
725 return 0;
726
727 /* Find a matching DNAME */
728 for ( i = _getdns_rrset_iter_init(&i_spc, cname->pkt, cname->pkt_len
729 , SECTION_ANSWER)
730 ; i
731 ; i = _getdns_rrset_iter_next(i)) {
732
733 dname = _getdns_rrset_iter_value(i);
734 if ( dname->rr_type != GETDNS_RRTYPE_DNAME
735 /* DNAME->owner is parent of CNAME->owner */
736 || !_dname_is_parent(dname->name, cname->name))
737 continue;
738
739
740 dname_labels = _dname_label_count(dname->name);
741 cname_labels = _dname_label_count(cname->name);
742
743 /* Synthesize the canonical name.
744 * First copy labels(cname) - labels(dname) labels from
745 * CNAME's owner name, then append DNAME rdata field.
746 * If it matches CNAME's rdata field then it was synthesized
747 * with this DNAME.
748 */
749 cname_labels -= dname_labels;
750 for ( c = cname->name, s = synth_name
751 ; cname_labels && s + *c + 1 < synth_name_end
752 ; cname_labels--, c += *c + 1, s += *s + 1 ) {
753
754 memcpy(s, c, *c + 1);
755 }
756 if (cname_labels)
757 continue;
758
759 /* Get DNAME's rdata field */
760 if ( !(drr = _getdns_rrtype_iter_init(&drr_spc, dname))
761 || !(drdf=_getdns_rdf_iter_init(&drdf_spc,&drr->rr_i))
762 || !(dname_rdata = _getdns_rdf_if_or_as_decompressed(
763 drdf, dname_rdata_spc, &dname_rdata_len)))
764 continue;
765
766 if (s + _dname_len(dname_rdata) > synth_name_end)
767 continue;
768
769 memcpy(s, dname_rdata, _dname_len(dname_rdata));
770 debug_sec_print_dname("Synthesized name: ", synth_name);
771 debug_sec_print_dname(" Canonical name: ", cname_rdata);
772 if (_dname_equal(synth_name, cname_rdata))
773 return 1;
774 }
775 return 0;
776 }
777
778 /* Create the validation chain structure for the given packet.
779 * When netreq is set, queries will be scheduled for the DS
780 * and DNSKEY RR's for the nodes on the validation chain.
781 *
782 * Scheduling is as follows.
783 * If the RRset has a signature, signer name is followed to schedule DS/DNSKEY.
784 * Otherwise, if the RRSET is a SOA, owner name is followed to schedule DS
785 * Otherwise, if the RRset is a CNAME, a SOA query is scheduled for the parent
786 * Otherwise, a SOA query is scheduled for the owner name.
787 *
788 * When a SOA query was successful, a query for DS will follow for that
789 * owner name.
790 */
add_pkt2val_chain(const struct mem_funcs * mf,chain_head ** chain_p,uint8_t * pkt,size_t pkt_len,getdns_network_req * netreq)791 static void add_pkt2val_chain(const struct mem_funcs *mf,
792 chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
793 getdns_network_req *netreq)
794 {
795 _getdns_rrset_iter *i, i_spc;
796 _getdns_rrset *rrset;
797 _getdns_rrsig_iter *rrsig, rrsig_spc;
798 size_t n_rrsigs;
799 chain_head *head;
800
801 assert(pkt);
802 assert(pkt_len >= GLDNS_HEADER_SIZE);
803
804 /* For all things with signatures, create a chain */
805
806 /* For all things without signature, find SOA (zonecut) and query DS */
807
808 for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len
809 , SECTION_NO_ADDITIONAL)
810 ; i
811 ; i = _getdns_rrset_iter_next(i)) {
812
813 rrset = _getdns_rrset_iter_value(i);
814 debug_sec_print_rrset("rrset: ", rrset);
815
816 /* Schedule validation for everything, except from DNAME
817 * synthesized CNAME's
818 */
819 if (is_synthesized_cname(rrset))
820 continue;
821
822 if (!(rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset))
823 && _getdns_rr_iter_section(&i->rr_i) != SECTION_ANSWER)
824 continue; /* No sigs in authority section is okayish */
825
826 if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq)))
827 continue;
828
829 for ( n_rrsigs = 0; rrsig
830 ; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
831
832 /* Signature, so lookup DS/DNSKEY at signer's name */
833 val_chain_sched_signer(head, rrsig);
834 }
835 if (n_rrsigs)
836 continue;
837
838 /* No signatures found for this RRset */
839 if (rrset->rr_type == GETDNS_RRTYPE_SOA)
840 val_chain_sched_ds(head, rrset->name);
841 else if (rrset->rr_type == GETDNS_RRTYPE_CNAME)
842 val_chain_sched_ds(head, rrset->name + *rrset->name + 1);
843 else
844 val_chain_sched_ds(head, rrset->name);
845 }
846 }
847
848 /* For NOERROR/NODATA or NXDOMAIN responses add extra rrset to
849 * the validation chain so the denial of existence will be
850 * checked eventually.
851 * But only if we know the question of course...
852 */
add_question2val_chain(const struct mem_funcs * mf,chain_head ** chain_p,uint8_t * pkt,size_t pkt_len,const uint8_t * qname,uint16_t qtype,uint16_t qclass,getdns_network_req * netreq)853 static void add_question2val_chain(const struct mem_funcs *mf,
854 chain_head **chain_p, uint8_t *pkt, size_t pkt_len,
855 const uint8_t *qname, uint16_t qtype, uint16_t qclass,
856 getdns_network_req *netreq)
857 {
858 _getdns_rrset_iter *i, i_spc;
859 _getdns_rrset *rrset;
860 _getdns_rrsig_iter rrsig_spc;
861 size_t n_soas;
862
863 _getdns_rrset_spc q_rrset;
864 chain_head *head;
865
866 assert(pkt);
867 assert(pkt_len >= GLDNS_HEADER_SIZE);
868 assert(qname);
869
870 /* First find the canonical name for the question */
871 q_rrset.rrset.name = qname;
872 q_rrset.rrset.rr_type = qtype;
873 q_rrset.rrset.rr_class = qclass;
874 q_rrset.rrset.pkt = pkt;
875 q_rrset.rrset.pkt_len = pkt_len;
876 q_rrset.rrset.sections = SECTION_ANSWER;
877
878 if (_getdns_initialized_rrset_answer(&q_rrset))
879 return;
880
881 /* No answer for the question. Add a head for this rrset
882 * anyway, to validate proof of non-existance, or to find
883 * proof that the packet is insecure.
884 */
885 debug_sec_print_rrset("Adding NX rrset: ", &q_rrset.rrset);
886 head = add_rrset2val_chain(mf, chain_p, &q_rrset.rrset, netreq);
887
888 /* Insecure SOA indicating a zonecut in the authority section?
889 * Then schedule a DS query at the zonecut for insecure proof.
890 */
891 n_soas = 0;
892 for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len
893 , SECTION_AUTHORITY)
894 ; i ; i = _getdns_rrset_iter_next(i)) {
895 rrset = _getdns_rrset_iter_value(i);
896 debug_sec_print_rrset("rrset: ", rrset);
897
898 if (rrset->rr_type != GETDNS_RRTYPE_SOA)
899 continue;
900
901 n_soas += 1;
902
903 if (_getdns_rrsig_iter_init(&rrsig_spc, rrset))
904 continue;
905
906 val_chain_sched_ds(head, rrset->name);
907 }
908 /* No answer and no SOA indicating a zonecut? Find zonecut */
909 if (n_soas == 0)
910 val_chain_sched_ds(head, q_rrset.rrset.name);
911 }
912
913
914 /************* Schedule Queries to Provision Validation Chain ***************
915 *****************************************************************************/
916
CD_extension(getdns_dns_req * dnsreq)917 static getdns_dict *CD_extension(getdns_dns_req *dnsreq)
918 {
919 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
920 return !dnsreq->dnssec_roadblock_avoidance
921 ? dnssec_ok_checking_disabled
922 : !dnsreq->avoid_dnssec_roadblocks
923 ? dnssec_ok_checking_disabled_roadblock_avoidance
924 : dnssec_ok_checking_disabled_avoid_roadblocks;
925 #else
926 (void)dnsreq;
927 return dnssec_ok_checking_disabled;
928 #endif
929 }
930
931 static void check_chain_complete(chain_head *chain);
932
_dnskey_query(const chain_node * node)933 static chain_head *_dnskey_query(const chain_node *node)
934 {
935 chain_head *head;
936
937 for (head = node->chains; head; head = head->next)
938 if (head->rrset.rr_type == GETDNS_RRTYPE_DNSKEY &&
939 head->parent == node)
940 return head;
941 return NULL;
942 }
943
944 static void val_chain_node_cb(getdns_dns_req *dnsreq);
val_chain_sched_node(chain_node * node)945 static void val_chain_sched_node(chain_node *node)
946 {
947 getdns_context *context;
948 getdns_eventloop *loop;
949 char name[1024];
950
951 context = node->chains->netreq->owner->context;
952 loop = node->chains->netreq->owner->loop;
953
954 if (!gldns_wire2str_dname_buf(
955 (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
956 return;
957
958 DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
959
960 node->lock++;
961 if (! node->dnskey_req) {
962 chain_head *head;
963
964 /* Reuse the DNSKEY query if this node is scheduled in the
965 * context of validating a DNSKEY query, because libunbound
966 * does not callback from a callback for the same query.
967 */
968
969 if ((head = _dnskey_query(node))) {
970 DEBUG_SEC("Found DNSKEY head: %p\n", (void *)head);
971 node->dnskey_req = head->netreq;
972 node->dnskey.pkt = head->netreq->response;
973 node->dnskey.pkt_len = head->netreq->response_len;
974
975 } else if (_getdns_general_loop(
976 context, loop, name, GETDNS_RRTYPE_DNSKEY,
977 CD_extension(node->chains->netreq->owner),
978 node, &node->dnskey_req, NULL, val_chain_node_cb))
979
980 node->dnskey_req = NULL;
981 }
982 if (! node->ds_req && node->parent /* not root */ &&
983 _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
984 CD_extension(node->chains->netreq->owner),
985 node, &node->ds_req, NULL, val_chain_node_cb))
986
987 node->ds_req = NULL;
988
989 if (node->lock) node->lock--;
990 }
991
val_chain_sched(chain_head * head,const uint8_t * dname)992 static void val_chain_sched(chain_head *head, const uint8_t *dname)
993 {
994 chain_node *node;
995
996 if (!head->netreq)
997 return;
998
999 for ( node = head->parent
1000 ; node && !_dname_equal(dname, node->ds.name)
1001 ; node = node->parent);
1002 if (node)
1003 val_chain_sched_node(node);
1004 }
1005
val_chain_sched_ds_node(chain_node * node)1006 static void val_chain_sched_ds_node(chain_node *node)
1007 {
1008 getdns_context *context;
1009 getdns_eventloop *loop;
1010 char name[1024];
1011
1012 context = node->chains->netreq->owner->context;
1013 loop = node->chains->netreq->owner->loop;
1014
1015 if (!gldns_wire2str_dname_buf(
1016 (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name)))
1017
1018 return;
1019
1020 DEBUG_SEC("schedule DS lookup for %s\n", name);
1021
1022 node->lock++;
1023 if (! node->ds_req && node->parent /* not root */ &&
1024 _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
1025 CD_extension(node->chains->netreq->owner),
1026 node, &node->ds_req, NULL, val_chain_node_cb))
1027
1028 node->ds_req = NULL;
1029
1030 if (node->lock) node->lock--;
1031 }
1032
val_chain_sched_ds(chain_head * head,const uint8_t * dname)1033 static void val_chain_sched_ds(chain_head *head, const uint8_t *dname)
1034 {
1035 chain_node *node;
1036
1037 if (!head->netreq)
1038 return;
1039
1040 for ( node = head->parent
1041 ; node && !_dname_equal(dname, node->ds.name)
1042 ; node = node->parent);
1043 if (node)
1044 val_chain_sched_ds_node(node);
1045 }
1046
val_chain_sched_signer_node(chain_node * node,_getdns_rrsig_iter * rrsig)1047 static void val_chain_sched_signer_node(chain_node *node, _getdns_rrsig_iter *rrsig)
1048 {
1049 _getdns_rdf_iter rdf_spc, *rdf;
1050 uint8_t signer_spc[256];
1051 const uint8_t *signer;
1052 size_t signer_len;
1053
1054 if (!(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rrsig->rr_i, 7)))
1055 return;
1056
1057 if (!(signer = _getdns_rdf_if_or_as_decompressed(
1058 rdf, signer_spc, &signer_len)))
1059 return;
1060
1061 while (node && !_dname_equal(signer, node->ds.name))
1062 node = node->parent;
1063 if (node)
1064 val_chain_sched_node(node);
1065 }
1066
val_chain_sched_signer(chain_head * head,_getdns_rrsig_iter * rrsig)1067 static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig)
1068 {
1069 if (!head->netreq)
1070 return;
1071
1072 val_chain_sched_signer_node(head->parent, rrsig);
1073 }
1074
1075 /* Cancel all DS and DNSKEY for subdomains of parent_dname,
1076 * and also the DNSKEY query at the parent_dname
1077 */
cancel_requests_for_subdomains_of(chain_head * head,const uint8_t * parent_dname)1078 static void cancel_requests_for_subdomains_of(
1079 chain_head *head, const uint8_t *parent_dname)
1080 {
1081 chain_head *next;
1082 chain_node *node;
1083 size_t node_count;
1084
1085 while (head) {
1086 next = head->next;
1087
1088 if (!_dname_is_parent(parent_dname, head->rrset.name)) {
1089 head = next;
1090 continue;
1091 }
1092 for ( node_count = head->node_count, node = head->parent
1093 ; node_count
1094 ; node_count--, node = node->parent ) {
1095
1096 if (!_getdns_netreq_finished(node->dnskey_req)) {
1097 _getdns_context_cancel_request(
1098 node->dnskey_req->owner);
1099 node->dnskey_req = NULL;
1100 }
1101
1102 if (_dname_equal(parent_dname, node->ds.name))
1103 break;
1104
1105 if (!_getdns_netreq_finished(node->ds_req)) {
1106 _getdns_context_cancel_request(
1107 node->ds_req->owner);
1108 node->ds_req = NULL;
1109 }
1110 }
1111 head = next;
1112 }
1113
1114 }
1115
1116 static int nsec3_matches_name(_getdns_rrset *nsec3, const uint8_t *name);
1117 static int nsec3_covers_name(
1118 _getdns_rrset *nsec3, const uint8_t *name, int *opt_out);
1119
insecure_delegation(_getdns_rrset * ds_rrset)1120 static int insecure_delegation(_getdns_rrset *ds_rrset)
1121 {
1122 _getdns_rrset nsec_rrset;
1123 _getdns_rrtype_iter *rr, rr_spc;
1124 _getdns_rrsig_iter rrsig_spc;
1125 _getdns_rdf_iter bitmap_spc, *bitmap;
1126 _getdns_rrset_iter *i, i_spc;
1127
1128 /* For NSEC, an insecure delegation is a NODATA proof for DS */
1129 nsec_rrset = *ds_rrset;
1130 nsec_rrset.rr_type = GETDNS_RRTYPE_NSEC;
1131 if (!_getdns_rrsig_iter_init(&rrsig_spc, &nsec_rrset))
1132 ; /* pass */
1133 else for ( rr = _getdns_rrtype_iter_init(&rr_spc, &nsec_rrset)
1134 ; rr ; rr = _getdns_rrtype_iter_next(rr)) {
1135
1136 if ((bitmap = _getdns_rdf_iter_init_at( &bitmap_spc
1137 , &rr->rr_i, 1))
1138 && bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
1139 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_DS)
1140 && _getdns_rrsig_iter_init(&rrsig_spc, &nsec_rrset))
1141 return 1;
1142 }
1143
1144 /* For NSEC3 it is either a NODATA proof with a delegation,
1145 or a NSEC3 opt-out coverage */
1146 for ( i = _getdns_rrset_iter_init(&i_spc, ds_rrset->pkt
1147 , ds_rrset->pkt_len
1148 , SECTION_NO_ADDITIONAL)
1149 ; i ; i = _getdns_rrset_iter_next(i)) {
1150 _getdns_rrset *nsec3_rrset = _getdns_rrset_iter_value(i);
1151 int opt_out;
1152
1153 if ( !nsec3_rrset
1154 || nsec3_rrset->rr_type != GETDNS_RRTYPE_NSEC3
1155 ||!(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3_rrset)))
1156 continue;
1157
1158 if (!nsec3_covers_name(nsec3_rrset, ds_rrset->name, &opt_out))
1159 continue;
1160
1161 if (nsec3_matches_name(nsec3_rrset, ds_rrset->name)) {
1162 bitmap = _getdns_rdf_iter_init_at( &bitmap_spc
1163 , &rr->rr_i, 5);
1164 return bitmap
1165 && bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
1166 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_DS);
1167 }
1168 else if (opt_out)
1169 return 1;
1170 }
1171 return 0;
1172 }
1173
val_chain_node_cb(getdns_dns_req * dnsreq)1174 static void val_chain_node_cb(getdns_dns_req *dnsreq)
1175 {
1176 chain_node *node = (chain_node *)dnsreq->user_pointer;
1177 getdns_network_req *netreq = dnsreq->netreqs[0];
1178 _getdns_rrset_iter *i, i_spc;
1179 _getdns_rrset *rrset;
1180 _getdns_rrsig_iter *rrsig, rrsig_spc;
1181 size_t n_signers;
1182
1183 switch (netreq->request_type) {
1184 case GETDNS_RRTYPE_DS : node->ds.pkt = netreq->response;
1185 node->ds.pkt_len = netreq->response_len;
1186 break;
1187 case GETDNS_RRTYPE_DNSKEY: node->dnskey.pkt = netreq->response;
1188 node->dnskey.pkt_len = netreq->response_len;
1189 /* fallthrough */
1190 default : check_chain_complete(node->chains);
1191 return;
1192 }
1193 node->lock++;
1194 n_signers = 0;
1195 for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response
1196 , netreq->response_len
1197 , SECTION_NO_ADDITIONAL)
1198 ; i
1199 ; i = _getdns_rrset_iter_next(i)) {
1200
1201 rrset = _getdns_rrset_iter_value(i);
1202
1203 if (rrset->rr_type != GETDNS_RRTYPE_DS &&
1204 rrset->rr_type != GETDNS_RRTYPE_NSEC &&
1205 rrset->rr_type != GETDNS_RRTYPE_NSEC3)
1206 continue;
1207
1208 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
1209 ; rrsig; rrsig = _getdns_rrsig_iter_next(rrsig)) {
1210
1211 val_chain_sched_signer_node(node, rrsig);
1212 n_signers++;
1213 }
1214 }
1215 if (netreq->request_type != GETDNS_RRTYPE_DS)
1216 ; /* pass */
1217 else if (n_signers) {
1218 _getdns_rrtype_iter ds_spc;
1219
1220 if (_getdns_rrtype_iter_init(&ds_spc, &node->ds))
1221 ; /* pass */
1222
1223 else if (insecure_delegation(&node->ds)) {
1224 debug_sec_print_rrset("Insecure delegation. "
1225 "Canceling requests below ", &node->ds);
1226 cancel_requests_for_subdomains_of(
1227 node->chains, node->ds.name);
1228 } else {
1229 debug_sec_print_rrset("No DS at ", &node->ds);
1230 }
1231 } else {
1232 /* No signed DS and no signed proof of non-existance.
1233 * Search further up the tree...
1234 */
1235 val_chain_sched_ds_node(node->parent);
1236 }
1237 if (node->lock) node->lock--;
1238 check_chain_complete(node->chains);
1239 }
1240
1241
1242 /*************************** DNSSEC Validation *****************************
1243 *****************************************************************************/
1244
1245
1246 /* Returns whether a key in set dnskey is used to sign rrset.
1247 * Only keytag and signer name is compared. The signature is not verified.
1248 */
key_matches_signer(_getdns_rrset * dnskey,_getdns_rrset * rrset)1249 static int key_matches_signer(_getdns_rrset *dnskey, _getdns_rrset *rrset)
1250 {
1251 _getdns_rrtype_iter rr_spc, *rr;
1252 _getdns_rrsig_iter rrsig_spc, *rrsig;
1253 uint16_t keytag;
1254 _getdns_rdf_iter rdf_spc, *rdf;
1255 uint8_t signer_spc[256];
1256 const uint8_t *signer;
1257 size_t signer_len = sizeof(signer_spc);
1258
1259 assert(dnskey->rr_type == GETDNS_RRTYPE_DNSKEY);
1260
1261
1262 for ( rr = _getdns_rrtype_iter_init(&rr_spc, dnskey)
1263 ; rr ; rr = _getdns_rrtype_iter_next(rr) ) {
1264
1265
1266 /* Enough space to at least read algorithm field? */
1267 if (rr->rr_i.nxt < rr->rr_i.rr_type + 14)
1268 continue;
1269
1270 /* Then we have at least 4 bytes to calculate keytag */
1271 keytag = gldns_calc_keytag_raw(
1272 (UNCONST_UINT8_p)rr->rr_i.rr_type + 10,
1273 rr->rr_i.nxt - rr->rr_i.rr_type - 10);
1274
1275 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
1276 ; rrsig ; rrsig = _getdns_rrsig_iter_next(rrsig) ) {
1277
1278 if (/* Space for keytag & signer in rrsig rdata? */
1279 rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 28
1280
1281 /* Does Algorithm match */
1282 && rrsig->rr_i.rr_type[12] == rr->rr_i.rr_type[13]
1283
1284 /* Does the keytag match? */
1285 && gldns_read_uint16(rrsig->rr_i.rr_type + 26)
1286 == keytag
1287
1288 /* Does the signer name match? */
1289 && (rdf = _getdns_rdf_iter_init_at(
1290 &rdf_spc, &rrsig->rr_i, 7))
1291
1292 && (signer = _getdns_rdf_if_or_as_decompressed(
1293 rdf, signer_spc, &signer_len))
1294
1295 && _dname_equal(dnskey->name, signer))
1296
1297 return keytag;
1298 }
1299 }
1300 return 0;
1301 }
1302
_rr_uncompressed_rdata_size(_getdns_rrtype_iter * rr)1303 static size_t _rr_uncompressed_rdata_size(_getdns_rrtype_iter *rr)
1304 {
1305 _getdns_rdf_iter *rdf, rdf_spc;
1306 uint8_t decompressed[256];
1307 size_t sz = 0, decompressed_sz;
1308
1309 for ( rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i)
1310 ; rdf
1311 ; rdf = _getdns_rdf_iter_next(rdf)) {
1312
1313 if ((rdf->rdd_pos->type & GETDNS_RDF_N_C) == GETDNS_RDF_N_C) {
1314 decompressed_sz = sizeof(decompressed);
1315 if (_getdns_rdf_if_or_as_decompressed(
1316 rdf, decompressed, &decompressed_sz))
1317 sz += decompressed_sz;
1318 } else
1319 sz += rdf->nxt - rdf->pos;
1320 }
1321 return sz;
1322 }
1323
_rr_rdata_size(_getdns_rrtype_iter * rr)1324 static size_t _rr_rdata_size(_getdns_rrtype_iter *rr)
1325 {
1326 const _getdns_rr_def *rr_def;
1327 size_t i;
1328
1329 rr_def = _getdns_rr_def_lookup(gldns_read_uint16(rr->rr_i.rr_type));
1330
1331 for (i = 0; i < rr_def->n_rdata_fields; i++)
1332 if ((rr_def->rdata[i].type & GETDNS_RDF_N_C) == GETDNS_RDF_N_C)
1333 return _rr_uncompressed_rdata_size(rr);
1334
1335 /* assert(gldns_read_uint16(rr->rr_type+8) == rr->nxt-rr->rr_type-10);
1336 */
1337 return rr->rr_i.nxt - rr->rr_i.rr_type - 10;
1338 }
1339
1340 /* Iterate byte by byte over rdata canonicalizing dname's */
1341 typedef struct canon_rdata_iter {
1342 _getdns_rdf_iter rdf_spc;
1343 _getdns_rdf_iter *rdf;
1344 uint8_t cdname[256]; /* Canonical dname */
1345 const uint8_t *pos;
1346 size_t len;
1347 } canon_rdata_iter;
1348
canon_rdata_iter_field_init(canon_rdata_iter * i)1349 static inline void canon_rdata_iter_field_init(canon_rdata_iter *i)
1350 {
1351 for (;;) {
1352 if ((i->rdf->rdd_pos->type & GETDNS_RDF_N) == GETDNS_RDF_N) {
1353 i->len = sizeof(i->cdname);
1354 if ((i->pos = _getdns_rdf_if_or_as_decompressed(
1355 i->rdf, i->cdname, &i->len))) {
1356 _dname_canonicalize(i->pos, i->cdname);
1357 i->pos = i->cdname;
1358 }
1359 } else {
1360 i->pos = i->rdf->pos;
1361 i->len = i->rdf->nxt - i->rdf->pos;
1362 }
1363 if (i->len || !(i->rdf = _getdns_rdf_iter_next(i->rdf)))
1364 return;
1365 }
1366 }
1367
canon_rdata_iter_init(canon_rdata_iter * i,_getdns_rr_iter * rr)1368 static inline void canon_rdata_iter_init(canon_rdata_iter*i,_getdns_rr_iter*rr)
1369 {
1370 if ((i->rdf = _getdns_rdf_iter_init(&i->rdf_spc, rr)))
1371 canon_rdata_iter_field_init(i);
1372 }
1373
canon_rdata_iter_data(canon_rdata_iter * i)1374 static inline int canon_rdata_iter_data(canon_rdata_iter *i)
1375 {
1376 return i->rdf != NULL;
1377 }
1378
canon_rdata_iter_byte(canon_rdata_iter * i)1379 static inline uint8_t canon_rdata_iter_byte(canon_rdata_iter *i)
1380 {
1381 return *i->pos;
1382 }
1383
canon_rdata_iter_next(canon_rdata_iter * i)1384 static inline void canon_rdata_iter_next(canon_rdata_iter *i)
1385 {
1386 if (--i->len == 0 && (i->rdf = _getdns_rdf_iter_next(i->rdf)))
1387 canon_rdata_iter_field_init(i);
1388 else
1389 i->pos++;
1390 }
1391
_rr_iter_rdata_cmp(const void * a,const void * b)1392 static int _rr_iter_rdata_cmp(const void *a, const void *b)
1393 {
1394 _getdns_rr_iter *x = (_getdns_rr_iter *)a;
1395 _getdns_rr_iter *y = (_getdns_rr_iter *)b;
1396
1397 uint16_t rr_type = gldns_read_uint16(x->rr_type);
1398 size_t x_rdata_len, y_rdata_len;
1399 int r;
1400
1401 canon_rdata_iter p, q;
1402
1403 assert(rr_type == gldns_read_uint16(y->rr_type));
1404
1405 if (!_dnssec_rdata_to_canonicalize(rr_type)) {
1406 /* Memory compare of rdata */
1407 x_rdata_len = x->nxt - x->rr_type - 10;
1408 y_rdata_len = y->nxt - y->rr_type - 10;
1409 if ((r = memcmp(x->rr_type + 10, y->rr_type + 10,
1410 x_rdata_len < y_rdata_len ? x_rdata_len : y_rdata_len)))
1411 return r;
1412 return x_rdata_len < y_rdata_len ? -1 :
1413 x_rdata_len > y_rdata_len ? 1 : 0;
1414 }
1415 for ( canon_rdata_iter_init(&p, x), canon_rdata_iter_init(&q, y)
1416 ; canon_rdata_iter_data(&p) && canon_rdata_iter_data(&q)
1417 ; canon_rdata_iter_next(&p) , canon_rdata_iter_next(&q) ) {
1418
1419 if (canon_rdata_iter_byte(&p) != canon_rdata_iter_byte(&q))
1420 return canon_rdata_iter_byte(&p) >
1421 canon_rdata_iter_byte(&q) ? 1 : -1;
1422 }
1423 return canon_rdata_iter_data(&p) ? 1
1424 : canon_rdata_iter_data(&q) ? -1 : 0;
1425 }
1426
1427 /* Verifies the signature rrsig for rrset rrset with key key.
1428 * When the rrset was a wildcard expansion (rrsig labels < labels owner name),
1429 * nc_name will be set to the next closer (within rrset->name).
1430 */
1431 #define VAL_RRSET_SPC_SZ 256
_getdns_verify_rrsig(const struct mem_funcs * mf,_getdns_rrset * rrset,_getdns_rrsig_iter * rrsig,_getdns_rrtype_iter * key,const uint8_t ** nc_name)1432 static int _getdns_verify_rrsig(const struct mem_funcs *mf,
1433 _getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key,
1434 const uint8_t **nc_name)
1435 {
1436 int r;
1437 int to_skip;
1438 _getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ];
1439 _getdns_rr_iter *val_rrset = val_rrset_spc;
1440 _getdns_rrtype_iter rr_spc, *rr;
1441 size_t n_rrs, i, valbuf_sz, owner_len;
1442 _getdns_rdf_iter *signer, signer_spc, *rdf, rdf_spc;
1443 uint8_t valbuf_spc[4096], *valbuf_buf = valbuf_spc;
1444 uint8_t cdname_spc[256], owner[256];
1445 const uint8_t *cdname, *owner_offset;
1446 size_t cdname_len, pos;
1447 uint32_t orig_ttl;
1448 gldns_buffer valbuf;
1449 char *reason;
1450
1451 /* nc_name should already have been initialized by the parent! */
1452 assert(nc_name);
1453 assert(!*nc_name);
1454
1455 if (!(signer = _getdns_rdf_iter_init_at(&signer_spc, &rrsig->rr_i, 7)))
1456 return 0;
1457 valbuf_sz = signer->nxt - rrsig->rr_i.rr_type - 10;
1458
1459 /* We were able to get the signer,
1460 * so the labels rdata field is definitely readable
1461 */
1462 assert(rrsig->rr_i.rr_type + 14 <= rrsig->rr_i.nxt);
1463
1464 /* If the number of labels in the owner is larger than "labels" rdata
1465 * field, then this is a wildcard expansion.
1466 */
1467 if (_dname_label_count(rrset->name) > (size_t)rrsig->rr_i.rr_type[13]) {
1468
1469 /* This is a valid wildcard expansion. Calculate and return the
1470 * "Next closer" name, because we need another NSEC to cover it.
1471 * (except for rrsigs for NSECs, but those are dealt with later)
1472 */
1473 to_skip = (int)_dname_label_count(rrset->name)
1474 - (int)rrsig->rr_i.rr_type[13];
1475
1476 for ( owner_offset = rrset->name
1477 ; to_skip > 0
1478 ; owner_offset += *owner_offset + 1, to_skip--);
1479
1480 if ((owner_len = _dname_len(owner_offset) + 2) > 255)
1481 return 0;
1482
1483 owner[0] = 1; owner[1] = '*';
1484 (void) memcpy(owner + 2, owner_offset, owner_len - 2);
1485
1486 } else if ((owner_len = _dname_len(rrset->name)) > 255)
1487 return 0;
1488 else
1489 (void) memcpy(owner, rrset->name, owner_len);
1490
1491 _dname_canonicalize2(owner);
1492
1493 for (;;) {
1494 for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset), n_rrs = 0
1495 ; rr
1496 ; rr = _getdns_rrtype_iter_next(rr), n_rrs++) {
1497
1498 if (val_rrset == val_rrset_spc) {
1499 valbuf_sz += owner_len
1500 + 2 /* type */
1501 + 2 /* class */
1502 + 4 /* Orig TTL */
1503 + 2 /* Rdata len */
1504 + _rr_rdata_size(rr);
1505 if (n_rrs < VAL_RRSET_SPC_SZ)
1506 val_rrset[n_rrs] = rr->rr_i;
1507 } else
1508 val_rrset[n_rrs] = rr->rr_i;
1509 }
1510 /* Did everything fit? Then break */
1511 if (val_rrset != val_rrset_spc || n_rrs <= VAL_RRSET_SPC_SZ)
1512 break;
1513
1514 /* More space needed for val_rrset */
1515 val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, n_rrs);
1516 }
1517 DEBUG_SEC( "sizes: %"PRIsz" rrs, %"PRIsz" bytes for validation buffer\n"
1518 , n_rrs, valbuf_sz);
1519
1520 qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
1521
1522 if (valbuf_sz >= sizeof(valbuf_spc))
1523 valbuf_buf = GETDNS_XMALLOC(*mf, uint8_t, valbuf_sz);
1524
1525 gldns_buffer_init_frm_data(&valbuf, valbuf_buf, valbuf_sz);
1526 gldns_buffer_write(&valbuf,
1527 rrsig->rr_i.rr_type + 10, signer->nxt - rrsig->rr_i.rr_type - 10);
1528 _dname_canonicalize2(gldns_buffer_at(&valbuf, 18));
1529
1530 orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
1531
1532 if (!_dnssec_rdata_to_canonicalize(rrset->rr_type))
1533 for (i = 0; i < n_rrs; i++) {
1534 /* Get rid of doubles */
1535 if (i && !_rr_iter_rdata_cmp(
1536 &val_rrset[i], &val_rrset[i-1]))
1537 continue;
1538
1539 gldns_buffer_write(&valbuf, owner, owner_len);
1540 gldns_buffer_write_u16(&valbuf, rrset->rr_type);
1541 gldns_buffer_write_u16(&valbuf, rrset->rr_class);
1542 gldns_buffer_write_u32(&valbuf, orig_ttl);
1543 gldns_buffer_write(&valbuf, val_rrset[i].rr_type + 8,
1544 val_rrset[i].nxt - val_rrset[i].rr_type - 8);
1545 }
1546 else for (i = 0; i < n_rrs; i++) {
1547 if (i && !_rr_iter_rdata_cmp(&val_rrset[i], &val_rrset[i-1]))
1548 continue;
1549 gldns_buffer_write(&valbuf, owner, owner_len);
1550 gldns_buffer_write_u16(&valbuf, rrset->rr_type);
1551 gldns_buffer_write_u16(&valbuf, rrset->rr_class);
1552 gldns_buffer_write_u32(&valbuf, orig_ttl);
1553 pos = gldns_buffer_position(&valbuf);
1554 gldns_buffer_skip(&valbuf, 2);
1555 for ( rdf = _getdns_rdf_iter_init(&rdf_spc, &val_rrset[i])
1556 ; rdf
1557 ; rdf = _getdns_rdf_iter_next(rdf) ) {
1558 if (!(rdf->rdd_pos->type & GETDNS_RDF_N)) {
1559 gldns_buffer_write(
1560 &valbuf, rdf->pos, rdf->nxt - rdf->pos);
1561 continue;
1562 }
1563 cdname_len = sizeof(cdname);
1564 if (!(cdname = _getdns_rdf_if_or_as_decompressed(
1565 rdf, cdname_spc, &cdname_len)))
1566 continue;
1567 gldns_buffer_write(&valbuf, cdname, cdname_len);
1568 _dname_canonicalize2(
1569 gldns_buffer_current(&valbuf) - cdname_len);
1570 }
1571 gldns_buffer_write_u16_at(&valbuf, pos,
1572 (uint16_t)(gldns_buffer_position(&valbuf) - pos - 2));
1573 }
1574 DEBUG_SEC( "written to valbuf: %"PRIsz" bytes\n"
1575 , gldns_buffer_position(&valbuf));
1576 assert(gldns_buffer_position(&valbuf) <= valbuf_sz);
1577
1578 gldns_buffer_flip(&valbuf);
1579 r = _getdns_verify_canonrrset(&valbuf, key->rr_i.rr_type[13],
1580 (UNCONST_UINT8_p)signer->nxt, rrsig->rr_i.nxt - signer->nxt,
1581 (UNCONST_UINT8_p)key->rr_i.rr_type+14,
1582 key->rr_i.nxt - key->rr_i.rr_type-14,
1583 &reason);
1584
1585 #if defined(SEC_DEBUG) && SEC_DEBUG
1586 if (r == 0) {
1587 DEBUG_SEC("verification failed: %s\n", reason);
1588 debug_sec_print_dname("verification failed for: ", owner);
1589 debug_sec_print_rrset("verification failed for rrset: ", rrset);
1590 debug_sec_print_rr("verification failed sig: ", &rrsig->rr_i);
1591 debug_sec_print_rr("verification failed key: ", &key->rr_i);
1592 }
1593 #endif
1594 if (val_rrset != val_rrset_spc)
1595 GETDNS_FREE(*mf, val_rrset);
1596 if (valbuf_buf != valbuf_spc)
1597 GETDNS_FREE(*mf, valbuf_buf);
1598 if (!r)
1599 return 0;
1600
1601 /* Verification has already been done, so the labels rdata field is
1602 * definitely readable
1603 */
1604 assert(rrsig->rr_i.rr_type + 14 <= rrsig->rr_i.nxt);
1605
1606 /* If the number of labels in the owner name mathes the "labels" rdata
1607 * field, then this was not a wildcard expansion, and everything is
1608 * good.
1609 */
1610 if ((size_t)rrsig->rr_i.rr_type[13] == _dname_label_count(rrset->name))
1611 return 1;
1612
1613 /* This is a valid wildcard expansion. Calculate and return the
1614 * "Next closer" name, because we need another NSEC to cover it.
1615 * (except for rrsigs for NSECs, but those are dealt with later)
1616 */
1617 to_skip = (int)_dname_label_count(rrset->name)
1618 - (int)rrsig->rr_i.rr_type[13] - 1;
1619
1620 for ( *nc_name = rrset->name
1621 ; to_skip > 0
1622 ; *nc_name += **nc_name + 1, to_skip--);
1623
1624 return 1;
1625 }
1626
1627 /* Calculates NSEC3 hash for name, and stores that into label */
_getdns_nsec3_hash_label(uint8_t * label,size_t label_len,const uint8_t * name,uint8_t algorithm,uint16_t iterations,const uint8_t * salt)1628 static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len,
1629 const uint8_t *name, uint8_t algorithm,
1630 uint16_t iterations, const uint8_t *salt)
1631 {
1632 uint8_t buf[512], *dst, *eob;
1633 const uint8_t *src;
1634 uint8_t md[SHA_DIGEST_LENGTH + 256];
1635
1636 assert(SHA_DIGEST_LENGTH + 256 < sizeof(buf));
1637
1638 if (algorithm != GLDNS_SHA1)
1639 return NULL;
1640
1641 for ( src = name, dst = buf, eob = buf + sizeof(buf)
1642 ; *src && dst + *src < eob
1643 ; src += *src + 1, dst += *dst + 1 )
1644 _dname_label_copy(dst, src, eob - dst);
1645
1646 if (*src || dst + *salt >= eob)
1647 return NULL;
1648 *dst++ = 0;
1649 (void)memcpy(dst, salt + 1, *salt);
1650 dst += *salt;
1651
1652 _getdns_tls_sha1(buf, dst - buf, md);
1653 if (iterations) {
1654 (void)memcpy(buf + SHA_DIGEST_LENGTH, salt + 1, *salt);
1655 while (iterations--) {
1656 (void)memcpy(buf, md, SHA_DIGEST_LENGTH);
1657 _getdns_tls_sha1(buf, SHA_DIGEST_LENGTH + *salt, md);
1658 }
1659 }
1660 *label = gldns_b32_ntop_extended_hex(
1661 md, SHA_DIGEST_LENGTH, (char *)label + 1, label_len - 1);
1662
1663 return label;
1664 }
1665
name2nsec3_label(_getdns_rrset * nsec3,const uint8_t * name,uint8_t * label,size_t label_len)1666 static uint8_t *name2nsec3_label(
1667 _getdns_rrset *nsec3, const uint8_t *name, uint8_t *label, size_t label_len)
1668 {
1669 _getdns_rrsig_iter rrsig_spc, *rrsig;
1670 _getdns_rdf_iter rdf_spc, *rdf;
1671 uint8_t signer_spc[256];
1672 const uint8_t *signer;
1673 size_t signer_len = sizeof(signer_spc);
1674 _getdns_rrtype_iter rr_spc, *rr;
1675
1676 if (/* With the "first" signature */
1677 (rrsig = _getdns_rrsig_iter_init(&rrsig_spc, nsec3))
1678
1679 /* Access the signer name rdata field (7th) */
1680 && (rdf = _getdns_rdf_iter_init_at(
1681 &rdf_spc, &rrsig->rr_i, 7))
1682
1683 /* Verify & decompress */
1684 && (signer = _getdns_rdf_if_or_as_decompressed(
1685 rdf, signer_spc, &signer_len))
1686
1687 /* signer of the NSEC3 is direct parent for this NSEC3? */
1688 && _dname_equal(
1689 signer, nsec3->name + *nsec3->name + 1)
1690
1691 /* signer of the NSEC3 is parent of name? */
1692 && _dname_is_parent(signer, name)
1693
1694 /* Initialize rr for getting NSEC3 rdata fields */
1695 && (rr = _getdns_rrtype_iter_init(&rr_spc, nsec3))
1696
1697 /* Check for available space to get rdata fields */
1698 && rr->rr_i.rr_type + 15 <= rr->rr_i.nxt
1699 && rr->rr_i.rr_type + 14 + rr->rr_i.rr_type[14] <= rr->rr_i.nxt)
1700
1701 /* Get the hashed label */
1702 return _getdns_nsec3_hash_label(label, label_len, name,
1703 rr->rr_i.rr_type[10],
1704 gldns_read_uint16(rr->rr_i.rr_type + 12),
1705 rr->rr_i.rr_type + 14);
1706 return NULL;
1707 }
1708
1709
nsec3_iteration_count_high(_getdns_rrtype_iter * dnskey,_getdns_rrset * nsec3)1710 static int nsec3_iteration_count_high(_getdns_rrtype_iter *dnskey, _getdns_rrset *nsec3)
1711 {
1712 _getdns_rrtype_iter rr_spc, *rr;
1713 size_t bits;
1714
1715 /* No NSEC3, then iteration count is not too high */
1716 if (nsec3->rr_type != GETDNS_RRTYPE_NSEC3)
1717 return 0;
1718
1719 /* Enough space to at least read algorithm field?
1720 * Without key data iteration count is definitely too high.
1721 */
1722 if (dnskey->rr_i.nxt < dnskey->rr_i.rr_type + 14)
1723 return 1;
1724
1725 if (/* Initialize rr for getting NSEC3 rdata fields */
1726 !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3))
1727
1728 /* Check for available space to get rdata fields */
1729 || rr->rr_i.rr_type + 14 > rr->rr_i.nxt)
1730 return 1;
1731
1732 bits = gldns_rr_dnskey_key_size_raw(dnskey->rr_i.rr_type + 10,
1733 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10,
1734 dnskey->rr_i.rr_type[13]);
1735
1736 if (bits > 2048)
1737 return gldns_read_uint16(rr->rr_i.rr_type + 12) > 2500;
1738 else if (bits > 1024)
1739 return gldns_read_uint16(rr->rr_i.rr_type + 12) > 500;
1740 else
1741 return gldns_read_uint16(rr->rr_i.rr_type + 12) > 150;
1742 }
1743
check_dates(time_t now,int32_t skew,int32_t exp,int32_t inc)1744 static int check_dates(time_t now, int32_t skew, int32_t exp, int32_t inc)
1745 {
1746 return (exp - inc > 0) && (inc - now < skew) && (now - exp < skew);
1747 }
1748
1749 /* Returns whether dnskey signed rrset. If the rrset was a valid wildcard
1750 * expansion, nc_name will point to the next closer part of the name in rrset.
1751 */
dnskey_signed_rrset(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrtype_iter * dnskey,_getdns_rrset * rrset,const uint8_t ** nc_name)1752 static int dnskey_signed_rrset(const struct mem_funcs *mf, time_t now,
1753 uint32_t skew, _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset,
1754 const uint8_t **nc_name)
1755 {
1756 _getdns_rrsig_iter rrsig_spc, *rrsig;
1757 _getdns_rdf_iter rdf_spc, *rdf;
1758 uint8_t signer_spc[256];
1759 const uint8_t *signer;
1760 size_t signer_len = sizeof(signer_spc);
1761 uint16_t keytag;
1762
1763 assert(dnskey->rrset->rr_type == GETDNS_RRTYPE_DNSKEY);
1764 assert(nc_name);
1765
1766 *nc_name = NULL;
1767
1768 /* Enough space to at least read algorithm field? */
1769 if (dnskey->rr_i.nxt < dnskey->rr_i.rr_type + 14)
1770 return 0;
1771
1772 /* Then we have at least 4 bytes to calculate keytag */
1773 keytag = gldns_calc_keytag_raw((UNCONST_UINT8_p)dnskey->rr_i.rr_type + 10,
1774 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
1775
1776 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
1777 ; rrsig ; rrsig = _getdns_rrsig_iter_next(rrsig) ) {
1778
1779 if (/* Space for keytag & signer in rrsig rdata? */
1780 rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 28
1781
1782 /* Does Algorithm match */
1783 && rrsig->rr_i.rr_type[12] == dnskey->rr_i.rr_type[13]
1784
1785 /* Does the keytag match? */
1786 && gldns_read_uint16(rrsig->rr_i.rr_type + 26) == keytag
1787
1788 /* Signature still (or already) valid? */
1789 && check_dates(now, skew,
1790 gldns_read_uint32(rrsig->rr_i.rr_type + 18),
1791 gldns_read_uint32(rrsig->rr_i.rr_type + 22))
1792
1793 /* Does the signer name match? */
1794 && (rdf = _getdns_rdf_iter_init_at(
1795 &rdf_spc, &rrsig->rr_i, 7))
1796
1797 && (signer = _getdns_rdf_if_or_as_decompressed(
1798 rdf, signer_spc, &signer_len))
1799
1800 && _dname_equal(dnskey->rrset->name, signer)
1801
1802 /* Does the signature verify? */
1803 && _getdns_verify_rrsig(mf, rrset,rrsig,dnskey,nc_name)) {
1804
1805 debug_sec_print_rr("key ", &dnskey->rr_i);
1806 debug_sec_print_rrset("signed ", rrset);
1807
1808 /* Signal insecurity by too high nsec3 iteration
1809 * count with NSEC3_ITERATION_COUNT_HIGH
1810 * bit in return value.
1811 */
1812 return ( nsec3_iteration_count_high(dnskey, rrset)
1813 ? NSEC3_ITERATION_COUNT_HIGH
1814 : SIGNATURE_VERIFIED
1815 ) | keytag;
1816 }
1817 }
1818 return 0;
1819 }
1820
1821 /* Returns whether a dnskey for keyset signed a non wildcard rrset. */
a_key_signed_rrset_no_wc(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * keyset,_getdns_rrset * rrset)1822 static int a_key_signed_rrset_no_wc(const struct mem_funcs *mf, time_t now,
1823 uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
1824 {
1825 _getdns_rrtype_iter dnskey_spc, *dnskey;
1826 const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
1827 int keytag;
1828
1829 assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
1830
1831 for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, keyset)
1832 ; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey) ) {
1833
1834 if (!(keytag = dnskey_signed_rrset(mf, now, skew,
1835 dnskey, rrset, &nc_name)))
1836 continue;
1837
1838 if (!nc_name) /* Not a wildcard, then success! */
1839 return keytag;
1840
1841 /* Not a wildcard expansion, but the wildcard name itself. */
1842 if (rrset->rr_type == GETDNS_RRTYPE_NSEC &&
1843 rrset->name[0] == 1 && rrset->name[1] == '*' &&
1844 nc_name == rrset->name)
1845 return keytag;
1846 }
1847 return 0;
1848 }
1849
1850 static int find_nsec_covering_name(const struct mem_funcs *mf,
1851 time_t now, uint32_t skew, _getdns_rrset *dnskey,
1852 _getdns_rrset *rrset, const uint8_t *name, int *opt_out);
1853
1854 /* Returns whether a dnskey for keyset signed rrset. */
a_key_signed_rrset(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * keyset,_getdns_rrset * rrset)1855 static int a_key_signed_rrset(const struct mem_funcs *mf, time_t now,
1856 uint32_t skew, _getdns_rrset *keyset, _getdns_rrset *rrset)
1857 {
1858 _getdns_rrtype_iter dnskey_spc, *dnskey;
1859 const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
1860
1861 int keytag;
1862
1863 assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
1864
1865 for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, keyset)
1866 ; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey) ) {
1867
1868 if (!(keytag = dnskey_signed_rrset(mf, now, skew,
1869 dnskey, rrset, &nc_name)))
1870 continue;
1871
1872 if (!nc_name) /* Not a wildcard, then success! */
1873 return keytag;
1874
1875 /* Wildcard RRSIG for a NSEC on the wildcard.
1876 * There is no more specific!
1877 */
1878 if (rrset->rr_type == GETDNS_RRTYPE_NSEC &&
1879 rrset->name[0] == 1 && rrset->name[1] == '*' &&
1880 nc_name == rrset->name)
1881 return keytag;
1882
1883 debug_sec_print_rrset("wildcard expanded to: ", rrset);
1884 debug_sec_print_dname("Find NSEC covering the more sepecific: "
1885 , nc_name);
1886
1887 if (find_nsec_covering_name(
1888 mf, now, skew, keyset, rrset, nc_name, NULL))
1889 return keytag;
1890 }
1891 return 0;
1892 }
1893
1894 /* Returns whether a DS in ds_set matches a dnskey in dnskey_set which in turn
1895 * signed the dnskey set.
1896 */
ds_authenticates_keys(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * ds_set,_getdns_rrset * dnskey_set)1897 static int ds_authenticates_keys(const struct mem_funcs *mf,
1898 time_t now, uint32_t skew, _getdns_rrset *ds_set, _getdns_rrset *dnskey_set)
1899 {
1900 _getdns_rrtype_iter dnskey_spc, *dnskey;
1901 _getdns_rrtype_iter ds_spc, *ds;
1902 uint16_t keytag;
1903 const uint8_t *nc_name; /* Initialized by dnskey_signed_rrset() */
1904 size_t valid_dsses = 0, supported_dsses = 0;
1905 uint8_t max_supported_digest = 0;
1906 int max_supported_result = 0;
1907 unsigned char digest_spc[256], *digest;
1908 unsigned char digest_buf_spc[2048], *digest_buf;
1909 size_t digest_len, digest_buf_len, dnskey_owner_len;
1910
1911 assert(ds_set->rr_type == GETDNS_RRTYPE_DS);
1912 assert(dnskey_set->rr_type == GETDNS_RRTYPE_DNSKEY);
1913
1914 /* The ds_set is already authenticated! */
1915
1916 if (!_dname_equal(ds_set->name, dnskey_set->name))
1917 return 0;
1918
1919 debug_sec_print_rrset("ds_authenticates_keys DS: ", ds_set);
1920 debug_sec_print_rrset("ds_authenticates_keys DNSKEY: ", dnskey_set);
1921
1922 if ((dnskey_owner_len = _dname_len(dnskey_set->name)) >= 255)
1923 return 0;
1924
1925 (void) memcpy(digest_buf_spc, dnskey_set->name, dnskey_owner_len);
1926 _dname_canonicalize2(digest_buf_spc);
1927
1928 for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, dnskey_set)
1929 ; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey)) {
1930
1931 /* Enough space to at least read algorithm field? */
1932 if (dnskey->rr_i.nxt < dnskey->rr_i.rr_type + 14)
1933 continue;
1934
1935 keytag = gldns_calc_keytag_raw(
1936 (UNCONST_UINT8_p) dnskey->rr_i.rr_type + 10,
1937 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
1938
1939 for ( ds = _getdns_rrtype_iter_init(&ds_spc, ds_set)
1940 ; ds ; ds = _getdns_rrtype_iter_next(ds)) {
1941
1942 if (/* Space for keytag, algorithm & digest type? */
1943 ds->rr_i.nxt < ds->rr_i.rr_type + 14
1944
1945 /* Does algorithm match? */
1946 || ds->rr_i.rr_type[12] != dnskey->rr_i.rr_type[13]
1947
1948 /* Does the keytag match? */
1949 || gldns_read_uint16(ds->rr_i.rr_type+10)!=keytag)
1950
1951 continue;
1952
1953 valid_dsses++;
1954
1955 if (/* Algorithm is not RSAMD5 (deprecated) */
1956 ds->rr_i.rr_type[12] == GLDNS_RSAMD5
1957
1958 /* Algorithm is supported */
1959 || !_getdns_dnskey_algo_id_is_supported(
1960 ds->rr_i.rr_type[12])
1961
1962 /* Digest is supported */
1963 || !(digest_len = _getdns_ds_digest_size_supported(
1964 ds->rr_i.rr_type[13])))
1965
1966 continue;
1967
1968 digest = digest_len <= sizeof(digest_spc) ? digest_spc
1969 : GETDNS_XMALLOC(*mf, unsigned char, digest_len);
1970
1971 digest_buf_len = dnskey->rr_i.nxt
1972 - dnskey->rr_i.rr_type - 10
1973 + dnskey_owner_len;
1974 digest_buf = digest_buf_len <= sizeof(digest_buf_spc)
1975 ? digest_buf_spc
1976 : GETDNS_XMALLOC(*mf, unsigned char, digest_buf_len);
1977
1978 if (digest_buf != digest_buf_spc)
1979 (void) memcpy(digest_buf,
1980 digest_buf_spc, dnskey_owner_len);
1981
1982 (void) memcpy(digest_buf + dnskey_owner_len,
1983 dnskey->rr_i.rr_type + 10,
1984 dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10);
1985
1986 if (!_getdns_secalgo_ds_digest(ds->rr_i.rr_type[13],
1987 digest_buf, digest_buf_len, digest)) {
1988
1989 if (digest != digest_spc)
1990 GETDNS_FREE(*mf, digest);
1991 if (digest_buf != digest_buf_spc)
1992 GETDNS_FREE(*mf, digest_buf);
1993 continue;
1994 }
1995 supported_dsses++;
1996
1997 /* The result of the best digest type counts!
1998 * We'll assume higher is better for now.
1999 * So, continue with next DS if...
2000 */
2001 if (/* we already had a better digest earlier */
2002 ds->rr_i.rr_type[13] < max_supported_digest
2003
2004 /* or we had the same digest and it already gave
2005 * a match (to a key in dnskey_set which
2006 * authenticated the dnskey_set).
2007 */
2008 || ( ds->rr_i.rr_type[13] == max_supported_digest
2009 && max_supported_result)) {
2010 if (digest != digest_spc)
2011 GETDNS_FREE(*mf, digest);
2012 if (digest_buf != digest_buf_spc)
2013 GETDNS_FREE(*mf, digest_buf);
2014
2015 DEBUG_SEC("Better DS available\n");
2016 continue;
2017 }
2018 max_supported_digest = ds->rr_i.rr_type[13];
2019 max_supported_result = 0;
2020
2021 if ((int)digest_len != ds->rr_i.nxt - ds->rr_i.rr_type-14
2022 || memcmp(digest, ds->rr_i.rr_type+14, digest_len) != 0) {
2023 if (digest != digest_spc)
2024 GETDNS_FREE(*mf, digest);
2025 if (digest_buf != digest_buf_spc)
2026 GETDNS_FREE(*mf, digest_buf);
2027
2028 DEBUG_SEC("HASH length mismatch %"PRIsz" != %"PRIsz"\n",
2029 digest_len, ds->rr_i.nxt - ds->rr_i.rr_type-14);
2030 continue;
2031 }
2032 /* Match! */
2033 if (digest != digest_spc)
2034 GETDNS_FREE(*mf, digest);
2035 if (digest_buf != digest_buf_spc)
2036 GETDNS_FREE(*mf, digest_buf);
2037
2038 if (!dnskey_signed_rrset(mf, now, skew,
2039 dnskey, dnskey_set, &nc_name)
2040 || nc_name /* No DNSKEY's on wildcards! */) {
2041
2042 debug_sec_print_rrset("keyset did not "
2043 "authenticate: ", dnskey_set);
2044 continue;
2045 }
2046 debug_sec_print_rrset(
2047 "keyset authenticated: ", dnskey_set);
2048 max_supported_result = SIGNATURE_VERIFIED | keytag;
2049 }
2050 }
2051 DEBUG_SEC("valid_dsses: %"PRIsz", supported_dsses: %"PRIsz"\n",
2052 valid_dsses, supported_dsses);
2053 if (valid_dsses && !supported_dsses)
2054 return NO_SUPPORTED_ALGORITHMS;
2055 else
2056 return max_supported_result;
2057 }
2058
nsec_covers_name(_getdns_rrset * nsec,const uint8_t * name,const uint8_t ** ce_name)2059 static int nsec_covers_name(
2060 _getdns_rrset *nsec, const uint8_t *name, const uint8_t **ce_name)
2061 {
2062 uint8_t owner_spc[256], next_spc[256];
2063 const uint8_t *owner, *next;
2064 size_t owner_len = sizeof(owner_spc), next_len = sizeof(next_spc);
2065
2066 _getdns_rrtype_iter rr_spc, *rr;
2067 _getdns_rdf_iter rdf_spc, *rdf;
2068 int nsec_cmp;
2069 const uint8_t *common1, *common2;
2070
2071 if (/* Get owner and next, nicely decompressed */
2072 !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec))
2073 || !(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))
2074 || !(owner = _getdns_owner_if_or_as_decompressed(
2075 &rr->rr_i, owner_spc, &owner_len))
2076 || !(next = _getdns_rdf_if_or_as_decompressed(
2077 rdf, next_spc, &next_len)))
2078 return 0;
2079
2080 debug_sec_print_dname("nsec owner: ", owner);
2081 debug_sec_print_dname("name : ", name);
2082 debug_sec_print_dname("nsec next : ", next);
2083
2084 if (ce_name) {
2085 common1 = dname_shared_parent(name, owner);
2086 common2 = dname_shared_parent(name, next);
2087 *ce_name = _dname_label_count(common1)
2088 > _dname_label_count(common2) ? common1 : common2;
2089 debug_sec_print_dname("nsec closest encloser: ", *ce_name);
2090 }
2091
2092 nsec_cmp = dname_compare(owner, next);
2093 if (nsec_cmp < 0) {
2094 /* Regular NSEC
2095 * >= so it can match the wildcard
2096 * (for wildcard NODATA proofs).
2097 */
2098 return dname_compare(name, owner) >= 0
2099 && dname_compare(name, next) < 0;
2100
2101 } else if (nsec_cmp > 0) {
2102 /* The wrap around nsec. So NSEC->nxt == zone.name.
2103 * qname must be a subdomain of that.
2104 */
2105 return dname_compare(name, owner) >= 0
2106 && _dname_is_parent(next, name) && dname_compare(next, name);
2107
2108 } else {
2109 /* This nsec is the only nsec.
2110 * zone.name NSEC zone.name, disproves everything else,
2111 * but only for subdomains of that zone.
2112 * (also no zone.name == qname of course)
2113 */
2114 return _dname_is_parent(owner, name) && dname_compare(owner, name);
2115 }
2116 }
2117
nsec3_matches_name(_getdns_rrset * nsec3,const uint8_t * name)2118 static int nsec3_matches_name(_getdns_rrset *nsec3, const uint8_t *name)
2119 {
2120 uint8_t label[64], owner[64];
2121
2122 if (name2nsec3_label(nsec3, name, label, sizeof(label))
2123 && _dname_label_copy(owner, nsec3->name, sizeof(owner)))
2124
2125 return *nsec3->name == label[0] /* Labels same size? */
2126 && memcmp(owner + 1, label + 1, label[0]) == 0;
2127
2128 return 0;
2129 }
2130
nsec3_covers_name(_getdns_rrset * nsec3,const uint8_t * name,int * opt_out)2131 static int nsec3_covers_name(
2132 _getdns_rrset *nsec3, const uint8_t *name, int *opt_out)
2133 {
2134 uint8_t label[65], next[65], owner[65];
2135 _getdns_rrtype_iter rr_spc, *rr;
2136 _getdns_rdf_iter rdf_spc, *rdf;
2137 int nsz = 0, nsec_cmp;
2138
2139 if (!name2nsec3_label(nsec3, name, label, sizeof(label)-1))
2140 return 0;
2141
2142 label[label[0]+1] = 0;
2143
2144 if ( !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3))
2145 || !(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rr->rr_i, 4))
2146 || rdf->pos + *rdf->pos + 1 > rdf->nxt
2147 || (nsz = gldns_b32_ntop_extended_hex(rdf->pos + 1, *rdf->pos,
2148 (char *)next + 1, sizeof(next)-2)) < 0
2149 || *nsec3->name > sizeof(owner) - 2
2150 || !_dname_label_copy(owner, nsec3->name, sizeof(owner)-1)) {
2151
2152 DEBUG_SEC("Error getting NSEC3 owner & next labels\n");
2153 return 0;
2154 }
2155 owner[owner[0]+1] = 0;
2156 next[(next[0] = (uint8_t)nsz)+1] = 0;
2157
2158 if (opt_out)
2159 *opt_out = (rr->rr_i.rr_type[11] & 1) != 0;
2160
2161 debug_sec_print_dname("NSEC3 for: ", name);
2162 debug_sec_print_dname(" is: ", label);
2163 debug_sec_print_dname("inbetween: ", owner);
2164 debug_sec_print_dname(" and: ", next);
2165
2166 nsec_cmp = dname_compare(owner, next);
2167 if (nsec_cmp >= 0) {
2168 /* The wrap around and apex-only nsec case */
2169 return dname_compare(label, owner) > 0
2170 || dname_compare(label, next) < 0;
2171 } else {
2172 assert(nsec_cmp < 0);
2173 /* The normal case
2174 * >= so it can match the wildcard
2175 * (for wildcard NODATA proofs).
2176 */
2177 return dname_compare(label, owner) >= 0
2178 && dname_compare(label, next) < 0;
2179 }
2180 }
2181
find_nsec_covering_name(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * dnskey,_getdns_rrset * rrset,const uint8_t * name,int * opt_out)2182 static int find_nsec_covering_name(const struct mem_funcs *mf, time_t now,
2183 uint32_t skew, _getdns_rrset *dnskey,
2184 _getdns_rrset *rrset, const uint8_t *name, int *opt_out)
2185 {
2186 _getdns_rrset_iter i_spc, *i;
2187 _getdns_rrset *n;
2188 _getdns_rrtype_iter nsec_spc, *nsec_rr;
2189 _getdns_rdf_iter bitmap_spc, *bitmap;
2190 int keytag;
2191
2192 if (opt_out)
2193 *opt_out = 0;
2194
2195 for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len
2196 , SECTION_NO_ADDITIONAL)
2197 ; i ; i = _getdns_rrset_iter_next(i)) {
2198
2199 if ((n = _getdns_rrset_iter_value(i))
2200 && n->rr_type == GETDNS_RRTYPE_NSEC3
2201
2202 /* Get the bitmap rdata field */
2203 && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, n))
2204 && (bitmap = _getdns_rdf_iter_init_at(
2205 &bitmap_spc, &nsec_rr->rr_i, 5))
2206
2207 && (keytag = a_key_signed_rrset_no_wc(
2208 mf, now, skew, dnskey, n))
2209 && ( keytag & NSEC3_ITERATION_COUNT_HIGH
2210
2211 || ( nsec3_covers_name(n, name, opt_out)
2212 /* NSEC should cover, but not match name...
2213 * Unless it is wildcard match, but then we have to
2214 * check that rrset->rr_type is not enlisted,
2215 * because otherwise it should have matched the
2216 * wildcard.
2217 *
2218 * Also no CNAME... cause that should have matched too.
2219 */
2220
2221 && ( !nsec3_matches_name(n, name)
2222 || ( name[0] == 1 && name[1] == (uint8_t)'*'
2223 && !bitmap_has_type(bitmap, rrset->rr_type)
2224 && !bitmap_has_type(bitmap,
2225 GETDNS_RRTYPE_CNAME)
2226 )
2227 )
2228 )
2229 )
2230 ) {
2231
2232 debug_sec_print_rrset("NSEC3: ", n);
2233 debug_sec_print_dname("covered: ", name);
2234
2235 return keytag;
2236 }
2237 if ((n = _getdns_rrset_iter_value(i))
2238 && n->rr_type == GETDNS_RRTYPE_NSEC
2239 && nsec_covers_name(n, name, NULL)
2240
2241 /* Get the bitmap rdata field */
2242 && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, n))
2243 && (bitmap = _getdns_rdf_iter_init_at(
2244 &bitmap_spc, &nsec_rr->rr_i, 1))
2245
2246 /* NSEC should cover, but not match name...
2247 * Unless it is wildcard match, but then we have to check
2248 * that rrset->rr_type is not enlisted, because otherwise
2249 * it should have matched the wildcard.
2250 *
2251 * Also no CNAME... cause that should have matched too.
2252 */
2253 && ( !_dname_equal(n->name, name)
2254 || ( name[0] == 1 && name[1] == (uint8_t)'*'
2255 && !bitmap_has_type(bitmap, rrset->rr_type)
2256 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_CNAME)
2257 )
2258 )
2259
2260 /* When qname is a subdomain of the NSEC owner, make
2261 * sure there is no DNAME, and no delegation point
2262 * there.
2263 */
2264 && ( !_dname_is_parent(n->name, name)
2265 || ( !bitmap_has_type(bitmap, GETDNS_RRTYPE_DNAME)
2266 && ( !bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2267 || bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
2268 )
2269 )
2270 )
2271
2272 && (keytag = a_key_signed_rrset_no_wc(
2273 mf, now, skew, dnskey, n))) {
2274
2275 debug_sec_print_rrset("NSEC: ", n);
2276 debug_sec_print_dname("covered: ", name);
2277
2278 return keytag;
2279 }
2280 }
2281 return 0;
2282 }
2283
nsec3_find_next_closer(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * dnskey,_getdns_rrset * rrset,const uint8_t * nc_name,int * opt_out)2284 static int nsec3_find_next_closer(
2285 const struct mem_funcs *mf, time_t now, uint32_t skew,
2286 _getdns_rrset *dnskey, _getdns_rrset *rrset,
2287 const uint8_t *nc_name, int *opt_out)
2288 {
2289 uint8_t wc_name[256] = { 1, (uint8_t)'*' };
2290 int my_opt_out, keytag;
2291
2292 if (opt_out)
2293 *opt_out = 0;
2294
2295 if (!(keytag = find_nsec_covering_name(
2296 mf, now, skew, dnskey, rrset, nc_name, &my_opt_out))) {
2297 /* TODO: At least google doesn't return next_closer on wildcard
2298 * nodata for DS query. And in fact returns even bogus for,
2299 * for example bladiebla.xavier.nlnet.nl DS.
2300 */
2301 return 0;
2302 }
2303 if (opt_out)
2304 *opt_out = my_opt_out;
2305
2306 /* Wild card not needed on a "covering" NODATA response,
2307 * because of opt-out?
2308 *
2309 * We check for opt-out bit, because rcode is unreliable...
2310 * ... the checked packet might be artificially constructed
2311 * (if we came here via getdns_validate_dnssec) in which case
2312 * rcode is always NOERROR.
2313 */
2314 if (my_opt_out || keytag & NSEC3_ITERATION_COUNT_HIGH)
2315 return keytag;
2316
2317 nc_name += *nc_name + 1;
2318 if (_dname_len(nc_name) > sizeof(wc_name) - 2)
2319 return 0;
2320 else
2321 (void) memcpy(wc_name + 2, nc_name, _dname_len(nc_name));
2322
2323 return find_nsec_covering_name(
2324 mf, now, skew, dnskey, rrset, wc_name, opt_out);
2325 }
2326
2327 /*
2328 * Does a key from keyset dnskey prove the nonexistence of the (name, type)
2329 * tuple in rrset?
2330 *
2331 * On success returns the keytag + SIGNATURE_VERIFIED (0x10000) of the key
2332 * that signed the proof.
2333 * Or in case there were NSEC3's with too high iteration count for the
2334 * verifying key: it returns keytag + NSEC3_ITERATION_COUNT_HIGH (0x20000)
2335 */
key_proves_nonexistance(const struct mem_funcs * mf,time_t now,uint32_t skew,_getdns_rrset * keyset,_getdns_rrset * rrset,int * opt_out)2336 static int key_proves_nonexistance(
2337 const struct mem_funcs *mf, time_t now, uint32_t skew,
2338 _getdns_rrset *keyset, _getdns_rrset *rrset, int *opt_out)
2339 {
2340 _getdns_rrset nsec_rrset, *cover, *ce;
2341 _getdns_rrtype_iter nsec_spc, *nsec_rr;
2342 _getdns_rdf_iter bitmap_spc, *bitmap;
2343 _getdns_rrset_iter i_spc, *i;
2344 const uint8_t *ce_name, *nc_name;
2345 uint8_t wc_name[256] = { 1, (uint8_t)'*' };
2346 int keytag;
2347
2348 assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
2349
2350 debug_sec_print_rrset("Commencing NX proof for: ", rrset);
2351 if (opt_out)
2352 *opt_out = 0;
2353
2354 /* The NSEC NODATA case
2355 * ====================
2356 * NSEC has same ownername as the rrset to deny.
2357 * Only the rr_type is missing from the bitmap.
2358 */
2359 nsec_rrset = *rrset;
2360 nsec_rrset.rr_type = GETDNS_RRTYPE_NSEC;
2361 nsec_rrset.sections = SECTION_NO_ADDITIONAL;
2362
2363 if (/* A NSEC RR exists at the owner name of rrset */
2364 (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &nsec_rrset))
2365
2366 /* Get the bitmap rdata field */
2367 && (bitmap = _getdns_rdf_iter_init_at(
2368 &bitmap_spc, &nsec_rr->rr_i, 1))
2369
2370 /* At least the rr_type of rrset should be missing from it */
2371 && !bitmap_has_type(bitmap, rrset->rr_type)
2372
2373 /* If the name is a CNAME, then we should have gotten the CNAME,
2374 * So no CNAME bit either.
2375 */
2376 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_CNAME)
2377
2378 /* In case of a DS query, make sure we have the parent side NSEC
2379 * and not the child (so no SOA).
2380 * Except for the root that is checked by itself.
2381 */
2382 && ( rrset->rr_type != GETDNS_RRTYPE_DS
2383 || !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
2384 || *rrset->name == 0
2385 )
2386
2387 /* If not a DS query, then make sure the NSEC does not contain NS,
2388 * or if it does, then also contains SOA, otherwise we have a parent
2389 * side delegation point NSEC where we should have gotten a child
2390 * side NSEC!
2391 */
2392 && ( rrset->rr_type == GETDNS_RRTYPE_DS
2393 || !bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2394 || bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
2395
2396 /* And a valid signature please */
2397 && (keytag = a_key_signed_rrset_no_wc(
2398 mf, now, skew, keyset, &nsec_rrset))) {
2399
2400 /* Flag an insecure delegation via opt_out.
2401 * See usage of key_proves_nonexistance() from
2402 * chain_node_get_trusted_keys() for explanation.
2403 */
2404 if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
2405 *opt_out = bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2406 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
2407
2408 debug_sec_print_rrset("NSEC NODATA proof for: ", rrset);
2409 return keytag;
2410 }
2411 /* More NSEC NODATA cases
2412 * ======================
2413 * There are a few NSEC NODATA cases where qname doesn't match
2414 * NSEC->name:
2415 *
2416 * - An empty non terminal (ENT) will result in a NSEC covering the
2417 * qname, where qname > NSEC->name and ce(qname) is parent of NXT.
2418 * This case is handled below after the covering NSEC is found.
2419 *
2420 * - Or a wildcard match without the type. The wildcard owner name
2421 * match has special handing in the find_nsec_covering_name function.
2422 * We still expect a NSEC covering the name though.
2423 */
2424
2425 /* The NSEC Name error case
2426 * ========================
2427 * - First find the NSEC that covers the owner name.
2428 */
2429 for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len
2430 , SECTION_NO_ADDITIONAL)
2431 ; i ; i = _getdns_rrset_iter_next(i)) {
2432
2433 cover = _getdns_rrset_iter_value(i);
2434
2435 if (/* Is cover an NSEC rrset? */
2436 cover->rr_type != GETDNS_RRTYPE_NSEC
2437
2438 /* Does it cover the name */
2439 || !nsec_covers_name(cover, rrset->name, &ce_name)
2440
2441 /* But not a match (because that would be NODATA case) */
2442 || _dname_equal(cover->name, rrset->name)
2443
2444 /* Get the bitmap rdata field */
2445 || !(nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, cover))
2446 || !(bitmap = _getdns_rdf_iter_init_at(
2447 &bitmap_spc, &nsec_rr->rr_i, 1))
2448
2449 /* When qname is a subdomain of the NSEC owner, make
2450 * sure there is no DNAME, and no delegation point
2451 * there.
2452 */
2453 || ( _dname_is_parent(cover->name, rrset->name)
2454 && ( bitmap_has_type(bitmap, GETDNS_RRTYPE_DNAME)
2455 || ( bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2456 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
2457 )
2458 )
2459 )
2460
2461 /* And a valid signature please (as always) */
2462 || !(keytag = a_key_signed_rrset_no_wc(
2463 mf, now, skew, keyset, cover)))
2464 continue;
2465
2466 /* We could have found a NSEC covering an Empty Non Terminal.
2467 * In that case no NSEC covering the wildcard is needed.
2468 * Because it was actually a NODATA proof.
2469 *
2470 * Empty NON terminals can be identified, by
2471 * qname > NSEC->name && NSEC->nxt is subdomain of qname.
2472 *
2473 * nsec_covers_name() will set ce_name to qname when NSEC->nxt
2474 * is a subdomain of qname.
2475 */
2476 if ( dname_compare(rrset->name, cover->name) > 0
2477 && dname_compare(rrset->name, ce_name) == 0) {
2478
2479 debug_sec_print_dname("Empty Non Terminal: ", ce_name);
2480 return keytag;
2481 }
2482
2483 debug_sec_print_dname("Closest Encloser: ", ce_name);
2484
2485 if (_dname_len(ce_name) > sizeof(wc_name) - 2)
2486 return 0;
2487 else
2488 (void) memcpy(wc_name+2, ce_name, _dname_len(ce_name));
2489
2490 debug_sec_print_dname(" Wildcard: ", wc_name);
2491
2492 return find_nsec_covering_name(
2493 mf, now, skew, keyset, rrset, wc_name, NULL);
2494 }
2495
2496 /* The NSEC3 NODATA case
2497 * =====================
2498 * NSEC3 has same (hashed) ownername as the rrset to deny.
2499 */
2500 for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len
2501 , SECTION_NO_ADDITIONAL)
2502 ; i ; i = _getdns_rrset_iter_next(i)) {
2503
2504 /* ce is potentially the NSEC3 that matches complete qname
2505 * (so is also the closest encloser)
2506 */
2507 ce = _getdns_rrset_iter_value(i);
2508 if ( ce->rr_type == GETDNS_RRTYPE_NSEC3
2509
2510 /* A NSEC3 RR exists at the owner name of rrset
2511 * (this is always true)
2512 */
2513 && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, ce))
2514
2515 /* Get the bitmap rdata field */
2516 && (bitmap = _getdns_rdf_iter_init_at(
2517 &bitmap_spc, &nsec_rr->rr_i, 5))
2518
2519 /* At least the rr_type of rrset should be missing */
2520 && !bitmap_has_type(bitmap, rrset->rr_type)
2521
2522 /* If the name is a CNAME, then we should have gotten it,
2523 * So no CNAME bit either.
2524 */
2525 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_CNAME)
2526
2527 /* In case of a DS query, make sure we have the parent side
2528 * NSEC and not the child (so no SOA).
2529 * (except for the root...)
2530 */
2531 && ( rrset->rr_type != GETDNS_RRTYPE_DS
2532 || !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
2533 || *rrset->name == 0
2534 )
2535
2536 /* If not a DS query, then make sure the NSEC does not
2537 * contain NS, or if it does, then also contains SOA,
2538 * otherwise we have a parent side delegation point NSEC
2539 * where we should have gotten a child side NSEC!
2540 */
2541 && ( rrset->rr_type == GETDNS_RRTYPE_DS
2542 || !bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2543 || bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
2544
2545 /* It must have a valid signature */
2546 && (keytag = a_key_signed_rrset_no_wc(
2547 mf, now, skew, keyset, ce))
2548
2549 /* The qname must match the NSEC3 */
2550 && ( keytag & NSEC3_ITERATION_COUNT_HIGH
2551 || nsec3_matches_name(ce, rrset->name))) {
2552
2553 /* Flag an insecure delegation via opt_out.
2554 * See usage of key_proves_nonexistance() from
2555 * chain_node_get_trusted_keys() for explanation.
2556 */
2557 if (opt_out && rrset->rr_type == GETDNS_RRTYPE_DS)
2558 *opt_out =
2559 bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2560 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA);
2561
2562 debug_sec_print_rrset("NSEC3 No Data for: ", rrset);
2563 return keytag;
2564 }
2565 }
2566 /* More NSEC3 NODATA cases
2567 * ======================
2568 * There are a few NSEC NODATA cases where qname doesn't match
2569 * NSEC->name:
2570 *
2571 * - NSEC3 ownername match for qtype == NSEC3 (TODO?)
2572 * - Wildcard NODATA (wildcard owner name match has special handing
2573 * find_nsec_covering_name())
2574 */
2575
2576 /* The NSEC3 Name error case
2577 * ========================+
2578 * First find the closest encloser.
2579 */
2580 if (*rrset->name)
2581 for ( nc_name = rrset->name, ce_name = rrset->name + *rrset->name + 1
2582 ; *ce_name ; nc_name = ce_name, ce_name += *ce_name + 1) {
2583
2584 for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len
2585 , SECTION_NO_ADDITIONAL)
2586 ; i ; i = _getdns_rrset_iter_next(i)) {
2587
2588 if ( !(ce = _getdns_rrset_iter_value(i))
2589 || ce->rr_type != GETDNS_RRTYPE_NSEC3
2590
2591 /* Get the bitmap rdata field */
2592 || !(nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, ce))
2593 || !(bitmap = _getdns_rdf_iter_init_at(
2594 &bitmap_spc, &nsec_rr->rr_i, 1))
2595
2596 /* No DNAME or delegation point at the closest
2597 * encloser.
2598 *
2599 * TODO: Ask Wouter
2600 * Unbound val_nsec3:1024 finishes insecurely
2601 * here (instead of bogus) when DS is also missing.
2602 * Should we not have followed the delegation then
2603 * too?
2604 * The NSEC could come from a parent zone!
2605 *
2606 */
2607 || bitmap_has_type(bitmap, GETDNS_RRTYPE_DNAME)
2608 || ( bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
2609 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
2610 )
2611
2612 || !(keytag = a_key_signed_rrset_no_wc(
2613 mf, now, skew, keyset, ce))
2614 || ( !(keytag & NSEC3_ITERATION_COUNT_HIGH)
2615 && !nsec3_matches_name(ce, ce_name)))
2616 continue;
2617
2618 debug_sec_print_rrset("Closest Encloser: ", ce);
2619 debug_sec_print_dname("Closest Encloser: ", ce_name);
2620 debug_sec_print_dname(" Next closer: ", nc_name);
2621
2622 if ( keytag & NSEC3_ITERATION_COUNT_HIGH
2623 || (keytag = nsec3_find_next_closer(mf, now, skew,
2624 keyset, rrset, nc_name, opt_out)))
2625
2626 return keytag;
2627 }
2628 }
2629 return 0;
2630 }
2631
2632 /* Ascend up to the root along chain_nodes. Try to find a keyset
2633 * authenticated by a key in ta rrset (trust anchor). When we found one,
2634 * descend back down, authenticating more specific keysets along the chain.
2635 *
2636 * The most specific keyset is returned in keys. Also a DNSSEC status is
2637 * returned. BOGUS if no keyset could be found. INSECURE if the
2638 * non-existence of a DS along the path is proofed, and SECURE otherwise.
2639 */
chain_node_get_trusted_keys(const struct mem_funcs * mf,time_t now,uint32_t skew,chain_node * node,_getdns_rrset * ta,_getdns_rrset ** keys)2640 static int chain_node_get_trusted_keys(
2641 const struct mem_funcs *mf, time_t now, uint32_t skew,
2642 chain_node *node, _getdns_rrset *ta, _getdns_rrset **keys)
2643 {
2644 int s, keytag;
2645 int opt_out;
2646
2647 /* Ascend up to the root */
2648 if (! node)
2649 return GETDNS_DNSSEC_BOGUS;
2650
2651 else if (ta->rr_type == GETDNS_RRTYPE_DS) {
2652
2653 if ((keytag = ds_authenticates_keys(
2654 mf, now, skew, ta, &node->dnskey))) {
2655 *keys = &node->dnskey;
2656 node->dnskey_signer = keytag;
2657 return keytag & NO_SUPPORTED_ALGORITHMS
2658 ? GETDNS_DNSSEC_INSECURE
2659 : GETDNS_DNSSEC_SECURE;
2660 }
2661
2662 } else if (ta->rr_type == GETDNS_RRTYPE_DNSKEY) {
2663
2664 /* ta is KSK */
2665 if ((keytag = a_key_signed_rrset_no_wc(
2666 mf, now, skew, ta, &node->dnskey))) {
2667 *keys = &node->dnskey;
2668 node->dnskey_signer = keytag;
2669 return GETDNS_DNSSEC_SECURE;
2670 }
2671 /* ta is the DNSKEY for this name? */
2672 if (_dname_equal(ta->name, node->dnskey.name)) {
2673 *keys = ta;
2674 return GETDNS_DNSSEC_SECURE;
2675 }
2676 /* ta is parent's ZSK proving insecurity below this node? */
2677 if ((keytag = key_proves_nonexistance(
2678 mf, now, skew, ta, &node->ds, &opt_out))) {
2679 node->ds_signer = keytag;
2680
2681 /* When the proof is in an opt_out span, result will
2682 * be INSECURE regardless the purpose of the searched
2683 * for key.
2684 *
2685 * Otherwise, INSECURE only when this is a zonecut.
2686 * i.e. a NODATA proof, with the NS bit and no SOA bit.
2687 *
2688 * key_proves_nonexistance() will set opt_out also for
2689 * these conditions.
2690 */
2691 if (opt_out)
2692 return GETDNS_DNSSEC_INSECURE;
2693
2694 /* If this is not an insecurity proof,
2695 * continue searching one label up.
2696 */
2697
2698 /* ta is parent's ZSK authenticating DS? */
2699 } else if ((keytag = a_key_signed_rrset_no_wc(
2700 mf, now, skew, ta, &node->ds))) {
2701 node->ds_signer = keytag;
2702 /* DS should authenticate the DNSKEY rrset now */
2703 if ((keytag = ds_authenticates_keys(
2704 mf, now, skew, &node->ds, &node->dnskey))) {
2705 *keys = &node->dnskey;
2706 node->dnskey_signer = keytag;
2707 return keytag & NO_SUPPORTED_ALGORITHMS
2708 ? GETDNS_DNSSEC_INSECURE
2709 : GETDNS_DNSSEC_SECURE;
2710 }
2711 /* DS without DNSKEY rrset == BOGUS */
2712 return GETDNS_DNSSEC_BOGUS;
2713 }
2714 } else
2715 return GETDNS_DNSSEC_BOGUS;
2716
2717 s = chain_node_get_trusted_keys(mf, now, skew, node->parent, ta, keys);
2718 /* Set dnssec status on root DNSKEY request (for TA management) */
2719 if (!node->parent && node->dnskey_req &&
2720 node->dnskey.name && *node->dnskey.name == 0)
2721 node->dnskey_req->dnssec_status = s;
2722
2723 if (s != GETDNS_DNSSEC_SECURE)
2724 return s;
2725
2726 /* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
2727 ta = *keys;
2728 /* Back down to the head */
2729 /*************************/
2730 if ((keytag = key_proves_nonexistance(
2731 mf, now, skew, ta, &node->ds, &opt_out))) {
2732 node->ds_signer = keytag;
2733
2734 /* When the proof is in an opt_out span, result will be
2735 * INSECURE regardless the purpose of the searched for key.
2736 *
2737 * Otherwise, INSECURE only when this is a zonecut.
2738 * i.e. a NODATA proof, with the NS bit, but no SOA bit.
2739 *
2740 * key_proves_nonexistance() will set opt_out also for these
2741 * conditions. (NODATA of DS with NS bit and wihout SOA bit)
2742 */
2743 return opt_out ? GETDNS_DNSSEC_INSECURE
2744 : GETDNS_DNSSEC_SECURE;
2745 }
2746 if (key_matches_signer(ta, &node->ds)) {
2747
2748 if ((node->ds_signer = a_key_signed_rrset_no_wc(
2749 mf, now, skew, ta, &node->ds))
2750 && (keytag = ds_authenticates_keys(
2751 mf, now, skew, &node->ds, &node->dnskey))){
2752
2753 *keys = &node->dnskey;
2754 node->dnskey_signer = keytag;
2755 return keytag & NO_SUPPORTED_ALGORITHMS
2756 ? GETDNS_DNSSEC_INSECURE
2757 : GETDNS_DNSSEC_SECURE;
2758 }
2759 return GETDNS_DNSSEC_BOGUS;
2760 }
2761 /* If we are on a zone cut, we must return BOGUS, because there should
2762 * have been a more specific DS set. We can be sure of a zone cut if
2763 * a request for the DSset was sent (because they are done only for
2764 * signer names and when there was a SOA) or if we do have a DS,
2765 * but not signed with a current trusted key.
2766 *
2767 * For the getdns_validate_dnssec case, we must make sure to insert
2768 * an empty DS for this name in the validation chain... so it can
2769 * be used for the support_records parameter.
2770 */
2771 if (node->ds_req || _getdns_rrset_has_rrs(&node->ds))
2772 return GETDNS_DNSSEC_BOGUS;
2773
2774 /* Not at a zone cut, the trusted keyset must be authenticating
2775 * something below (closer to head) this node.
2776 */
2777 return GETDNS_DNSSEC_SECURE;
2778 }
2779
2780 /* The DNSSEC status of the rrset of head is evaluated with trust anchor ta.
2781 * For this first a secure keyset is looked up, with which the keyset is
2782 * evaluated.
2783 */
chain_head_validate_with_ta(const struct mem_funcs * mf,time_t now,uint32_t skew,chain_head * head,_getdns_rrset * ta)2784 static int chain_head_validate_with_ta(const struct mem_funcs *mf,
2785 time_t now, uint32_t skew, chain_head *head, _getdns_rrset *ta)
2786 {
2787 _getdns_rrset *keys;
2788 int s, keytag, opt_out;
2789
2790 _getdns_rrtype_iter nsec_spc, *nsec_rr;
2791 _getdns_rdf_iter bitmap_spc, *bitmap;
2792 chain_node *parent;
2793
2794 debug_sec_print_rrset("Validating ", &head->rrset);
2795 debug_sec_print_rrset("\twith trust anchor ", ta);
2796
2797 /* A DS is never at the apex */
2798 if ( head->rrset.rr_type == GETDNS_RRTYPE_DS
2799 && head->parent->parent)
2800 parent = head->parent->parent;
2801
2802 /* Only at the apex, a NSEC is signed with a DNSKEY with the same
2803 * owner name. All other are signed by the parent domain or higher.
2804 * Besides a shortcut, choosing to search for a trusted key from the
2805 * parent is essential for NSECs at a delagation point! (which would
2806 * otherwise turn out BOGUS).
2807 */
2808 else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC
2809 && head->parent->parent
2810 && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &head->rrset))
2811 && (bitmap = _getdns_rdf_iter_init_at(
2812 &bitmap_spc, &nsec_rr->rr_i, 1))
2813 && !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
2814 parent = head->parent->parent;
2815
2816 /* NSEC3 is always signed by the parent domain!
2817 * ( the ownername of the NSEC3 itself is not in the original zone!
2818 * so a search for a trusted key at that name gives either INSECURE
2819 * (with opt-out) or BOGUS! )
2820 */
2821 else if (head->rrset.rr_type == GETDNS_RRTYPE_NSEC3
2822 && head->parent->parent)
2823 parent = head->parent->parent;
2824 else
2825 parent = head->parent;
2826
2827 if ((s = chain_node_get_trusted_keys(
2828 mf, now, skew, parent, ta, &keys)) != GETDNS_DNSSEC_SECURE) {
2829 debug_sec_print_rrset("Could not get trusted keys "
2830 "for validating ", &head->rrset);
2831 DEBUG_SEC("\tstatus: %d\n", (int)s);
2832 return s;
2833 }
2834 debug_sec_print_rrset("Validating ", &head->rrset);
2835 debug_sec_print_rrset("\twith keys ", keys);
2836
2837 if (_getdns_rrset_has_rrs(&head->rrset)) {
2838 if ((keytag = a_key_signed_rrset(
2839 mf, now, skew, keys, &head->rrset))) {
2840 DEBUG_SEC("Key %d proved\n", (int)keytag);
2841 debug_sec_print_rrset("\tSECURE: ", &head->rrset);
2842 head->signer = keytag;
2843 return GETDNS_DNSSEC_SECURE;
2844
2845 } else if (!_getdns_rrset_has_rrsigs(&head->rrset)
2846 && (keytag = key_proves_nonexistance(mf, now,
2847 skew, keys, &head->rrset, &opt_out))
2848 && opt_out) {
2849
2850 DEBUG_SEC("Key %d proved (optout)\n", (int)keytag);
2851 debug_sec_print_rrset("\tINSECURE: ", &head->rrset);
2852 head->signer = keytag;
2853 return GETDNS_DNSSEC_INSECURE;
2854 }
2855 } else if ((keytag = key_proves_nonexistance(mf, now, skew,
2856 keys, &head->rrset, &opt_out))) {
2857 DEBUG_SEC("Key %d proved (NX)\n", (int)keytag);
2858 debug_sec_print_rrset("\tSECURE: ", &head->rrset);
2859 head->signer = keytag;
2860 return opt_out || (keytag & NSEC3_ITERATION_COUNT_HIGH)
2861 ? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE;
2862 }
2863 debug_sec_print_rrset("BOGUS: ", &head->rrset);
2864 debug_sec_print_rrset("\twith trust anchor: ", ta);
2865 return GETDNS_DNSSEC_BOGUS;
2866 }
2867
2868 /* The DNSSEC status of the rrset in head is evaluated by trying the trust
2869 * anchors in tas in turn. The best outcome counts.
2870 */
chain_head_validate(const struct mem_funcs * mf,time_t now,uint32_t skew,chain_head * head,_getdns_rrset_iter * tas)2871 static int chain_head_validate(const struct mem_funcs *mf, time_t now,
2872 uint32_t skew, chain_head *head, _getdns_rrset_iter *tas)
2873 {
2874 _getdns_rrset_iter *i;
2875 _getdns_rrset *ta, dnskey_ta, ds_ta;
2876 _getdns_rrset_iter closest_ta;
2877 int closest_labels, s = GETDNS_DNSSEC_INDETERMINATE;
2878 size_t ta_labels, supported_algorithms;
2879 _getdns_rrtype_iter rr_spc, *rr;
2880
2881 /* Find the TA closest to the head's RRset name */
2882 closest_labels = -1;
2883 for (i = _getdns_rrset_iter_rewind(tas); i ;i = _getdns_rrset_iter_next(i)) {
2884 ta = _getdns_rrset_iter_value(i);
2885
2886 if ((ta->rr_type == GETDNS_RRTYPE_DNSKEY ||
2887 ta->rr_type == GETDNS_RRTYPE_DS)
2888 && _dname_is_parent(ta->name, head->rrset.name)
2889 && (int)(ta_labels = _dname_label_count(ta->name))
2890 > closest_labels ) {
2891
2892 closest_labels = (int)ta_labels;
2893 closest_ta = *i;
2894 if (i->rrset.name == i->name_spc)
2895 closest_ta.rrset.name = closest_ta.name_spc;
2896 }
2897 }
2898 DEBUG_SEC("closest labels for TA: %d\n", closest_labels);
2899 if (closest_labels == -1)
2900 return GETDNS_DNSSEC_INDETERMINATE;
2901
2902 ta = _getdns_rrset_iter_value(&closest_ta);
2903 dnskey_ta = *ta;
2904 dnskey_ta.rr_type = GETDNS_RRTYPE_DNSKEY;
2905 ds_ta = *ta;
2906 ds_ta.rr_type = GETDNS_RRTYPE_DS;
2907
2908 if (!_getdns_rrset_has_rrs(&dnskey_ta))
2909 return chain_head_validate_with_ta(mf,now,skew,head,&ds_ta);
2910
2911 /* Does the selected DNSKEY set have supported algorithms? */
2912 supported_algorithms = 0;
2913 for ( rr = _getdns_rrtype_iter_init(&rr_spc, ta)
2914 ; rr; rr = _getdns_rrtype_iter_next(rr)) {
2915
2916 if ( rr->rr_i.rr_type + 14 <= rr->rr_i.nxt
2917 && _getdns_dnskey_algo_id_is_supported(
2918 rr->rr_i.rr_type[13]))
2919
2920 supported_algorithms++;
2921 }
2922 if (!supported_algorithms) {
2923 if (_getdns_rrset_has_rrs(&ds_ta))
2924 return chain_head_validate_with_ta(
2925 mf, now, skew, head, &ds_ta);
2926
2927 return GETDNS_DNSSEC_INSECURE;
2928 }
2929 s = chain_head_validate_with_ta(mf, now, skew, head, &dnskey_ta);
2930 if (_getdns_rrset_has_rrs(&ds_ta)) {
2931 switch (chain_head_validate_with_ta(mf,now,skew,head,&ds_ta)) {
2932 case GETDNS_DNSSEC_SECURE : s = GETDNS_DNSSEC_SECURE;
2933 /* fallthrough */
2934 case GETDNS_DNSSEC_INSECURE: if (s != GETDNS_DNSSEC_SECURE)
2935 s = GETDNS_DNSSEC_INSECURE;
2936 break;
2937 case GETDNS_DNSSEC_BOGUS : if (s != GETDNS_DNSSEC_SECURE &&
2938 s != GETDNS_DNSSEC_INSECURE)
2939 s = GETDNS_DNSSEC_BOGUS;
2940 break;
2941 default : break;
2942 }
2943 }
2944 return s;
2945 }
2946
2947 /* The DNSSEC status of the network requests which constructed the chain is
2948 * evaluated by processing each head in turn. The worst outcome per network request
2949 * is the dnssec status for that network request.
2950 */
2951 #ifdef STUB_NATIVE_DNSSEC
chain_set_netreq_dnssec_status(chain_head * chain,_getdns_rrset_iter * tas)2952 static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter *tas)
2953 {
2954 chain_head *head;
2955
2956 /* The netreq status is the worst for any head */
2957 for (head = chain; head; head = head->next) {
2958 if (!head->netreq)
2959 continue;
2960
2961 switch (chain_head_validate(priv_getdns_context_mf(
2962 head->netreq->owner->context), time(NULL),
2963 head->netreq->owner->context->dnssec_allowed_skew,
2964 head, tas)) {
2965
2966 case GETDNS_DNSSEC_SECURE:
2967 if (head->netreq->dnssec_status ==
2968 GETDNS_DNSSEC_INDETERMINATE)
2969 head->netreq->dnssec_status =
2970 GETDNS_DNSSEC_SECURE;
2971 break;
2972
2973 case GETDNS_DNSSEC_INSECURE:
2974 if (head->netreq->dnssec_status != GETDNS_DNSSEC_BOGUS)
2975 head->netreq->dnssec_status =
2976 GETDNS_DNSSEC_INSECURE;
2977 break;
2978
2979 case GETDNS_DNSSEC_BOGUS :
2980 head->netreq->dnssec_status = GETDNS_DNSSEC_BOGUS;
2981 break;
2982
2983 default:
2984 break;
2985 }
2986 }
2987 }
2988
chain_clear_netreq_dnssec_status(chain_head * chain)2989 static void chain_clear_netreq_dnssec_status(chain_head *chain)
2990 {
2991 chain_head *head;
2992 size_t node_count;
2993 chain_node *node;
2994
2995 /* The netreq status is the worst for any head */
2996 for (head = chain; head; head = head->next) {
2997 if (!head->netreq)
2998 continue;
2999
3000 head->netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
3001 for ( node_count = head->node_count, node = head->parent
3002 ; node && node_count ; node_count--, node = node->parent ) {
3003
3004 node->ds_signer = -1;
3005 node->dnskey_signer = -1;
3006
3007 if ( ! node->parent && node->dnskey_req
3008 && node->dnskey.name && !*node->dnskey.name) {
3009 node->dnskey_req->dnssec_status =
3010 GETDNS_DNSSEC_INDETERMINATE;
3011 }
3012 }
3013 }
3014 }
3015 #endif
3016
3017 /* The DNSSEC status of all heads for a chain structure is evaluated by
3018 * processing each head in turn. The worst outcome is the dnssec status for
3019 * the whole.
3020 */
chain_validate_dnssec(const struct mem_funcs * mf,time_t now,uint32_t skew,chain_head * chain,_getdns_rrset_iter * tas)3021 static int chain_validate_dnssec(const struct mem_funcs *mf,
3022 time_t now, uint32_t skew, chain_head *chain, _getdns_rrset_iter *tas)
3023 {
3024 int s = GETDNS_DNSSEC_INDETERMINATE, t;
3025 chain_head *head;
3026
3027 /* The netreq status is the worst for any head */
3028 for (head = chain; head; head = head->next) {
3029 t = chain_head_validate(mf, now, skew, head, tas);
3030 switch (t) {
3031 case GETDNS_DNSSEC_SECURE:
3032 if (s == GETDNS_DNSSEC_INDETERMINATE)
3033 s = GETDNS_DNSSEC_SECURE;
3034 break;
3035
3036 case GETDNS_DNSSEC_INSECURE:
3037 if (s != GETDNS_DNSSEC_BOGUS)
3038 s = GETDNS_DNSSEC_INSECURE;
3039 break;
3040
3041 case GETDNS_DNSSEC_BOGUS :
3042 s = GETDNS_DNSSEC_BOGUS;
3043 break;
3044
3045 default:
3046 break;
3047 }
3048 }
3049 DEBUG_SEC("chain_validate_dnssec() returning %d\n", s);
3050 return s;
3051 }
3052
3053
3054 /**************** dnssec_return_validation_chain Extension ******************
3055 *****************************************************************************/
3056
count_outstanding_requests(chain_head * head)3057 static size_t count_outstanding_requests(chain_head *head)
3058 {
3059 size_t count;
3060 chain_node *node;
3061
3062 if (!head)
3063 return 0;
3064
3065 for ( node = head->parent, count = head->lock
3066 ; node
3067 ; node = node->parent) {
3068
3069 count += node->lock;
3070
3071 if (!_getdns_netreq_finished(node->dnskey_req))
3072 count++;
3073
3074 if (!_getdns_netreq_finished(node->ds_req))
3075 count++;
3076 }
3077 return count + count_outstanding_requests(head->next);
3078 }
3079
rrset_in_list(_getdns_rrset * rrset,getdns_list * list)3080 static int rrset_in_list(_getdns_rrset *rrset, getdns_list *list)
3081 {
3082 size_t i;
3083 getdns_dict *rr_dict;
3084 uint32_t rr_type;
3085 uint32_t rr_class;
3086 getdns_bindata *name;
3087
3088 for (i = 0; !getdns_list_get_dict(list, i, &rr_dict); i++) {
3089 if (!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
3090 rrset->rr_type == rr_type &&
3091 !getdns_dict_get_int(rr_dict, "class", &rr_class) &&
3092 rrset->rr_class == rr_class &&
3093 !getdns_dict_get_bindata(rr_dict, "name", &name) &&
3094 dname_compare(rrset->name, name->data) == 0)
3095 return 1;
3096 }
3097 return 0;
3098 }
3099
append_rrset2val_chain_list(getdns_list * val_chain_list,_getdns_rrset * rrset,int signer)3100 static void append_rrset2val_chain_list(
3101 getdns_list *val_chain_list, _getdns_rrset *rrset, int signer)
3102 {
3103 _getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ];
3104 _getdns_rr_iter *val_rrset = val_rrset_spc;
3105 _getdns_rrtype_iter rr_spc, *rr;
3106 size_t n_rrs, i;
3107 uint32_t orig_ttl;
3108 getdns_dict *rr_dict;
3109 _getdns_rrsig_iter *rrsig, rrsig_spc;
3110
3111 assert(val_chain_list && rrset);
3112
3113 if (signer < 0)
3114 return;
3115
3116 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
3117 ; rrsig &&
3118 ( rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28
3119 || gldns_read_uint16(rrsig->rr_i.rr_type + 26)
3120 != (signer & 0xFFFF))
3121 ; rrsig = _getdns_rrsig_iter_next(rrsig))
3122 ; /* pass */
3123
3124 if (!rrsig)
3125 return;
3126
3127 /* keytag was already read, so orig_ttl should cause no problem */
3128 assert(rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 18);
3129
3130 orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
3131
3132 for (;;) {
3133 for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset), n_rrs = 0
3134 ; rr
3135 ; rr = _getdns_rrtype_iter_next(rr), n_rrs++) {
3136
3137 if (n_rrs < VAL_RRSET_SPC_SZ ||
3138 val_rrset != val_rrset_spc)
3139 val_rrset[n_rrs] = rr->rr_i;
3140 }
3141 /* Did everything fit? Then break */
3142 if (val_rrset != val_rrset_spc || n_rrs <= VAL_RRSET_SPC_SZ)
3143 break;
3144
3145 /* More space needed for val_rrset */
3146 val_rrset = GETDNS_XMALLOC(
3147 val_chain_list->mf, _getdns_rr_iter, n_rrs);
3148 }
3149 qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
3150 for (i = 0; i < n_rrs; i++) {
3151 /* Get rid of doubles */
3152 if (i && !_rr_iter_rdata_cmp(&val_rrset[i], &val_rrset[i-1]))
3153 continue;
3154
3155 if (!(rr_dict = _getdns_rr_iter2rr_dict_canonical(
3156 &val_chain_list->mf, &val_rrset[i], &orig_ttl)))
3157 continue;
3158
3159 if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
3160 getdns_dict_destroy(rr_dict);
3161 }
3162 if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
3163 &val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
3164 _getdns_list_append_this_dict(val_chain_list, rr_dict))
3165 getdns_dict_destroy(rr_dict);
3166
3167 /* Append the other RRSIGs, which were not used for validation too,
3168 * because other validators might not have the same algorithm support.
3169 */
3170 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
3171 ; rrsig
3172 ; rrsig = _getdns_rrsig_iter_next(rrsig)) {
3173
3174 if (rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28)
3175 continue;
3176
3177 if (gldns_read_uint16(rrsig->rr_i.rr_type + 26)
3178 == (signer & 0xFFFF))
3179 continue;
3180
3181 orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
3182 if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
3183 &val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
3184 _getdns_list_append_this_dict(val_chain_list, rr_dict))
3185 getdns_dict_destroy(rr_dict);
3186 }
3187 if (val_rrset != val_rrset_spc)
3188 GETDNS_FREE(val_chain_list->mf, val_rrset);
3189 }
3190
append_rrs2val_chain_list(getdns_context * ctxt,getdns_list * val_chain_list,getdns_network_req * netreq,int signer)3191 static void append_rrs2val_chain_list(getdns_context *ctxt,
3192 getdns_list *val_chain_list, getdns_network_req *netreq, int signer)
3193 {
3194 _getdns_rrset_iter *i, i_spc;
3195 _getdns_rrset *rrset;
3196 _getdns_rrtype_iter *rr, rr_spc;
3197 _getdns_rrsig_iter *rrsig, rrsig_spc;
3198 getdns_dict *rr_dict;
3199
3200 for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response
3201 , netreq->response_len
3202 , SECTION_NO_ADDITIONAL)
3203 ; i
3204 ; i = _getdns_rrset_iter_next(i)) {
3205
3206 rrset = _getdns_rrset_iter_value(i);
3207
3208 if (rrset->rr_type == GETDNS_RRTYPE_NSEC ||
3209 rrset->rr_type == GETDNS_RRTYPE_NSEC3) {
3210
3211 if (rrset_in_list(rrset, val_chain_list))
3212 continue;
3213
3214 } else if (rrset->rr_type != GETDNS_RRTYPE_DNSKEY &&
3215 rrset->rr_type != GETDNS_RRTYPE_DS)
3216 continue;
3217
3218 if (signer > 0) {
3219 /* We have a signer! Return RRset in canonical
3220 * form and order with only the RRSIG that signed
3221 * the RRset.
3222 */
3223 append_rrset2val_chain_list(
3224 val_chain_list, rrset, signer);
3225 continue;
3226 }
3227 for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset)
3228 ; rr; rr = _getdns_rrtype_iter_next(rr)) {
3229
3230 if (!(rr_dict = _getdns_rr_iter2rr_dict(
3231 &ctxt->mf, &rr->rr_i)))
3232 continue;
3233
3234 if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
3235 getdns_dict_destroy(rr_dict);
3236 }
3237 for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
3238 ; rrsig; rrsig = _getdns_rrsig_iter_next(rrsig)) {
3239
3240 if (!(rr_dict = _getdns_rr_iter2rr_dict(
3241 &ctxt->mf, &rrsig->rr_i)))
3242 continue;
3243
3244 if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
3245 getdns_dict_destroy(rr_dict);
3246 }
3247 }
3248 }
3249
append_empty_ds2val_chain_list(getdns_context * context,getdns_list * val_chain_list,_getdns_rrset * ds)3250 static void append_empty_ds2val_chain_list(
3251 getdns_context *context, getdns_list *val_chain_list, _getdns_rrset *ds)
3252 {
3253 getdns_dict *rr_dict;
3254 getdns_bindata bindata;
3255 getdns_dict *rdata_dict;
3256
3257 if (!(rr_dict = getdns_dict_create_with_context(context)))
3258 return;
3259
3260 bindata.size = _dname_len(ds->name);
3261 bindata.data = (UNCONST_UINT8_p)ds->name;
3262 (void) getdns_dict_set_bindata(rr_dict, "name", &bindata);
3263 (void) getdns_dict_set_int(rr_dict, "class", ds->rr_class);
3264 (void) getdns_dict_set_int(rr_dict, "type", ds->rr_type);
3265 (void) getdns_dict_set_int(rr_dict, "ttl", 0);
3266
3267 if (!(rdata_dict = getdns_dict_create_with_context(context))) {
3268 getdns_dict_destroy(rr_dict);
3269 return;
3270 }
3271 bindata.size = 0;
3272 bindata.data = NULL;
3273 (void) getdns_dict_set_bindata(rdata_dict, "rdata_raw", &bindata);
3274 getdns_dict_destroy(rdata_dict);
3275
3276 if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
3277 getdns_dict_destroy(rr_dict);
3278 }
_to_the_root(chain_node * node)3279 static inline chain_node *_to_the_root(chain_node *node)
3280 {
3281 while (node->parent) node = node->parent;
3282 return node;
3283 }
3284
_getdns_bogus(getdns_dns_req * dnsreq)3285 int _getdns_bogus(getdns_dns_req *dnsreq)
3286 {
3287 getdns_network_req **netreq_p, *netreq;
3288
3289 for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
3290 if (netreq->dnssec_status == GETDNS_DNSSEC_BOGUS)
3291 return 1;
3292 }
3293 return 0;
3294 }
3295
check_chain_complete(chain_head * chain)3296 static void check_chain_complete(chain_head *chain)
3297 {
3298 getdns_dns_req *dnsreq;
3299 getdns_context *context;
3300 size_t o, node_count;
3301 chain_head *head, *next, *same_chain;
3302 chain_node *node;
3303 getdns_list *val_chain_list;
3304 getdns_dict *response_dict;
3305 _getdns_rrset_iter tas_iter;
3306
3307 if ((o = count_outstanding_requests(chain)) > 0) {
3308 DEBUG_SEC("%"PRIsz" outstanding requests\n", o);
3309 return;
3310 }
3311 DEBUG_SEC("Chain done!\n");
3312 dnsreq = chain->netreq->owner;
3313 context = dnsreq->context;
3314
3315 if (dnsreq->waiting_for_ta) {
3316 getdns_dns_req **d;
3317
3318 for (d = &context->ta_notify; *d; d = &(*d)->ta_notify) {
3319 if (*d == dnsreq) {
3320 *d = dnsreq->ta_notify;
3321 dnsreq->ta_notify = NULL;
3322 break;
3323 }
3324 }
3325
3326 } else {
3327 if (context->trust_anchors_source == GETDNS_TASRC_FETCHING) {
3328 dnsreq->waiting_for_ta = 1;
3329 dnsreq->ta_notify = context->ta_notify;
3330 context->ta_notify = dnsreq;
3331 return;
3332 }
3333 }
3334 #ifdef STUB_NATIVE_DNSSEC
3335 if (context->trust_anchors)
3336
3337 chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter,
3338 context->trust_anchors, context->trust_anchors_len,
3339 SECTION_ANSWER));
3340 #else
3341 if (context->trust_anchors)
3342
3343 (void) chain_validate_dnssec(priv_getdns_context_mf(context),
3344 time(NULL), context->dnssec_allowed_skew,
3345 chain, _getdns_rrset_iter_init( &tas_iter
3346 , context->trust_anchors
3347 , context->trust_anchors_len
3348 , SECTION_ANSWER));
3349 #endif
3350 if (context->trust_anchors_source == GETDNS_TASRC_XML) {
3351 if ((head = chain) && (node = _to_the_root(head->parent)) &&
3352 node->dnskey.name && *node->dnskey.name == 0)
3353 _getdns_context_update_root_ksk(context,&node->dnskey);
3354
3355 } else if (_getdns_bogus(dnsreq)) {
3356 _getdns_rrsig_iter rrsig_spc;
3357
3358 if ((head = chain) && (node = _to_the_root(head->parent))
3359 /* The root DNSKEY rrset */
3360 && node->dnskey.name && *node->dnskey.name == 0
3361 /* We queried it and had a response */
3362 && node->dnskey_req
3363 /* The response was bogus */
3364 && node->dnskey_req->dnssec_status == GETDNS_DNSSEC_BOGUS
3365 /* The response was bogus, but not because it has no rrsigs */
3366 && _getdns_rrsig_iter_init(&rrsig_spc, &node->dnskey)
3367 ){
3368
3369 _getdns_log( &context->log
3370 , GETDNS_LOG_SYS_ANCHOR, GETDNS_LOG_NOTICE
3371 , "root DNSKEY set was bogus!\n");
3372 if (!dnsreq->waiting_for_ta) {
3373 uint64_t now_ms = 0;
3374
3375 dnsreq->waiting_for_ta = 1;
3376 _getdns_context_equip_with_anchor(
3377 context, &now_ms);
3378
3379 if (context->trust_anchors_source
3380 == GETDNS_TASRC_XML) {
3381 chain_clear_netreq_dnssec_status(chain);
3382 check_chain_complete(chain);
3383 return;
3384 }
3385 if (context->trust_anchors_source ==
3386 GETDNS_TASRC_FAILED
3387 && 0 == _getdns_ms_until_expiry2(
3388 context->trust_anchors_backoff_expiry,
3389 &now_ms)) {
3390 context->trust_anchors_source =
3391 GETDNS_TASRC_NONE;
3392 }
3393 if (context->trust_anchors_source
3394 != GETDNS_TASRC_FAILED) {
3395 _getdns_start_fetching_ta(
3396 context, dnsreq->loop, &now_ms);
3397 }
3398 if (dnsreq->waiting_for_ta &&
3399 context->trust_anchors_source
3400 == GETDNS_TASRC_FETCHING) {
3401
3402 chain_clear_netreq_dnssec_status(chain);
3403 dnsreq->ta_notify = context->ta_notify;
3404 context->ta_notify = dnsreq;
3405 return;
3406 }
3407 }
3408 }
3409 }
3410
3411 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
3412 if ( dnsreq->dnssec_roadblock_avoidance
3413 && !dnsreq->avoid_dnssec_roadblocks
3414 && _getdns_bogus(dnsreq)) {
3415
3416 getdns_network_req **netreq_p, *netreq;
3417 uint64_t now_ms = 0;
3418
3419 dnsreq->avoid_dnssec_roadblocks = 1;
3420 dnsreq->chain->lock += 1;
3421
3422 for ( netreq_p = dnsreq->netreqs
3423 ; (netreq = *netreq_p)
3424 ; netreq_p++) {
3425
3426 _getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT);
3427 netreq->dnssec_status =
3428 GETDNS_DNSSEC_INDETERMINATE;
3429 netreq->owner = dnsreq;
3430 (void) _getdns_submit_netreq(netreq, &now_ms);
3431 }
3432 if (!dnsreq->dnssec_return_validation_chain)
3433 return;
3434
3435 for ( head = chain; head ; head = next ) {
3436 next = head->next;
3437 for ( node_count = head->node_count
3438 , node = head->parent
3439 ; node_count
3440 ; node_count--, node = node->parent ) {
3441
3442 if (node->dnskey_req) {
3443 _getdns_netreq_change_state(
3444 node->dnskey_req,
3445 NET_REQ_NOT_SENT);
3446 node->dnskey_req->owner->
3447 avoid_dnssec_roadblocks = 1;
3448 (void) _getdns_submit_netreq(
3449 node->dnskey_req, &now_ms);
3450 }
3451 if (node->ds_req) {
3452 _getdns_netreq_change_state(
3453 node->ds_req, NET_REQ_NOT_SENT);
3454 node->ds_req->owner->
3455 avoid_dnssec_roadblocks = 1;
3456 (void) _getdns_submit_netreq(
3457 node->ds_req, &now_ms);
3458 }
3459 }
3460 }
3461 return;
3462 }
3463 #endif
3464 dnsreq->waiting_for_ta = 0;
3465 val_chain_list = dnsreq->dnssec_return_validation_chain
3466 ? getdns_list_create_with_context(context) : NULL;
3467
3468 /* Walk chain to add values to val_chain_list. We do not cleanup yet.
3469 * The chain will eventually be freed when the dns request is descheduled
3470 * with getdns_context_clear_outbound_request().
3471 */
3472 for ( head = chain; head ; head = next ) {
3473 next = head->next;
3474 if (dnsreq->dnssec_return_full_validation_chain &&
3475 head->node_count && head->signer > 0) {
3476
3477 append_rrset2val_chain_list(
3478 val_chain_list, &head->rrset, head->signer);
3479
3480 for ( same_chain = next
3481 ; same_chain && same_chain->signer == head->signer
3482 ; same_chain = same_chain->next) {
3483 append_rrset2val_chain_list(val_chain_list,
3484 &same_chain->rrset, same_chain->signer);
3485 same_chain->signer = -1;
3486 }
3487 }
3488 for ( node_count = head->node_count, node = head->parent
3489 ; node_count
3490 ; node_count--, node = node->parent ) {
3491
3492 if (node->dnskey_req) {
3493 if (val_chain_list)
3494 append_rrs2val_chain_list(
3495 context, val_chain_list,
3496 node->dnskey_req,
3497 node->dnskey_signer);
3498 }
3499 if (node->ds_req) {
3500 if (val_chain_list)
3501 append_rrs2val_chain_list(
3502 context, val_chain_list,
3503 node->ds_req, node->ds_signer);
3504
3505 if (val_chain_list && node->ds_signer == -1 &&
3506 !_getdns_rrset_has_rrs(&node->ds)) {
3507 /* Add empty DS, to prevent less
3508 * specific to be able to authenticate
3509 * below a zone cut (closer to head)
3510 */
3511 append_empty_ds2val_chain_list(
3512 context, val_chain_list,
3513 &node->ds);
3514 }
3515 }
3516 }
3517 }
3518
3519 response_dict = _getdns_create_getdns_response(dnsreq);
3520 if (val_chain_list) {
3521 if (_getdns_dict_set_this_list(
3522 response_dict, "validation_chain", val_chain_list))
3523 getdns_list_destroy(val_chain_list);
3524 }
3525
3526 /* Final user callback */
3527 dnsreq->validating = 0;
3528 _getdns_call_user_callback(dnsreq, response_dict);
3529 }
3530
_getdns_ta_notify_dnsreqs(getdns_context * context)3531 void _getdns_ta_notify_dnsreqs(getdns_context *context)
3532 {
3533 getdns_dns_req **dnsreq_p, *dnsreq = NULL;
3534 uint64_t now_ms = 0;
3535
3536 assert(context);
3537
3538 if (context->trust_anchors_source == GETDNS_TASRC_NONE ||
3539 context->trust_anchors_source == GETDNS_TASRC_FETCHING)
3540 return;
3541
3542 dnsreq_p = &context->ta_notify;
3543 while ((dnsreq = *dnsreq_p)) {
3544 assert(dnsreq->waiting_for_ta);
3545
3546 if (dnsreq->chain)
3547 check_chain_complete(dnsreq->chain);
3548 else {
3549 getdns_network_req *netreq, **netreq_p;
3550 int r = GETDNS_RETURN_GOOD;
3551
3552 (void) _getdns_context_prepare_for_resolution(context);
3553
3554 *dnsreq_p = dnsreq->ta_notify;
3555 for ( netreq_p = dnsreq->netreqs
3556 ; !r && (netreq = *netreq_p)
3557 ; netreq_p++ ) {
3558
3559 if (!(r = _getdns_submit_netreq(netreq, &now_ms)))
3560 continue;
3561 if (r == DNS_REQ_FINISHED)
3562 break;
3563 _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
3564 }
3565 }
3566 assert(*dnsreq_p != dnsreq);
3567 }
3568 }
3569
_getdns_validation_chain_timeout(getdns_dns_req * dnsreq)3570 void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
3571 {
3572 cancel_requests_for_subdomains_of(dnsreq->chain, (uint8_t *)"\0");
3573 dnsreq->request_timed_out = 1;
3574 check_chain_complete(dnsreq->chain);
3575 }
3576
_getdns_cancel_validation_chain(getdns_dns_req * dnsreq)3577 void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
3578 {
3579 chain_head *head, *next;
3580 chain_node *node;
3581 size_t node_count;
3582
3583 /* Clear nodes under direct DNSKEY queries.
3584 * They share the DNSKEY lookup netreq, but _dnskey_query() can not
3585 * be used because we're free'ing the heads.
3586 */
3587 for (head = dnsreq->chain; head; head = head->next) {
3588 if ( head->rrset.rr_type == GETDNS_RRTYPE_DNSKEY
3589 && head->node_count
3590 && head->netreq == head->parent->dnskey_req)
3591 head->parent->dnskey_req = NULL;
3592 }
3593 head = dnsreq->chain;
3594 dnsreq->chain = NULL;
3595 while (head) {
3596 next = head->next;
3597
3598 for ( node_count = head->node_count, node = head->parent
3599 ; node_count
3600 ; node_count--, node = node->parent ) {
3601
3602 if (node->dnskey_req)
3603 _getdns_context_cancel_request(
3604 node->dnskey_req->owner);
3605
3606 if (node->ds_req)
3607 _getdns_context_cancel_request(
3608 node->ds_req->owner);
3609 }
3610 GETDNS_FREE(head->my_mf, head);
3611 head = next;
3612 }
3613 }
3614
_getdns_get_validation_chain(getdns_dns_req * dnsreq)3615 void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
3616 {
3617 getdns_network_req *netreq, **netreq_p;
3618 chain_head *chain = NULL, *chain_p;
3619
3620 if (dnsreq->avoid_dnssec_roadblocks) {
3621 chain = dnsreq->chain;
3622
3623 } else if (dnsreq->validating)
3624 return;
3625 dnsreq->validating = 1;
3626
3627 if (dnsreq->avoid_dnssec_roadblocks && chain->lock == 0)
3628 ; /* pass */
3629
3630 else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
3631 if (! netreq->response
3632 || netreq->response_len < GLDNS_HEADER_SIZE
3633 || ( GLDNS_RCODE_WIRE(netreq->response)
3634 != GETDNS_RCODE_NOERROR &&
3635 GLDNS_RCODE_WIRE(netreq->response)
3636 != GETDNS_RCODE_NXDOMAIN) ) {
3637
3638 netreq->dnssec_status = GETDNS_DNSSEC_INSECURE;
3639 continue;
3640
3641 } else if (netreq->unbound_id != -1)
3642 netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
3643
3644 add_pkt2val_chain( &dnsreq->my_mf, &chain
3645 , netreq->response, netreq->response_len
3646 , netreq
3647 );
3648 add_question2val_chain( &dnsreq->my_mf, &chain
3649 , netreq->response, netreq->response_len
3650 , netreq->owner->name
3651 , netreq->request_type
3652 , netreq->owner->request_class
3653 , netreq
3654 );
3655 }
3656 if (chain) {
3657 for (chain_p = chain; chain_p; chain_p = chain_p->next) {
3658 if (chain_p->lock) chain_p->lock--;
3659 }
3660 dnsreq->chain = chain;
3661 if (dnsreq->avoid_dnssec_roadblocks && chain->lock)
3662 chain->lock -= 1;
3663
3664 check_chain_complete(chain);
3665 } else {
3666 dnsreq->validating = 0;
3667 _getdns_call_user_callback(dnsreq,
3668 _getdns_create_getdns_response(dnsreq));
3669 }
3670 }
3671
3672
3673 /******************* getdns_validate_dnssec() Function *********************
3674 *****************************************************************************/
3675
3676
wire_validate_dnssec(const struct mem_funcs * mf,time_t now,uint32_t skew,uint8_t * to_val,size_t to_val_len,uint8_t * support,size_t support_len,uint8_t * tas,size_t tas_len)3677 static int wire_validate_dnssec(const struct mem_funcs *mf,
3678 time_t now, uint32_t skew, uint8_t *to_val, size_t to_val_len,
3679 uint8_t *support, size_t support_len, uint8_t *tas, size_t tas_len)
3680 {
3681 chain_head *chain, *head, *next_head;
3682 chain_node *node;
3683
3684 uint8_t qname_spc[256];
3685 const uint8_t *qname = NULL;
3686 size_t qname_len = sizeof(qname_spc);
3687 uint16_t qtype = 0, qclass = GETDNS_RRCLASS_IN;
3688
3689 _getdns_rr_iter rr_spc, *rr;
3690 _getdns_rrset_iter tas_iter;
3691
3692 int s;
3693
3694
3695 if (to_val_len < GLDNS_HEADER_SIZE)
3696 return GETDNS_RETURN_GENERIC_ERROR;
3697
3698 #if defined(SEC_DEBUG) && SEC_DEBUG
3699 char *str = gldns_wire2str_pkt(to_val, to_val_len);
3700 DEBUG_SEC("to validate: %s\n", str);
3701 free(str);
3702 #endif
3703
3704 if (GLDNS_RCODE_WIRE(to_val) != GETDNS_RCODE_NOERROR &&
3705 GLDNS_RCODE_WIRE(to_val) != GETDNS_RCODE_NXDOMAIN)
3706 return GETDNS_DNSSEC_INSECURE;
3707
3708 if (GLDNS_QDCOUNT(to_val) == 0 && GLDNS_ANCOUNT(to_val) == 0)
3709 return GETDNS_RETURN_GENERIC_ERROR;
3710
3711 chain = NULL;
3712 /* First create a chain (head + nodes) for each rr in the answer and
3713 * authority section of the fake to_val packet.
3714 */
3715 add_pkt2val_chain(mf, &chain, to_val, to_val_len, NULL);
3716
3717 /* For each question in the question section add a chain head.
3718 */
3719 if ( (rr = _getdns_rr_iter_init(&rr_spc, to_val, to_val_len))
3720 && _getdns_rr_iter_section(rr) == SECTION_QUESTION
3721 && (qname = _getdns_owner_if_or_as_decompressed(
3722 rr, qname_spc, &qname_len))
3723 && rr->nxt >= rr->rr_type + 4) {
3724
3725 qtype = gldns_read_uint16(rr->rr_type);
3726 qclass = gldns_read_uint16(rr->rr_type + 2);
3727
3728 add_question2val_chain(mf, &chain, to_val, to_val_len,
3729 qname, qtype, qclass, NULL);
3730 }
3731
3732 /* Now equip the nodes with the support records wireformat */
3733 for (head = chain; head; head = head->next) {
3734 for (node = head->parent; node; node = node->parent) {
3735
3736 node->dnskey.pkt = support;
3737 node->dnskey.pkt_len = support_len;
3738 node->ds.pkt = support;
3739 node->ds.pkt_len = support_len;
3740 }
3741 }
3742 s = chain_validate_dnssec(mf, now, skew, chain,
3743 _getdns_rrset_iter_init(
3744 &tas_iter, tas, tas_len, SECTION_ANSWER));
3745
3746 /* Cleanup the chain */
3747 for (head = chain; head; head = next_head) {
3748 next_head = head->next;
3749 GETDNS_FREE(*mf, head);
3750 }
3751 return s;
3752 }
3753
3754 /*
3755 * getdns_validate_dnssec
3756 *
3757 */
3758 getdns_return_t
getdns_validate_dnssec2(const getdns_list * records_to_validate,const getdns_list * support_records,const getdns_list * trust_anchors,time_t now,uint32_t skew)3759 getdns_validate_dnssec2(const getdns_list *records_to_validate,
3760 const getdns_list *support_records,
3761 const getdns_list *trust_anchors,
3762 time_t now, uint32_t skew)
3763 {
3764 uint8_t to_val_buf[4096], *to_val,
3765 support_buf[4096], *support,
3766 tas_buf[4096], *tas;
3767
3768 size_t to_val_len = sizeof(to_val_buf),
3769 support_len = sizeof(support_buf),
3770 tas_len = sizeof(tas_buf);
3771
3772 int r = GETDNS_RETURN_MEMORY_ERROR;
3773 const struct mem_funcs *mf;
3774
3775 size_t i;
3776 getdns_dict *reply;
3777
3778 #if defined(SEC_DEBUG) && SEC_DEBUG
3779 fflush(stdout);
3780 #endif
3781
3782 if (!records_to_validate || !trust_anchors)
3783 return GETDNS_RETURN_INVALID_PARAMETER;
3784 mf = &records_to_validate->mf;
3785
3786 /* First convert everything to wire format
3787 */
3788
3789 if (!support_records)
3790 (void) memset((support = support_buf), 0, GLDNS_HEADER_SIZE);
3791
3792 else if (!(support = _getdns_list2wire(support_records,
3793 support_buf, &support_len, mf)))
3794 return GETDNS_RETURN_MEMORY_ERROR;
3795
3796 if (!(tas = _getdns_list2wire(trust_anchors,
3797 tas_buf, &tas_len, mf)))
3798 goto exit_free_support;
3799
3800 if (!(to_val = _getdns_list2wire(records_to_validate,
3801 to_val_buf, &to_val_len, mf)))
3802 goto exit_free_tas;
3803
3804 if ((r = wire_validate_dnssec(mf, now, skew, to_val, to_val_len,
3805 support,support_len, tas,tas_len)) != GETDNS_RETURN_GENERIC_ERROR)
3806 goto exit_free_to_val;
3807
3808 for (i = 0; !getdns_list_get_dict(records_to_validate,i,&reply); i++) {
3809
3810 DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
3811 if (to_val != to_val_buf)
3812 GETDNS_FREE(*mf, to_val);
3813 to_val_len = sizeof(to_val_buf);
3814
3815 if (!(to_val = _getdns_reply2wire(
3816 reply, to_val_buf, &to_val_len, mf)))
3817 continue;
3818
3819 r = GETDNS_DNSSEC_INDETERMINATE;
3820 switch (wire_validate_dnssec(mf, now, skew,
3821 to_val, to_val_len, support, support_len, tas, tas_len)) {
3822 case GETDNS_DNSSEC_SECURE:
3823 if (r == GETDNS_DNSSEC_INDETERMINATE)
3824 r = GETDNS_DNSSEC_SECURE;
3825 break;
3826 case GETDNS_DNSSEC_INSECURE:
3827 if (r != GETDNS_DNSSEC_BOGUS)
3828 r = GETDNS_DNSSEC_INSECURE;
3829 break;
3830 case GETDNS_DNSSEC_BOGUS:
3831 r = GETDNS_DNSSEC_BOGUS;
3832 break;
3833 default:
3834 break;
3835 }
3836 }
3837 DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
3838
3839 exit_free_to_val:
3840 if (to_val != to_val_buf)
3841 GETDNS_FREE(*mf, to_val);
3842 exit_free_tas:
3843 if (tas != tas_buf)
3844 GETDNS_FREE(*mf, tas);
3845 exit_free_support:
3846 if (support != support_buf)
3847 GETDNS_FREE(*mf, support);
3848
3849 return r;
3850 }
3851
3852
3853 getdns_return_t
getdns_validate_dnssec(const getdns_list * records_to_validate,const getdns_list * support_records,const getdns_list * trust_anchors)3854 getdns_validate_dnssec(const getdns_list *records_to_validate,
3855 const getdns_list *support_records,
3856 const getdns_list *trust_anchors)
3857 {
3858 return getdns_validate_dnssec2(records_to_validate, support_records,
3859 trust_anchors, time(NULL), 0);
3860 }
3861
3862 /****************** getdns_root_trust_anchor() Function ********************
3863 *****************************************************************************/
3864
3865 uint16_t
_getdns_parse_ta_file(time_t * ta_mtime,gldns_buffer * gbuf)3866 _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf)
3867 {
3868
3869 struct gldns_file_parse_state pst;
3870 struct stat st;
3871 uint8_t rr[8192]; /* Reasonable size for a single DNSKEY or DS RR */
3872 size_t len, dname_len;
3873 FILE *in;
3874 uint16_t ta_count = 0;
3875 size_t pkt_start;
3876
3877 if (stat(TRUST_ANCHOR_FILE, &st) != 0)
3878 return 0;
3879
3880 if (ta_mtime)
3881 *ta_mtime = st.st_mtime;
3882
3883 if (!(in = fopen(TRUST_ANCHOR_FILE, "r")))
3884 return 0;
3885
3886 memset(&pst, 0, sizeof(pst));
3887 pst.default_ttl = 3600;
3888 pst.lineno = 1;
3889
3890 pkt_start = gldns_buffer_position(gbuf);
3891 /* Empty header */
3892 gldns_buffer_write_u32(gbuf, 0);
3893 gldns_buffer_write_u32(gbuf, 0);
3894 gldns_buffer_write_u32(gbuf, 0);
3895
3896 while (!feof(in)) {
3897 len = sizeof(rr);
3898 dname_len = 0;
3899 if (gldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst))
3900 break;
3901 if (len == 0) /* empty, $TTL, $ORIGIN */
3902 continue;
3903 if (gldns_wirerr_get_type(rr, len, dname_len)
3904 != GLDNS_RR_TYPE_DS &&
3905 gldns_wirerr_get_type(rr, len, dname_len)
3906 != GLDNS_RR_TYPE_DNSKEY)
3907 continue;
3908
3909 gldns_buffer_write(gbuf, rr, len);
3910 ta_count++;
3911 }
3912 fclose(in);
3913 gldns_buffer_write_u16_at(gbuf, pkt_start+GLDNS_ANCOUNT_OFF, ta_count);
3914
3915 return ta_count;
3916 }
3917
3918 getdns_list *
getdns_root_trust_anchor(time_t * utc_date_of_anchor)3919 getdns_root_trust_anchor(time_t *utc_date_of_anchor)
3920 {
3921 gldns_buffer *gbuf;
3922 getdns_list *ta_rrs;
3923
3924 if (!(ta_rrs = getdns_list_create()))
3925 return NULL;
3926
3927 if (!(gbuf = gldns_buffer_new(4096)))
3928 goto error_free_ta_rrs;
3929
3930 if (!_getdns_parse_ta_file(utc_date_of_anchor, gbuf))
3931 goto error_free_gbuf;
3932
3933 _getdns_wire2list( gldns_buffer_begin(gbuf)
3934 , gldns_buffer_position(gbuf), ta_rrs);
3935
3936 gldns_buffer_free(gbuf);
3937 return ta_rrs;
3938
3939 error_free_gbuf:
3940 gldns_buffer_free(gbuf);
3941 error_free_ta_rrs:
3942 getdns_list_destroy(ta_rrs);
3943 return NULL;
3944 }
3945
3946 /* dnssec.c */
3947