3 * Some DNSSEC helper function are defined here
7 * See the file LICENSE for the license
12 #include <ldns/ldns.h>
14 /* get rr_type from a server from a server */
16 get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
18 /* query, retrieve, extract and return */
25 if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) {
29 found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
35 drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
37 ldns_rr_list *new_nss;
38 ldns_rr_list *hostnames;
44 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
46 new_nss = ldns_pkt_rr_list_by_type(p,
47 LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
48 ldns_rr_list_print(fd, new_nss);
50 /* new_nss can be empty.... */
52 fprintf(fd, ";; Received %d bytes from %s#%d(",
53 (int) ldns_pkt_size(p),
54 ldns_rdf2str(ldns_pkt_answerfrom(p)),
55 (int) ldns_resolver_port(r));
56 /* if we can resolve this print it, other print the ip again */
59 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
60 ldns_rr_list_deep_free(hostnames);
62 fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
64 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
68 drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
70 ldns_rr_list *hostnames;
76 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
78 fprintf(fd, ";; Received %d bytes from %s#%d(",
79 (int) ldns_pkt_size(p),
80 ldns_rdf2str(ldns_pkt_answerfrom(p)),
81 (int) ldns_resolver_port(r));
82 /* if we can resolve this print it, other print the ip again */
85 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
86 ldns_rr_list_deep_free(hostnames);
88 fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
90 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
93 * generic function to get some RRset from a nameserver
94 * and possible some signatures too (that would be the day...)
97 get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
98 ldns_rr_list **rrlist, ldns_rr_list **sig)
100 ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
101 ldns_rr_list *rr = NULL;
102 ldns_rr_list *sigs = NULL;
109 return LDNS_PACKET_UNKNOWN;
112 pt = ldns_pkt_reply_type(p);
114 rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER);
116 rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY);
118 sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG,
119 LDNS_SECTION_ANSWER);
121 sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG,
122 LDNS_SECTION_AUTHORITY);
125 /* A DS-referral - get the DS records if they are there */
126 rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY);
127 sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG,
128 LDNS_SECTION_AUTHORITY);
131 *sig = ldns_rr_list_new();
132 for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
133 /* only add the sigs that cover this type */
134 if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) ==
136 ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i)));
140 ldns_rr_list_deep_free(sigs);
145 if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
148 return LDNS_PACKET_ANSWER;
154 ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
161 if (verbosity >= 5) {
162 printf("VERIFY DENIAL FROM:\n");
163 ldns_pkt_print(stdout, pkt);
166 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
167 /* Try to see if there are NSECS in the packet */
168 nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
170 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
171 /* there are four options:
172 * - name equals ownername and is covered by the type bitmap
173 * - name equals ownername but is not covered by the type bitmap
174 * - name falls within nsec coverage but is not equal to the owner name
175 * - name falls outside of nsec coverage
177 if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
179 printf("CHECKING NSEC:\n");
180 ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
183 if (ldns_nsec_bitmap_covers_type(
184 ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
187 /* Error, according to the nsec this rrset is signed */
188 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
190 /* ok nsec denies existence */
191 if (verbosity >= 3) {
192 printf(";; Existence of data set with this type denied by NSEC\n");
194 /*printf(";; Verifiably insecure.\n");*/
195 if (nsec_rrs && nsec_rr_sigs) {
196 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
198 ldns_rr_list_deep_free(nsecs);
199 return LDNS_STATUS_OK;
201 } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
202 if (verbosity >= 3) {
203 printf(";; Existence of data set with this name denied by NSEC\n");
205 if (nsec_rrs && nsec_rr_sigs) {
206 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
208 ldns_rr_list_deep_free(nsecs);
209 return LDNS_STATUS_OK;
211 /* nsec has nothing to do with this data */
214 ldns_rr_list_deep_free(nsecs);
215 } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
216 ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
217 ldns_rr* q = ldns_rr_new();
218 ldns_rr* match = NULL;
219 if(!sigs) return LDNS_STATUS_MEM_ERR;
220 if(!q) return LDNS_STATUS_MEM_ERR;
221 ldns_rr_set_question(q, 1);
222 ldns_rr_set_ttl(q, 0);
223 ldns_rr_set_owner(q, ldns_rdf_clone(name));
224 if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR;
225 ldns_rr_set_type(q, type);
227 /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
228 result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
229 if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
230 (void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
233 ldns_rr_list_deep_free(nsecs);
234 ldns_rr_list_deep_free(sigs);
239 /* NSEC3 draft -07 */
240 /*return hash name match*/
242 ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
248 ldns_rdf *sname, *hashed_sname;
252 ldns_rr *result = NULL;
256 const ldns_rr_descriptor *descriptor;
260 if (verbosity >= 4) {
261 printf(";; finding exact match for ");
262 descriptor = ldns_rr_descript(qtype);
263 if (descriptor && descriptor->_name) {
264 printf("%s ", descriptor->_name);
266 printf("TYPE%d ", qtype);
268 ldns_rdf_print(stdout, qname);
272 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
273 if (verbosity >= 4) {
274 printf("no qname, nsec3s or list empty\n");
279 nsec = ldns_rr_list_rr(nsec3s, 0);
280 algorithm = ldns_nsec3_algorithm(nsec);
281 salt_length = ldns_nsec3_salt_length(nsec);
282 salt = ldns_nsec3_salt_data(nsec);
283 iterations = ldns_nsec3_iterations(nsec);
285 sname = ldns_rdf_clone(qname);
287 if (verbosity >= 4) {
288 printf(";; owner name hashes to: ");
290 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
292 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
293 status = ldns_dname_cat(hashed_sname, zone_name);
295 if (verbosity >= 4) {
296 ldns_rdf_print(stdout, hashed_sname);
300 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
301 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
303 /* check values of iterations etc! */
306 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
314 ldns_rdf_deep_free(zone_name);
315 ldns_rdf_deep_free(sname);
316 ldns_rdf_deep_free(hashed_sname);
319 if (verbosity >= 4) {
321 printf(";; Found.\n");
323 printf(";; Not foud.\n");
329 /*return the owner name of the closest encloser for name from the list of rrs */
330 /* this is NOT the hash, but the original name! */
332 ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
334 /* remember parameters, they must match */
340 ldns_rdf *sname, *hashed_sname, *tmp;
344 bool exact_match_found;
352 ldns_rdf *result = NULL;
354 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
358 if (verbosity >= 4) {
359 printf(";; finding closest encloser for type %d ", qtype);
360 ldns_rdf_print(stdout, qname);
364 nsec = ldns_rr_list_rr(nsec3s, 0);
365 algorithm = ldns_nsec3_algorithm(nsec);
366 salt_length = ldns_nsec3_salt_length(nsec);
367 salt = ldns_nsec3_salt_data(nsec);
368 iterations = ldns_nsec3_iterations(nsec);
370 sname = ldns_rdf_clone(qname);
375 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
377 /* algorithm from nsec3-07 8.3 */
378 while (ldns_dname_label_count(sname) > 0) {
379 exact_match_found = false;
380 in_range_found = false;
382 if (verbosity >= 3) {
384 ldns_rdf_print(stdout, sname);
385 printf(" hashes to: ");
387 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
389 status = ldns_dname_cat(hashed_sname, zone_name);
391 if (verbosity >= 3) {
392 ldns_rdf_print(stdout, hashed_sname);
396 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
397 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
399 /* check values of iterations etc! */
402 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
403 if (verbosity >= 4) {
404 printf(";; exact match found\n");
406 exact_match_found = true;
407 } else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
408 if (verbosity >= 4) {
409 printf(";; in range of an nsec\n");
411 in_range_found = true;
415 if (!exact_match_found && in_range_found) {
417 } else if (exact_match_found && flag) {
418 result = ldns_rdf_clone(sname);
419 } else if (exact_match_found && !flag) {
421 if (verbosity >= 4) {
422 printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
424 ldns_rdf_deep_free(hashed_sname);
430 ldns_rdf_deep_free(hashed_sname);
432 sname = ldns_dname_left_chop(sname);
433 ldns_rdf_deep_free(tmp);
438 ldns_rdf_deep_free(zone_name);
439 ldns_rdf_deep_free(sname);
442 if (verbosity >= 4) {
443 printf(";; no closest encloser found\n");
447 /* todo checks from end of 6.2. here or in caller? */
452 /* special case were there was a wildcard expansion match, the exact match must be disproven */
454 ldns_verify_denial_wildcard(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
456 ldns_rdf *nsec3_ce = NULL;
457 ldns_rr *nsec3_ex = NULL;
458 ldns_rdf *wildcard_name = NULL;
459 ldns_rdf *nsec3_wc_ce = NULL;
460 ldns_rr *nsec3_wc_ex = NULL;
461 ldns_rdf *chopped_dname = NULL;
463 ldns_status result = LDNS_STATUS_ERR;
465 nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION);
467 wildcard_name = ldns_dname_new_frm_str("*");
468 chopped_dname = ldns_dname_left_chop(name);
469 result = ldns_dname_cat(wildcard_name, chopped_dname);
470 ldns_rdf_deep_free(chopped_dname);
472 nsec3_ex = ldns_nsec3_exact_match(name, type, nsecs);
473 nsec3_ce = ldns_nsec3_closest_encloser(name, type, nsecs);
474 nsec3_wc_ce = ldns_nsec3_closest_encloser(wildcard_name, type, nsecs);
475 nsec3_wc_ex = ldns_nsec3_exact_match(wildcard_name, type, nsecs);
478 if (verbosity >= 3) {
479 printf(";; Error, exact match for for name found, but should not exist (draft -07 section 8.8)\n");
481 result = LDNS_STATUS_NSEC3_ERR;
482 } else if (!nsec3_ce) {
483 if (verbosity >= 3) {
484 printf(";; Error, closest encloser for exact match missing in wildcard response (draft -07 section 8.8)\n");
486 result = LDNS_STATUS_NSEC3_ERR;
488 } else if (!nsec3_wc_ex) {
489 printf(";; Error, no wildcard nsec3 match: ");
490 ldns_rdf_print(stdout, wildcard_name);
491 printf(" (draft -07 section 8.8)\n");
492 result = LDNS_STATUS_NSEC3_ERR;
494 /* } else if (!nsec */
496 if (verbosity >= 3) {
497 printf(";; wilcard expansion proven\n");
499 result = LDNS_STATUS_OK;
502 if (verbosity >= 3) {
503 printf(";; Error: no NSEC or NSEC3 records in answer\n");
505 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
508 if (nsecs && nsec_rrs && nsec_rr_sigs) {
509 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, 0)), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);