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) {
26 found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
33 drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
35 ldns_rr_list *new_nss;
36 ldns_rr_list *hostnames;
43 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
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);
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 */
57 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
58 ldns_rr_list_deep_free(hostnames);
60 answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
62 fprintf(fd, "%s", answerfrom_str);
63 LDNS_FREE(answerfrom_str);
66 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
70 drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
72 ldns_rr_list *hostnames;
79 hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
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 */
88 ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
89 ldns_rr_list_deep_free(hostnames);
91 answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
93 fprintf(fd, "%s", answerfrom_str);
94 LDNS_FREE(answerfrom_str);
97 fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
100 * generic function to get some RRset from a nameserver
101 * and possible some signatures too (that would be the day...)
104 get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
105 ldns_rr_list **rrlist, ldns_rr_list **sig)
107 ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
108 ldns_rr_list *sigs = NULL;
115 return LDNS_PACKET_UNKNOWN;
118 pt = ldns_pkt_reply_type(p);
121 *rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t,
122 LDNS_SECTION_ANSWER);
124 *rrlist = ldns_pkt_rr_list_by_name_and_type(
126 LDNS_SECTION_AUTHORITY);
130 sigs = ldns_pkt_rr_list_by_name_and_type(p, name,
132 LDNS_SECTION_ANSWER);
134 sigs = ldns_pkt_rr_list_by_name_and_type(
135 p, name, LDNS_RR_TYPE_RRSIG,
136 LDNS_SECTION_AUTHORITY);
140 /* A DS-referral - get the DS records if they are there */
142 *rrlist = ldns_pkt_rr_list_by_type(
143 p, t, LDNS_SECTION_AUTHORITY);
146 sigs = ldns_pkt_rr_list_by_type(p,
148 LDNS_SECTION_AUTHORITY);
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)))) {
158 ldns_rr_list_push_rr(*sig,
165 ldns_rr_list_deep_free(sigs);
167 if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
170 return LDNS_PACKET_ANSWER;
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)
184 if (verbosity >= 5) {
185 printf("VERIFY DENIAL FROM:\n");
186 ldns_pkt_print(stdout, pkt);
189 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
190 /* Try to see if there are NSECS in the packet */
191 nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
193 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
194 /* there are four options:
195 * - name equals ownername and is covered by the type bitmap
196 * - name equals ownername but is not covered by the type bitmap
197 * - name falls within nsec coverage but is not equal to the owner name
198 * - name falls outside of nsec coverage
200 if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
202 printf("CHECKING NSEC:\n");
203 ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
206 if (ldns_nsec_bitmap_covers_type(
207 ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
210 /* Error, according to the nsec this rrset is signed */
211 result = LDNS_STATUS_CRYPTO_NO_RRSIG;
213 /* ok nsec denies existence */
214 if (verbosity >= 3) {
215 printf(";; Existence of data set with this type denied by NSEC\n");
217 /*printf(";; Verifiably insecure.\n");*/
218 if (nsec_rrs && nsec_rr_sigs) {
219 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
221 ldns_rr_list_deep_free(nsecs);
222 return LDNS_STATUS_OK;
224 } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
225 if (verbosity >= 3) {
226 printf(";; Existence of data set with this name denied by NSEC\n");
228 if (nsec_rrs && nsec_rr_sigs) {
229 (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
231 ldns_rr_list_deep_free(nsecs);
232 return LDNS_STATUS_OK;
234 /* nsec has nothing to do with this data */
237 ldns_rr_list_deep_free(nsecs);
238 } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
239 ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
240 ldns_rr* q = ldns_rr_new();
241 ldns_rr* match = NULL;
247 ldns_rr_list_deep_free(nsecs);
248 return LDNS_STATUS_MEM_ERR;
251 ldns_rr_list_deep_free(nsecs);
252 ldns_rr_list_deep_free(sigs);
253 return LDNS_STATUS_MEM_ERR;
255 ldns_rr_set_question(q, 1);
256 ldns_rr_set_ttl(q, 0);
257 ldns_rr_set_owner(q, ldns_rdf_clone(name));
258 if(!ldns_rr_owner(q)) {
260 ldns_rr_list_deep_free(sigs);
261 ldns_rr_list_deep_free(nsecs);
262 return LDNS_STATUS_MEM_ERR;
264 ldns_rr_set_type(q, type);
266 /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
267 result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
268 if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
269 (void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
272 ldns_rr_list_deep_free(nsecs);
273 ldns_rr_list_deep_free(sigs);
282 return LDNS_STATUS_ERR;
283 #endif /* HAVE_SSL */
286 /* NSEC3 draft -07 */
287 /*return hash name match*/
289 ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
295 ldns_rdf *sname = NULL, *hashed_sname = NULL;
299 ldns_rr *result = NULL;
301 const ldns_rr_descriptor *descriptor;
303 ldns_rdf *zone_name = NULL;
305 if (verbosity >= 4) {
306 printf(";; finding exact match for ");
307 descriptor = ldns_rr_descript(qtype);
308 if (descriptor && descriptor->_name) {
309 printf("%s ", descriptor->_name);
311 printf("TYPE%d ", qtype);
313 ldns_rdf_print(stdout, qname);
317 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
318 if (verbosity >= 4) {
319 printf("no qname, nsec3s or list empty\n");
324 nsec = ldns_rr_list_rr(nsec3s, 0);
325 algorithm = ldns_nsec3_algorithm(nsec);
326 salt_length = ldns_nsec3_salt_length(nsec);
327 salt = ldns_nsec3_salt_data(nsec);
328 iterations = ldns_nsec3_iterations(nsec);
333 sname = ldns_rdf_clone(qname);
337 if (verbosity >= 4) {
338 printf(";; owner name hashes to: ");
340 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
341 if (hashed_sname == NULL) {
344 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
345 if (zone_name == NULL) {
348 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) {
352 if (verbosity >= 4) {
353 ldns_rdf_print(stdout, hashed_sname);
357 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
358 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
360 /* check values of iterations etc! */
363 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
371 ldns_rdf_deep_free(zone_name);
372 ldns_rdf_deep_free(sname);
373 ldns_rdf_deep_free(hashed_sname);
376 if (verbosity >= 4) {
378 printf(";; Found.\n");
380 printf(";; Not foud.\n");
386 /*return the owner name of the closest encloser for name from the list of rrs */
387 /* this is NOT the hash, but the original name! */
389 ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
391 /* remember parameters, they must match */
397 ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
400 bool exact_match_found;
403 ldns_rdf *zone_name = NULL;
407 ldns_rdf *result = NULL;
409 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
413 if (verbosity >= 4) {
414 printf(";; finding closest encloser for type %d ", qtype);
415 ldns_rdf_print(stdout, qname);
419 nsec = ldns_rr_list_rr(nsec3s, 0);
420 algorithm = ldns_nsec3_algorithm(nsec);
421 salt_length = ldns_nsec3_salt_length(nsec);
422 salt = ldns_nsec3_salt_data(nsec);
423 iterations = ldns_nsec3_iterations(nsec);
428 sname = ldns_rdf_clone(qname);
435 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
436 if (zone_name == NULL) {
440 /* algorithm from nsec3-07 8.3 */
441 while (ldns_dname_label_count(sname) > 0) {
442 exact_match_found = false;
443 in_range_found = false;
445 if (verbosity >= 3) {
447 ldns_rdf_print(stdout, sname);
448 printf(" hashes to: ");
450 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
451 if (hashed_sname == NULL) {
455 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
459 if (verbosity >= 3) {
460 ldns_rdf_print(stdout, hashed_sname);
464 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
465 nsec = ldns_rr_list_rr(nsec3s, nsec_i);
467 /* check values of iterations etc! */
470 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
471 if (verbosity >= 4) {
472 printf(";; exact match found\n");
474 exact_match_found = true;
475 } else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
476 if (verbosity >= 4) {
477 printf(";; in range of an nsec\n");
479 in_range_found = true;
483 if (!exact_match_found && in_range_found) {
485 } else if (exact_match_found && flag) {
486 result = ldns_rdf_clone(sname);
487 } else if (exact_match_found && !flag) {
489 if (verbosity >= 4) {
490 printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
492 ldns_rdf_deep_free(hashed_sname);
498 ldns_rdf_deep_free(hashed_sname);
500 sname = ldns_dname_left_chop(sname);
501 ldns_rdf_deep_free(tmp);
509 ldns_rdf_deep_free(zone_name);
510 ldns_rdf_deep_free(sname);
513 if (verbosity >= 4) {
514 printf(";; no closest encloser found\n");
518 /* todo checks from end of 6.2. here or in caller? */