xref: /freebsd-src/contrib/ldns/drill/dnssec.c (revision 5afab0e5e56fe90a378fb57249600e7924e1cab2)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * dnssec.c
37b5038d7SDag-Erling Smørgrav  * Some DNSSEC helper function are defined here
47b5038d7SDag-Erling Smørgrav  * and tracing is done
57b5038d7SDag-Erling Smørgrav  * (c) 2005 NLnet Labs
67b5038d7SDag-Erling Smørgrav  *
77b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
87b5038d7SDag-Erling Smørgrav  *
97b5038d7SDag-Erling Smørgrav  */
107b5038d7SDag-Erling Smørgrav 
117b5038d7SDag-Erling Smørgrav #include "drill.h"
127b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
137b5038d7SDag-Erling Smørgrav 
147b5038d7SDag-Erling Smørgrav /* get rr_type from a server from a server */
157b5038d7SDag-Erling Smørgrav ldns_rr_list *
get_rr(ldns_resolver * res,ldns_rdf * zname,ldns_rr_type t,ldns_rr_class c)167b5038d7SDag-Erling Smørgrav get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
177b5038d7SDag-Erling Smørgrav {
187b5038d7SDag-Erling Smørgrav 	/* query, retrieve, extract and return */
197b5038d7SDag-Erling Smørgrav 	ldns_pkt *p;
207b5038d7SDag-Erling Smørgrav 	ldns_rr_list *found;
217b5038d7SDag-Erling Smørgrav 
227b5038d7SDag-Erling Smørgrav 	p = ldns_pkt_new();
237b5038d7SDag-Erling Smørgrav 	found = NULL;
247b5038d7SDag-Erling Smørgrav 
252787e39aSDag-Erling Smørgrav 	if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) {
267b5038d7SDag-Erling Smørgrav 		found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
277b5038d7SDag-Erling Smørgrav 	}
282787e39aSDag-Erling Smørgrav 	ldns_pkt_free(p);
297b5038d7SDag-Erling Smørgrav 	return found;
307b5038d7SDag-Erling Smørgrav }
317b5038d7SDag-Erling Smørgrav 
327b5038d7SDag-Erling Smørgrav void
drill_pkt_print(FILE * fd,ldns_resolver * r,ldns_pkt * p)337b5038d7SDag-Erling Smørgrav drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
347b5038d7SDag-Erling Smørgrav {
357b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new_nss;
367b5038d7SDag-Erling Smørgrav 	ldns_rr_list *hostnames;
372787e39aSDag-Erling Smørgrav 	char *answerfrom_str;
387b5038d7SDag-Erling Smørgrav 
397b5038d7SDag-Erling Smørgrav 	if (verbosity < 5) {
407b5038d7SDag-Erling Smørgrav 		return;
417b5038d7SDag-Erling Smørgrav 	}
427b5038d7SDag-Erling Smørgrav 
437b5038d7SDag-Erling Smørgrav 	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
447b5038d7SDag-Erling Smørgrav 
457b5038d7SDag-Erling Smørgrav 	new_nss = ldns_pkt_rr_list_by_type(p,
467b5038d7SDag-Erling Smørgrav 			LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
477b5038d7SDag-Erling Smørgrav 	ldns_rr_list_print(fd, new_nss);
482787e39aSDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_nss);
497b5038d7SDag-Erling Smørgrav 
507b5038d7SDag-Erling Smørgrav 	fprintf(fd, ";; Received %d bytes from %s#%d(",
517b5038d7SDag-Erling Smørgrav 			(int) ldns_pkt_size(p),
527b5038d7SDag-Erling Smørgrav 			ldns_rdf2str(ldns_pkt_answerfrom(p)),
537b5038d7SDag-Erling Smørgrav 			(int) ldns_resolver_port(r));
547b5038d7SDag-Erling Smørgrav 	/* if we can resolve this print it, other print the ip again */
557b5038d7SDag-Erling Smørgrav 	if (hostnames) {
567b5038d7SDag-Erling Smørgrav 		ldns_rdf_print(fd,
577b5038d7SDag-Erling Smørgrav 				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
587b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(hostnames);
597b5038d7SDag-Erling Smørgrav 	} else {
602787e39aSDag-Erling Smørgrav 		answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
612787e39aSDag-Erling Smørgrav 		if (answerfrom_str) {
622787e39aSDag-Erling Smørgrav 			fprintf(fd, "%s", answerfrom_str);
632787e39aSDag-Erling Smørgrav 			LDNS_FREE(answerfrom_str);
642787e39aSDag-Erling Smørgrav 		}
657b5038d7SDag-Erling Smørgrav 	}
667b5038d7SDag-Erling Smørgrav 	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
677b5038d7SDag-Erling Smørgrav }
687b5038d7SDag-Erling Smørgrav 
697b5038d7SDag-Erling Smørgrav void
drill_pkt_print_footer(FILE * fd,ldns_resolver * r,ldns_pkt * p)707b5038d7SDag-Erling Smørgrav drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
717b5038d7SDag-Erling Smørgrav {
727b5038d7SDag-Erling Smørgrav 	ldns_rr_list *hostnames;
732787e39aSDag-Erling Smørgrav 	char *answerfrom_str;
747b5038d7SDag-Erling Smørgrav 
757b5038d7SDag-Erling Smørgrav 	if (verbosity < 5) {
767b5038d7SDag-Erling Smørgrav 		return;
777b5038d7SDag-Erling Smørgrav 	}
787b5038d7SDag-Erling Smørgrav 
797b5038d7SDag-Erling Smørgrav 	hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
807b5038d7SDag-Erling Smørgrav 
817b5038d7SDag-Erling Smørgrav 	fprintf(fd, ";; Received %d bytes from %s#%d(",
827b5038d7SDag-Erling Smørgrav 			(int) ldns_pkt_size(p),
837b5038d7SDag-Erling Smørgrav 			ldns_rdf2str(ldns_pkt_answerfrom(p)),
847b5038d7SDag-Erling Smørgrav 			(int) ldns_resolver_port(r));
857b5038d7SDag-Erling Smørgrav 	/* if we can resolve this print it, other print the ip again */
867b5038d7SDag-Erling Smørgrav 	if (hostnames) {
877b5038d7SDag-Erling Smørgrav 		ldns_rdf_print(fd,
887b5038d7SDag-Erling Smørgrav 				ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
897b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(hostnames);
907b5038d7SDag-Erling Smørgrav 	} else {
912787e39aSDag-Erling Smørgrav 		answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p));
922787e39aSDag-Erling Smørgrav 		if (answerfrom_str) {
932787e39aSDag-Erling Smørgrav 			fprintf(fd, "%s", answerfrom_str);
942787e39aSDag-Erling Smørgrav 			LDNS_FREE(answerfrom_str);
952787e39aSDag-Erling Smørgrav 		}
967b5038d7SDag-Erling Smørgrav 	}
977b5038d7SDag-Erling Smørgrav 	fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
987b5038d7SDag-Erling Smørgrav }
997b5038d7SDag-Erling Smørgrav /*
1007b5038d7SDag-Erling Smørgrav  * generic function to get some RRset from a nameserver
1017b5038d7SDag-Erling Smørgrav  * and possible some signatures too (that would be the day...)
1027b5038d7SDag-Erling Smørgrav  */
1037b5038d7SDag-Erling Smørgrav ldns_pkt_type
get_dnssec_rr(ldns_pkt * p,ldns_rdf * name,ldns_rr_type t,ldns_rr_list ** rrlist,ldns_rr_list ** sig)1047b5038d7SDag-Erling Smørgrav get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
1057b5038d7SDag-Erling Smørgrav 	ldns_rr_list **rrlist, ldns_rr_list **sig)
1067b5038d7SDag-Erling Smørgrav {
1077b5038d7SDag-Erling Smørgrav 	ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
1087b5038d7SDag-Erling Smørgrav 	ldns_rr_list *sigs = NULL;
1097b5038d7SDag-Erling Smørgrav 	size_t i;
1107b5038d7SDag-Erling Smørgrav 
1117b5038d7SDag-Erling Smørgrav 	if (!p) {
1127b5038d7SDag-Erling Smørgrav 		if (rrlist) {
1137b5038d7SDag-Erling Smørgrav 			*rrlist = NULL;
1147b5038d7SDag-Erling Smørgrav 		}
1157b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_UNKNOWN;
1167b5038d7SDag-Erling Smørgrav 	}
1177b5038d7SDag-Erling Smørgrav 
1187b5038d7SDag-Erling Smørgrav 	pt = ldns_pkt_reply_type(p);
1197b5038d7SDag-Erling Smørgrav 	if (name) {
1202787e39aSDag-Erling Smørgrav 		if (rrlist) {
1212787e39aSDag-Erling Smørgrav 			*rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t,
1222787e39aSDag-Erling Smørgrav 					LDNS_SECTION_ANSWER);
1232787e39aSDag-Erling Smørgrav 			if (!*rrlist) {
1242787e39aSDag-Erling Smørgrav 				*rrlist = ldns_pkt_rr_list_by_name_and_type(
1252787e39aSDag-Erling Smørgrav 						p, name, t,
1262787e39aSDag-Erling Smørgrav 						LDNS_SECTION_AUTHORITY);
1277b5038d7SDag-Erling Smørgrav 			}
1282787e39aSDag-Erling Smørgrav 		}
1292787e39aSDag-Erling Smørgrav 		if (sig) {
1302787e39aSDag-Erling Smørgrav 			sigs = ldns_pkt_rr_list_by_name_and_type(p, name,
1312787e39aSDag-Erling Smørgrav 					LDNS_RR_TYPE_RRSIG,
1327b5038d7SDag-Erling Smørgrav 					LDNS_SECTION_ANSWER);
1337b5038d7SDag-Erling Smørgrav 			if (!sigs) {
1342787e39aSDag-Erling Smørgrav 				sigs = ldns_pkt_rr_list_by_name_and_type(
1352787e39aSDag-Erling Smørgrav 						p, name, LDNS_RR_TYPE_RRSIG,
1367b5038d7SDag-Erling Smørgrav 						LDNS_SECTION_AUTHORITY);
1377b5038d7SDag-Erling Smørgrav 			}
1382787e39aSDag-Erling Smørgrav 		}
1397b5038d7SDag-Erling Smørgrav 	} else {
1407b5038d7SDag-Erling Smørgrav 		/* A DS-referral - get the DS records if they are there */
1412787e39aSDag-Erling Smørgrav 		if (rrlist) {
1422787e39aSDag-Erling Smørgrav 			*rrlist = ldns_pkt_rr_list_by_type(
1432787e39aSDag-Erling Smørgrav 					p, t, LDNS_SECTION_AUTHORITY);
1442787e39aSDag-Erling Smørgrav 		}
1452787e39aSDag-Erling Smørgrav 		if (sig) {
1462787e39aSDag-Erling Smørgrav 			sigs = ldns_pkt_rr_list_by_type(p,
1472787e39aSDag-Erling Smørgrav 					LDNS_RR_TYPE_RRSIG,
1487b5038d7SDag-Erling Smørgrav 					LDNS_SECTION_AUTHORITY);
1497b5038d7SDag-Erling Smørgrav 		}
1502787e39aSDag-Erling Smørgrav 	}
1517b5038d7SDag-Erling Smørgrav 	if (sig) {
1527b5038d7SDag-Erling Smørgrav 		*sig = ldns_rr_list_new();
1537b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
1547b5038d7SDag-Erling Smørgrav 			/* only add the sigs that cover this type */
1552787e39aSDag-Erling Smørgrav 			if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(
1562787e39aSDag-Erling Smørgrav 						ldns_rr_list_rr(sigs, i)))) {
1572787e39aSDag-Erling Smørgrav 
1582787e39aSDag-Erling Smørgrav 				ldns_rr_list_push_rr(*sig,
1592787e39aSDag-Erling Smørgrav 						ldns_rr_clone(
1602787e39aSDag-Erling Smørgrav 							ldns_rr_list_rr(
1612787e39aSDag-Erling Smørgrav 								sigs, i)));
1627b5038d7SDag-Erling Smørgrav 			}
1637b5038d7SDag-Erling Smørgrav 		}
1647b5038d7SDag-Erling Smørgrav 	}
1657b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(sigs);
1667b5038d7SDag-Erling Smørgrav 
1677b5038d7SDag-Erling Smørgrav 	if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
1687b5038d7SDag-Erling Smørgrav 		return pt;
1697b5038d7SDag-Erling Smørgrav 	} else {
1707b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_ANSWER;
1717b5038d7SDag-Erling Smørgrav 	}
1727b5038d7SDag-Erling Smørgrav }
1737b5038d7SDag-Erling Smørgrav 
1747b5038d7SDag-Erling Smørgrav 
1757b5038d7SDag-Erling Smørgrav 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)1767b5038d7SDag-Erling Smørgrav ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
1777b5038d7SDag-Erling Smørgrav {
1782787e39aSDag-Erling Smørgrav #ifdef HAVE_SSL
1797b5038d7SDag-Erling Smørgrav 	uint16_t nsec_i;
1807b5038d7SDag-Erling Smørgrav 
1817b5038d7SDag-Erling Smørgrav 	ldns_rr_list *nsecs;
1827b5038d7SDag-Erling Smørgrav 	ldns_status result;
183*5afab0e5SDag-Erling Smørgrav 	const ldns_rr_descriptor *descriptor;
1847b5038d7SDag-Erling Smørgrav 
185*5afab0e5SDag-Erling Smørgrav 	if (!pkt) {
186*5afab0e5SDag-Erling Smørgrav 		descriptor = ldns_rr_descript(type);
187*5afab0e5SDag-Erling Smørgrav 
188*5afab0e5SDag-Erling Smørgrav 		printf("NETWORk ERROR! Cannot verify denial for: ");
189*5afab0e5SDag-Erling Smørgrav 		ldns_rdf_print(stdout, name);
190*5afab0e5SDag-Erling Smørgrav 		printf(" type ");
191*5afab0e5SDag-Erling Smørgrav 		if (descriptor && descriptor->_name)
192*5afab0e5SDag-Erling Smørgrav 			printf("%s", descriptor->_name);
193*5afab0e5SDag-Erling Smørgrav 		else
194*5afab0e5SDag-Erling Smørgrav 			printf("TYPE%u", type);
195*5afab0e5SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
196*5afab0e5SDag-Erling Smørgrav 	}
1977b5038d7SDag-Erling Smørgrav 	if (verbosity >= 5) {
1987b5038d7SDag-Erling Smørgrav 		printf("VERIFY DENIAL FROM:\n");
1997b5038d7SDag-Erling Smørgrav 		ldns_pkt_print(stdout, pkt);
2007b5038d7SDag-Erling Smørgrav 	}
2017b5038d7SDag-Erling Smørgrav 
2027b5038d7SDag-Erling Smørgrav 	result = LDNS_STATUS_CRYPTO_NO_RRSIG;
2037b5038d7SDag-Erling Smørgrav 	/* Try to see if there are NSECS in the packet */
2047b5038d7SDag-Erling Smørgrav 	nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
2057b5038d7SDag-Erling Smørgrav 	if (nsecs) {
2067b5038d7SDag-Erling Smørgrav 		for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
2077b5038d7SDag-Erling Smørgrav 			/* there are four options:
2087b5038d7SDag-Erling Smørgrav 			 * - name equals ownername and is covered by the type bitmap
2097b5038d7SDag-Erling Smørgrav 			 * - name equals ownername but is not covered by the type bitmap
2107b5038d7SDag-Erling Smørgrav 			 * - name falls within nsec coverage but is not equal to the owner name
2117b5038d7SDag-Erling Smørgrav 			 * - name falls outside of nsec coverage
2127b5038d7SDag-Erling Smørgrav 			 */
2137b5038d7SDag-Erling Smørgrav 			if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
2147b5038d7SDag-Erling Smørgrav 				/*
2157b5038d7SDag-Erling Smørgrav 				printf("CHECKING NSEC:\n");
2167b5038d7SDag-Erling Smørgrav 				ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
2177b5038d7SDag-Erling Smørgrav 				printf("DAWASEM\n");
2187b5038d7SDag-Erling Smørgrav 				*/
2197b5038d7SDag-Erling Smørgrav 				if (ldns_nsec_bitmap_covers_type(
2207b5038d7SDag-Erling Smørgrav 					   ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
2217b5038d7SDag-Erling Smørgrav 													nsec_i)),
2227b5038d7SDag-Erling Smørgrav 					   type)) {
2237b5038d7SDag-Erling Smørgrav 					/* Error, according to the nsec this rrset is signed */
2247b5038d7SDag-Erling Smørgrav 					result = LDNS_STATUS_CRYPTO_NO_RRSIG;
2257b5038d7SDag-Erling Smørgrav 				} else {
2267b5038d7SDag-Erling Smørgrav 					/* ok nsec denies existence */
2277b5038d7SDag-Erling Smørgrav 					if (verbosity >= 3) {
2287b5038d7SDag-Erling Smørgrav 						printf(";; Existence of data set with this type denied by NSEC\n");
2297b5038d7SDag-Erling Smørgrav 					}
2307b5038d7SDag-Erling Smørgrav 						/*printf(";; Verifiably insecure.\n");*/
2317b5038d7SDag-Erling Smørgrav 						if (nsec_rrs && nsec_rr_sigs) {
2327b5038d7SDag-Erling Smørgrav 							(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
2337b5038d7SDag-Erling Smørgrav 						}
2347b5038d7SDag-Erling Smørgrav 						ldns_rr_list_deep_free(nsecs);
2357b5038d7SDag-Erling Smørgrav 						return LDNS_STATUS_OK;
2367b5038d7SDag-Erling Smørgrav 				}
2377b5038d7SDag-Erling Smørgrav 			} else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
2387b5038d7SDag-Erling Smørgrav 				if (verbosity >= 3) {
2397b5038d7SDag-Erling Smørgrav 					printf(";; Existence of data set with this name denied by NSEC\n");
2407b5038d7SDag-Erling Smørgrav 				}
2417b5038d7SDag-Erling Smørgrav 				if (nsec_rrs && nsec_rr_sigs) {
2427b5038d7SDag-Erling Smørgrav 					(void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
2437b5038d7SDag-Erling Smørgrav 				}
2447b5038d7SDag-Erling Smørgrav 				ldns_rr_list_deep_free(nsecs);
2457b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_OK;
2467b5038d7SDag-Erling Smørgrav 			} else {
2477b5038d7SDag-Erling Smørgrav 				/* nsec has nothing to do with this data */
2487b5038d7SDag-Erling Smørgrav 			}
2497b5038d7SDag-Erling Smørgrav 		}
2507b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(nsecs);
2517b5038d7SDag-Erling Smørgrav 	} else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
2527b5038d7SDag-Erling Smørgrav                 ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
2537b5038d7SDag-Erling Smørgrav                 ldns_rr* q = ldns_rr_new();
2547b5038d7SDag-Erling Smørgrav 		ldns_rr* match = NULL;
2552787e39aSDag-Erling Smørgrav 
2562787e39aSDag-Erling Smørgrav                 if(!sigs) {
2572787e39aSDag-Erling Smørgrav 			if (q) {
2582787e39aSDag-Erling Smørgrav                 		ldns_rr_free(q);
2592787e39aSDag-Erling Smørgrav 			}
2602787e39aSDag-Erling Smørgrav 			ldns_rr_list_deep_free(nsecs);
2612787e39aSDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2622787e39aSDag-Erling Smørgrav 		}
2632787e39aSDag-Erling Smørgrav                 if(!q) {
2642787e39aSDag-Erling Smørgrav 			ldns_rr_list_deep_free(nsecs);
2652787e39aSDag-Erling Smørgrav 			ldns_rr_list_deep_free(sigs);
2662787e39aSDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2672787e39aSDag-Erling Smørgrav 		}
2687b5038d7SDag-Erling Smørgrav                 ldns_rr_set_question(q, 1);
2697b5038d7SDag-Erling Smørgrav                 ldns_rr_set_ttl(q, 0);
2707b5038d7SDag-Erling Smørgrav                 ldns_rr_set_owner(q, ldns_rdf_clone(name));
2712787e39aSDag-Erling Smørgrav                 if(!ldns_rr_owner(q)) {
2722787e39aSDag-Erling Smørgrav                 	ldns_rr_free(q);
2732787e39aSDag-Erling Smørgrav 			ldns_rr_list_deep_free(sigs);
2742787e39aSDag-Erling Smørgrav 			ldns_rr_list_deep_free(nsecs);
2752787e39aSDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2762787e39aSDag-Erling Smørgrav 		}
2777b5038d7SDag-Erling Smørgrav                 ldns_rr_set_type(q, type);
2787b5038d7SDag-Erling Smørgrav 
2797b5038d7SDag-Erling Smørgrav                 /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */
2807b5038d7SDag-Erling Smørgrav                 result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match);
2817b5038d7SDag-Erling Smørgrav 		if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) {
2827b5038d7SDag-Erling Smørgrav 			(void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
2837b5038d7SDag-Erling Smørgrav 		}
2847b5038d7SDag-Erling Smørgrav                 ldns_rr_free(q);
2857b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(nsecs);
2867b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(sigs);
2877b5038d7SDag-Erling Smørgrav         }
2887b5038d7SDag-Erling Smørgrav 	return result;
2892787e39aSDag-Erling Smørgrav #else
2902787e39aSDag-Erling Smørgrav 	(void)pkt;
2912787e39aSDag-Erling Smørgrav 	(void)name;
2922787e39aSDag-Erling Smørgrav 	(void)type;
2932787e39aSDag-Erling Smørgrav 	(void)nsec_rrs;
2942787e39aSDag-Erling Smørgrav 	(void)nsec_rr_sigs;
2952787e39aSDag-Erling Smørgrav 	return LDNS_STATUS_ERR;
2962787e39aSDag-Erling Smørgrav #endif /* HAVE_SSL */
2977b5038d7SDag-Erling Smørgrav }
2987b5038d7SDag-Erling Smørgrav 
2997b5038d7SDag-Erling Smørgrav /* NSEC3 draft -07 */
3007b5038d7SDag-Erling Smørgrav /*return hash name match*/
3017b5038d7SDag-Erling Smørgrav ldns_rr *
ldns_nsec3_exact_match(ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_list * nsec3s)3027b5038d7SDag-Erling Smørgrav ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
3037b5038d7SDag-Erling Smørgrav 	uint8_t algorithm;
3047b5038d7SDag-Erling Smørgrav 	uint32_t iterations;
3057b5038d7SDag-Erling Smørgrav 	uint8_t salt_length;
3067b5038d7SDag-Erling Smørgrav 	uint8_t *salt;
3077b5038d7SDag-Erling Smørgrav 
3087b5038d7SDag-Erling Smørgrav 	ldns_rdf *sname = NULL, *hashed_sname = NULL;
3097b5038d7SDag-Erling Smørgrav 
3107b5038d7SDag-Erling Smørgrav 	size_t nsec_i;
3117b5038d7SDag-Erling Smørgrav 	ldns_rr *nsec;
3127b5038d7SDag-Erling Smørgrav 	ldns_rr *result = NULL;
3137b5038d7SDag-Erling Smørgrav 
3147b5038d7SDag-Erling Smørgrav 	const ldns_rr_descriptor *descriptor;
3157b5038d7SDag-Erling Smørgrav 
3167b5038d7SDag-Erling Smørgrav 	ldns_rdf *zone_name = NULL;
3177b5038d7SDag-Erling Smørgrav 
3187b5038d7SDag-Erling Smørgrav 	if (verbosity >= 4) {
3197b5038d7SDag-Erling Smørgrav 		printf(";; finding exact match for ");
3207b5038d7SDag-Erling Smørgrav 		descriptor = ldns_rr_descript(qtype);
3217b5038d7SDag-Erling Smørgrav 		if (descriptor && descriptor->_name) {
3227b5038d7SDag-Erling Smørgrav 			printf("%s ", descriptor->_name);
3237b5038d7SDag-Erling Smørgrav 		} else {
3247b5038d7SDag-Erling Smørgrav 			printf("TYPE%d ", qtype);
3257b5038d7SDag-Erling Smørgrav 		}
3267b5038d7SDag-Erling Smørgrav 		ldns_rdf_print(stdout, qname);
3277b5038d7SDag-Erling Smørgrav 		printf("\n");
3287b5038d7SDag-Erling Smørgrav 	}
3297b5038d7SDag-Erling Smørgrav 
3307b5038d7SDag-Erling Smørgrav 	if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
3317b5038d7SDag-Erling Smørgrav 		if (verbosity >= 4) {
3327b5038d7SDag-Erling Smørgrav 			printf("no qname, nsec3s or list empty\n");
3337b5038d7SDag-Erling Smørgrav 		}
3347b5038d7SDag-Erling Smørgrav 		return NULL;
3357b5038d7SDag-Erling Smørgrav 	}
3367b5038d7SDag-Erling Smørgrav 
3377b5038d7SDag-Erling Smørgrav 	nsec = ldns_rr_list_rr(nsec3s, 0);
3387b5038d7SDag-Erling Smørgrav 	algorithm = ldns_nsec3_algorithm(nsec);
3397b5038d7SDag-Erling Smørgrav 	salt_length = ldns_nsec3_salt_length(nsec);
3407b5038d7SDag-Erling Smørgrav 	salt = ldns_nsec3_salt_data(nsec);
3417b5038d7SDag-Erling Smørgrav 	iterations = ldns_nsec3_iterations(nsec);
3427b5038d7SDag-Erling Smørgrav 	if (salt == NULL) {
3437b5038d7SDag-Erling Smørgrav 		goto done;
3447b5038d7SDag-Erling Smørgrav 	}
3457b5038d7SDag-Erling Smørgrav 
3467b5038d7SDag-Erling Smørgrav 	sname = ldns_rdf_clone(qname);
3477b5038d7SDag-Erling Smørgrav 	if (sname == NULL) {
3487b5038d7SDag-Erling Smørgrav 		goto done;
3497b5038d7SDag-Erling Smørgrav 	}
3507b5038d7SDag-Erling Smørgrav 	if (verbosity >= 4) {
3517b5038d7SDag-Erling Smørgrav 		printf(";; owner name hashes to: ");
3527b5038d7SDag-Erling Smørgrav 	}
3537b5038d7SDag-Erling Smørgrav 	hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
3547b5038d7SDag-Erling Smørgrav 	if (hashed_sname == NULL) {
3557b5038d7SDag-Erling Smørgrav 		goto done;
3567b5038d7SDag-Erling Smørgrav 	}
3577b5038d7SDag-Erling Smørgrav 	zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
3587b5038d7SDag-Erling Smørgrav 	if (zone_name == NULL) {
3597b5038d7SDag-Erling Smørgrav 		goto done;
3607b5038d7SDag-Erling Smørgrav 	}
3617b5038d7SDag-Erling Smørgrav 	if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) {
3627b5038d7SDag-Erling Smørgrav 		goto done;
3637b5038d7SDag-Erling Smørgrav 	};
3647b5038d7SDag-Erling Smørgrav 
3657b5038d7SDag-Erling Smørgrav 	if (verbosity >= 4) {
3667b5038d7SDag-Erling Smørgrav 		ldns_rdf_print(stdout, hashed_sname);
3677b5038d7SDag-Erling Smørgrav 		printf("\n");
3687b5038d7SDag-Erling Smørgrav 	}
3697b5038d7SDag-Erling Smørgrav 
3707b5038d7SDag-Erling Smørgrav 	for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
3717b5038d7SDag-Erling Smørgrav 		nsec = ldns_rr_list_rr(nsec3s, nsec_i);
3727b5038d7SDag-Erling Smørgrav 
3737b5038d7SDag-Erling Smørgrav 		/* check values of iterations etc! */
3747b5038d7SDag-Erling Smørgrav 
3757b5038d7SDag-Erling Smørgrav 		/* exact match? */
3767b5038d7SDag-Erling Smørgrav 		if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
3777b5038d7SDag-Erling Smørgrav 			result = nsec;
3787b5038d7SDag-Erling Smørgrav 			goto done;
3797b5038d7SDag-Erling Smørgrav 		}
3807b5038d7SDag-Erling Smørgrav 
3817b5038d7SDag-Erling Smørgrav 	}
3827b5038d7SDag-Erling Smørgrav 
3837b5038d7SDag-Erling Smørgrav done:
3847b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(zone_name);
3857b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(sname);
3867b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(hashed_sname);
3877b5038d7SDag-Erling Smørgrav 	LDNS_FREE(salt);
3887b5038d7SDag-Erling Smørgrav 
3897b5038d7SDag-Erling Smørgrav 	if (verbosity >= 4) {
3907b5038d7SDag-Erling Smørgrav 		if (result) {
3917b5038d7SDag-Erling Smørgrav 			printf(";; Found.\n");
3927b5038d7SDag-Erling Smørgrav 		} else {
3937b5038d7SDag-Erling Smørgrav 			printf(";; Not foud.\n");
3947b5038d7SDag-Erling Smørgrav 		}
3957b5038d7SDag-Erling Smørgrav 	}
3967b5038d7SDag-Erling Smørgrav 	return result;
3977b5038d7SDag-Erling Smørgrav }
3987b5038d7SDag-Erling Smørgrav 
3997b5038d7SDag-Erling Smørgrav /*return the owner name of the closest encloser for name from the list of rrs */
4007b5038d7SDag-Erling Smørgrav /* this is NOT the hash, but the original name! */
4017b5038d7SDag-Erling Smørgrav ldns_rdf *
ldns_nsec3_closest_encloser(ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_list * nsec3s)4027b5038d7SDag-Erling Smørgrav ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
4037b5038d7SDag-Erling Smørgrav {
4047b5038d7SDag-Erling Smørgrav 	/* remember parameters, they must match */
4057b5038d7SDag-Erling Smørgrav 	uint8_t algorithm;
4067b5038d7SDag-Erling Smørgrav 	uint32_t iterations;
4077b5038d7SDag-Erling Smørgrav 	uint8_t salt_length;
4087b5038d7SDag-Erling Smørgrav 	uint8_t *salt;
4097b5038d7SDag-Erling Smørgrav 
4107b5038d7SDag-Erling Smørgrav 	ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp;
4117b5038d7SDag-Erling Smørgrav 	bool flag;
4127b5038d7SDag-Erling Smørgrav 
4137b5038d7SDag-Erling Smørgrav 	bool exact_match_found;
4147b5038d7SDag-Erling Smørgrav 	bool in_range_found;
4157b5038d7SDag-Erling Smørgrav 
4167b5038d7SDag-Erling Smørgrav 	ldns_rdf *zone_name = NULL;
4177b5038d7SDag-Erling Smørgrav 
4187b5038d7SDag-Erling Smørgrav 	size_t nsec_i;
4197b5038d7SDag-Erling Smørgrav 	ldns_rr *nsec;
4207b5038d7SDag-Erling Smørgrav 	ldns_rdf *result = NULL;
4217b5038d7SDag-Erling Smørgrav 
4227b5038d7SDag-Erling Smørgrav 	if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
4237b5038d7SDag-Erling Smørgrav 		return NULL;
4247b5038d7SDag-Erling Smørgrav 	}
4257b5038d7SDag-Erling Smørgrav 
4267b5038d7SDag-Erling Smørgrav 	if (verbosity >= 4) {
4277b5038d7SDag-Erling Smørgrav 		printf(";; finding closest encloser for type %d ", qtype);
4287b5038d7SDag-Erling Smørgrav 		ldns_rdf_print(stdout, qname);
4297b5038d7SDag-Erling Smørgrav 		printf("\n");
4307b5038d7SDag-Erling Smørgrav 	}
4317b5038d7SDag-Erling Smørgrav 
4327b5038d7SDag-Erling Smørgrav 	nsec = ldns_rr_list_rr(nsec3s, 0);
4337b5038d7SDag-Erling Smørgrav 	algorithm = ldns_nsec3_algorithm(nsec);
4347b5038d7SDag-Erling Smørgrav 	salt_length = ldns_nsec3_salt_length(nsec);
4357b5038d7SDag-Erling Smørgrav 	salt = ldns_nsec3_salt_data(nsec);
4367b5038d7SDag-Erling Smørgrav 	iterations = ldns_nsec3_iterations(nsec);
4377b5038d7SDag-Erling Smørgrav 	if (salt == NULL) {
4387b5038d7SDag-Erling Smørgrav 		goto done;
4397b5038d7SDag-Erling Smørgrav 	}
4407b5038d7SDag-Erling Smørgrav 
4417b5038d7SDag-Erling Smørgrav 	sname = ldns_rdf_clone(qname);
4427b5038d7SDag-Erling Smørgrav 	if (sname == NULL) {
4437b5038d7SDag-Erling Smørgrav 		goto done;
4447b5038d7SDag-Erling Smørgrav 	}
4457b5038d7SDag-Erling Smørgrav 
4467b5038d7SDag-Erling Smørgrav 	flag = false;
4477b5038d7SDag-Erling Smørgrav 
4487b5038d7SDag-Erling Smørgrav 	zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
4497b5038d7SDag-Erling Smørgrav 	if (zone_name == NULL) {
4507b5038d7SDag-Erling Smørgrav 		goto done;
4517b5038d7SDag-Erling Smørgrav 	}
4527b5038d7SDag-Erling Smørgrav 
4537b5038d7SDag-Erling Smørgrav 	/* algorithm from nsec3-07 8.3 */
4547b5038d7SDag-Erling Smørgrav 	while (ldns_dname_label_count(sname) > 0) {
4557b5038d7SDag-Erling Smørgrav 		exact_match_found = false;
4567b5038d7SDag-Erling Smørgrav 		in_range_found = false;
4577b5038d7SDag-Erling Smørgrav 
4587b5038d7SDag-Erling Smørgrav 		if (verbosity >= 3) {
4597b5038d7SDag-Erling Smørgrav 			printf(";; ");
4607b5038d7SDag-Erling Smørgrav 			ldns_rdf_print(stdout, sname);
4617b5038d7SDag-Erling Smørgrav 			printf(" hashes to: ");
4627b5038d7SDag-Erling Smørgrav 		}
4637b5038d7SDag-Erling Smørgrav 		hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
4647b5038d7SDag-Erling Smørgrav 		if (hashed_sname == NULL) {
4657b5038d7SDag-Erling Smørgrav 			goto done;
4667b5038d7SDag-Erling Smørgrav 		}
4677b5038d7SDag-Erling Smørgrav 
4687b5038d7SDag-Erling Smørgrav 		if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){
469*5afab0e5SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_sname);
4707b5038d7SDag-Erling Smørgrav 			goto done;
4717b5038d7SDag-Erling Smørgrav 		}
4727b5038d7SDag-Erling Smørgrav 
4737b5038d7SDag-Erling Smørgrav 		if (verbosity >= 3) {
4747b5038d7SDag-Erling Smørgrav 			ldns_rdf_print(stdout, hashed_sname);
4757b5038d7SDag-Erling Smørgrav 			printf("\n");
4767b5038d7SDag-Erling Smørgrav 		}
4777b5038d7SDag-Erling Smørgrav 
4787b5038d7SDag-Erling Smørgrav 		for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
4797b5038d7SDag-Erling Smørgrav 			nsec = ldns_rr_list_rr(nsec3s, nsec_i);
4807b5038d7SDag-Erling Smørgrav 
4817b5038d7SDag-Erling Smørgrav 			/* check values of iterations etc! */
4827b5038d7SDag-Erling Smørgrav 
4837b5038d7SDag-Erling Smørgrav 			/* exact match? */
4847b5038d7SDag-Erling Smørgrav 			if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
4857b5038d7SDag-Erling Smørgrav 				if (verbosity >= 4) {
4867b5038d7SDag-Erling Smørgrav 					printf(";; exact match found\n");
4877b5038d7SDag-Erling Smørgrav 				}
4887b5038d7SDag-Erling Smørgrav 			 	exact_match_found = true;
4897b5038d7SDag-Erling Smørgrav 			} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
4907b5038d7SDag-Erling Smørgrav 				if (verbosity >= 4) {
4917b5038d7SDag-Erling Smørgrav 					printf(";; in range of an nsec\n");
4927b5038d7SDag-Erling Smørgrav 				}
4937b5038d7SDag-Erling Smørgrav 				in_range_found = true;
4947b5038d7SDag-Erling Smørgrav 			}
4957b5038d7SDag-Erling Smørgrav 
4967b5038d7SDag-Erling Smørgrav 		}
4977b5038d7SDag-Erling Smørgrav 		if (!exact_match_found && in_range_found) {
4987b5038d7SDag-Erling Smørgrav 			flag = true;
4997b5038d7SDag-Erling Smørgrav 		} else if (exact_match_found && flag) {
5007b5038d7SDag-Erling Smørgrav 			result = ldns_rdf_clone(sname);
5017b5038d7SDag-Erling Smørgrav 		} else if (exact_match_found && !flag) {
5027b5038d7SDag-Erling Smørgrav 			// error!
5037b5038d7SDag-Erling Smørgrav 			if (verbosity >= 4) {
5047b5038d7SDag-Erling Smørgrav 				printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
5057b5038d7SDag-Erling Smørgrav 			}
5067b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_sname);
5077b5038d7SDag-Erling Smørgrav 			goto done;
5087b5038d7SDag-Erling Smørgrav 		} else {
5097b5038d7SDag-Erling Smørgrav 			flag = false;
5107b5038d7SDag-Erling Smørgrav 		}
5117b5038d7SDag-Erling Smørgrav 
5127b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(hashed_sname);
5137b5038d7SDag-Erling Smørgrav 		tmp = sname;
5147b5038d7SDag-Erling Smørgrav 		sname = ldns_dname_left_chop(sname);
5157b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(tmp);
5167b5038d7SDag-Erling Smørgrav 		if (sname == NULL) {
5177b5038d7SDag-Erling Smørgrav 			goto done;
5187b5038d7SDag-Erling Smørgrav 		}
5197b5038d7SDag-Erling Smørgrav 	}
5207b5038d7SDag-Erling Smørgrav 
5217b5038d7SDag-Erling Smørgrav done:
5227b5038d7SDag-Erling Smørgrav 	LDNS_FREE(salt);
5237b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(zone_name);
5247b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(sname);
5257b5038d7SDag-Erling Smørgrav 
5267b5038d7SDag-Erling Smørgrav 	if (!result) {
5277b5038d7SDag-Erling Smørgrav 		if (verbosity >= 4) {
5287b5038d7SDag-Erling Smørgrav 			printf(";; no closest encloser found\n");
5297b5038d7SDag-Erling Smørgrav 		}
5307b5038d7SDag-Erling Smørgrav 	}
5317b5038d7SDag-Erling Smørgrav 
5327b5038d7SDag-Erling Smørgrav 	/* todo checks from end of 6.2. here or in caller? */
5337b5038d7SDag-Erling Smørgrav 	return result;
5347b5038d7SDag-Erling Smørgrav }
535