1 /*
2 * dnssec.c
3 * Some DNSSEC helper function are defined here
4 * and tracing is done
5 * (c) 2005 NLnet Labs
6 *
7 * See the file LICENSE for the license
8 *
9 */
10
11 #include "drill.h"
12 #include <ldns/ldns.h>
13
14 /* get rr_type from a server from a server */
15 ldns_rr_list *
get_rr(ldns_resolver * res,ldns_rdf * zname,ldns_rr_type t,ldns_rr_class c)16 get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
17 {
18 /* query, retrieve, extract and return */
19 ldns_pkt *p;
20 ldns_rr_list *found;
21
22 p = ldns_pkt_new();
23 found = NULL;
24
25 if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) {
26 found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
27 }
28 ldns_pkt_free(p);
29 return found;
30 }
31
32 void
drill_pkt_print(FILE * fd,ldns_resolver * r,ldns_pkt * p)33 drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
34 {
35 ldns_rr_list *new_nss;
36 ldns_rr_list *hostnames;
37 char *answerfrom_str;
38
39 if (verbosity < 5) {
40 return;
41 }
42
43 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
44
45 new_nss = ldns_pkt_rr_list_by_type(p,
46 LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
47 ldns_rr_list_print(fd, new_nss);
48 ldns_rr_list_deep_free(new_nss);
49
50 fprintf(fd, ";; Received %d bytes from %s#%d(",
51 (int) ldns_pkt_size(p),
52 ldns_rdf2str(ldns_pkt_answerfrom(p)),
53 (int) ldns_resolver_port(r));
54 /* if we can resolve this print it, other print the ip again */
55 if (hostnames) {
56 ldns_rdf_print(fd,
57 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
58 ldns_rr_list_deep_free(hostnames);
59 } else {
60 answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
61 if (answerfrom_str) {
62 fprintf(fd, "%s", answerfrom_str);
63 LDNS_FREE(answerfrom_str);
64 }
65 }
66 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
67 }
68
69 void
drill_pkt_print_footer(FILE * fd,ldns_resolver * r,ldns_pkt * p)70 drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
71 {
72 ldns_rr_list *hostnames;
73 char *answerfrom_str;
74
75 if (verbosity < 5) {
76 return;
77 }
78
79 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
80
81 fprintf(fd, ";; Received %d bytes from %s#%d(",
82 (int) ldns_pkt_size(p),
83 ldns_rdf2str(ldns_pkt_answerfrom(p)),
84 (int) ldns_resolver_port(r));
85 /* if we can resolve this print it, other print the ip again */
86 if (hostnames) {
87 ldns_rdf_print(fd,
88 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
89 ldns_rr_list_deep_free(hostnames);
90 } else {
91 answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
92 if (answerfrom_str) {
93 fprintf(fd, "%s", answerfrom_str);
94 LDNS_FREE(answerfrom_str);
95 }
96 }
97 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
98 }
99 /*
100 * generic function to get some RRset from a nameserver
101 * and possible some signatures too (that would be the day...)
102 */
103 ldns_pkt_type
get_dnssec_rr(ldns_pkt * p,ldns_rdf * name,ldns_rr_type t,ldns_rr_list ** rrlist,ldns_rr_list ** sig)104 get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
105 ldns_rr_list **rrlist, ldns_rr_list **sig)
106 {
107 ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
108 ldns_rr_list *sigs = NULL;
109 size_t i;
110
111 if (!p) {
112 if (rrlist) {
113 *rrlist = NULL;
114 }
115 return LDNS_PACKET_UNKNOWN;
116 }
117
118 pt = ldns_pkt_reply_type(p);
119 if (name) {
120 if (rrlist) {
121 *rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t,
122 LDNS_SECTION_ANSWER);
123 if (!*rrlist) {
124 *rrlist = ldns_pkt_rr_list_by_name_and_type(
125 p, name, t,
126 LDNS_SECTION_AUTHORITY);
127 }
128 }
129 if (sig) {
130 sigs = ldns_pkt_rr_list_by_name_and_type(p, name,
131 LDNS_RR_TYPE_RRSIG,
132 LDNS_SECTION_ANSWER);
133 if (!sigs) {
134 sigs = ldns_pkt_rr_list_by_name_and_type(
135 p, name, LDNS_RR_TYPE_RRSIG,
136 LDNS_SECTION_AUTHORITY);
137 }
138 }
139 } else {
140 /* A DS-referral - get the DS records if they are there */
141 if (rrlist) {
142 *rrlist = ldns_pkt_rr_list_by_type(
143 p, t, LDNS_SECTION_AUTHORITY);
144 }
145 if (sig) {
146 sigs = ldns_pkt_rr_list_by_type(p,
147 LDNS_RR_TYPE_RRSIG,
148 LDNS_SECTION_AUTHORITY);
149 }
150 }
151 if (sig) {
152 *sig = ldns_rr_list_new();
153 for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
154 /* only add the sigs that cover this type */
155 if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(
156 ldns_rr_list_rr(sigs, i)))) {
157
158 ldns_rr_list_push_rr(*sig,
159 ldns_rr_clone(
160 ldns_rr_list_rr(
161 sigs, i)));
162 }
163 }
164 }
165 ldns_rr_list_deep_free(sigs);
166
167 if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
168 return pt;
169 } else {
170 return LDNS_PACKET_ANSWER;
171 }
172 }
173
174
175 ldns_status
ldns_verify_denial(ldns_pkt * pkt,ldns_rdf * name,ldns_rr_type type,ldns_rr_list ** nsec_rrs,ldns_rr_list ** nsec_rr_sigs)176 ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
177 {
178 #ifdef HAVE_SSL
179 uint16_t nsec_i;
180
181 ldns_rr_list *nsecs;
182 ldns_status result;
183 const ldns_rr_descriptor *descriptor;
184
185 if (!pkt) {
186 descriptor = ldns_rr_descript(type);
187
188 printf("NETWORk ERROR! Cannot verify denial for: ");
189 ldns_rdf_print(stdout, name);
190 printf(" type ");
191 if (descriptor && descriptor->_name)
192 printf("%s", descriptor->_name);
193 else
194 printf("TYPE%u", type);
195 return LDNS_STATUS_CRYPTO_NO_RRSIG;
196 }
197 if (verbosity >= 5) {
198 printf("VERIFY DENIAL FROM:\n");
199 ldns_pkt_print(stdout, pkt);
200 }
201
202 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
203 /* Try to see if there are NSECS in the packet */
204 nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
205 if (nsecs) {
206 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
207 /* there are four options:
208 * - name equals ownername and is covered by the type bitmap
209 * - name equals ownername but is not covered by the type bitmap
210 * - name falls within nsec coverage but is not equal to the owner name
211 * - name falls outside of nsec coverage
212 */
213 if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
214 /*
215 printf("CHECKING NSEC:\n");
216 ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
217 printf("DAWASEM\n");
218 */
219 if (ldns_nsec_bitmap_covers_type(
220 ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
221 nsec_i)),
222 type)) {
223 /* Error, according to the nsec this rrset is signed */
224 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
225 } else {
226 /* ok nsec denies existence */
227 if (verbosity >= 3) {
228 printf(";; Existence of data set with this type denied by NSEC\n");
229 }
230 /*printf(";; Verifiably insecure.\n");*/
231 if (nsec_rrs && nsec_rr_sigs) {
232 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
233 }
234 ldns_rr_list_deep_free(nsecs);
235 return LDNS_STATUS_OK;
236 }
237 } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
238 if (verbosity >= 3) {
239 printf(";; Existence of data set with this name denied by NSEC\n");
240 }
241 if (nsec_rrs && nsec_rr_sigs) {
242 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
243 }
244 ldns_rr_list_deep_free(nsecs);
245 return LDNS_STATUS_OK;
246 } else {
247 /* nsec has nothing to do with this data */
248 }
249 }
250 ldns_rr_list_deep_free(nsecs);
251 } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
252 ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
253 ldns_rr* q = ldns_rr_new();
254 ldns_rr* match = NULL;
255
256 if(!sigs) {
257 if (q) {
258 ldns_rr_free(q);
259 }
260 ldns_rr_list_deep_free(nsecs);
261 return LDNS_STATUS_MEM_ERR;
262 }
263 if(!q) {
264 ldns_rr_list_deep_free(nsecs);
265 ldns_rr_list_deep_free(sigs);
266 return LDNS_STATUS_MEM_ERR;
267 }
268 ldns_rr_set_question(q, 1);
269 ldns_rr_set_ttl(q, 0);
270 ldns_rr_set_owner(q, ldns_rdf_clone(name));
271 if(!ldns_rr_owner(q)) {
272 ldns_rr_free(q);
273 ldns_rr_list_deep_free(sigs);
274 ldns_rr_list_deep_free(nsecs);
275 return LDNS_STATUS_MEM_ERR;
276 }
277 ldns_rr_set_type(q, type);
278
279 /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
280 result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
281 if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
282 (void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
283 }
284 ldns_rr_free(q);
285 ldns_rr_list_deep_free(nsecs);
286 ldns_rr_list_deep_free(sigs);
287 }
288 return result;
289 #else
290 (void)pkt;
291 (void)name;
292 (void)type;
293 (void)nsec_rrs;
294 (void)nsec_rr_sigs;
295 return LDNS_STATUS_ERR;
296 #endif /* HAVE_SSL */
297 }
298
299 /* NSEC3 draft -07 */
300 /*return hash name match*/
301 ldns_rr *
ldns_nsec3_exact_match(ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_list * nsec3s)302 ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
303 uint8_t algorithm;
304 uint32_t iterations;
305 uint8_t salt_length;
306 uint8_t *salt;
307
308 ldns_rdf *sname = NULL, *hashed_sname = NULL;
309
310 size_t nsec_i;
311 ldns_rr *nsec;
312 ldns_rr *result = NULL;
313
314 const ldns_rr_descriptor *descriptor;
315
316 ldns_rdf *zone_name = NULL;
317
318 if (verbosity >= 4) {
319 printf(";; finding exact match for ");
320 descriptor = ldns_rr_descript(qtype);
321 if (descriptor && descriptor->_name) {
322 printf("%s ", descriptor->_name);
323 } else {
324 printf("TYPE%d ", qtype);
325 }
326 ldns_rdf_print(stdout, qname);
327 printf("\n");
328 }
329
330 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
331 if (verbosity >= 4) {
332 printf("no qname, nsec3s or list empty\n");
333 }
334 return NULL;
335 }
336
337 nsec = ldns_rr_list_rr(nsec3s, 0);
338 algorithm = ldns_nsec3_algorithm(nsec);
339 salt_length = ldns_nsec3_salt_length(nsec);
340 salt = ldns_nsec3_salt_data(nsec);
341 iterations = ldns_nsec3_iterations(nsec);
342 if (salt == NULL) {
343 goto done;
344 }
345
346 sname = ldns_rdf_clone(qname);
347 if (sname == NULL) {
348 goto done;
349 }
350 if (verbosity >= 4) {
351 printf(";; owner name hashes to: ");
352 }
353 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
354 if (hashed_sname == NULL) {
355 goto done;
356 }
357 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
358 if (zone_name == NULL) {
359 goto done;
360 }
361 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) {
362 goto done;
363 };
364
365 if (verbosity >= 4) {
366 ldns_rdf_print(stdout, hashed_sname);
367 printf("\n");
368 }
369
370 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
371 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
372
373 /* check values of iterations etc! */
374
375 /* exact match? */
376 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
377 result = nsec;
378 goto done;
379 }
380
381 }
382
383 done:
384 ldns_rdf_deep_free(zone_name);
385 ldns_rdf_deep_free(sname);
386 ldns_rdf_deep_free(hashed_sname);
387 LDNS_FREE(salt);
388
389 if (verbosity >= 4) {
390 if (result) {
391 printf(";; Found.\n");
392 } else {
393 printf(";; Not foud.\n");
394 }
395 }
396 return result;
397 }
398
399 /*return the owner name of the closest encloser for name from the list of rrs */
400 /* this is NOT the hash, but the original name! */
401 ldns_rdf *
ldns_nsec3_closest_encloser(ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_list * nsec3s)402 ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
403 {
404 /* remember parameters, they must match */
405 uint8_t algorithm;
406 uint32_t iterations;
407 uint8_t salt_length;
408 uint8_t *salt;
409
410 ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
411 bool flag;
412
413 bool exact_match_found;
414 bool in_range_found;
415
416 ldns_rdf *zone_name = NULL;
417
418 size_t nsec_i;
419 ldns_rr *nsec;
420 ldns_rdf *result = NULL;
421
422 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
423 return NULL;
424 }
425
426 if (verbosity >= 4) {
427 printf(";; finding closest encloser for type %d ", qtype);
428 ldns_rdf_print(stdout, qname);
429 printf("\n");
430 }
431
432 nsec = ldns_rr_list_rr(nsec3s, 0);
433 algorithm = ldns_nsec3_algorithm(nsec);
434 salt_length = ldns_nsec3_salt_length(nsec);
435 salt = ldns_nsec3_salt_data(nsec);
436 iterations = ldns_nsec3_iterations(nsec);
437 if (salt == NULL) {
438 goto done;
439 }
440
441 sname = ldns_rdf_clone(qname);
442 if (sname == NULL) {
443 goto done;
444 }
445
446 flag = false;
447
448 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
449 if (zone_name == NULL) {
450 goto done;
451 }
452
453 /* algorithm from nsec3-07 8.3 */
454 while (ldns_dname_label_count(sname) > 0) {
455 exact_match_found = false;
456 in_range_found = false;
457
458 if (verbosity >= 3) {
459 printf(";; ");
460 ldns_rdf_print(stdout, sname);
461 printf(" hashes to: ");
462 }
463 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
464 if (hashed_sname == NULL) {
465 goto done;
466 }
467
468 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
469 ldns_rdf_deep_free(hashed_sname);
470 goto done;
471 }
472
473 if (verbosity >= 3) {
474 ldns_rdf_print(stdout, hashed_sname);
475 printf("\n");
476 }
477
478 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
479 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
480
481 /* check values of iterations etc! */
482
483 /* exact match? */
484 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
485 if (verbosity >= 4) {
486 printf(";; exact match found\n");
487 }
488 exact_match_found = true;
489 } else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
490 if (verbosity >= 4) {
491 printf(";; in range of an nsec\n");
492 }
493 in_range_found = true;
494 }
495
496 }
497 if (!exact_match_found && in_range_found) {
498 flag = true;
499 } else if (exact_match_found && flag) {
500 result = ldns_rdf_clone(sname);
501 } else if (exact_match_found && !flag) {
502 // error!
503 if (verbosity >= 4) {
504 printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
505 }
506 ldns_rdf_deep_free(hashed_sname);
507 goto done;
508 } else {
509 flag = false;
510 }
511
512 ldns_rdf_deep_free(hashed_sname);
513 tmp = sname;
514 sname = ldns_dname_left_chop(sname);
515 ldns_rdf_deep_free(tmp);
516 if (sname == NULL) {
517 goto done;
518 }
519 }
520
521 done:
522 LDNS_FREE(salt);
523 ldns_rdf_deep_free(zone_name);
524 ldns_rdf_deep_free(sname);
525
526 if (!result) {
527 if (verbosity >= 4) {
528 printf(";; no closest encloser found\n");
529 }
530 }
531
532 /* todo checks from end of 6.2. here or in caller? */
533 return result;
534 }
535