1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * dnssec.c 3825eb42bSJan Lentfer * Some DNSSEC helper function are defined here 4825eb42bSJan Lentfer * and tracing is done 5825eb42bSJan Lentfer * (c) 2005 NLnet Labs 6825eb42bSJan Lentfer * 7825eb42bSJan Lentfer * See the file LICENSE for the license 8825eb42bSJan Lentfer * 9825eb42bSJan Lentfer */ 10825eb42bSJan Lentfer 11825eb42bSJan Lentfer #include "drill.h" 12825eb42bSJan Lentfer #include <ldns/ldns.h> 13825eb42bSJan Lentfer 14825eb42bSJan Lentfer /* get rr_type from a server from a server */ 15825eb42bSJan Lentfer ldns_rr_list * 16825eb42bSJan Lentfer get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c) 17825eb42bSJan Lentfer { 18825eb42bSJan Lentfer /* query, retrieve, extract and return */ 19825eb42bSJan Lentfer ldns_pkt *p; 20825eb42bSJan Lentfer ldns_rr_list *found; 21825eb42bSJan Lentfer 22825eb42bSJan Lentfer p = ldns_pkt_new(); 23825eb42bSJan Lentfer found = NULL; 24825eb42bSJan Lentfer 25*d1b2b5caSJohn Marino if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) { 26825eb42bSJan Lentfer found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION); 27825eb42bSJan Lentfer } 28*d1b2b5caSJohn Marino ldns_pkt_free(p); 29825eb42bSJan Lentfer return found; 30825eb42bSJan Lentfer } 31825eb42bSJan Lentfer 32825eb42bSJan Lentfer void 33825eb42bSJan Lentfer drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) 34825eb42bSJan Lentfer { 35825eb42bSJan Lentfer ldns_rr_list *new_nss; 36825eb42bSJan Lentfer ldns_rr_list *hostnames; 37*d1b2b5caSJohn Marino char *answerfrom_str; 38825eb42bSJan Lentfer 39825eb42bSJan Lentfer if (verbosity < 5) { 40825eb42bSJan Lentfer return; 41825eb42bSJan Lentfer } 42825eb42bSJan Lentfer 43825eb42bSJan Lentfer hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0); 44825eb42bSJan Lentfer 45825eb42bSJan Lentfer new_nss = ldns_pkt_rr_list_by_type(p, 46825eb42bSJan Lentfer LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); 47825eb42bSJan Lentfer ldns_rr_list_print(fd, new_nss); 48*d1b2b5caSJohn Marino ldns_rr_list_deep_free(new_nss); 49825eb42bSJan Lentfer 50825eb42bSJan Lentfer fprintf(fd, ";; Received %d bytes from %s#%d(", 51825eb42bSJan Lentfer (int) ldns_pkt_size(p), 52825eb42bSJan Lentfer ldns_rdf2str(ldns_pkt_answerfrom(p)), 53825eb42bSJan Lentfer (int) ldns_resolver_port(r)); 54825eb42bSJan Lentfer /* if we can resolve this print it, other print the ip again */ 55825eb42bSJan Lentfer if (hostnames) { 56825eb42bSJan Lentfer ldns_rdf_print(fd, 57825eb42bSJan Lentfer ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); 58825eb42bSJan Lentfer ldns_rr_list_deep_free(hostnames); 59825eb42bSJan Lentfer } else { 60*d1b2b5caSJohn Marino answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); 61*d1b2b5caSJohn Marino if (answerfrom_str) { 62*d1b2b5caSJohn Marino fprintf(fd, "%s", answerfrom_str); 63*d1b2b5caSJohn Marino LDNS_FREE(answerfrom_str); 64*d1b2b5caSJohn Marino } 65825eb42bSJan Lentfer } 66825eb42bSJan Lentfer fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); 67825eb42bSJan Lentfer } 68825eb42bSJan Lentfer 69825eb42bSJan Lentfer void 70825eb42bSJan Lentfer drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) 71825eb42bSJan Lentfer { 72825eb42bSJan Lentfer ldns_rr_list *hostnames; 73*d1b2b5caSJohn Marino char *answerfrom_str; 74825eb42bSJan Lentfer 75825eb42bSJan Lentfer if (verbosity < 5) { 76825eb42bSJan Lentfer return; 77825eb42bSJan Lentfer } 78825eb42bSJan Lentfer 79825eb42bSJan Lentfer hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0); 80825eb42bSJan Lentfer 81825eb42bSJan Lentfer fprintf(fd, ";; Received %d bytes from %s#%d(", 82825eb42bSJan Lentfer (int) ldns_pkt_size(p), 83825eb42bSJan Lentfer ldns_rdf2str(ldns_pkt_answerfrom(p)), 84825eb42bSJan Lentfer (int) ldns_resolver_port(r)); 85825eb42bSJan Lentfer /* if we can resolve this print it, other print the ip again */ 86825eb42bSJan Lentfer if (hostnames) { 87825eb42bSJan Lentfer ldns_rdf_print(fd, 88825eb42bSJan Lentfer ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); 89825eb42bSJan Lentfer ldns_rr_list_deep_free(hostnames); 90825eb42bSJan Lentfer } else { 91*d1b2b5caSJohn Marino answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); 92*d1b2b5caSJohn Marino if (answerfrom_str) { 93*d1b2b5caSJohn Marino fprintf(fd, "%s", answerfrom_str); 94*d1b2b5caSJohn Marino LDNS_FREE(answerfrom_str); 95*d1b2b5caSJohn Marino } 96825eb42bSJan Lentfer } 97825eb42bSJan Lentfer fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); 98825eb42bSJan Lentfer } 99825eb42bSJan Lentfer /* 100825eb42bSJan Lentfer * generic function to get some RRset from a nameserver 101825eb42bSJan Lentfer * and possible some signatures too (that would be the day...) 102825eb42bSJan Lentfer */ 103825eb42bSJan Lentfer ldns_pkt_type 104825eb42bSJan Lentfer get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, 105825eb42bSJan Lentfer ldns_rr_list **rrlist, ldns_rr_list **sig) 106825eb42bSJan Lentfer { 107825eb42bSJan Lentfer ldns_pkt_type pt = LDNS_PACKET_UNKNOWN; 108825eb42bSJan Lentfer ldns_rr_list *sigs = NULL; 109825eb42bSJan Lentfer size_t i; 110825eb42bSJan Lentfer 111825eb42bSJan Lentfer if (!p) { 112825eb42bSJan Lentfer if (rrlist) { 113825eb42bSJan Lentfer *rrlist = NULL; 114825eb42bSJan Lentfer } 115825eb42bSJan Lentfer return LDNS_PACKET_UNKNOWN; 116825eb42bSJan Lentfer } 117825eb42bSJan Lentfer 118825eb42bSJan Lentfer pt = ldns_pkt_reply_type(p); 119825eb42bSJan Lentfer if (name) { 120*d1b2b5caSJohn Marino if (rrlist) { 121*d1b2b5caSJohn Marino *rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t, 122*d1b2b5caSJohn Marino LDNS_SECTION_ANSWER); 123*d1b2b5caSJohn Marino if (!*rrlist) { 124*d1b2b5caSJohn Marino *rrlist = ldns_pkt_rr_list_by_name_and_type( 125*d1b2b5caSJohn Marino p, name, t, 126*d1b2b5caSJohn Marino LDNS_SECTION_AUTHORITY); 127825eb42bSJan Lentfer } 128*d1b2b5caSJohn Marino } 129*d1b2b5caSJohn Marino if (sig) { 130*d1b2b5caSJohn Marino sigs = ldns_pkt_rr_list_by_name_and_type(p, name, 131*d1b2b5caSJohn Marino LDNS_RR_TYPE_RRSIG, 132825eb42bSJan Lentfer LDNS_SECTION_ANSWER); 133825eb42bSJan Lentfer if (!sigs) { 134*d1b2b5caSJohn Marino sigs = ldns_pkt_rr_list_by_name_and_type( 135*d1b2b5caSJohn Marino p, name, LDNS_RR_TYPE_RRSIG, 136825eb42bSJan Lentfer LDNS_SECTION_AUTHORITY); 137825eb42bSJan Lentfer } 138*d1b2b5caSJohn Marino } 139825eb42bSJan Lentfer } else { 140825eb42bSJan Lentfer /* A DS-referral - get the DS records if they are there */ 141*d1b2b5caSJohn Marino if (rrlist) { 142*d1b2b5caSJohn Marino *rrlist = ldns_pkt_rr_list_by_type( 143*d1b2b5caSJohn Marino p, t, LDNS_SECTION_AUTHORITY); 144*d1b2b5caSJohn Marino } 145*d1b2b5caSJohn Marino if (sig) { 146*d1b2b5caSJohn Marino sigs = ldns_pkt_rr_list_by_type(p, 147*d1b2b5caSJohn Marino LDNS_RR_TYPE_RRSIG, 148825eb42bSJan Lentfer LDNS_SECTION_AUTHORITY); 149825eb42bSJan Lentfer } 150*d1b2b5caSJohn Marino } 151825eb42bSJan Lentfer if (sig) { 152825eb42bSJan Lentfer *sig = ldns_rr_list_new(); 153825eb42bSJan Lentfer for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) { 154825eb42bSJan Lentfer /* only add the sigs that cover this type */ 155*d1b2b5caSJohn Marino if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered( 156*d1b2b5caSJohn Marino ldns_rr_list_rr(sigs, i)))) { 157*d1b2b5caSJohn Marino 158*d1b2b5caSJohn Marino ldns_rr_list_push_rr(*sig, 159*d1b2b5caSJohn Marino ldns_rr_clone( 160*d1b2b5caSJohn Marino ldns_rr_list_rr( 161*d1b2b5caSJohn Marino sigs, i))); 162825eb42bSJan Lentfer } 163825eb42bSJan Lentfer } 164825eb42bSJan Lentfer } 165825eb42bSJan Lentfer ldns_rr_list_deep_free(sigs); 166825eb42bSJan Lentfer 167825eb42bSJan Lentfer if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) { 168825eb42bSJan Lentfer return pt; 169825eb42bSJan Lentfer } else { 170825eb42bSJan Lentfer return LDNS_PACKET_ANSWER; 171825eb42bSJan Lentfer } 172825eb42bSJan Lentfer } 173825eb42bSJan Lentfer 174825eb42bSJan Lentfer 175825eb42bSJan Lentfer ldns_status 176825eb42bSJan Lentfer ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) 177825eb42bSJan Lentfer { 178*d1b2b5caSJohn Marino #ifdef HAVE_SSL 179825eb42bSJan Lentfer uint16_t nsec_i; 180825eb42bSJan Lentfer 181825eb42bSJan Lentfer ldns_rr_list *nsecs; 182825eb42bSJan Lentfer ldns_status result; 183825eb42bSJan Lentfer 184825eb42bSJan Lentfer if (verbosity >= 5) { 185825eb42bSJan Lentfer printf("VERIFY DENIAL FROM:\n"); 186825eb42bSJan Lentfer ldns_pkt_print(stdout, pkt); 187825eb42bSJan Lentfer } 188825eb42bSJan Lentfer 189825eb42bSJan Lentfer result = LDNS_STATUS_CRYPTO_NO_RRSIG; 190825eb42bSJan Lentfer /* Try to see if there are NSECS in the packet */ 191825eb42bSJan Lentfer nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION); 192825eb42bSJan Lentfer if (nsecs) { 193825eb42bSJan Lentfer for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) { 194825eb42bSJan Lentfer /* there are four options: 195825eb42bSJan Lentfer * - name equals ownername and is covered by the type bitmap 196825eb42bSJan Lentfer * - name equals ownername but is not covered by the type bitmap 197825eb42bSJan Lentfer * - name falls within nsec coverage but is not equal to the owner name 198825eb42bSJan Lentfer * - name falls outside of nsec coverage 199825eb42bSJan Lentfer */ 200825eb42bSJan Lentfer if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) { 201825eb42bSJan Lentfer /* 202825eb42bSJan Lentfer printf("CHECKING NSEC:\n"); 203825eb42bSJan Lentfer ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i)); 204825eb42bSJan Lentfer printf("DAWASEM\n"); 205825eb42bSJan Lentfer */ 206825eb42bSJan Lentfer if (ldns_nsec_bitmap_covers_type( 207825eb42bSJan Lentfer ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs, 208825eb42bSJan Lentfer nsec_i)), 209825eb42bSJan Lentfer type)) { 210825eb42bSJan Lentfer /* Error, according to the nsec this rrset is signed */ 211825eb42bSJan Lentfer result = LDNS_STATUS_CRYPTO_NO_RRSIG; 212825eb42bSJan Lentfer } else { 213825eb42bSJan Lentfer /* ok nsec denies existence */ 214825eb42bSJan Lentfer if (verbosity >= 3) { 215825eb42bSJan Lentfer printf(";; Existence of data set with this type denied by NSEC\n"); 216825eb42bSJan Lentfer } 217825eb42bSJan Lentfer /*printf(";; Verifiably insecure.\n");*/ 218825eb42bSJan Lentfer if (nsec_rrs && nsec_rr_sigs) { 219825eb42bSJan Lentfer (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); 220825eb42bSJan Lentfer } 221825eb42bSJan Lentfer ldns_rr_list_deep_free(nsecs); 222825eb42bSJan Lentfer return LDNS_STATUS_OK; 223825eb42bSJan Lentfer } 224825eb42bSJan Lentfer } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) { 225825eb42bSJan Lentfer if (verbosity >= 3) { 226825eb42bSJan Lentfer printf(";; Existence of data set with this name denied by NSEC\n"); 227825eb42bSJan Lentfer } 228825eb42bSJan Lentfer if (nsec_rrs && nsec_rr_sigs) { 229825eb42bSJan Lentfer (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); 230825eb42bSJan Lentfer } 231825eb42bSJan Lentfer ldns_rr_list_deep_free(nsecs); 232825eb42bSJan Lentfer return LDNS_STATUS_OK; 233825eb42bSJan Lentfer } else { 234825eb42bSJan Lentfer /* nsec has nothing to do with this data */ 235825eb42bSJan Lentfer } 236825eb42bSJan Lentfer } 237825eb42bSJan Lentfer ldns_rr_list_deep_free(nsecs); 238ac996e71SJan Lentfer } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) { 239ac996e71SJan Lentfer ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); 240ac996e71SJan Lentfer ldns_rr* q = ldns_rr_new(); 241b5dedccaSJan Lentfer ldns_rr* match = NULL; 242*d1b2b5caSJohn Marino 243*d1b2b5caSJohn Marino if(!sigs) { 244*d1b2b5caSJohn Marino if (q) { 245*d1b2b5caSJohn Marino ldns_rr_free(q); 246*d1b2b5caSJohn Marino } 247*d1b2b5caSJohn Marino ldns_rr_list_deep_free(nsecs); 248*d1b2b5caSJohn Marino return LDNS_STATUS_MEM_ERR; 249*d1b2b5caSJohn Marino } 250*d1b2b5caSJohn Marino if(!q) { 251*d1b2b5caSJohn Marino ldns_rr_list_deep_free(nsecs); 252*d1b2b5caSJohn Marino ldns_rr_list_deep_free(sigs); 253*d1b2b5caSJohn Marino return LDNS_STATUS_MEM_ERR; 254*d1b2b5caSJohn Marino } 255ac996e71SJan Lentfer ldns_rr_set_question(q, 1); 256ac996e71SJan Lentfer ldns_rr_set_ttl(q, 0); 257ac996e71SJan Lentfer ldns_rr_set_owner(q, ldns_rdf_clone(name)); 258*d1b2b5caSJohn Marino if(!ldns_rr_owner(q)) { 259*d1b2b5caSJohn Marino ldns_rr_free(q); 260*d1b2b5caSJohn Marino ldns_rr_list_deep_free(sigs); 261*d1b2b5caSJohn Marino ldns_rr_list_deep_free(nsecs); 262*d1b2b5caSJohn Marino return LDNS_STATUS_MEM_ERR; 263*d1b2b5caSJohn Marino } 264ac996e71SJan Lentfer ldns_rr_set_type(q, type); 265ac996e71SJan Lentfer 266b5dedccaSJan Lentfer /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */ 267b5dedccaSJan Lentfer result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match); 268b5dedccaSJan Lentfer if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) { 269b5dedccaSJan Lentfer (void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs); 270b5dedccaSJan Lentfer } 271ac996e71SJan Lentfer ldns_rr_free(q); 272ac996e71SJan Lentfer ldns_rr_list_deep_free(nsecs); 273ac996e71SJan Lentfer ldns_rr_list_deep_free(sigs); 274825eb42bSJan Lentfer } 275825eb42bSJan Lentfer return result; 276*d1b2b5caSJohn Marino #else 277*d1b2b5caSJohn Marino (void)pkt; 278*d1b2b5caSJohn Marino (void)name; 279*d1b2b5caSJohn Marino (void)type; 280*d1b2b5caSJohn Marino (void)nsec_rrs; 281*d1b2b5caSJohn Marino (void)nsec_rr_sigs; 282*d1b2b5caSJohn Marino return LDNS_STATUS_ERR; 283*d1b2b5caSJohn Marino #endif /* HAVE_SSL */ 284825eb42bSJan Lentfer } 285825eb42bSJan Lentfer 286825eb42bSJan Lentfer /* NSEC3 draft -07 */ 287825eb42bSJan Lentfer /*return hash name match*/ 288825eb42bSJan Lentfer ldns_rr * 289825eb42bSJan Lentfer ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { 290825eb42bSJan Lentfer uint8_t algorithm; 291825eb42bSJan Lentfer uint32_t iterations; 292825eb42bSJan Lentfer uint8_t salt_length; 293825eb42bSJan Lentfer uint8_t *salt; 294825eb42bSJan Lentfer 295*d1b2b5caSJohn Marino ldns_rdf *sname = NULL, *hashed_sname = NULL; 296825eb42bSJan Lentfer 297825eb42bSJan Lentfer size_t nsec_i; 298825eb42bSJan Lentfer ldns_rr *nsec; 299825eb42bSJan Lentfer ldns_rr *result = NULL; 300825eb42bSJan Lentfer 301825eb42bSJan Lentfer const ldns_rr_descriptor *descriptor; 302825eb42bSJan Lentfer 303*d1b2b5caSJohn Marino ldns_rdf *zone_name = NULL; 304825eb42bSJan Lentfer 305825eb42bSJan Lentfer if (verbosity >= 4) { 306825eb42bSJan Lentfer printf(";; finding exact match for "); 307825eb42bSJan Lentfer descriptor = ldns_rr_descript(qtype); 308825eb42bSJan Lentfer if (descriptor && descriptor->_name) { 309825eb42bSJan Lentfer printf("%s ", descriptor->_name); 310825eb42bSJan Lentfer } else { 311825eb42bSJan Lentfer printf("TYPE%d ", qtype); 312825eb42bSJan Lentfer } 313825eb42bSJan Lentfer ldns_rdf_print(stdout, qname); 314825eb42bSJan Lentfer printf("\n"); 315825eb42bSJan Lentfer } 316825eb42bSJan Lentfer 317825eb42bSJan Lentfer if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 318825eb42bSJan Lentfer if (verbosity >= 4) { 319825eb42bSJan Lentfer printf("no qname, nsec3s or list empty\n"); 320825eb42bSJan Lentfer } 321825eb42bSJan Lentfer return NULL; 322825eb42bSJan Lentfer } 323825eb42bSJan Lentfer 324825eb42bSJan Lentfer nsec = ldns_rr_list_rr(nsec3s, 0); 325825eb42bSJan Lentfer algorithm = ldns_nsec3_algorithm(nsec); 326825eb42bSJan Lentfer salt_length = ldns_nsec3_salt_length(nsec); 327825eb42bSJan Lentfer salt = ldns_nsec3_salt_data(nsec); 328825eb42bSJan Lentfer iterations = ldns_nsec3_iterations(nsec); 329*d1b2b5caSJohn Marino if (salt == NULL) { 330*d1b2b5caSJohn Marino goto done; 331*d1b2b5caSJohn Marino } 332825eb42bSJan Lentfer 333825eb42bSJan Lentfer sname = ldns_rdf_clone(qname); 334*d1b2b5caSJohn Marino if (sname == NULL) { 335*d1b2b5caSJohn Marino goto done; 336*d1b2b5caSJohn Marino } 337825eb42bSJan Lentfer if (verbosity >= 4) { 338825eb42bSJan Lentfer printf(";; owner name hashes to: "); 339825eb42bSJan Lentfer } 340825eb42bSJan Lentfer hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); 341*d1b2b5caSJohn Marino if (hashed_sname == NULL) { 342*d1b2b5caSJohn Marino goto done; 343*d1b2b5caSJohn Marino } 344825eb42bSJan Lentfer zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 345*d1b2b5caSJohn Marino if (zone_name == NULL) { 346*d1b2b5caSJohn Marino goto done; 347*d1b2b5caSJohn Marino } 348*d1b2b5caSJohn Marino if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) { 349*d1b2b5caSJohn Marino goto done; 350*d1b2b5caSJohn Marino }; 351825eb42bSJan Lentfer 352825eb42bSJan Lentfer if (verbosity >= 4) { 353825eb42bSJan Lentfer ldns_rdf_print(stdout, hashed_sname); 354825eb42bSJan Lentfer printf("\n"); 355825eb42bSJan Lentfer } 356825eb42bSJan Lentfer 357825eb42bSJan Lentfer for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 358825eb42bSJan Lentfer nsec = ldns_rr_list_rr(nsec3s, nsec_i); 359825eb42bSJan Lentfer 360825eb42bSJan Lentfer /* check values of iterations etc! */ 361825eb42bSJan Lentfer 362825eb42bSJan Lentfer /* exact match? */ 363825eb42bSJan Lentfer if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 364825eb42bSJan Lentfer result = nsec; 365825eb42bSJan Lentfer goto done; 366825eb42bSJan Lentfer } 367825eb42bSJan Lentfer 368825eb42bSJan Lentfer } 369825eb42bSJan Lentfer 370825eb42bSJan Lentfer done: 371825eb42bSJan Lentfer ldns_rdf_deep_free(zone_name); 372825eb42bSJan Lentfer ldns_rdf_deep_free(sname); 373825eb42bSJan Lentfer ldns_rdf_deep_free(hashed_sname); 374825eb42bSJan Lentfer LDNS_FREE(salt); 375825eb42bSJan Lentfer 376825eb42bSJan Lentfer if (verbosity >= 4) { 377825eb42bSJan Lentfer if (result) { 378825eb42bSJan Lentfer printf(";; Found.\n"); 379825eb42bSJan Lentfer } else { 380825eb42bSJan Lentfer printf(";; Not foud.\n"); 381825eb42bSJan Lentfer } 382825eb42bSJan Lentfer } 383825eb42bSJan Lentfer return result; 384825eb42bSJan Lentfer } 385825eb42bSJan Lentfer 386825eb42bSJan Lentfer /*return the owner name of the closest encloser for name from the list of rrs */ 387825eb42bSJan Lentfer /* this is NOT the hash, but the original name! */ 388825eb42bSJan Lentfer ldns_rdf * 389825eb42bSJan Lentfer ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) 390825eb42bSJan Lentfer { 391825eb42bSJan Lentfer /* remember parameters, they must match */ 392825eb42bSJan Lentfer uint8_t algorithm; 393825eb42bSJan Lentfer uint32_t iterations; 394825eb42bSJan Lentfer uint8_t salt_length; 395825eb42bSJan Lentfer uint8_t *salt; 396825eb42bSJan Lentfer 397*d1b2b5caSJohn Marino ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp; 398825eb42bSJan Lentfer bool flag; 399825eb42bSJan Lentfer 400825eb42bSJan Lentfer bool exact_match_found; 401825eb42bSJan Lentfer bool in_range_found; 402825eb42bSJan Lentfer 403*d1b2b5caSJohn Marino ldns_rdf *zone_name = NULL; 404825eb42bSJan Lentfer 405825eb42bSJan Lentfer size_t nsec_i; 406825eb42bSJan Lentfer ldns_rr *nsec; 407825eb42bSJan Lentfer ldns_rdf *result = NULL; 408825eb42bSJan Lentfer 409825eb42bSJan Lentfer if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 410825eb42bSJan Lentfer return NULL; 411825eb42bSJan Lentfer } 412825eb42bSJan Lentfer 413825eb42bSJan Lentfer if (verbosity >= 4) { 414825eb42bSJan Lentfer printf(";; finding closest encloser for type %d ", qtype); 415825eb42bSJan Lentfer ldns_rdf_print(stdout, qname); 416825eb42bSJan Lentfer printf("\n"); 417825eb42bSJan Lentfer } 418825eb42bSJan Lentfer 419825eb42bSJan Lentfer nsec = ldns_rr_list_rr(nsec3s, 0); 420825eb42bSJan Lentfer algorithm = ldns_nsec3_algorithm(nsec); 421825eb42bSJan Lentfer salt_length = ldns_nsec3_salt_length(nsec); 422825eb42bSJan Lentfer salt = ldns_nsec3_salt_data(nsec); 423825eb42bSJan Lentfer iterations = ldns_nsec3_iterations(nsec); 424*d1b2b5caSJohn Marino if (salt == NULL) { 425*d1b2b5caSJohn Marino goto done; 426*d1b2b5caSJohn Marino } 427825eb42bSJan Lentfer 428825eb42bSJan Lentfer sname = ldns_rdf_clone(qname); 429*d1b2b5caSJohn Marino if (sname == NULL) { 430*d1b2b5caSJohn Marino goto done; 431*d1b2b5caSJohn Marino } 432825eb42bSJan Lentfer 433825eb42bSJan Lentfer flag = false; 434825eb42bSJan Lentfer 435825eb42bSJan Lentfer zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 436*d1b2b5caSJohn Marino if (zone_name == NULL) { 437*d1b2b5caSJohn Marino goto done; 438*d1b2b5caSJohn Marino } 439825eb42bSJan Lentfer 440825eb42bSJan Lentfer /* algorithm from nsec3-07 8.3 */ 441825eb42bSJan Lentfer while (ldns_dname_label_count(sname) > 0) { 442825eb42bSJan Lentfer exact_match_found = false; 443825eb42bSJan Lentfer in_range_found = false; 444825eb42bSJan Lentfer 445825eb42bSJan Lentfer if (verbosity >= 3) { 446825eb42bSJan Lentfer printf(";; "); 447825eb42bSJan Lentfer ldns_rdf_print(stdout, sname); 448825eb42bSJan Lentfer printf(" hashes to: "); 449825eb42bSJan Lentfer } 450825eb42bSJan Lentfer hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); 451*d1b2b5caSJohn Marino if (hashed_sname == NULL) { 452*d1b2b5caSJohn Marino goto done; 453*d1b2b5caSJohn Marino } 454825eb42bSJan Lentfer 455*d1b2b5caSJohn Marino if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){ 456*d1b2b5caSJohn Marino goto done; 457*d1b2b5caSJohn Marino } 458825eb42bSJan Lentfer 459825eb42bSJan Lentfer if (verbosity >= 3) { 460825eb42bSJan Lentfer ldns_rdf_print(stdout, hashed_sname); 461825eb42bSJan Lentfer printf("\n"); 462825eb42bSJan Lentfer } 463825eb42bSJan Lentfer 464825eb42bSJan Lentfer for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 465825eb42bSJan Lentfer nsec = ldns_rr_list_rr(nsec3s, nsec_i); 466825eb42bSJan Lentfer 467825eb42bSJan Lentfer /* check values of iterations etc! */ 468825eb42bSJan Lentfer 469825eb42bSJan Lentfer /* exact match? */ 470825eb42bSJan Lentfer if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 471825eb42bSJan Lentfer if (verbosity >= 4) { 472825eb42bSJan Lentfer printf(";; exact match found\n"); 473825eb42bSJan Lentfer } 474825eb42bSJan Lentfer exact_match_found = true; 475825eb42bSJan Lentfer } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { 476825eb42bSJan Lentfer if (verbosity >= 4) { 477825eb42bSJan Lentfer printf(";; in range of an nsec\n"); 478825eb42bSJan Lentfer } 479825eb42bSJan Lentfer in_range_found = true; 480825eb42bSJan Lentfer } 481825eb42bSJan Lentfer 482825eb42bSJan Lentfer } 483825eb42bSJan Lentfer if (!exact_match_found && in_range_found) { 484825eb42bSJan Lentfer flag = true; 485825eb42bSJan Lentfer } else if (exact_match_found && flag) { 486825eb42bSJan Lentfer result = ldns_rdf_clone(sname); 487825eb42bSJan Lentfer } else if (exact_match_found && !flag) { 488825eb42bSJan Lentfer // error! 489825eb42bSJan Lentfer if (verbosity >= 4) { 490825eb42bSJan Lentfer printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n"); 491825eb42bSJan Lentfer } 492825eb42bSJan Lentfer ldns_rdf_deep_free(hashed_sname); 493825eb42bSJan Lentfer goto done; 494825eb42bSJan Lentfer } else { 495825eb42bSJan Lentfer flag = false; 496825eb42bSJan Lentfer } 497825eb42bSJan Lentfer 498825eb42bSJan Lentfer ldns_rdf_deep_free(hashed_sname); 499825eb42bSJan Lentfer tmp = sname; 500825eb42bSJan Lentfer sname = ldns_dname_left_chop(sname); 501825eb42bSJan Lentfer ldns_rdf_deep_free(tmp); 502*d1b2b5caSJohn Marino if (sname == NULL) { 503*d1b2b5caSJohn Marino goto done; 504*d1b2b5caSJohn Marino } 505825eb42bSJan Lentfer } 506825eb42bSJan Lentfer 507825eb42bSJan Lentfer done: 508825eb42bSJan Lentfer LDNS_FREE(salt); 509825eb42bSJan Lentfer ldns_rdf_deep_free(zone_name); 510825eb42bSJan Lentfer ldns_rdf_deep_free(sname); 511825eb42bSJan Lentfer 512825eb42bSJan Lentfer if (!result) { 513825eb42bSJan Lentfer if (verbosity >= 4) { 514825eb42bSJan Lentfer printf(";; no closest encloser found\n"); 515825eb42bSJan Lentfer } 516825eb42bSJan Lentfer } 517825eb42bSJan Lentfer 518825eb42bSJan Lentfer /* todo checks from end of 6.2. here or in caller? */ 519825eb42bSJan Lentfer return result; 520825eb42bSJan Lentfer } 521