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 184 if (verbosity >= 5) { 185 printf("VERIFY DENIAL FROM:\n"); 186 ldns_pkt_print(stdout, pkt); 187 } 188 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); 192 if (nsecs) { 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 199 */ 200 if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) { 201 /* 202 printf("CHECKING NSEC:\n"); 203 ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i)); 204 printf("DAWASEM\n"); 205 */ 206 if (ldns_nsec_bitmap_covers_type( 207 ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs, 208 nsec_i)), 209 type)) { 210 /* Error, according to the nsec this rrset is signed */ 211 result = LDNS_STATUS_CRYPTO_NO_RRSIG; 212 } else { 213 /* ok nsec denies existence */ 214 if (verbosity >= 3) { 215 printf(";; Existence of data set with this type denied by NSEC\n"); 216 } 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); 220 } 221 ldns_rr_list_deep_free(nsecs); 222 return LDNS_STATUS_OK; 223 } 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"); 227 } 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); 230 } 231 ldns_rr_list_deep_free(nsecs); 232 return LDNS_STATUS_OK; 233 } else { 234 /* nsec has nothing to do with this data */ 235 } 236 } 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; 242 243 if(!sigs) { 244 if (q) { 245 ldns_rr_free(q); 246 } 247 ldns_rr_list_deep_free(nsecs); 248 return LDNS_STATUS_MEM_ERR; 249 } 250 if(!q) { 251 ldns_rr_list_deep_free(nsecs); 252 ldns_rr_list_deep_free(sigs); 253 return LDNS_STATUS_MEM_ERR; 254 } 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)) { 259 ldns_rr_free(q); 260 ldns_rr_list_deep_free(sigs); 261 ldns_rr_list_deep_free(nsecs); 262 return LDNS_STATUS_MEM_ERR; 263 } 264 ldns_rr_set_type(q, type); 265 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); 270 } 271 ldns_rr_free(q); 272 ldns_rr_list_deep_free(nsecs); 273 ldns_rr_list_deep_free(sigs); 274 } 275 return result; 276 #else 277 (void)pkt; 278 (void)name; 279 (void)type; 280 (void)nsec_rrs; 281 (void)nsec_rr_sigs; 282 return LDNS_STATUS_ERR; 283 #endif /* HAVE_SSL */ 284 } 285 286 /* NSEC3 draft -07 */ 287 /*return hash name match*/ 288 ldns_rr * 289 ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { 290 uint8_t algorithm; 291 uint32_t iterations; 292 uint8_t salt_length; 293 uint8_t *salt; 294 295 ldns_rdf *sname = NULL, *hashed_sname = NULL; 296 297 size_t nsec_i; 298 ldns_rr *nsec; 299 ldns_rr *result = NULL; 300 301 const ldns_rr_descriptor *descriptor; 302 303 ldns_rdf *zone_name = NULL; 304 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); 310 } else { 311 printf("TYPE%d ", qtype); 312 } 313 ldns_rdf_print(stdout, qname); 314 printf("\n"); 315 } 316 317 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 318 if (verbosity >= 4) { 319 printf("no qname, nsec3s or list empty\n"); 320 } 321 return NULL; 322 } 323 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); 329 if (salt == NULL) { 330 goto done; 331 } 332 333 sname = ldns_rdf_clone(qname); 334 if (sname == NULL) { 335 goto done; 336 } 337 if (verbosity >= 4) { 338 printf(";; owner name hashes to: "); 339 } 340 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); 341 if (hashed_sname == NULL) { 342 goto done; 343 } 344 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 345 if (zone_name == NULL) { 346 goto done; 347 } 348 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) { 349 goto done; 350 }; 351 352 if (verbosity >= 4) { 353 ldns_rdf_print(stdout, hashed_sname); 354 printf("\n"); 355 } 356 357 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 358 nsec = ldns_rr_list_rr(nsec3s, nsec_i); 359 360 /* check values of iterations etc! */ 361 362 /* exact match? */ 363 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 364 result = nsec; 365 goto done; 366 } 367 368 } 369 370 done: 371 ldns_rdf_deep_free(zone_name); 372 ldns_rdf_deep_free(sname); 373 ldns_rdf_deep_free(hashed_sname); 374 LDNS_FREE(salt); 375 376 if (verbosity >= 4) { 377 if (result) { 378 printf(";; Found.\n"); 379 } else { 380 printf(";; Not foud.\n"); 381 } 382 } 383 return result; 384 } 385 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! */ 388 ldns_rdf * 389 ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) 390 { 391 /* remember parameters, they must match */ 392 uint8_t algorithm; 393 uint32_t iterations; 394 uint8_t salt_length; 395 uint8_t *salt; 396 397 ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp; 398 bool flag; 399 400 bool exact_match_found; 401 bool in_range_found; 402 403 ldns_rdf *zone_name = NULL; 404 405 size_t nsec_i; 406 ldns_rr *nsec; 407 ldns_rdf *result = NULL; 408 409 if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 410 return NULL; 411 } 412 413 if (verbosity >= 4) { 414 printf(";; finding closest encloser for type %d ", qtype); 415 ldns_rdf_print(stdout, qname); 416 printf("\n"); 417 } 418 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); 424 if (salt == NULL) { 425 goto done; 426 } 427 428 sname = ldns_rdf_clone(qname); 429 if (sname == NULL) { 430 goto done; 431 } 432 433 flag = false; 434 435 zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 436 if (zone_name == NULL) { 437 goto done; 438 } 439 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; 444 445 if (verbosity >= 3) { 446 printf(";; "); 447 ldns_rdf_print(stdout, sname); 448 printf(" hashes to: "); 449 } 450 hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); 451 if (hashed_sname == NULL) { 452 goto done; 453 } 454 455 if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){ 456 goto done; 457 } 458 459 if (verbosity >= 3) { 460 ldns_rdf_print(stdout, hashed_sname); 461 printf("\n"); 462 } 463 464 for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 465 nsec = ldns_rr_list_rr(nsec3s, nsec_i); 466 467 /* check values of iterations etc! */ 468 469 /* exact match? */ 470 if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 471 if (verbosity >= 4) { 472 printf(";; exact match found\n"); 473 } 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"); 478 } 479 in_range_found = true; 480 } 481 482 } 483 if (!exact_match_found && in_range_found) { 484 flag = true; 485 } else if (exact_match_found && flag) { 486 result = ldns_rdf_clone(sname); 487 } else if (exact_match_found && !flag) { 488 // error! 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"); 491 } 492 ldns_rdf_deep_free(hashed_sname); 493 goto done; 494 } else { 495 flag = false; 496 } 497 498 ldns_rdf_deep_free(hashed_sname); 499 tmp = sname; 500 sname = ldns_dname_left_chop(sname); 501 ldns_rdf_deep_free(tmp); 502 if (sname == NULL) { 503 goto done; 504 } 505 } 506 507 done: 508 LDNS_FREE(salt); 509 ldns_rdf_deep_free(zone_name); 510 ldns_rdf_deep_free(sname); 511 512 if (!result) { 513 if (verbosity >= 4) { 514 printf(";; no closest encloser found\n"); 515 } 516 } 517 518 /* todo checks from end of 6.2. here or in caller? */ 519 return result; 520 } 521