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 * 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 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 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 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 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 * 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 * 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