Annotation of embedaddon/dnsmasq/src/dnssec.c, revision 1.1
1.1 ! misho 1: /* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
! 2: and Copyright (c) 2012-2014 Simon Kelley
! 3:
! 4: This program is free software; you can redistribute it and/or modify
! 5: it under the terms of the GNU General Public License as published by
! 6: the Free Software Foundation; version 2 dated June, 1991, or
! 7: (at your option) version 3 dated 29 June, 2007.
! 8:
! 9: This program is distributed in the hope that it will be useful,
! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 12: GNU General Public License for more details.
! 13:
! 14: You should have received a copy of the GNU General Public License
! 15: along with this program. If not, see <http://www.gnu.org/licenses/>.
! 16: */
! 17:
! 18: #include "dnsmasq.h"
! 19:
! 20: #ifdef HAVE_DNSSEC
! 21:
! 22: #include <nettle/rsa.h>
! 23: #include <nettle/dsa.h>
! 24: #ifndef NO_NETTLE_ECC
! 25: # include <nettle/ecdsa.h>
! 26: # include <nettle/ecc-curve.h>
! 27: #endif
! 28: #include <nettle/nettle-meta.h>
! 29: #include <gmp.h>
! 30:
! 31: #define SERIAL_UNDEF -100
! 32: #define SERIAL_EQ 0
! 33: #define SERIAL_LT -1
! 34: #define SERIAL_GT 1
! 35:
! 36: /* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
! 37: static char *ds_digest_name(int digest)
! 38: {
! 39: switch (digest)
! 40: {
! 41: case 1: return "sha1";
! 42: case 2: return "sha256";
! 43: case 3: return "gosthash94";
! 44: case 4: return "sha384";
! 45: default: return NULL;
! 46: }
! 47: }
! 48:
! 49: /* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
! 50: static char *algo_digest_name(int algo)
! 51: {
! 52: switch (algo)
! 53: {
! 54: case 1: return "md5";
! 55: case 3: return "sha1";
! 56: case 5: return "sha1";
! 57: case 6: return "sha1";
! 58: case 7: return "sha1";
! 59: case 8: return "sha256";
! 60: case 10: return "sha512";
! 61: case 12: return "gosthash94";
! 62: case 13: return "sha256";
! 63: case 14: return "sha384";
! 64: default: return NULL;
! 65: }
! 66: }
! 67:
! 68: /* Find pointer to correct hash function in nettle library */
! 69: static const struct nettle_hash *hash_find(char *name)
! 70: {
! 71: int i;
! 72:
! 73: if (!name)
! 74: return NULL;
! 75:
! 76: for (i = 0; nettle_hashes[i]; i++)
! 77: {
! 78: if (strcmp(nettle_hashes[i]->name, name) == 0)
! 79: return nettle_hashes[i];
! 80: }
! 81:
! 82: return NULL;
! 83: }
! 84:
! 85: /* expand ctx and digest memory allocations if necessary and init hash function */
! 86: static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
! 87: {
! 88: static void *ctx = NULL;
! 89: static unsigned char *digest = NULL;
! 90: static unsigned int ctx_sz = 0;
! 91: static unsigned int digest_sz = 0;
! 92:
! 93: void *new;
! 94:
! 95: if (ctx_sz < hash->context_size)
! 96: {
! 97: if (!(new = whine_malloc(hash->context_size)))
! 98: return 0;
! 99: if (ctx)
! 100: free(ctx);
! 101: ctx = new;
! 102: ctx_sz = hash->context_size;
! 103: }
! 104:
! 105: if (digest_sz < hash->digest_size)
! 106: {
! 107: if (!(new = whine_malloc(hash->digest_size)))
! 108: return 0;
! 109: if (digest)
! 110: free(digest);
! 111: digest = new;
! 112: digest_sz = hash->digest_size;
! 113: }
! 114:
! 115: *ctxp = ctx;
! 116: *digestp = digest;
! 117:
! 118: hash->init(ctx);
! 119:
! 120: return 1;
! 121: }
! 122:
! 123: static int rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
! 124: unsigned char *digest, int algo)
! 125: {
! 126: unsigned char *p;
! 127: size_t exp_len;
! 128:
! 129: static struct rsa_public_key *key = NULL;
! 130: static mpz_t sig_mpz;
! 131:
! 132: if (key == NULL)
! 133: {
! 134: if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
! 135: return 0;
! 136:
! 137: nettle_rsa_public_key_init(key);
! 138: mpz_init(sig_mpz);
! 139: }
! 140:
! 141: if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
! 142: return 0;
! 143:
! 144: key_len--;
! 145: if ((exp_len = *p++) == 0)
! 146: {
! 147: GETSHORT(exp_len, p);
! 148: key_len -= 2;
! 149: }
! 150:
! 151: if (exp_len >= key_len)
! 152: return 0;
! 153:
! 154: key->size = key_len - exp_len;
! 155: mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
! 156: mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
! 157:
! 158: mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
! 159:
! 160: switch (algo)
! 161: {
! 162: case 1:
! 163: return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
! 164: case 5: case 7:
! 165: return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
! 166: case 8:
! 167: return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
! 168: case 10:
! 169: return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
! 170: }
! 171:
! 172: return 0;
! 173: }
! 174:
! 175: static int dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
! 176: unsigned char *digest, int algo)
! 177: {
! 178: unsigned char *p;
! 179: unsigned int t;
! 180:
! 181: static struct dsa_public_key *key = NULL;
! 182: static struct dsa_signature *sig_struct;
! 183:
! 184: if (key == NULL)
! 185: {
! 186: if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
! 187: !(key = whine_malloc(sizeof(struct dsa_public_key))))
! 188: return 0;
! 189:
! 190: nettle_dsa_public_key_init(key);
! 191: nettle_dsa_signature_init(sig_struct);
! 192: }
! 193:
! 194: if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
! 195: return 0;
! 196:
! 197: t = *p++;
! 198:
! 199: if (key_len < (213 + (t * 24)))
! 200: return 0;
! 201:
! 202: mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
! 203: mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
! 204: mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
! 205: mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
! 206:
! 207: mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
! 208: mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
! 209:
! 210: (void)algo;
! 211:
! 212: return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
! 213: }
! 214:
! 215: #ifndef NO_NETTLE_ECC
! 216: static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
! 217: unsigned char *sig, size_t sig_len,
! 218: unsigned char *digest, size_t digest_len, int algo)
! 219: {
! 220: unsigned char *p;
! 221: unsigned int t;
! 222: struct ecc_point *key;
! 223:
! 224: static struct ecc_point *key_256 = NULL, *key_384 = NULL;
! 225: static mpz_t x, y;
! 226: static struct dsa_signature *sig_struct;
! 227:
! 228: if (!sig_struct)
! 229: {
! 230: if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
! 231: return 0;
! 232:
! 233: nettle_dsa_signature_init(sig_struct);
! 234: mpz_init(x);
! 235: mpz_init(y);
! 236: }
! 237:
! 238: switch (algo)
! 239: {
! 240: case 13:
! 241: if (!key_256)
! 242: {
! 243: if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
! 244: return 0;
! 245:
! 246: nettle_ecc_point_init(key_256, &nettle_secp_256r1);
! 247: }
! 248:
! 249: key = key_256;
! 250: t = 32;
! 251: break;
! 252:
! 253: case 14:
! 254: if (!key_384)
! 255: {
! 256: if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
! 257: return 0;
! 258:
! 259: nettle_ecc_point_init(key_384, &nettle_secp_384r1);
! 260: }
! 261:
! 262: key = key_384;
! 263: t = 48;
! 264: break;
! 265:
! 266: default:
! 267: return 0;
! 268: }
! 269:
! 270: if (sig_len != 2*t || key_len != 2*t ||
! 271: (p = blockdata_retrieve(key_data, key_len, NULL)))
! 272: return 0;
! 273:
! 274: mpz_import(x, t , 1, 1, 0, 0, p);
! 275: mpz_import(y, t , 1, 1, 0, 0, p + t);
! 276:
! 277: if (!ecc_point_set(key, x, y))
! 278: return 0;
! 279:
! 280: mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
! 281: mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
! 282:
! 283: return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
! 284: }
! 285: #endif
! 286:
! 287: static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
! 288: unsigned char *digest, size_t digest_len, int algo)
! 289: {
! 290: (void)digest_len;
! 291:
! 292: switch (algo)
! 293: {
! 294: case 1: case 5: case 7: case 8: case 10:
! 295: return rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
! 296:
! 297: case 3: case 6:
! 298: return dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
! 299:
! 300: #ifndef NO_NETTLE_ECC
! 301: case 13: case 14:
! 302: return dnsmasq_ecdsa_verify(key_data, key_len, sig, sig_len, digest, digest_len, algo);
! 303: #endif
! 304: }
! 305:
! 306: return 0;
! 307: }
! 308:
! 309: /* Convert from presentation format to wire format, in place.
! 310: Also map UC -> LC.
! 311: Note that using extract_name to get presentation format
! 312: then calling to_wire() removes compression and maps case,
! 313: thus generating names in canonical form.
! 314: Calling to_wire followed by from_wire is almost an identity,
! 315: except that the UC remains mapped to LC.
! 316: */
! 317: static int to_wire(char *name)
! 318: {
! 319: unsigned char *l, *p, term;
! 320: int len;
! 321:
! 322: for (l = (unsigned char*)name; *l != 0; l = p)
! 323: {
! 324: for (p = l; *p != '.' && *p != 0; p++)
! 325: if (*p >= 'A' && *p <= 'Z')
! 326: *p = *p - 'A' + 'a';
! 327:
! 328: term = *p;
! 329:
! 330: if ((len = p - l) != 0)
! 331: memmove(l+1, l, len);
! 332: *l = len;
! 333:
! 334: p++;
! 335:
! 336: if (term == 0)
! 337: *p = 0;
! 338: }
! 339:
! 340: return l + 1 - (unsigned char *)name;
! 341: }
! 342:
! 343: /* Note: no compression allowed in input. */
! 344: static void from_wire(char *name)
! 345: {
! 346: unsigned char *l;
! 347: int len;
! 348:
! 349: for (l = (unsigned char *)name; *l != 0; l += len+1)
! 350: {
! 351: len = *l;
! 352: memmove(l, l+1, len);
! 353: l[len] = '.';
! 354: }
! 355:
! 356: if ((char *)l != name)
! 357: *(l-1) = 0;
! 358: }
! 359:
! 360: /* Input in presentation format */
! 361: static int count_labels(char *name)
! 362: {
! 363: int i;
! 364:
! 365: if (*name == 0)
! 366: return 0;
! 367:
! 368: for (i = 0; *name; name++)
! 369: if (*name == '.')
! 370: i++;
! 371:
! 372: return i+1;
! 373: }
! 374:
! 375: /* Implement RFC1982 wrapped compare for 32-bit numbers */
! 376: static int serial_compare_32(unsigned long s1, unsigned long s2)
! 377: {
! 378: if (s1 == s2)
! 379: return SERIAL_EQ;
! 380:
! 381: if ((s1 < s2 && (s2 - s1) < (1UL<<31)) ||
! 382: (s1 > s2 && (s1 - s2) > (1UL<<31)))
! 383: return SERIAL_LT;
! 384: if ((s1 < s2 && (s2 - s1) > (1UL<<31)) ||
! 385: (s1 > s2 && (s1 - s2) < (1UL<<31)))
! 386: return SERIAL_GT;
! 387: return SERIAL_UNDEF;
! 388: }
! 389:
! 390: /* Check whether today/now is between date_start and date_end */
! 391: static int check_date_range(unsigned long date_start, unsigned long date_end)
! 392: {
! 393: unsigned long curtime;
! 394:
! 395: /* Checking timestamps may be temporarily disabled */
! 396: if (option_bool(OPT_DNSSEC_TIME))
! 397: return 1;
! 398:
! 399: curtime = time(0);
! 400:
! 401: /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
! 402: return serial_compare_32(curtime, date_start) == SERIAL_GT
! 403: && serial_compare_32(curtime, date_end) == SERIAL_LT;
! 404: }
! 405:
! 406: static u16 *get_desc(int type)
! 407: {
! 408: /* List of RRtypes which include domains in the data.
! 409: 0 -> domain
! 410: integer -> no of plain bytes
! 411: -1 -> end
! 412:
! 413: zero is not a valid RRtype, so the final entry is returned for
! 414: anything which needs no mangling.
! 415: */
! 416:
! 417: static u16 rr_desc[] =
! 418: {
! 419: T_NS, 0, -1,
! 420: T_MD, 0, -1,
! 421: T_MF, 0, -1,
! 422: T_CNAME, 0, -1,
! 423: T_SOA, 0, 0, -1,
! 424: T_MB, 0, -1,
! 425: T_MG, 0, -1,
! 426: T_MR, 0, -1,
! 427: T_PTR, 0, -1,
! 428: T_MINFO, 0, 0, -1,
! 429: T_MX, 2, 0, -1,
! 430: T_RP, 0, 0, -1,
! 431: T_AFSDB, 2, 0, -1,
! 432: T_RT, 2, 0, -1,
! 433: T_SIG, 18, 0, -1,
! 434: T_PX, 2, 0, 0, -1,
! 435: T_NXT, 0, -1,
! 436: T_KX, 2, 0, -1,
! 437: T_SRV, 6, 0, -1,
! 438: T_DNAME, 0, -1,
! 439: 0, -1 /* wildcard/catchall */
! 440: };
! 441:
! 442: u16 *p = rr_desc;
! 443:
! 444: while (*p != type && *p != 0)
! 445: while (*p++ != (u16)-1);
! 446:
! 447: return p+1;
! 448: }
! 449:
! 450: /* Return bytes of canonicalised rdata, when the return value is zero, the remaining
! 451: data, pointed to by *p, should be used raw. */
! 452: static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff,
! 453: unsigned char **p, u16 **desc)
! 454: {
! 455: int d = **desc;
! 456:
! 457: (*desc)++;
! 458:
! 459: /* No more data needs mangling */
! 460: if (d == (u16)-1)
! 461: return 0;
! 462:
! 463: if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
! 464: /* domain-name, canonicalise */
! 465: return to_wire(buff);
! 466: else
! 467: {
! 468: /* plain data preceding a domain-name, don't run off the end of the data */
! 469: if ((end - *p) < d)
! 470: d = end - *p;
! 471:
! 472: if (d != 0)
! 473: {
! 474: memcpy(buff, *p, d);
! 475: *p += d;
! 476: }
! 477:
! 478: return d;
! 479: }
! 480: }
! 481:
! 482: static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
! 483: {
! 484: unsigned char **p;
! 485: int new_sz = *sz;
! 486:
! 487: if (new_sz > new)
! 488: return 1;
! 489:
! 490: if (new >= 100)
! 491: return 0;
! 492:
! 493: new_sz += 5;
! 494:
! 495: if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
! 496: return 0;
! 497:
! 498: if (*wkspc)
! 499: {
! 500: memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
! 501: free(*wkspc);
! 502: }
! 503:
! 504: *wkspc = p;
! 505: *sz = new_sz;
! 506:
! 507: return 1;
! 508: }
! 509:
! 510: /* Bubble sort the RRset into the canonical order.
! 511: Note that the byte-streams from two RRs may get unsynced: consider
! 512: RRs which have two domain-names at the start and then other data.
! 513: The domain-names may have different lengths in each RR, but sort equal
! 514:
! 515: ------------
! 516: |abcde|fghi|
! 517: ------------
! 518: |abcd|efghi|
! 519: ------------
! 520:
! 521: leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
! 522: */
! 523:
! 524: static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
! 525: unsigned char **rrset, char *buff1, char *buff2)
! 526: {
! 527: int swap, quit, i;
! 528:
! 529: do
! 530: {
! 531: for (swap = 0, i = 0; i < rrsetidx-1; i++)
! 532: {
! 533: int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
! 534: u16 *dp1, *dp2;
! 535: unsigned char *end1, *end2;
! 536: /* Note that these have been determined to be OK previously,
! 537: so we don't need to check for NULL return here. */
! 538: unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
! 539: unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
! 540:
! 541: p1 += 8; /* skip class, type, ttl */
! 542: GETSHORT(rdlen1, p1);
! 543: end1 = p1 + rdlen1;
! 544:
! 545: p2 += 8; /* skip class, type, ttl */
! 546: GETSHORT(rdlen2, p2);
! 547: end2 = p2 + rdlen2;
! 548:
! 549: dp1 = dp2 = rr_desc;
! 550:
! 551: for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
! 552: {
! 553: if (left1 != 0)
! 554: memmove(buff1, buff1 + len1 - left1, left1);
! 555:
! 556: if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
! 557: {
! 558: quit = 1;
! 559: len1 = end1 - p1;
! 560: memcpy(buff1 + left1, p1, len1);
! 561: }
! 562: len1 += left1;
! 563:
! 564: if (left2 != 0)
! 565: memmove(buff2, buff2 + len2 - left2, left2);
! 566:
! 567: if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
! 568: {
! 569: quit = 1;
! 570: len2 = end2 - p2;
! 571: memcpy(buff2 + left2, p2, len2);
! 572: }
! 573: len2 += left2;
! 574:
! 575: if (len1 > len2)
! 576: left1 = len1 - len2, left2 = 0, len = len2;
! 577: else
! 578: left2 = len2 - len1, left1 = 0, len = len1;
! 579:
! 580: rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
! 581:
! 582: if (rc > 0 || (rc == 0 && quit && len1 > len2))
! 583: {
! 584: unsigned char *tmp = rrset[i+1];
! 585: rrset[i+1] = rrset[i];
! 586: rrset[i] = tmp;
! 587: swap = quit = 1;
! 588: }
! 589: else if (rc < 0)
! 590: quit = 1;
! 591: }
! 592: }
! 593: } while (swap);
! 594: }
! 595:
! 596: /* Validate a single RRset (class, type, name) in the supplied DNS reply
! 597: Return code:
! 598: STAT_SECURE if it validates.
! 599: STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
! 600: STAT_NO_SIG no RRsigs found.
! 601: STAT_INSECURE RRset empty.
! 602: STAT_BOGUS signature is wrong, bad packet.
! 603: STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
! 604:
! 605: if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
! 606: otherwise find the key in the cache.
! 607:
! 608: name is unchanged on exit. keyname is used as workspace and trashed.
! 609: */
! 610: static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class,
! 611: int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
! 612: {
! 613: static unsigned char **rrset = NULL, **sigs = NULL;
! 614: static int rrset_sz = 0, sig_sz = 0;
! 615:
! 616: unsigned char *p;
! 617: int rrsetidx, sigidx, res, rdlen, j, name_labels;
! 618: struct crec *crecp = NULL;
! 619: int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
! 620: u16 *rr_desc = get_desc(type);
! 621:
! 622: if (!(p = skip_questions(header, plen)))
! 623: return STAT_BOGUS;
! 624:
! 625: name_labels = count_labels(name); /* For 4035 5.3.2 check */
! 626:
! 627: /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
! 628: for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
! 629: j != 0; j--)
! 630: {
! 631: unsigned char *pstart, *pdata;
! 632: int stype, sclass;
! 633:
! 634: pstart = p;
! 635:
! 636: if (!(res = extract_name(header, plen, &p, name, 0, 10)))
! 637: return STAT_BOGUS; /* bad packet */
! 638:
! 639: GETSHORT(stype, p);
! 640: GETSHORT(sclass, p);
! 641: p += 4; /* TTL */
! 642:
! 643: pdata = p;
! 644:
! 645: GETSHORT(rdlen, p);
! 646:
! 647: if (!CHECK_LEN(header, p, plen, rdlen))
! 648: return STAT_BOGUS;
! 649:
! 650: if (res == 1 && sclass == class)
! 651: {
! 652: if (stype == type)
! 653: {
! 654: if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
! 655: return STAT_BOGUS;
! 656:
! 657: rrset[rrsetidx++] = pstart;
! 658: }
! 659:
! 660: if (stype == T_RRSIG)
! 661: {
! 662: if (rdlen < 18)
! 663: return STAT_BOGUS; /* bad packet */
! 664:
! 665: GETSHORT(type_covered, p);
! 666:
! 667: if (type_covered == type)
! 668: {
! 669: if (!expand_workspace(&sigs, &sig_sz, sigidx))
! 670: return STAT_BOGUS;
! 671:
! 672: sigs[sigidx++] = pdata;
! 673: }
! 674:
! 675: p = pdata + 2; /* restore for ADD_RDLEN */
! 676: }
! 677: }
! 678:
! 679: if (!ADD_RDLEN(header, p, plen, rdlen))
! 680: return STAT_BOGUS;
! 681: }
! 682:
! 683: /* RRset empty */
! 684: if (rrsetidx == 0)
! 685: return STAT_INSECURE;
! 686:
! 687: /* no RRSIGs */
! 688: if (sigidx == 0)
! 689: return STAT_NO_SIG;
! 690:
! 691: /* Sort RRset records into canonical order.
! 692: Note that at this point keyname and daemon->workspacename buffs are
! 693: unused, and used as workspace by the sort. */
! 694: sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
! 695:
! 696: /* Now try all the sigs to try and find one which validates */
! 697: for (j = 0; j <sigidx; j++)
! 698: {
! 699: unsigned char *psav, *sig, *digest;
! 700: int i, wire_len, sig_len;
! 701: const struct nettle_hash *hash;
! 702: void *ctx;
! 703: char *name_start;
! 704: u32 nsigttl;
! 705:
! 706: p = sigs[j];
! 707: GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
! 708: psav = p;
! 709:
! 710: p += 2; /* type_covered - already checked */
! 711: algo = *p++;
! 712: labels = *p++;
! 713: GETLONG(orig_ttl, p);
! 714: GETLONG(sig_expiration, p);
! 715: GETLONG(sig_inception, p);
! 716: GETSHORT(key_tag, p);
! 717:
! 718: if (!extract_name(header, plen, &p, keyname, 1, 0))
! 719: return STAT_BOGUS;
! 720:
! 721: /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
! 722: the name of the zone containing the RRset. We can't tell that
! 723: for certain, but we can check that the RRset name is equal to
! 724: or encloses the signers name, which should be enough to stop
! 725: an attacker using signatures made with the key of an unrelated
! 726: zone he controls. Note that the root key is always allowed. */
! 727: if (*keyname != 0)
! 728: {
! 729: int failed = 0;
! 730:
! 731: for (name_start = name; !hostname_isequal(name_start, keyname); )
! 732: if ((name_start = strchr(name_start, '.')))
! 733: name_start++; /* chop a label off and try again */
! 734: else
! 735: {
! 736: failed = 1;
! 737: break;
! 738: }
! 739:
! 740: /* Bad sig, try another */
! 741: if (failed)
! 742: continue;
! 743: }
! 744:
! 745: /* Other 5.3.1 checks */
! 746: if (!check_date_range(sig_inception, sig_expiration) ||
! 747: labels > name_labels ||
! 748: !(hash = hash_find(algo_digest_name(algo))) ||
! 749: !hash_init(hash, &ctx, &digest))
! 750: continue;
! 751:
! 752: /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
! 753: if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
! 754: return STAT_NEED_KEY;
! 755:
! 756: sig = p;
! 757: sig_len = rdlen - (p - psav);
! 758:
! 759: nsigttl = htonl(orig_ttl);
! 760:
! 761: hash->update(ctx, 18, psav);
! 762: wire_len = to_wire(keyname);
! 763: hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
! 764: from_wire(keyname);
! 765:
! 766: for (i = 0; i < rrsetidx; ++i)
! 767: {
! 768: int seg;
! 769: unsigned char *end, *cp;
! 770: u16 len, *dp;
! 771:
! 772: p = rrset[i];
! 773: if (!extract_name(header, plen, &p, name, 1, 10))
! 774: return STAT_BOGUS;
! 775:
! 776: name_start = name;
! 777:
! 778: /* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
! 779: if (labels < name_labels)
! 780: {
! 781: int k;
! 782: for (k = name_labels - labels; k != 0; k--)
! 783: while (*name_start != '.' && *name_start != 0)
! 784: name_start++;
! 785: name_start--;
! 786: *name_start = '*';
! 787: }
! 788:
! 789: wire_len = to_wire(name_start);
! 790: hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
! 791: hash->update(ctx, 4, p); /* class and type */
! 792: hash->update(ctx, 4, (unsigned char *)&nsigttl);
! 793:
! 794: p += 8; /* skip class, type, ttl */
! 795: GETSHORT(rdlen, p);
! 796: if (!CHECK_LEN(header, p, plen, rdlen))
! 797: return STAT_BOGUS;
! 798:
! 799: end = p + rdlen;
! 800:
! 801: /* canonicalise rdata and calculate length of same, use name buffer as workspace */
! 802: cp = p;
! 803: dp = rr_desc;
! 804: for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
! 805: len += end - cp;
! 806: len = htons(len);
! 807: hash->update(ctx, 2, (unsigned char *)&len);
! 808:
! 809: /* Now canonicalise again and digest. */
! 810: cp = p;
! 811: dp = rr_desc;
! 812: while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
! 813: hash->update(ctx, seg, (unsigned char *)name);
! 814: if (cp != end)
! 815: hash->update(ctx, end - cp, cp);
! 816: }
! 817:
! 818: hash->digest(ctx, hash->digest_size, digest);
! 819:
! 820: /* namebuff used for workspace above, restore to leave unchanged on exit */
! 821: p = (unsigned char*)(rrset[0]);
! 822: extract_name(header, plen, &p, name, 1, 0);
! 823:
! 824: if (key)
! 825: {
! 826: if (algo_in == algo && keytag_in == key_tag &&
! 827: verify(key, keylen, sig, sig_len, digest, hash->digest_size, algo))
! 828: return STAT_SECURE;
! 829: }
! 830: else
! 831: {
! 832: /* iterate through all possible keys 4035 5.3.1 */
! 833: for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
! 834: if (crecp->addr.key.algo == algo &&
! 835: crecp->addr.key.keytag == key_tag &&
! 836: crecp->uid == (unsigned int)class &&
! 837: verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
! 838: return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
! 839: }
! 840: }
! 841:
! 842: return STAT_BOGUS;
! 843: }
! 844:
! 845: /* The DNS packet is expected to contain the answer to a DNSKEY query.
! 846: Put all DNSKEYs in the answer which are valid into the cache.
! 847: return codes:
! 848: STAT_INSECURE No DNSKEYs in reply.
! 849: STAT_SECURE At least one valid DNSKEY found and in cache.
! 850: STAT_BOGUS No DNSKEYs found, which can be validated with DS,
! 851: or self-sign for DNSKEY RRset is not valid, bad packet.
! 852: STAT_NEED_DS DS records to validate a key not found, name in keyname
! 853: */
! 854: int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
! 855: {
! 856: unsigned char *psave, *p = (unsigned char *)(header+1);
! 857: struct crec *crecp, *recp1;
! 858: int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
! 859: struct blockdata *key;
! 860: struct all_addr a;
! 861:
! 862: if (ntohs(header->qdcount) != 1 ||
! 863: !extract_name(header, plen, &p, name, 1, 4))
! 864: return STAT_BOGUS;
! 865:
! 866: GETSHORT(qtype, p);
! 867: GETSHORT(qclass, p);
! 868:
! 869: if (qtype != T_DNSKEY || qclass != class)
! 870: return STAT_BOGUS;
! 871:
! 872: if (ntohs(header->ancount) == 0)
! 873: return STAT_INSECURE;
! 874:
! 875: /* See if we have cached a DS record which validates this key */
! 876: if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
! 877: {
! 878: strcpy(keyname, name);
! 879: return STAT_NEED_DS;
! 880: }
! 881:
! 882: /* If we've cached that DS provably doesn't exist, result must be INSECURE */
! 883: if (crecp->flags & F_NEG)
! 884: return STAT_INSECURE;
! 885:
! 886: /* NOTE, we need to find ONE DNSKEY which matches the DS */
! 887: for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
! 888: {
! 889: /* Ensure we have type, class TTL and length */
! 890: if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
! 891: return STAT_BOGUS; /* bad packet */
! 892:
! 893: GETSHORT(qtype, p);
! 894: GETSHORT(qclass, p);
! 895: GETLONG(ttl, p);
! 896: GETSHORT(rdlen, p);
! 897:
! 898: if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
! 899: return STAT_BOGUS; /* bad packet */
! 900:
! 901: if (qclass != class || qtype != T_DNSKEY || rc == 2)
! 902: {
! 903: p += rdlen;
! 904: continue;
! 905: }
! 906:
! 907: psave = p;
! 908:
! 909: GETSHORT(flags, p);
! 910: if (*p++ != 3)
! 911: return STAT_BOGUS;
! 912: algo = *p++;
! 913: keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
! 914: key = NULL;
! 915:
! 916: /* key must have zone key flag set */
! 917: if (flags & 0x100)
! 918: key = blockdata_alloc((char*)p, rdlen - 4);
! 919:
! 920: p = psave;
! 921:
! 922: if (!ADD_RDLEN(header, p, plen, rdlen))
! 923: {
! 924: if (key)
! 925: blockdata_free(key);
! 926: return STAT_BOGUS; /* bad packet */
! 927: }
! 928:
! 929: /* No zone key flag or malloc failure */
! 930: if (!key)
! 931: continue;
! 932:
! 933: for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
! 934: {
! 935: void *ctx;
! 936: unsigned char *digest, *ds_digest;
! 937: const struct nettle_hash *hash;
! 938:
! 939: if (recp1->addr.ds.algo == algo &&
! 940: recp1->addr.ds.keytag == keytag &&
! 941: recp1->uid == (unsigned int)class &&
! 942: (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
! 943: hash_init(hash, &ctx, &digest))
! 944:
! 945: {
! 946: int wire_len = to_wire(name);
! 947:
! 948: /* Note that digest may be different between DSs, so
! 949: we can't move this outside the loop. */
! 950: hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
! 951: hash->update(ctx, (unsigned int)rdlen, psave);
! 952: hash->digest(ctx, hash->digest_size, digest);
! 953:
! 954: from_wire(name);
! 955:
! 956: if (recp1->addr.ds.keylen == (int)hash->digest_size &&
! 957: (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
! 958: memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
! 959: validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE)
! 960: {
! 961: valid = 1;
! 962: break;
! 963: }
! 964: }
! 965: }
! 966: blockdata_free(key);
! 967: }
! 968:
! 969: if (valid)
! 970: {
! 971: /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
! 972: cache_start_insert();
! 973:
! 974: p = skip_questions(header, plen);
! 975:
! 976: for (j = ntohs(header->ancount); j != 0; j--)
! 977: {
! 978: /* Ensure we have type, class TTL and length */
! 979: if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
! 980: return STAT_INSECURE; /* bad packet */
! 981:
! 982: GETSHORT(qtype, p);
! 983: GETSHORT(qclass, p);
! 984: GETLONG(ttl, p);
! 985: GETSHORT(rdlen, p);
! 986:
! 987: if (!CHECK_LEN(header, p, plen, rdlen))
! 988: return STAT_BOGUS; /* bad packet */
! 989:
! 990: if (qclass == class && rc == 1)
! 991: {
! 992: psave = p;
! 993:
! 994: if (qtype == T_DNSKEY)
! 995: {
! 996: if (rdlen < 4)
! 997: return STAT_BOGUS; /* bad packet */
! 998:
! 999: GETSHORT(flags, p);
! 1000: if (*p++ != 3)
! 1001: return STAT_BOGUS;
! 1002: algo = *p++;
! 1003: keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
! 1004:
! 1005: /* Cache needs to known class for DNSSEC stuff */
! 1006: a.addr.dnssec.class = class;
! 1007:
! 1008: if ((key = blockdata_alloc((char*)p, rdlen - 4)))
! 1009: {
! 1010: if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
! 1011: blockdata_free(key);
! 1012: else
! 1013: {
! 1014: a.addr.keytag = keytag;
! 1015: log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
! 1016:
! 1017: recp1->addr.key.keylen = rdlen - 4;
! 1018: recp1->addr.key.keydata = key;
! 1019: recp1->addr.key.algo = algo;
! 1020: recp1->addr.key.keytag = keytag;
! 1021: recp1->addr.key.flags = flags;
! 1022: }
! 1023: }
! 1024: }
! 1025: else if (qtype == T_RRSIG)
! 1026: {
! 1027: /* RRSIG, cache if covers DNSKEY RRset */
! 1028: if (rdlen < 18)
! 1029: return STAT_BOGUS; /* bad packet */
! 1030:
! 1031: GETSHORT(type_covered, p);
! 1032:
! 1033: if (type_covered == T_DNSKEY)
! 1034: {
! 1035: a.addr.dnssec.class = class;
! 1036: a.addr.dnssec.type = type_covered;
! 1037:
! 1038: algo = *p++;
! 1039: p += 13; /* labels, orig_ttl, expiration, inception */
! 1040: GETSHORT(keytag, p);
! 1041: if ((key = blockdata_alloc((char*)psave, rdlen)))
! 1042: {
! 1043: if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
! 1044: blockdata_free(key);
! 1045: else
! 1046: {
! 1047: crecp->addr.sig.keydata = key;
! 1048: crecp->addr.sig.keylen = rdlen;
! 1049: crecp->addr.sig.keytag = keytag;
! 1050: crecp->addr.sig.type_covered = type_covered;
! 1051: crecp->addr.sig.algo = algo;
! 1052: }
! 1053: }
! 1054: }
! 1055: }
! 1056:
! 1057: p = psave;
! 1058: }
! 1059:
! 1060: if (!ADD_RDLEN(header, p, plen, rdlen))
! 1061: return STAT_BOGUS; /* bad packet */
! 1062: }
! 1063:
! 1064: /* commit cache insert. */
! 1065: cache_end_insert();
! 1066: return STAT_SECURE;
! 1067: }
! 1068:
! 1069: log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
! 1070: return STAT_BOGUS;
! 1071: }
! 1072:
! 1073: /* The DNS packet is expected to contain the answer to a DS query
! 1074: Put all DSs in the answer which are valid into the cache.
! 1075: return codes:
! 1076: STAT_INSECURE no DS in reply or not signed.
! 1077: STAT_SECURE At least one valid DS found and in cache.
! 1078: STAT_NO_DS It's proved there's no DS here.
! 1079: STAT_BOGUS At least one DS found, which fails validation, bad packet.
! 1080: STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
! 1081: */
! 1082:
! 1083: int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
! 1084: {
! 1085: unsigned char *p = (unsigned char *)(header+1);
! 1086: int qtype, qclass, val, i, neganswer;
! 1087:
! 1088: if (ntohs(header->qdcount) != 1 ||
! 1089: !(p = skip_name(p, header, plen, 4)))
! 1090: return STAT_BOGUS;
! 1091:
! 1092: GETSHORT(qtype, p);
! 1093: GETSHORT(qclass, p);
! 1094:
! 1095: if (qtype != T_DS || qclass != class)
! 1096: val = STAT_BOGUS;
! 1097: else
! 1098: val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer);
! 1099:
! 1100: if (val == STAT_NO_SIG)
! 1101: val = STAT_INSECURE;
! 1102:
! 1103: p = (unsigned char *)(header+1);
! 1104: extract_name(header, plen, &p, name, 1, 4);
! 1105: p += 4; /* qtype, qclass */
! 1106:
! 1107: if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
! 1108: return STAT_BOGUS;
! 1109:
! 1110: if (val == STAT_BOGUS)
! 1111: log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
! 1112:
! 1113: if ((val == STAT_SECURE || val == STAT_INSECURE) && neganswer)
! 1114: {
! 1115: int rdlen, flags = F_FORWARD | F_DS | F_NEG;
! 1116: unsigned long ttl, minttl = ULONG_MAX;
! 1117: struct all_addr a;
! 1118:
! 1119: if (RCODE(header) == NXDOMAIN)
! 1120: flags |= F_NXDOMAIN;
! 1121:
! 1122: if (val == STAT_SECURE)
! 1123: flags |= F_DNSSECOK;
! 1124:
! 1125: for (i = ntohs(header->nscount); i != 0; i--)
! 1126: {
! 1127: if (!(p = skip_name(p, header, plen, 0)))
! 1128: return STAT_BOGUS;
! 1129:
! 1130: GETSHORT(qtype, p);
! 1131: GETSHORT(qclass, p);
! 1132: GETLONG(ttl, p);
! 1133: GETSHORT(rdlen, p);
! 1134:
! 1135: if (!CHECK_LEN(header, p, plen, rdlen))
! 1136: return STAT_BOGUS; /* bad packet */
! 1137:
! 1138: if (qclass != class || qtype != T_SOA)
! 1139: {
! 1140: p += rdlen;
! 1141: continue;
! 1142: }
! 1143:
! 1144: if (ttl < minttl)
! 1145: minttl = ttl;
! 1146:
! 1147: /* MNAME */
! 1148: if (!(p = skip_name(p, header, plen, 0)))
! 1149: return STAT_BOGUS;
! 1150: /* RNAME */
! 1151: if (!(p = skip_name(p, header, plen, 20)))
! 1152: return STAT_BOGUS;
! 1153: p += 16; /* SERIAL REFRESH RETRY EXPIRE */
! 1154:
! 1155: GETLONG(ttl, p); /* minTTL */
! 1156: if (ttl < minttl)
! 1157: minttl = ttl;
! 1158:
! 1159: break;
! 1160: }
! 1161:
! 1162: if (i != 0)
! 1163: {
! 1164: cache_start_insert();
! 1165:
! 1166: a.addr.dnssec.class = class;
! 1167: cache_insert(name, &a, now, ttl, flags);
! 1168:
! 1169: cache_end_insert();
! 1170: }
! 1171:
! 1172: return (val == STAT_SECURE) ? STAT_NO_DS : STAT_INSECURE;
! 1173: }
! 1174:
! 1175: return val;
! 1176: }
! 1177:
! 1178: /* 4034 6.1 */
! 1179: static int hostname_cmp(const char *a, const char *b)
! 1180: {
! 1181: char *sa, *ea, *ca, *sb, *eb, *cb;
! 1182: unsigned char ac, bc;
! 1183:
! 1184: sa = ea = (char *)a + strlen(a);
! 1185: sb = eb = (char *)b + strlen(b);
! 1186:
! 1187: while (1)
! 1188: {
! 1189: while (sa != a && *(sa-1) != '.')
! 1190: sa--;
! 1191:
! 1192: while (sb != b && *(sb-1) != '.')
! 1193: sb--;
! 1194:
! 1195: ca = sa;
! 1196: cb = sb;
! 1197:
! 1198: while (1)
! 1199: {
! 1200: if (ca == ea)
! 1201: {
! 1202: if (cb == eb)
! 1203: break;
! 1204:
! 1205: return -1;
! 1206: }
! 1207:
! 1208: if (cb == eb)
! 1209: return 1;
! 1210:
! 1211: ac = (unsigned char) *ca++;
! 1212: bc = (unsigned char) *cb++;
! 1213:
! 1214: if (ac >= 'A' && ac <= 'Z')
! 1215: ac += 'a' - 'A';
! 1216: if (bc >= 'A' && bc <= 'Z')
! 1217: bc += 'a' - 'A';
! 1218:
! 1219: if (ac < bc)
! 1220: return -1;
! 1221: else if (ac != bc)
! 1222: return 1;
! 1223: }
! 1224:
! 1225:
! 1226: if (sa == a)
! 1227: {
! 1228: if (sb == b)
! 1229: return 0;
! 1230:
! 1231: return -1;
! 1232: }
! 1233:
! 1234: if (sb == b)
! 1235: return 1;
! 1236:
! 1237: ea = sa--;
! 1238: eb = sb--;
! 1239: }
! 1240: }
! 1241:
! 1242: /* Find all the NSEC or NSEC3 records in a reply.
! 1243: return an array of pointers to them. */
! 1244: static int find_nsec_records(struct dns_header *header, size_t plen, unsigned char ***nsecsetp, int *nsecsetl, int class_reqd)
! 1245: {
! 1246: static unsigned char **nsecset = NULL;
! 1247: static int nsecset_sz = 0;
! 1248:
! 1249: int type_found = 0;
! 1250: unsigned char *p = skip_questions(header, plen);
! 1251: int type, class, rdlen, i, nsecs_found;
! 1252:
! 1253: /* Move to NS section */
! 1254: if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
! 1255: return 0;
! 1256:
! 1257: for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
! 1258: {
! 1259: unsigned char *pstart = p;
! 1260:
! 1261: if (!(p = skip_name(p, header, plen, 10)))
! 1262: return 0;
! 1263:
! 1264: GETSHORT(type, p);
! 1265: GETSHORT(class, p);
! 1266: p += 4; /* TTL */
! 1267: GETSHORT(rdlen, p);
! 1268:
! 1269: if (class == class_reqd && (type == T_NSEC || type == T_NSEC3))
! 1270: {
! 1271: /* No mixed NSECing 'round here, thankyouverymuch */
! 1272: if (type_found == T_NSEC && type == T_NSEC3)
! 1273: return 0;
! 1274: if (type_found == T_NSEC3 && type == T_NSEC)
! 1275: return 0;
! 1276:
! 1277: type_found = type;
! 1278:
! 1279: if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
! 1280: return 0;
! 1281:
! 1282: nsecset[nsecs_found++] = pstart;
! 1283: }
! 1284:
! 1285: if (!ADD_RDLEN(header, p, plen, rdlen))
! 1286: return 0;
! 1287: }
! 1288:
! 1289: *nsecsetp = nsecset;
! 1290: *nsecsetl = nsecs_found;
! 1291:
! 1292: return type_found;
! 1293: }
! 1294:
! 1295: static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
! 1296: char *workspace1, char *workspace2, char *name, int type)
! 1297: {
! 1298: int i, rc, rdlen;
! 1299: unsigned char *p, *psave;
! 1300: int offset = (type & 0xff) >> 3;
! 1301: int mask = 0x80 >> (type & 0x07);
! 1302:
! 1303: /* Find NSEC record that proves name doesn't exist */
! 1304: for (i = 0; i < nsec_count; i++)
! 1305: {
! 1306: p = nsecs[i];
! 1307: if (!extract_name(header, plen, &p, workspace1, 1, 10))
! 1308: return STAT_BOGUS;
! 1309: p += 8; /* class, type, TTL */
! 1310: GETSHORT(rdlen, p);
! 1311: psave = p;
! 1312: if (!extract_name(header, plen, &p, workspace2, 1, 10))
! 1313: return STAT_BOGUS;
! 1314:
! 1315: rc = hostname_cmp(workspace1, name);
! 1316:
! 1317: if (rc == 0)
! 1318: {
! 1319: /* 4035 para 5.4. Last sentence */
! 1320: if (type == T_NSEC || type == T_RRSIG)
! 1321: return STAT_SECURE;
! 1322:
! 1323: /* NSEC with the same name as the RR we're testing, check
! 1324: that the type in question doesn't appear in the type map */
! 1325: rdlen -= p - psave;
! 1326: /* rdlen is now length of type map, and p points to it */
! 1327:
! 1328: while (rdlen >= 2)
! 1329: {
! 1330: if (!CHECK_LEN(header, p, plen, rdlen))
! 1331: return STAT_BOGUS;
! 1332:
! 1333: if (p[0] == type >> 8)
! 1334: {
! 1335: /* Does the NSEC say our type exists? */
! 1336: if (offset < p[1] && (p[offset+2] & mask) != 0)
! 1337: return STAT_BOGUS;
! 1338:
! 1339: break; /* finshed checking */
! 1340: }
! 1341:
! 1342: rdlen -= p[1];
! 1343: p += p[1];
! 1344: }
! 1345:
! 1346: return STAT_SECURE;
! 1347: }
! 1348: else if (rc == -1)
! 1349: {
! 1350: /* Normal case, name falls between NSEC name and next domain name,
! 1351: wrap around case, name falls between NSEC name (rc == -1) and end */
! 1352: if (hostname_cmp(workspace2, name) == 1 || hostname_cmp(workspace1, workspace2) == 1)
! 1353: return STAT_SECURE;
! 1354: }
! 1355: else
! 1356: {
! 1357: /* wrap around case, name falls between start and next domain name */
! 1358: if (hostname_cmp(workspace1, workspace2) == 1 && hostname_cmp(workspace2, name) == 1)
! 1359: return STAT_SECURE;
! 1360: }
! 1361: }
! 1362:
! 1363: return STAT_BOGUS;
! 1364: }
! 1365:
! 1366: /* return digest length, or zero on error */
! 1367: static int hash_name(char *in, unsigned char **out, struct nettle_hash const *hash,
! 1368: unsigned char *salt, int salt_len, int iterations)
! 1369: {
! 1370: void *ctx;
! 1371: unsigned char *digest;
! 1372: int i;
! 1373:
! 1374: if (!hash_init(hash, &ctx, &digest))
! 1375: return 0;
! 1376:
! 1377: hash->update(ctx, to_wire(in), (unsigned char *)in);
! 1378: hash->update(ctx, salt_len, salt);
! 1379: hash->digest(ctx, hash->digest_size, digest);
! 1380:
! 1381: for(i = 0; i < iterations; i++)
! 1382: {
! 1383: hash->update(ctx, hash->digest_size, digest);
! 1384: hash->update(ctx, salt_len, salt);
! 1385: hash->digest(ctx, hash->digest_size, digest);
! 1386: }
! 1387:
! 1388: from_wire(in);
! 1389:
! 1390: *out = digest;
! 1391: return hash->digest_size;
! 1392: }
! 1393:
! 1394: /* Decode base32 to first "." or end of string */
! 1395: static int base32_decode(char *in, unsigned char *out)
! 1396: {
! 1397: int oc, on, c, mask, i;
! 1398: unsigned char *p = out;
! 1399:
! 1400: for (c = *in, oc = 0, on = 0; c != 0 && c != '.'; c = *++in)
! 1401: {
! 1402: if (c >= '0' && c <= '9')
! 1403: c -= '0';
! 1404: else if (c >= 'a' && c <= 'v')
! 1405: c -= 'a', c += 10;
! 1406: else if (c >= 'A' && c <= 'V')
! 1407: c -= 'A', c += 10;
! 1408: else
! 1409: return 0;
! 1410:
! 1411: for (mask = 0x10, i = 0; i < 5; i++)
! 1412: {
! 1413: if (c & mask)
! 1414: oc |= 1;
! 1415: mask = mask >> 1;
! 1416: if (((++on) & 7) == 0)
! 1417: *p++ = oc;
! 1418: oc = oc << 1;
! 1419: }
! 1420: }
! 1421:
! 1422: if ((on & 7) != 0)
! 1423: return 0;
! 1424:
! 1425: return p - out;
! 1426: }
! 1427:
! 1428: static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
! 1429: char *workspace1, char *workspace2, char *name, int type)
! 1430: {
! 1431: unsigned char *salt, *p, *digest;
! 1432: int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0;
! 1433: struct nettle_hash const *hash;
! 1434: char *closest_encloser, *next_closest, *wildcard;
! 1435:
! 1436: /* Look though the NSEC3 records to find the first one with
! 1437: an algorithm we support (currently only algo == 1).
! 1438:
! 1439: Take the algo, iterations, and salt of that record
! 1440: as the ones we're going to use, and prune any
! 1441: that don't match. */
! 1442:
! 1443: for (i = 0; i < nsec_count; i++)
! 1444: {
! 1445: if (!(p = skip_name(nsecs[i], header, plen, 15)))
! 1446: return STAT_BOGUS; /* bad packet */
! 1447:
! 1448: p += 10; /* type, class, TTL, rdlen */
! 1449: algo = *p++;
! 1450:
! 1451: if (algo == 1)
! 1452: break; /* known algo */
! 1453: }
! 1454:
! 1455: /* No usable NSEC3s */
! 1456: if (i == nsec_count)
! 1457: return STAT_BOGUS;
! 1458:
! 1459: p++; /* flags */
! 1460: GETSHORT (iterations, p);
! 1461: salt_len = *p++;
! 1462: salt = p;
! 1463: if (!CHECK_LEN(header, salt, plen, salt_len))
! 1464: return STAT_BOGUS; /* bad packet */
! 1465:
! 1466: /* Now prune so we only have NSEC3 records with same iterations, salt and algo */
! 1467: for (i = 0; i < nsec_count; i++)
! 1468: {
! 1469: unsigned char *nsec3p = nsecs[i];
! 1470: int this_iter;
! 1471:
! 1472: nsecs[i] = NULL; /* Speculative, will be restored if OK. */
! 1473:
! 1474: if (!(p = skip_name(nsec3p, header, plen, 15)))
! 1475: return STAT_BOGUS; /* bad packet */
! 1476:
! 1477: p += 10; /* type, class, TTL, rdlen */
! 1478:
! 1479: if (*p++ != algo)
! 1480: continue;
! 1481:
! 1482: p++; /* flags */
! 1483:
! 1484: GETSHORT(this_iter, p);
! 1485: if (this_iter != iterations)
! 1486: continue;
! 1487:
! 1488: if (salt_len != *p++)
! 1489: continue;
! 1490:
! 1491: if (!CHECK_LEN(header, p, plen, salt_len))
! 1492: return STAT_BOGUS; /* bad packet */
! 1493:
! 1494: if (memcmp(p, salt, salt_len) != 0)
! 1495: continue;
! 1496:
! 1497: /* All match, put the pointer back */
! 1498: nsecs[i] = nsec3p;
! 1499: }
! 1500:
! 1501: /* Algo is checked as 1 above */
! 1502: if (!(hash = hash_find("sha1")))
! 1503: return STAT_BOGUS;
! 1504:
! 1505: /* Now, we need the "closest encloser NSEC3" */
! 1506: closest_encloser = name;
! 1507: next_closest = NULL;
! 1508:
! 1509: do
! 1510: {
! 1511: if (*closest_encloser == '.')
! 1512: closest_encloser++;
! 1513:
! 1514: if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
! 1515: return STAT_BOGUS;
! 1516:
! 1517: for (i = 0; i < nsec_count; i++)
! 1518: if ((p = nsecs[i]))
! 1519: {
! 1520: if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
! 1521: !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
! 1522: return STAT_BOGUS;
! 1523:
! 1524: if (digest_len == base32_len &&
! 1525: memcmp(digest, workspace2, digest_len) == 0)
! 1526: break; /* Gotit */
! 1527: }
! 1528:
! 1529: if (i != nsec_count)
! 1530: break;
! 1531:
! 1532: next_closest = closest_encloser;
! 1533: }
! 1534: while ((closest_encloser = strchr(closest_encloser, '.')));
! 1535:
! 1536: /* No usable NSEC3s */
! 1537: if (i == nsec_count)
! 1538: return STAT_BOGUS;
! 1539:
! 1540: if (!next_closest)
! 1541: {
! 1542: /* We found an NSEC3 whose hashed name exactly matches the query, so
! 1543: Now we just need to check the type map. p points to the RR data for the record. */
! 1544: int rdlen;
! 1545: unsigned char *psave;
! 1546: int offset = (type & 0xff) >> 3;
! 1547: int mask = 0x80 >> (type & 0x07);
! 1548:
! 1549: p += 8; /* class, type, TTL */
! 1550: GETSHORT(rdlen, p);
! 1551: psave = p;
! 1552: p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */
! 1553: hash_len = *p++;
! 1554: if (!CHECK_LEN(header, p, plen, hash_len))
! 1555: return STAT_BOGUS; /* bad packet */
! 1556: p += hash_len;
! 1557: rdlen -= p - psave;
! 1558:
! 1559: while (rdlen >= 2)
! 1560: {
! 1561: if (!CHECK_LEN(header, p, plen, rdlen))
! 1562: return STAT_BOGUS;
! 1563:
! 1564: if (p[0] == type >> 8)
! 1565: {
! 1566: /* Does the NSEC3 say our type exists? */
! 1567: if (offset < p[1] && (p[offset+2] & mask) != 0)
! 1568: return STAT_BOGUS;
! 1569:
! 1570: break; /* finshed checking */
! 1571: }
! 1572:
! 1573: rdlen -= p[1];
! 1574: p += p[1];
! 1575: }
! 1576:
! 1577: return STAT_SECURE;
! 1578: }
! 1579:
! 1580: /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
! 1581: if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
! 1582: return STAT_BOGUS;
! 1583:
! 1584: for (i = 0; i < nsec_count; i++)
! 1585: if ((p = nsecs[i]))
! 1586: {
! 1587: if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
! 1588: !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
! 1589: return STAT_BOGUS;
! 1590:
! 1591: p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
! 1592: hash_len = *p++; /* p now points to next hashed name */
! 1593:
! 1594: if (!CHECK_LEN(header, p, plen, hash_len))
! 1595: return STAT_BOGUS;
! 1596:
! 1597: if (digest_len == base32_len && hash_len == base32_len)
! 1598: {
! 1599: if (memcmp(workspace2, digest, digest_len) <= 0)
! 1600: {
! 1601: /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
! 1602: wrap around case, name-hash falls between NSEC3 name-hash and end */
! 1603: if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
! 1604: return STAT_SECURE;
! 1605: }
! 1606: else
! 1607: {
! 1608: /* wrap around case, name falls between start and next domain name */
! 1609: if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
! 1610: return STAT_SECURE;
! 1611: }
! 1612: }
! 1613: }
! 1614:
! 1615: /* Finally, check that there's no seat of wildcard synthesis */
! 1616: if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
! 1617: return STAT_BOGUS;
! 1618:
! 1619: wildcard--;
! 1620: *wildcard = '*';
! 1621:
! 1622: if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
! 1623: return STAT_BOGUS;
! 1624:
! 1625: for (i = 0; i < nsec_count; i++)
! 1626: if ((p = nsecs[i]))
! 1627: {
! 1628: if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
! 1629: !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
! 1630: return STAT_BOGUS;
! 1631:
! 1632: p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
! 1633: hash_len = *p++; /* p now points to next hashed name */
! 1634:
! 1635: if (!CHECK_LEN(header, p, plen, hash_len))
! 1636: return STAT_BOGUS;
! 1637:
! 1638: if (digest_len == base32_len && hash_len == base32_len)
! 1639: {
! 1640: if (memcmp(workspace2, digest, digest_len) <= 0)
! 1641: {
! 1642: /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
! 1643: wrap around case, name-hash falls between NSEC3 name-hash and end */
! 1644: if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
! 1645: return STAT_SECURE;
! 1646: }
! 1647: else
! 1648: {
! 1649: /* wrap around case, name falls between start and next domain name */
! 1650: if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
! 1651: return STAT_SECURE;
! 1652: }
! 1653: }
! 1654: }
! 1655:
! 1656: return STAT_BOGUS;
! 1657: }
! 1658:
! 1659: /* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
! 1660: /* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
! 1661: int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer)
! 1662: {
! 1663: unsigned char *ans_start, *qname, *p1, *p2, **nsecs;
! 1664: int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype;
! 1665: int i, j, rc, nsec_count, cname_count = CNAME_CHAIN;
! 1666: int nsec_type = 0, have_answer = 0;
! 1667:
! 1668: if (neganswer)
! 1669: *neganswer = 0;
! 1670:
! 1671: if (RCODE(header) == SERVFAIL || ntohs(header->qdcount) != 1)
! 1672: return STAT_BOGUS;
! 1673:
! 1674: if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
! 1675: return STAT_INSECURE;
! 1676:
! 1677: qname = p1 = (unsigned char *)(header+1);
! 1678:
! 1679: if (!extract_name(header, plen, &p1, name, 1, 4))
! 1680: return STAT_BOGUS;
! 1681:
! 1682: GETSHORT(qtype, p1);
! 1683: GETSHORT(qclass, p1);
! 1684: ans_start = p1;
! 1685:
! 1686: if (qtype == T_ANY)
! 1687: have_answer = 1;
! 1688:
! 1689: /* Can't validate an RRISG query */
! 1690: if (qtype == T_RRSIG)
! 1691: return STAT_INSECURE;
! 1692:
! 1693: cname_loop:
! 1694: for (j = ntohs(header->ancount); j != 0; j--)
! 1695: {
! 1696: /* leave pointer to missing name in qname */
! 1697:
! 1698: if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
! 1699: return STAT_BOGUS; /* bad packet */
! 1700:
! 1701: GETSHORT(type2, p1);
! 1702: GETSHORT(class2, p1);
! 1703: p1 += 4; /* TTL */
! 1704: GETSHORT(rdlen2, p1);
! 1705:
! 1706: if (rc == 1 && qclass == class2)
! 1707: {
! 1708: /* Do we have an answer for the question? */
! 1709: if (type2 == qtype)
! 1710: {
! 1711: have_answer = 1;
! 1712: break;
! 1713: }
! 1714: else if (type2 == T_CNAME)
! 1715: {
! 1716: qname = p1;
! 1717:
! 1718: /* looped CNAMES */
! 1719: if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
! 1720: return STAT_BOGUS;
! 1721:
! 1722: p1 = ans_start;
! 1723: goto cname_loop;
! 1724: }
! 1725: }
! 1726:
! 1727: if (!ADD_RDLEN(header, p1, plen, rdlen2))
! 1728: return STAT_BOGUS;
! 1729: }
! 1730:
! 1731: if (neganswer && !have_answer)
! 1732: *neganswer = 1;
! 1733:
! 1734: /* No data, therefore no sigs */
! 1735: if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
! 1736: return STAT_NO_SIG;
! 1737:
! 1738: for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
! 1739: {
! 1740: if (!extract_name(header, plen, &p1, name, 1, 10))
! 1741: return STAT_BOGUS; /* bad packet */
! 1742:
! 1743: GETSHORT(type1, p1);
! 1744: GETSHORT(class1, p1);
! 1745: p1 += 4; /* TTL */
! 1746: GETSHORT(rdlen1, p1);
! 1747:
! 1748: /* Don't try and validate RRSIGs! */
! 1749: if (type1 != T_RRSIG)
! 1750: {
! 1751: /* Check if we've done this RRset already */
! 1752: for (p2 = ans_start, j = 0; j < i; j++)
! 1753: {
! 1754: if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
! 1755: return STAT_BOGUS; /* bad packet */
! 1756:
! 1757: GETSHORT(type2, p2);
! 1758: GETSHORT(class2, p2);
! 1759: p2 += 4; /* TTL */
! 1760: GETSHORT(rdlen2, p2);
! 1761:
! 1762: if (type2 == type1 && class2 == class1 && rc == 1)
! 1763: break; /* Done it before: name, type, class all match. */
! 1764:
! 1765: if (!ADD_RDLEN(header, p2, plen, rdlen2))
! 1766: return STAT_BOGUS;
! 1767: }
! 1768:
! 1769: /* Not done, validate now */
! 1770: if (j == i)
! 1771: {
! 1772: int ttl, keytag, algo, digest, type_covered;
! 1773: unsigned char *psave;
! 1774: struct all_addr a;
! 1775: struct blockdata *key;
! 1776: struct crec *crecp;
! 1777:
! 1778: rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0);
! 1779:
! 1780: if (rc == STAT_SECURE_WILDCARD)
! 1781: {
! 1782: /* An attacker replay a wildcard answer with a different
! 1783: answer and overlay a genuine RR. To prove this
! 1784: hasn't happened, the answer must prove that
! 1785: the gennuine record doesn't exist. Check that here. */
! 1786: if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
! 1787: return STAT_BOGUS; /* No NSECs or bad packet */
! 1788:
! 1789: if (nsec_type == T_NSEC)
! 1790: rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
! 1791: else
! 1792: rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
! 1793:
! 1794: if (rc != STAT_SECURE)
! 1795: return rc;
! 1796: }
! 1797: else if (rc != STAT_SECURE)
! 1798: {
! 1799: if (class)
! 1800: *class = class1; /* Class for DS or DNSKEY */
! 1801: return rc;
! 1802: }
! 1803:
! 1804: /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
! 1805: cache_start_insert();
! 1806:
! 1807: for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
! 1808: {
! 1809: if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
! 1810: return STAT_BOGUS; /* bad packet */
! 1811:
! 1812: GETSHORT(type2, p2);
! 1813: GETSHORT(class2, p2);
! 1814: GETLONG(ttl, p2);
! 1815: GETSHORT(rdlen2, p2);
! 1816:
! 1817: if (!CHECK_LEN(header, p2, plen, rdlen2))
! 1818: return STAT_BOGUS; /* bad packet */
! 1819:
! 1820: if (class2 == class1 && rc == 1)
! 1821: {
! 1822: psave = p2;
! 1823:
! 1824: if (type1 == T_DS && type2 == T_DS)
! 1825: {
! 1826: if (rdlen2 < 4)
! 1827: return STAT_BOGUS; /* bad packet */
! 1828:
! 1829: GETSHORT(keytag, p2);
! 1830: algo = *p2++;
! 1831: digest = *p2++;
! 1832:
! 1833: /* Cache needs to known class for DNSSEC stuff */
! 1834: a.addr.dnssec.class = class2;
! 1835:
! 1836: if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
! 1837: {
! 1838: if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
! 1839: blockdata_free(key);
! 1840: else
! 1841: {
! 1842: a.addr.keytag = keytag;
! 1843: log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
! 1844: crecp->addr.ds.digest = digest;
! 1845: crecp->addr.ds.keydata = key;
! 1846: crecp->addr.ds.algo = algo;
! 1847: crecp->addr.ds.keytag = keytag;
! 1848: crecp->addr.ds.keylen = rdlen2 - 4;
! 1849: }
! 1850: }
! 1851: }
! 1852: else if (type2 == T_RRSIG)
! 1853: {
! 1854: if (rdlen2 < 18)
! 1855: return STAT_BOGUS; /* bad packet */
! 1856:
! 1857: GETSHORT(type_covered, p2);
! 1858:
! 1859: if (type_covered == type1 &&
! 1860: (type_covered == T_A || type_covered == T_AAAA ||
! 1861: type_covered == T_CNAME || type_covered == T_DS ||
! 1862: type_covered == T_DNSKEY || type_covered == T_PTR))
! 1863: {
! 1864: a.addr.dnssec.type = type_covered;
! 1865: a.addr.dnssec.class = class1;
! 1866:
! 1867: algo = *p2++;
! 1868: p2 += 13; /* labels, orig_ttl, expiration, inception */
! 1869: GETSHORT(keytag, p2);
! 1870:
! 1871: if ((key = blockdata_alloc((char*)psave, rdlen2)))
! 1872: {
! 1873: if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
! 1874: blockdata_free(key);
! 1875: else
! 1876: {
! 1877: crecp->addr.sig.keydata = key;
! 1878: crecp->addr.sig.keylen = rdlen2;
! 1879: crecp->addr.sig.keytag = keytag;
! 1880: crecp->addr.sig.type_covered = type_covered;
! 1881: crecp->addr.sig.algo = algo;
! 1882: }
! 1883: }
! 1884: }
! 1885: }
! 1886:
! 1887: p2 = psave;
! 1888: }
! 1889:
! 1890: if (!ADD_RDLEN(header, p2, plen, rdlen2))
! 1891: return STAT_BOGUS; /* bad packet */
! 1892: }
! 1893:
! 1894: cache_end_insert();
! 1895: }
! 1896: }
! 1897:
! 1898: if (!ADD_RDLEN(header, p1, plen, rdlen1))
! 1899: return STAT_BOGUS;
! 1900: }
! 1901:
! 1902: /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
! 1903: if (have_answer)
! 1904: return STAT_SECURE;
! 1905:
! 1906: /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
! 1907: /* First marshall the NSEC records, if we've not done it previously */
! 1908: if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
! 1909: return STAT_BOGUS; /* No NSECs */
! 1910:
! 1911: /* Get name of missing answer */
! 1912: if (!extract_name(header, plen, &qname, name, 1, 0))
! 1913: return STAT_BOGUS;
! 1914:
! 1915: if (nsec_type == T_NSEC)
! 1916: return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
! 1917: else
! 1918: return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
! 1919: }
! 1920:
! 1921: /* Chase the CNAME chain in the packet until the first record which _doesn't validate.
! 1922: Needed for proving answer in unsigned space.
! 1923: Return STAT_NEED_*
! 1924: STAT_BOGUS - error
! 1925: STAT_INSECURE - name of first non-secure record in name
! 1926: */
! 1927: int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
! 1928: {
! 1929: unsigned char *p = (unsigned char *)(header+1);
! 1930: int type, class, qclass, rdlen, j, rc;
! 1931: int cname_count = CNAME_CHAIN;
! 1932:
! 1933: /* Get question */
! 1934: if (!extract_name(header, plen, &p, name, 1, 4))
! 1935: return STAT_BOGUS;
! 1936:
! 1937: p +=2; /* type */
! 1938: GETSHORT(qclass, p);
! 1939:
! 1940: while (1)
! 1941: {
! 1942: for (j = ntohs(header->ancount); j != 0; j--)
! 1943: {
! 1944: if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
! 1945: return STAT_BOGUS; /* bad packet */
! 1946:
! 1947: GETSHORT(type, p);
! 1948: GETSHORT(class, p);
! 1949: p += 4; /* TTL */
! 1950: GETSHORT(rdlen, p);
! 1951:
! 1952: /* Not target, loop */
! 1953: if (rc == 2 || qclass != class)
! 1954: {
! 1955: if (!ADD_RDLEN(header, p, plen, rdlen))
! 1956: return STAT_BOGUS;
! 1957: continue;
! 1958: }
! 1959:
! 1960: /* Got to end of CNAME chain. */
! 1961: if (type != T_CNAME)
! 1962: return STAT_INSECURE;
! 1963:
! 1964: /* validate CNAME chain, return if insecure or need more data */
! 1965: rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0);
! 1966: if (rc != STAT_SECURE)
! 1967: {
! 1968: if (rc == STAT_NO_SIG)
! 1969: rc = STAT_INSECURE;
! 1970: return rc;
! 1971: }
! 1972:
! 1973: /* Loop down CNAME chain/ */
! 1974: if (!cname_count-- ||
! 1975: !extract_name(header, plen, &p, name, 1, 0) ||
! 1976: !(p = skip_questions(header, plen)))
! 1977: return STAT_BOGUS;
! 1978:
! 1979: break;
! 1980: }
! 1981:
! 1982: /* End of CNAME chain */
! 1983: return STAT_INSECURE;
! 1984: }
! 1985: }
! 1986:
! 1987:
! 1988: /* Compute keytag (checksum to quickly index a key). See RFC4034 */
! 1989: int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
! 1990: {
! 1991: if (alg == 1)
! 1992: {
! 1993: /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
! 1994: See RFC4034, Appendix B.1 */
! 1995: return key[keylen-4] * 256 + key[keylen-3];
! 1996: }
! 1997: else
! 1998: {
! 1999: unsigned long ac = flags + 0x300 + alg;
! 2000: int i;
! 2001:
! 2002: for (i = 0; i < keylen; ++i)
! 2003: ac += (i & 1) ? key[i] : key[i] << 8;
! 2004:
! 2005: ac += (ac >> 16) & 0xffff;
! 2006: return ac & 0xffff;
! 2007: }
! 2008: }
! 2009:
! 2010: size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
! 2011: {
! 2012: unsigned char *p;
! 2013: char *types = querystr("dnssec-query", type);
! 2014:
! 2015: if (addr->sa.sa_family == AF_INET)
! 2016: log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
! 2017: #ifdef HAVE_IPV6
! 2018: else
! 2019: log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
! 2020: #endif
! 2021:
! 2022: header->qdcount = htons(1);
! 2023: header->ancount = htons(0);
! 2024: header->nscount = htons(0);
! 2025: header->arcount = htons(0);
! 2026:
! 2027: header->hb3 = HB3_RD;
! 2028: SET_OPCODE(header, QUERY);
! 2029: /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
! 2030: this allows it to select auth servers when one is returning bad data. */
! 2031: header->hb4 = option_bool(OPT_DNSSEC_DEBUG) ? HB4_CD : 0;
! 2032:
! 2033: /* ID filled in later */
! 2034:
! 2035: p = (unsigned char *)(header+1);
! 2036:
! 2037: p = do_rfc1035_name(p, name);
! 2038: *p++ = 0;
! 2039: PUTSHORT(type, p);
! 2040: PUTSHORT(class, p);
! 2041:
! 2042: return add_do_bit(header, p - (unsigned char *)header, end);
! 2043: }
! 2044:
! 2045: /* Go through a domain name, find "pointers" and fix them up based on how many bytes
! 2046: we've chopped out of the packet, or check they don't point into an elided part. */
! 2047: static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
! 2048: {
! 2049: unsigned char *ansp = *namep;
! 2050:
! 2051: while(1)
! 2052: {
! 2053: unsigned int label_type;
! 2054:
! 2055: if (!CHECK_LEN(header, ansp, plen, 1))
! 2056: return 0;
! 2057:
! 2058: label_type = (*ansp) & 0xc0;
! 2059:
! 2060: if (label_type == 0xc0)
! 2061: {
! 2062: /* pointer for compression. */
! 2063: unsigned int offset;
! 2064: int i;
! 2065: unsigned char *p;
! 2066:
! 2067: if (!CHECK_LEN(header, ansp, plen, 2))
! 2068: return 0;
! 2069:
! 2070: offset = ((*ansp++) & 0x3f) << 8;
! 2071: offset |= *ansp++;
! 2072:
! 2073: p = offset + (unsigned char *)header;
! 2074:
! 2075: for (i = 0; i < rr_count; i++)
! 2076: if (p < rrs[i])
! 2077: break;
! 2078: else
! 2079: if (i & 1)
! 2080: offset -= rrs[i] - rrs[i-1];
! 2081:
! 2082: /* does the pointer end up in an elided RR? */
! 2083: if (i & 1)
! 2084: return 0;
! 2085:
! 2086: /* No, scale the pointer */
! 2087: if (fixup)
! 2088: {
! 2089: ansp -= 2;
! 2090: *ansp++ = (offset >> 8) | 0xc0;
! 2091: *ansp++ = offset & 0xff;
! 2092: }
! 2093: break;
! 2094: }
! 2095: else if (label_type == 0x80)
! 2096: return 0; /* reserved */
! 2097: else if (label_type == 0x40)
! 2098: {
! 2099: /* Extended label type */
! 2100: unsigned int count;
! 2101:
! 2102: if (!CHECK_LEN(header, ansp, plen, 2))
! 2103: return 0;
! 2104:
! 2105: if (((*ansp++) & 0x3f) != 1)
! 2106: return 0; /* we only understand bitstrings */
! 2107:
! 2108: count = *(ansp++); /* Bits in bitstring */
! 2109:
! 2110: if (count == 0) /* count == 0 means 256 bits */
! 2111: ansp += 32;
! 2112: else
! 2113: ansp += ((count-1)>>3)+1;
! 2114: }
! 2115: else
! 2116: { /* label type == 0 Bottom six bits is length */
! 2117: unsigned int len = (*ansp++) & 0x3f;
! 2118:
! 2119: if (!ADD_RDLEN(header, ansp, plen, len))
! 2120: return 0;
! 2121:
! 2122: if (len == 0)
! 2123: break; /* zero length label marks the end. */
! 2124: }
! 2125: }
! 2126:
! 2127: *namep = ansp;
! 2128:
! 2129: return 1;
! 2130: }
! 2131:
! 2132: /* Go through RRs and check or fixup the domain names contained within */
! 2133: static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
! 2134: {
! 2135: int i, type, class, rdlen;
! 2136: unsigned char *pp;
! 2137:
! 2138: for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
! 2139: {
! 2140: pp = p;
! 2141:
! 2142: if (!(p = skip_name(p, header, plen, 10)))
! 2143: return 0;
! 2144:
! 2145: GETSHORT(type, p);
! 2146: GETSHORT(class, p);
! 2147: p += 4; /* TTL */
! 2148: GETSHORT(rdlen, p);
! 2149:
! 2150: if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
! 2151: {
! 2152: /* fixup name of RR */
! 2153: if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
! 2154: return 0;
! 2155:
! 2156: if (class == C_IN)
! 2157: {
! 2158: u16 *d;
! 2159:
! 2160: for (pp = p, d = get_desc(type); *d != (u16)-1; d++)
! 2161: {
! 2162: if (*d != 0)
! 2163: pp += *d;
! 2164: else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
! 2165: return 0;
! 2166: }
! 2167: }
! 2168: }
! 2169:
! 2170: if (!ADD_RDLEN(header, p, plen, rdlen))
! 2171: return 0;
! 2172: }
! 2173:
! 2174: return 1;
! 2175: }
! 2176:
! 2177:
! 2178: size_t filter_rrsigs(struct dns_header *header, size_t plen)
! 2179: {
! 2180: static unsigned char **rrs;
! 2181: static int rr_sz = 0;
! 2182:
! 2183: unsigned char *p = (unsigned char *)(header+1);
! 2184: int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
! 2185:
! 2186: if (ntohs(header->qdcount) != 1 ||
! 2187: !(p = skip_name(p, header, plen, 4)))
! 2188: return plen;
! 2189:
! 2190: GETSHORT(qtype, p);
! 2191: GETSHORT(qclass, p);
! 2192:
! 2193: /* First pass, find pointers to start and end of all the records we wish to elide:
! 2194: records added for DNSSEC, unless explicity queried for */
! 2195: for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
! 2196: i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
! 2197: i++)
! 2198: {
! 2199: unsigned char *pstart = p;
! 2200: int type, class;
! 2201:
! 2202: if (!(p = skip_name(p, header, plen, 10)))
! 2203: return plen;
! 2204:
! 2205: GETSHORT(type, p);
! 2206: GETSHORT(class, p);
! 2207: p += 4; /* TTL */
! 2208: GETSHORT(rdlen, p);
! 2209:
! 2210: if ((type == T_NSEC || type == T_NSEC3 || type == T_RRSIG) &&
! 2211: (type != qtype || class != qclass))
! 2212: {
! 2213: if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
! 2214: return plen;
! 2215:
! 2216: rrs[rr_found++] = pstart;
! 2217:
! 2218: if (!ADD_RDLEN(header, p, plen, rdlen))
! 2219: return plen;
! 2220:
! 2221: rrs[rr_found++] = p;
! 2222:
! 2223: if (i < ntohs(header->ancount))
! 2224: chop_an++;
! 2225: else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
! 2226: chop_ns++;
! 2227: else
! 2228: chop_ar++;
! 2229: }
! 2230: else if (!ADD_RDLEN(header, p, plen, rdlen))
! 2231: return plen;
! 2232: }
! 2233:
! 2234: /* Nothing to do. */
! 2235: if (rr_found == 0)
! 2236: return plen;
! 2237:
! 2238: /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
! 2239: point to records we're going to elide. This is theoretically possible, but unlikely. If
! 2240: it happens, we give up and leave the answer unchanged. */
! 2241: p = (unsigned char *)(header+1);
! 2242:
! 2243: /* question first */
! 2244: if (!check_name(&p, header, plen, 0, rrs, rr_found))
! 2245: return plen;
! 2246: p += 4; /* qclass, qtype */
! 2247:
! 2248: /* Now answers and NS */
! 2249: if (!check_rrs(p, header, plen, 0, rrs, rr_found))
! 2250: return plen;
! 2251:
! 2252: /* Third pass, elide records */
! 2253: for (p = rrs[0], i = 1; i < rr_found; i += 2)
! 2254: {
! 2255: unsigned char *start = rrs[i];
! 2256: unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
! 2257:
! 2258: memmove(p, start, end-start);
! 2259: p += end-start;
! 2260: }
! 2261:
! 2262: plen = p - (unsigned char *)header;
! 2263: header->ancount = htons(ntohs(header->ancount) - chop_an);
! 2264: header->nscount = htons(ntohs(header->nscount) - chop_ns);
! 2265: header->arcount = htons(ntohs(header->arcount) - chop_ar);
! 2266:
! 2267: /* Fourth pass, fix up pointers in the remaining records */
! 2268: p = (unsigned char *)(header+1);
! 2269:
! 2270: check_name(&p, header, plen, 1, rrs, rr_found);
! 2271: p += 4; /* qclass, qtype */
! 2272:
! 2273: check_rrs(p, header, plen, 1, rrs, rr_found);
! 2274:
! 2275: return plen;
! 2276: }
! 2277:
! 2278: unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
! 2279: {
! 2280: int q;
! 2281: unsigned int len;
! 2282: unsigned char *p = (unsigned char *)(header+1);
! 2283: const struct nettle_hash *hash;
! 2284: void *ctx;
! 2285: unsigned char *digest;
! 2286:
! 2287: if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
! 2288: return NULL;
! 2289:
! 2290: for (q = ntohs(header->qdcount); q != 0; q--)
! 2291: {
! 2292: if (!extract_name(header, plen, &p, name, 1, 4))
! 2293: break; /* bad packet */
! 2294:
! 2295: len = to_wire(name);
! 2296: hash->update(ctx, len, (unsigned char *)name);
! 2297: /* CRC the class and type as well */
! 2298: hash->update(ctx, 4, p);
! 2299:
! 2300: p += 4;
! 2301: if (!CHECK_LEN(header, p, plen, 0))
! 2302: break; /* bad packet */
! 2303: }
! 2304:
! 2305: hash->digest(ctx, hash->digest_size, digest);
! 2306: return digest;
! 2307: }
! 2308:
! 2309: #endif /* HAVE_DNSSEC */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>