1 From 9a31b68b59adcac01016d4026d906b69c4216c01 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Tue, 15 Dec 2015 10:20:39 +0000
4 Subject: [PATCH] Major rationalisation of DNSSEC validation.
6 Much gnarly special-case code removed and replaced with correct
7 general implementaion. Checking of zone-status moved to DNSSEC code,
8 where it should be, vastly simplifying query-forwarding code.
11 src/dnssec.c | 926 ++++++++++++++++++++++++++++++---------------------------
12 src/forward.c | 741 ++++++++++-----------------------------------
13 3 files changed, 653 insertions(+), 1033 deletions(-)
15 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
16 index f42acdb..023a1cf 100644
19 @@ -586,12 +586,8 @@ struct hostsfile {
20 #define STAT_NEED_KEY 5
21 #define STAT_TRUNCATED 6
22 #define STAT_SECURE_WILDCARD 7
23 -#define STAT_NO_SIG 8
25 -#define STAT_NO_NS 10
26 -#define STAT_NEED_DS_NEG 11
27 -#define STAT_CHASE_CNAME 12
28 -#define STAT_INSECURE_DS 13
30 +#define STAT_ABANDONED 9
32 #define FREC_NOREBIND 1
33 #define FREC_CHECKING_DISABLED 2
34 @@ -601,8 +597,7 @@ struct hostsfile {
35 #define FREC_AD_QUESTION 32
36 #define FREC_DO_QUESTION 64
37 #define FREC_ADDED_PHEADER 128
38 -#define FREC_CHECK_NOSIGN 256
39 -#define FREC_TEST_PKTSZ 512
40 +#define FREC_TEST_PKTSZ 256
43 #define HASH_SIZE 20 /* SHA-1 digest size */
44 @@ -626,9 +621,7 @@ struct frec {
46 int class, work_counter;
47 struct blockdata *stash; /* Saved reply, whilst we validate */
48 - struct blockdata *orig_domain; /* domain of original query, whilst
49 - we're seeing is if in unsigned domain */
50 - size_t stash_len, name_start, name_len;
52 struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
53 struct frec *blocking_query; /* Query which is blocking us. */
55 @@ -1162,8 +1155,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
56 size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
57 int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
58 int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
59 -int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer, int *nons);
60 -int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
61 +int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
62 + int check_unsigned, int *neganswer, int *nons);
63 int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
64 size_t filter_rrsigs(struct dns_header *header, size_t plen);
65 unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
66 diff --git a/src/dnssec.c b/src/dnssec.c
67 index b4dc14e..de7b335 100644
70 @@ -65,8 +65,10 @@ static char *algo_digest_name(int algo)
71 case 8: return "sha256";
72 case 10: return "sha512";
73 case 12: return "gosthash94";
74 +#ifndef NO_NETTLE_ECC
75 case 13: return "sha256";
76 case 14: return "sha384";
81 @@ -592,30 +594,30 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
85 -static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
86 +static int expand_workspace(unsigned char ***wkspc, int *szp, int new)
103 - if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
104 + if (!(p = whine_malloc(new * sizeof(unsigned char **))))
108 + if (old != 0 && *wkspc)
110 - memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
111 + memcpy(p, *wkspc, old * sizeof(unsigned char **));
121 @@ -706,47 +708,28 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
125 -/* Validate a single RRset (class, type, name) in the supplied DNS reply
127 - STAT_SECURE if it validates.
128 - STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
129 - (In this case *wildcard_out points to the "body" of the wildcard within name.)
130 - STAT_NO_SIG no RRsigs found.
131 - STAT_INSECURE RRset empty.
132 - STAT_BOGUS signature is wrong, bad packet.
133 - STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
135 - if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
136 - otherwise find the key in the cache.
137 +static unsigned char **rrset = NULL, **sigs = NULL;
139 - name is unchanged on exit. keyname is used as workspace and trashed.
141 -static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type,
142 - char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in)
143 +/* Get pointers to RRset menbers and signature(s) for same.
144 + Check signatures, and return keyname associated in keyname. */
145 +static int explore_rrset(struct dns_header *header, size_t plen, int class, int type,
146 + char *name, char *keyname, int *sigcnt, int *rrcnt)
148 - static unsigned char **rrset = NULL, **sigs = NULL;
149 - static int rrset_sz = 0, sig_sz = 0;
151 + static int rrset_sz = 0, sig_sz = 0;
153 - int rrsetidx, sigidx, res, rdlen, j, name_labels;
154 - struct crec *crecp = NULL;
155 - int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
156 - u16 *rr_desc = get_desc(type);
159 - *wildcard_out = NULL;
161 + int rrsetidx, sigidx, j, rdlen, res;
162 + int name_labels = count_labels(name); /* For 4035 5.3.2 check */
165 if (!(p = skip_questions(header, plen)))
168 - name_labels = count_labels(name); /* For 4035 5.3.2 check */
170 - /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
171 + /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
172 for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
175 unsigned char *pstart, *pdata;
177 + int stype, sclass, algo, type_covered, labels, sig_expiration, sig_inception;
181 @@ -762,14 +745,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
184 if (!CHECK_LEN(header, p, plen, rdlen))
188 if (res == 1 && sclass == class)
192 if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
196 rrset[rrsetidx++] = pstart;
198 @@ -777,14 +760,54 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
199 if (stype == T_RRSIG)
202 - return STAT_BOGUS; /* bad packet */
203 + return 0; /* bad packet */
205 GETSHORT(type_covered, p);
208 + p += 4; /* orig_ttl */
209 + GETLONG(sig_expiration, p);
210 + GETLONG(sig_inception, p);
211 + p += 2; /* key_tag */
213 - if (type_covered == type)
216 + /* If there's more than one SIG, ensure they all have same keyname */
217 + if (extract_name(header, plen, &p, keyname, 0, 0) != 1)
224 + if (!extract_name(header, plen, &p, keyname, 1, 0))
227 + /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
228 + the name of the zone containing the RRset. We can't tell that
229 + for certain, but we can check that the RRset name is equal to
230 + or encloses the signers name, which should be enough to stop
231 + an attacker using signatures made with the key of an unrelated
232 + zone he controls. Note that the root key is always allowed. */
236 + for (name_start = name; !hostname_isequal(name_start, keyname); )
237 + if ((name_start = strchr(name_start, '.')))
238 + name_start++; /* chop a label off and try again */
244 + /* Don't count signatures for algos we don't support */
245 + if (check_date_range(sig_inception, sig_expiration) &&
246 + labels <= name_labels &&
247 + type_covered == type &&
248 + algo_digest_name(algo))
250 if (!expand_workspace(&sigs, &sig_sz, sigidx))
254 sigs[sigidx++] = pdata;
256 @@ -794,17 +817,45 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
259 if (!ADD_RDLEN(header, p, plen, rdlen))
266 - return STAT_INSECURE;
273 +/* Validate a single RRset (class, type, name) in the supplied DNS reply
275 + STAT_SECURE if it validates.
276 + STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
277 + (In this case *wildcard_out points to the "body" of the wildcard within name.)
278 + STAT_BOGUS signature is wrong, bad packet.
279 + STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
280 + STAT_NEED_DS need DS to complete validation (name is returned in keyname)
282 + if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
283 + otherwise find the key in the cache.
287 - return STAT_NO_SIG;
288 + name is unchanged on exit. keyname is used as workspace and trashed.
290 + Call explore_rrset first to find and count RRs and sigs.
292 +static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, int sigidx, int rrsetidx,
293 + char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in)
296 + int rdlen, j, name_labels;
297 + struct crec *crecp = NULL;
298 + int algo, labels, orig_ttl, key_tag;
299 + u16 *rr_desc = get_desc(type);
302 + *wildcard_out = NULL;
304 + name_labels = count_labels(name); /* For 4035 5.3.2 check */
306 /* Sort RRset records into canonical order.
307 Note that at this point keyname and daemon->workspacename buffs are
308 unused, and used as workspace by the sort. */
309 @@ -828,44 +879,16 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
312 GETLONG(orig_ttl, p);
313 - GETLONG(sig_expiration, p);
314 - GETLONG(sig_inception, p);
315 + p += 8; /* sig_expiration, sig_inception already checked */
316 GETSHORT(key_tag, p);
318 if (!extract_name(header, plen, &p, keyname, 1, 0))
321 - /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
322 - the name of the zone containing the RRset. We can't tell that
323 - for certain, but we can check that the RRset name is equal to
324 - or encloses the signers name, which should be enough to stop
325 - an attacker using signatures made with the key of an unrelated
326 - zone he controls. Note that the root key is always allowed. */
331 - for (name_start = name; !hostname_isequal(name_start, keyname); )
332 - if ((name_start = strchr(name_start, '.')))
333 - name_start++; /* chop a label off and try again */
340 - /* Bad sig, try another */
345 - /* Other 5.3.1 checks */
346 - if (!check_date_range(sig_inception, sig_expiration) ||
347 - labels > name_labels ||
348 - !(hash = hash_find(algo_digest_name(algo))) ||
349 + if (!(hash = hash_find(algo_digest_name(algo))) ||
350 !hash_init(hash, &ctx, &digest))
354 /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
355 if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
356 return STAT_NEED_KEY;
357 @@ -971,10 +994,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
358 /* The DNS packet is expected to contain the answer to a DNSKEY query.
359 Put all DNSKEYs in the answer which are valid into the cache.
361 - STAT_SECURE At least one valid DNSKEY found and in cache.
362 - STAT_BOGUS No DNSKEYs found, which can be validated with DS,
363 - or self-sign for DNSKEY RRset is not valid, bad packet.
364 - STAT_NEED_DS DS records to validate a key not found, name in keyname
365 + STAT_OK Done, key(s) in cache.
366 + STAT_BOGUS No DNSKEYs found, which can be validated with DS,
367 + or self-sign for DNSKEY RRset is not valid, bad packet.
368 + STAT_NEED_DS DS records to validate a key not found, name in keyname
369 + STAT_NEED_DNSKEY DNSKEY records to validate a key not found, name in keyname
371 int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
373 @@ -1001,23 +1025,6 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
377 - /* If we've cached that DS provably doesn't exist, result must be INSECURE */
378 - if (crecp->flags & F_NEG)
379 - return STAT_INSECURE_DS;
382 - If the validator does not support any of the algorithms listed in an
383 - authenticated DS RRset, then the resolver has no supported
384 - authentication path leading from the parent to the child. The
385 - resolver should treat this case as it would the case of an
386 - authenticated NSEC RRset proving that no DS RRset exists, */
387 - for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
388 - if (hash_find(ds_digest_name(recp1->addr.ds.digest)))
392 - return STAT_INSECURE_DS;
394 /* NOTE, we need to find ONE DNSKEY which matches the DS */
395 for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
397 @@ -1070,7 +1077,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
399 unsigned char *digest, *ds_digest;
400 const struct nettle_hash *hash;
404 if (recp1->addr.ds.algo == algo &&
405 recp1->addr.ds.keytag == keytag &&
406 recp1->uid == (unsigned int)class &&
407 @@ -1088,10 +1096,14 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
411 - if (recp1->addr.ds.keylen == (int)hash->digest_size &&
412 + if (!(recp1->flags & F_NEG) &&
413 + recp1->addr.ds.keylen == (int)hash->digest_size &&
414 (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
415 memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
416 - validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE)
417 + explore_rrset(header, plen, class, T_DNSKEY, name, keyname, &sigcnt, &rrcnt) &&
418 + sigcnt != 0 && rrcnt != 0 &&
419 + validate_rrset(now, header, plen, class, T_DNSKEY, sigcnt, rrcnt, name, keyname,
420 + NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE)
424 @@ -1112,7 +1124,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
426 /* Ensure we have type, class TTL and length */
427 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
428 - return STAT_INSECURE; /* bad packet */
429 + return STAT_BOGUS; /* bad packet */
433 @@ -1198,7 +1210,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
435 /* commit cache insert. */
437 - return STAT_SECURE;
441 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
442 @@ -1207,12 +1219,14 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
444 /* The DNS packet is expected to contain the answer to a DS query
445 Put all DSs in the answer which are valid into the cache.
446 + Also handles replies which prove that there's no DS at this location,
447 + either because the zone is unsigned or this isn't a zone cut. These are
450 - STAT_SECURE At least one valid DS found and in cache.
451 - STAT_NO_DS It's proved there's no DS here.
452 - STAT_NO_NS It's proved there's no DS _or_ NS here.
453 + STAT_OK At least one valid DS found and in cache.
454 STAT_BOGUS no DS in reply or not signed, fails validation, bad packet.
455 STAT_NEED_KEY DNSKEY records to validate a DS not found, name in keyname
456 + STAT_NEED_DS DS record needed.
459 int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
460 @@ -1230,7 +1244,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
461 if (qtype != T_DS || qclass != class)
464 - val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons);
465 + val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
466 /* Note dnssec_validate_reply() will have cached positive answers */
468 if (val == STAT_INSECURE)
469 @@ -1242,22 +1256,21 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
471 if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
474 - /* If we return STAT_NO_SIG, name contains the name of the DS query */
475 - if (val == STAT_NO_SIG)
478 /* If the key needed to validate the DS is on the same domain as the DS, we'll
479 loop getting nowhere. Stop that now. This can happen of the DS answer comes
480 from the DS's zone, and not the parent zone. */
481 - if (val == STAT_BOGUS || (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
482 + if (val == STAT_BOGUS || (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
484 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
488 + if (val != STAT_SECURE)
491 /* By here, the answer is proved secure, and a positive answer has been cached. */
492 - if (val == STAT_SECURE && neganswer)
495 int rdlen, flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
496 unsigned long ttl, minttl = ULONG_MAX;
497 @@ -1317,15 +1330,14 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
501 - log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS");
502 + log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS");
505 - return nons ? STAT_NO_NS : STAT_NO_DS;
514 static int hostname_cmp(const char *a, const char *b)
516 @@ -1452,7 +1464,7 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
517 int mask = 0x80 >> (type & 0x07);
523 /* Find NSEC record that proves name doesn't exist */
524 for (i = 0; i < nsec_count; i++)
525 @@ -1480,9 +1492,22 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
526 /* rdlen is now length of type map, and p points to it */
528 /* If we can prove that there's no NS record, return that information. */
529 - if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0)
531 + if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
534 + if (rdlen >= 2 && p[0] == 0)
536 + /* A CNAME answer would also be valid, so if there's a CNAME is should
537 + have been returned. */
538 + if ((p[2] & (0x80 >> T_CNAME)) != 0)
541 + /* If the SOA bit is set for a DS record, then we have the
542 + DS from the wrong side of the delegation. */
543 + if (type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
549 if (!CHECK_LEN(header, p, plen, rdlen))
550 @@ -1586,7 +1611,7 @@ static int base32_decode(char *in, unsigned char *out)
551 static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type,
552 char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons)
554 - int i, hash_len, salt_len, base32_len, rdlen;
555 + int i, hash_len, salt_len, base32_len, rdlen, flags;
556 unsigned char *p, *psave;
558 for (i = 0; i < nsec_count; i++)
559 @@ -1599,7 +1624,9 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
560 p += 8; /* class, type, TTL */
563 - p += 4; /* algo, flags, iterations */
565 + flags = *p++; /* flags */
566 + p += 2; /* iterations */
567 salt_len = *p++; /* salt_len */
568 p += salt_len; /* salt */
569 hash_len = *p++; /* p now points to next hashed name */
570 @@ -1626,16 +1653,29 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
573 /* If we can prove that there's no NS record, return that information. */
574 - if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0)
576 + if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
579 + if (rdlen >= 2 && p[0] == 0)
581 + /* A CNAME answer would also be valid, so if there's a CNAME is should
582 + have been returned. */
583 + if ((p[2] & (0x80 >> T_CNAME)) != 0)
586 + /* If the SOA bit is set for a DS record, then we have the
587 + DS from the wrong side of the delegation. */
588 + if (type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
594 if (p[0] == type >> 8)
596 /* Does the NSEC3 say our type exists? */
597 if (offset < p[1] && (p[offset+2] & mask) != 0)
601 break; /* finshed checking */
603 @@ -1643,7 +1683,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
612 @@ -1651,16 +1691,27 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
613 /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
614 wrap around case, name-hash falls between NSEC3 name-hash and end */
615 if (memcmp(p, digest, digest_len) >= 0 || memcmp(workspace2, p, digest_len) >= 0)
618 + if ((flags & 0x01) && nons) /* opt out */
626 /* wrap around case, name falls between start and next domain name */
627 if (memcmp(workspace2, p, digest_len) >= 0 && memcmp(p, digest, digest_len) >= 0)
630 + if ((flags & 0x01) && nons) /* opt out */
642 @@ -1673,7 +1724,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
643 char *closest_encloser, *next_closest, *wildcard;
649 /* Look though the NSEC3 records to find the first one with
650 an algorithm we support (currently only algo == 1).
651 @@ -1813,16 +1864,81 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
656 -/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
657 -/* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
659 +/* Check signing status of name.
661 + STAT_SECURE zone is signed.
662 + STAT_INSECURE zone proved unsigned.
663 + STAT_NEED_DS require DS record of name returned in keyname.
665 + name returned unaltered.
667 +static int zone_status(char *name, int class, char *keyname, time_t now)
669 + int name_start = strlen(name);
670 + struct crec *crecp;
675 + strcpy(keyname, &name[name_start]);
677 + if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS)))
678 + return STAT_NEED_DS;
682 + if (crecp->uid == (unsigned int)class)
684 + /* F_DNSSECOK misused in DS cache records to non-existance of NS record.
685 + F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here,
686 + but that's because there's no NS record either, ie this isn't the start
687 + of a zone. We only prove that the DNS tree below a node is unsigned when
688 + we prove that we're at a zone cut AND there's no DS record.
690 + if (crecp->flags & F_NEG)
692 + if (crecp->flags & F_DNSSECOK)
693 + return STAT_INSECURE; /* proved no DS here */
695 + else if (!ds_digest_name(crecp->addr.ds.digest) || !algo_digest_name(crecp->addr.ds.algo))
696 + return STAT_INSECURE; /* algo we can't use - insecure */
699 + while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
701 + if (name_start == 0)
704 + for (p = &name[name_start-2]; (*p != '.') && (p != name); p--);
709 + name_start = p - name;
712 + return STAT_SECURE;
715 +/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3)
717 + STAT_SECURE if it validates.
718 + STAT_INSECURE at least one RRset not validated, because in unsigned zone.
719 + STAT_BOGUS signature is wrong, bad packet, no validation where there should be.
720 + STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname, class in *class)
721 + STAT_NEED_DS need DS to complete validation (name is returned in keyname)
723 int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname,
724 - int *class, int *neganswer, int *nons)
725 + int *class, int check_unsigned, int *neganswer, int *nons)
727 - unsigned char *ans_start, *qname, *p1, *p2, **nsecs;
728 - int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype;
729 - int i, j, rc, nsec_count, cname_count = CNAME_CHAIN;
730 - int nsec_type = 0, have_answer = 0;
731 + static unsigned char **targets = NULL;
732 + static int target_sz = 0;
734 + unsigned char *ans_start, *p1, *p2, **nsecs;
735 + int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype, targetidx;
736 + int i, j, rc, nsec_count;
741 @@ -1833,70 +1949,51 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
742 if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
743 return STAT_INSECURE;
745 - qname = p1 = (unsigned char *)(header+1);
746 + p1 = (unsigned char *)(header+1);
748 + /* Find all the targets we're looking for answers to.
749 + The zeroth array element is for the query, subsequent ones
750 + for CNAME targets, unless the query is for a CNAME. */
752 + if (!expand_workspace(&targets, &target_sz, 0))
758 if (!extract_name(header, plen, &p1, name, 1, 4))
763 GETSHORT(qclass, p1);
766 - if (qtype == T_ANY)
769 - /* Can't validate an RRISG query */
770 + /* Can't validate an RRSIG query */
771 if (qtype == T_RRSIG)
772 return STAT_INSECURE;
775 - for (j = ntohs(header->ancount); j != 0; j--)
777 - /* leave pointer to missing name in qname */
779 - if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
780 - return STAT_BOGUS; /* bad packet */
782 - GETSHORT(type2, p1);
783 - GETSHORT(class2, p1);
785 - GETSHORT(rdlen2, p1);
787 - if (rc == 1 && qclass == class2)
789 - /* Do we have an answer for the question? */
790 - if (type2 == qtype)
795 - else if (type2 == T_CNAME)
799 - /* looped CNAMES */
800 - if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
808 - if (!ADD_RDLEN(header, p1, plen, rdlen2))
812 - if (neganswer && !have_answer)
815 - /* No data, therefore no sigs */
816 - if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
819 - return STAT_NO_SIG;
822 + if (qtype != T_CNAME)
823 + for (j = ntohs(header->ancount); j != 0; j--)
825 + if (!(p1 = skip_name(p1, header, plen, 10)))
826 + return STAT_BOGUS; /* bad packet */
828 + GETSHORT(type2, p1);
829 + p1 += 6; /* class, TTL */
830 + GETSHORT(rdlen2, p1);
832 + if (type2 == T_CNAME)
834 + if (!expand_workspace(&targets, &target_sz, targetidx))
837 + targets[targetidx++] = p1; /* pointer to target name */
840 + if (!ADD_RDLEN(header, p1, plen, rdlen2))
844 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
846 if (!extract_name(header, plen, &p1, name, 1, 10))
847 @@ -1931,7 +2028,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
848 /* Not done, validate now */
851 - int ttl, keytag, algo, digest, type_covered;
852 + int ttl, keytag, algo, digest, type_covered, sigcnt, rrcnt;
853 unsigned char *psave;
855 struct blockdata *key;
856 @@ -1939,143 +2036,186 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
858 int have_wildcard = 0;
860 - rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
862 - if (rc == STAT_SECURE_WILDCARD)
866 - /* An attacker replay a wildcard answer with a different
867 - answer and overlay a genuine RR. To prove this
868 - hasn't happened, the answer must prove that
869 - the gennuine record doesn't exist. Check that here. */
870 - if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
871 - return STAT_BOGUS; /* No NSECs or bad packet */
873 - if (nsec_type == T_NSEC)
874 - rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, NULL);
876 - rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
877 - keyname, name, type1, wildname, NULL);
879 - if (rc != STAT_SECURE)
882 - else if (rc != STAT_SECURE)
885 - *class = class1; /* Class for DS or DNSKEY */
886 + if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
889 - if (rc == STAT_NO_SIG)
890 + /* No signatures for RRset. We can be configured to assume this is OK and return a INSECURE result. */
893 + if (check_unsigned)
895 - /* If we dropped off the end of a CNAME chain, return
896 - STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
897 - if DS records in CNAME chains. */
898 - if (cname_count == CNAME_CHAIN || i < ntohs(header->ancount))
899 - /* No CNAME chain, or no sig in answer section, return empty name. */
901 - else if (!extract_name(header, plen, &qname, keyname, 1, 0))
903 + rc = zone_status(name, class1, keyname, now);
904 + if (rc == STAT_SECURE)
907 + *class = class1; /* Class for NEED_DS or NEED_DNSKEY */
911 + rc = STAT_INSECURE;
916 - /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
917 - cache_start_insert();
918 + /* explore_rrset() gives us key name from sigs in keyname.
919 + Can't overwrite name here. */
920 + strcpy(daemon->workspacename, keyname);
921 + rc = zone_status(daemon->workspacename, class1, keyname, now);
922 + if (rc != STAT_SECURE)
924 + /* Zone is insecure, don't need to validate RRset */
926 + *class = class1; /* Class for NEED_DS or NEED_DNSKEY */
930 + rc = validate_rrset(now, header, plen, class1, type1, sigcnt, rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
932 - for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
933 + if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
935 - if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
936 - return STAT_BOGUS; /* bad packet */
938 + *class = class1; /* Class for DS or DNSKEY */
943 + /* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
945 + /* Note if we've validated either the answer to the question
946 + or the target of a CNAME. Any not noted will need NSEC or
947 + to be in unsigned space. */
949 + for (j = 0; j <targetidx; j++)
950 + if ((p2 = targets[j]))
952 + if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
953 + return STAT_BOGUS; /* bad packet */
955 + if (class1 == qclass && rc == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
959 + if (rc == STAT_SECURE_WILDCARD)
963 - GETSHORT(type2, p2);
964 - GETSHORT(class2, p2);
966 - GETSHORT(rdlen2, p2);
968 - if (!CHECK_LEN(header, p2, plen, rdlen2))
969 - return STAT_BOGUS; /* bad packet */
971 - if (class2 == class1 && rc == 1)
974 + /* An attacker replay a wildcard answer with a different
975 + answer and overlay a genuine RR. To prove this
976 + hasn't happened, the answer must prove that
977 + the gennuine record doesn't exist. Check that here. */
978 + if (!(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
979 + return STAT_BOGUS; /* No NSECs or bad packet */
981 + /* Note that we may not yet have validated the NSEC/NSEC3 RRsets. Since the check
982 + below returns either SECURE or BOGUS, that's not a problem. If the RRsets later fail
983 + we'll return BOGUS then. */
985 - if (type1 == T_DS && type2 == T_DS)
988 - return STAT_BOGUS; /* bad packet */
990 - GETSHORT(keytag, p2);
994 - /* Cache needs to known class for DNSSEC stuff */
995 - a.addr.dnssec.class = class2;
997 - if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
999 - if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1000 - blockdata_free(key);
1003 - a.addr.keytag = keytag;
1004 - log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
1005 - crecp->addr.ds.digest = digest;
1006 - crecp->addr.ds.keydata = key;
1007 - crecp->addr.ds.algo = algo;
1008 - crecp->addr.ds.keytag = keytag;
1009 - crecp->addr.ds.keylen = rdlen2 - 4;
1013 - else if (type2 == T_RRSIG)
1016 - return STAT_BOGUS; /* bad packet */
1017 + if (nsec_type == T_NSEC)
1018 + rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, NULL);
1020 + rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
1021 + keyname, name, type1, wildname, NULL);
1023 + if (rc == STAT_BOGUS)
1027 + /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
1028 + /* Also note if the RRset is the answer to the question, or the target of a CNAME */
1029 + cache_start_insert();
1031 + for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
1033 + if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1034 + return STAT_BOGUS; /* bad packet */
1036 + GETSHORT(type2, p2);
1037 + GETSHORT(class2, p2);
1039 + GETSHORT(rdlen2, p2);
1041 + if (!CHECK_LEN(header, p2, plen, rdlen2))
1042 + return STAT_BOGUS; /* bad packet */
1044 + if (class2 == class1 && rc == 1)
1048 - GETSHORT(type_covered, p2);
1050 - if (type_covered == type1 &&
1051 - (type_covered == T_A || type_covered == T_AAAA ||
1052 - type_covered == T_CNAME || type_covered == T_DS ||
1053 - type_covered == T_DNSKEY || type_covered == T_PTR))
1054 + if (type1 == T_DS && type2 == T_DS)
1056 - a.addr.dnssec.type = type_covered;
1057 - a.addr.dnssec.class = class1;
1059 + return STAT_BOGUS; /* bad packet */
1062 - p2 += 13; /* labels, orig_ttl, expiration, inception */
1063 GETSHORT(keytag, p2);
1067 + /* Cache needs to known class for DNSSEC stuff */
1068 + a.addr.dnssec.class = class2;
1070 - /* We don't cache sigs for wildcard answers, because to reproduce the
1071 - answer from the cache will require one or more NSEC/NSEC3 records
1072 - which we don't cache. The lack of the RRSIG ensures that a query for
1073 - this RRset asking for a secure answer will always be forwarded. */
1074 - if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
1075 + if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
1077 - if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
1078 + if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1079 blockdata_free(key);
1082 - crecp->addr.sig.keydata = key;
1083 - crecp->addr.sig.keylen = rdlen2;
1084 - crecp->addr.sig.keytag = keytag;
1085 - crecp->addr.sig.type_covered = type_covered;
1086 - crecp->addr.sig.algo = algo;
1087 + a.addr.keytag = keytag;
1088 + log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
1089 + crecp->addr.ds.digest = digest;
1090 + crecp->addr.ds.keydata = key;
1091 + crecp->addr.ds.algo = algo;
1092 + crecp->addr.ds.keytag = keytag;
1093 + crecp->addr.ds.keylen = rdlen2 - 4;
1097 + else if (type2 == T_RRSIG)
1100 + return STAT_BOGUS; /* bad packet */
1102 + GETSHORT(type_covered, p2);
1104 + if (type_covered == type1 &&
1105 + (type_covered == T_A || type_covered == T_AAAA ||
1106 + type_covered == T_CNAME || type_covered == T_DS ||
1107 + type_covered == T_DNSKEY || type_covered == T_PTR))
1109 + a.addr.dnssec.type = type_covered;
1110 + a.addr.dnssec.class = class1;
1113 + p2 += 13; /* labels, orig_ttl, expiration, inception */
1114 + GETSHORT(keytag, p2);
1116 + /* We don't cache sigs for wildcard answers, because to reproduce the
1117 + answer from the cache will require one or more NSEC/NSEC3 records
1118 + which we don't cache. The lack of the RRSIG ensures that a query for
1119 + this RRset asking for a secure answer will always be forwarded. */
1120 + if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
1122 + if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
1123 + blockdata_free(key);
1126 + crecp->addr.sig.keydata = key;
1127 + crecp->addr.sig.keylen = rdlen2;
1128 + crecp->addr.sig.keytag = keytag;
1129 + crecp->addr.sig.type_covered = type_covered;
1130 + crecp->addr.sig.algo = algo;
1140 + if (!ADD_RDLEN(header, p2, plen, rdlen2))
1141 + return STAT_BOGUS; /* bad packet */
1144 - if (!ADD_RDLEN(header, p2, plen, rdlen2))
1145 - return STAT_BOGUS; /* bad packet */
1146 + cache_end_insert();
1149 - cache_end_insert();
1153 @@ -2083,143 +2223,49 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
1157 - /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
1159 - return STAT_SECURE;
1161 - /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
1162 - /* First marshall the NSEC records, if we've not done it previously */
1163 - if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
1165 - /* No NSEC records. If we dropped off the end of a CNAME chain, return
1166 - STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
1167 - if DS records in CNAME chains. */
1168 - if (cname_count == CNAME_CHAIN) /* No CNAME chain, return empty name. */
1170 - else if (!extract_name(header, plen, &qname, keyname, 1, 0))
1171 - return STAT_BOGUS;
1172 - return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
1173 - an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
1176 - /* Get name of missing answer */
1177 - if (!extract_name(header, plen, &qname, name, 1, 0))
1178 - return STAT_BOGUS;
1180 - if (nsec_type == T_NSEC)
1181 - return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons);
1183 - return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons);
1186 -/* Chase the CNAME chain in the packet until the first record which _doesn't validate.
1187 - Needed for proving answer in unsigned space.
1188 - Return STAT_NEED_*
1189 - STAT_BOGUS - error
1190 - STAT_INSECURE - name of first non-secure record in name
1192 -int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
1194 - unsigned char *p = (unsigned char *)(header+1);
1195 - int type, class, qclass, rdlen, j, rc;
1196 - int cname_count = CNAME_CHAIN;
1199 - /* Get question */
1200 - if (!extract_name(header, plen, &p, name, 1, 4))
1201 - return STAT_BOGUS;
1204 - GETSHORT(qclass, p);
1208 - for (j = ntohs(header->ancount); j != 0; j--)
1210 - if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
1211 - return STAT_BOGUS; /* bad packet */
1213 - GETSHORT(type, p);
1214 - GETSHORT(class, p);
1216 - GETSHORT(rdlen, p);
1218 - /* Not target, loop */
1219 - if (rc == 2 || qclass != class)
1221 - if (!ADD_RDLEN(header, p, plen, rdlen))
1222 - return STAT_BOGUS;
1226 - /* Got to end of CNAME chain. */
1227 - if (type != T_CNAME)
1228 - return STAT_INSECURE;
1230 - /* validate CNAME chain, return if insecure or need more data */
1231 - rc = validate_rrset(now, header, plen, class, type, name, keyname, &wildname, NULL, 0, 0, 0);
1233 - if (rc == STAT_SECURE_WILDCARD)
1235 - int nsec_type, nsec_count, i;
1236 - unsigned char **nsecs;
1238 - /* An attacker can replay a wildcard answer with a different
1239 - answer and overlay a genuine RR. To prove this
1240 - hasn't happened, the answer must prove that
1241 - the genuine record doesn't exist. Check that here. */
1242 - if (!(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class)))
1243 - return STAT_BOGUS; /* No NSECs or bad packet */
1245 - /* Note that we're called here because something didn't validate in validate_reply,
1246 - so we can't assume that any NSEC records have been validated. We do them by steam here */
1248 - for (i = 0; i < nsec_count; i++)
1250 - unsigned char *p1 = nsecs[i];
1252 - if (!extract_name(header, plen, &p1, daemon->workspacename, 1, 0))
1253 - return STAT_BOGUS;
1255 - rc = validate_rrset(now, header, plen, class, nsec_type, daemon->workspacename, keyname, NULL, NULL, 0, 0, 0);
1256 + /* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
1257 + for (j = 0; j <targetidx; j++)
1258 + if ((p2 = targets[j]))
1263 - /* NSECs can't be wildcards. */
1264 - if (rc == STAT_SECURE_WILDCARD)
1266 + if (!extract_name(header, plen, &p2, name, 1, 10))
1267 + return STAT_BOGUS; /* bad packet */
1269 + /* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
1271 - if (rc != STAT_SECURE)
1272 + /* For anything other than a DS record, this situation is OK if either
1273 + the answer is in an unsigned zone, or there's a NSEC records. */
1274 + if (!(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
1276 + /* Empty DS without NSECS */
1277 + if (qtype == T_DS)
1278 + return STAT_BOGUS;
1281 + rc = zone_status(name, qclass, keyname, now);
1282 + if (rc != STAT_SECURE)
1285 + *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
1289 - if (nsec_type == T_NSEC)
1290 - rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type, NULL);
1292 - rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
1293 - keyname, name, type, wildname, NULL);
1295 - if (rc != STAT_SECURE)
1299 - if (rc != STAT_SECURE)
1301 - if (rc == STAT_NO_SIG)
1302 - rc = STAT_INSECURE;
1307 + return STAT_BOGUS; /* signed zone, no NSECs */
1311 - /* Loop down CNAME chain/ */
1312 - if (!cname_count-- ||
1313 - !extract_name(header, plen, &p, name, 1, 0) ||
1314 - !(p = skip_questions(header, plen)))
1315 - return STAT_BOGUS;
1319 + if (nsec_type == T_NSEC)
1320 + rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons);
1322 + rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons);
1324 - /* End of CNAME chain */
1325 - return STAT_INSECURE;
1327 + if (rc != STAT_SECURE)
1331 + return STAT_SECURE;
1335 diff --git a/src/forward.c b/src/forward.c
1336 index b76a974..dd22a62 100644
1339 @@ -23,15 +23,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
1340 static unsigned short get_id(void);
1341 static void free_frec(struct frec *f);
1344 -static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
1345 - int class, char *name, char *keyname, struct server *server, int *keycount);
1346 -static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname);
1347 -static int send_check_sign(struct frec *forward, time_t now, struct dns_header *header, size_t plen,
1348 - char *name, char *keyname);
1352 /* Send a UDP packet with its source address set as "source"
1353 unless nowild is true, when we just send it with the kernel default */
1354 int send_from(int fd, int nowild, char *packet, size_t len,
1355 @@ -825,236 +816,142 @@ void reply_query(int fd, int family, time_t now)
1357 if (server && option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
1362 /* We've had a reply already, which we're validating. Ignore this duplicate */
1363 if (forward->blocking_query)
1366 - if (header->hb3 & HB3_TC)
1368 - /* Truncated answer can't be validated.
1370 + /* Truncated answer can't be validated.
1371 If this is an answer to a DNSSEC-generated query, we still
1372 need to get the client to retry over TCP, so return
1373 an answer with the TC bit set, even if the actual answer fits.
1375 - status = STAT_TRUNCATED;
1377 - else if (forward->flags & FREC_DNSKEY_QUERY)
1378 - status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1379 - else if (forward->flags & FREC_DS_QUERY)
1381 - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1382 - /* Provably no DS, everything below is insecure, even if signatures are offered */
1383 - if (status == STAT_NO_DS)
1384 - /* We only cache sigs when we've validated a reply.
1385 - Avoid caching a reply with sigs if there's a vaildated break in the
1386 - DS chain, so we don't return replies from cache missing sigs. */
1387 - status = STAT_INSECURE_DS;
1388 - else if (status == STAT_NO_SIG)
1390 - if (option_bool(OPT_DNSSEC_NO_SIGN))
1392 - status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1393 - if (status == STAT_INSECURE)
1394 - status = STAT_INSECURE_DS;
1397 - status = STAT_INSECURE_DS;
1399 - else if (status == STAT_NO_NS)
1400 - status = STAT_BOGUS;
1402 - else if (forward->flags & FREC_CHECK_NOSIGN)
1404 - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1405 - if (status != STAT_NEED_KEY)
1406 - status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname);
1409 + if (header->hb3 & HB3_TC)
1410 + status = STAT_TRUNCATED;
1414 - status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL);
1415 - if (status == STAT_NO_SIG)
1416 + /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
1417 + would invite infinite loops, since the answers to DNSKEY and DS queries
1418 + will not be cached, so they'll be repeated. */
1419 + if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
1421 - if (option_bool(OPT_DNSSEC_NO_SIGN))
1422 - status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1423 + if (forward->flags & FREC_DNSKEY_QUERY)
1424 + status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1425 + else if (forward->flags & FREC_DS_QUERY)
1426 + status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1428 - status = STAT_INSECURE;
1429 + status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
1430 + option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
1433 - /* Can't validate, as we're missing key data. Put this
1434 - answer aside, whilst we get that. */
1435 - if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
1437 - struct frec *new, *orig;
1439 - /* Free any saved query */
1440 - if (forward->stash)
1441 - blockdata_free(forward->stash);
1443 - /* Now save reply pending receipt of key data */
1444 - if (!(forward->stash = blockdata_alloc((char *)header, n)))
1446 - forward->stash_len = n;
1449 - /* Find the original query that started it all.... */
1450 - for (orig = forward; orig->dependent; orig = orig->dependent);
1452 - if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1453 - status = STAT_INSECURE;
1455 + /* Can't validate, as we're missing key data. Put this
1456 + answer aside, whilst we get that. */
1457 + if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
1460 - struct frec *next = new->next;
1461 - *new = *forward; /* copy everything, then overwrite */
1463 - new->blocking_query = NULL;
1464 - new->sentto = server;
1466 - new->orig_domain = NULL;
1470 - new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_CHECK_NOSIGN);
1471 + struct frec *new, *orig;
1473 - new->dependent = forward; /* to find query awaiting new one. */
1474 - forward->blocking_query = new; /* for garbage cleaning */
1475 - /* validate routines leave name of required record in daemon->keyname */
1476 - if (status == STAT_NEED_KEY)
1478 - new->flags |= FREC_DNSKEY_QUERY;
1479 - nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
1480 - daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
1484 - if (status == STAT_NEED_DS_NEG)
1485 - new->flags |= FREC_CHECK_NOSIGN;
1487 - new->flags |= FREC_DS_QUERY;
1488 - nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
1489 - daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
1491 - if ((hash = hash_questions(header, nn, daemon->namebuff)))
1492 - memcpy(new->hash, hash, HASH_SIZE);
1493 - new->new_id = get_id();
1494 - header->id = htons(new->new_id);
1495 - /* Save query for retransmission */
1496 - if (!(new->stash = blockdata_alloc((char *)header, nn)))
1497 + /* Free any saved query */
1498 + if (forward->stash)
1499 + blockdata_free(forward->stash);
1501 + /* Now save reply pending receipt of key data */
1502 + if (!(forward->stash = blockdata_alloc((char *)header, n)))
1505 - new->stash_len = nn;
1506 + forward->stash_len = n;
1508 - /* Don't resend this. */
1509 - daemon->srv_save = NULL;
1510 + /* Find the original query that started it all.... */
1511 + for (orig = forward; orig->dependent; orig = orig->dependent);
1514 - fd = server->sfd->fd;
1515 + if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1516 + status = STAT_ABANDONED;
1521 + struct frec *next = new->next;
1522 + *new = *forward; /* copy everything, then overwrite */
1524 + new->blocking_query = NULL;
1525 + new->sentto = server;
1528 - if (server->addr.sa.sa_family == AF_INET6)
1531 + new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
1533 + new->dependent = forward; /* to find query awaiting new one. */
1534 + forward->blocking_query = new; /* for garbage cleaning */
1535 + /* validate routines leave name of required record in daemon->keyname */
1536 + if (status == STAT_NEED_KEY)
1538 + new->flags |= FREC_DNSKEY_QUERY;
1539 + nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
1540 + daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
1544 - if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1545 - fd = new->rfd6->fd;
1546 + new->flags |= FREC_DS_QUERY;
1547 + nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
1548 + daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
1550 + if ((hash = hash_questions(header, nn, daemon->namebuff)))
1551 + memcpy(new->hash, hash, HASH_SIZE);
1552 + new->new_id = get_id();
1553 + header->id = htons(new->new_id);
1554 + /* Save query for retransmission */
1555 + new->stash = blockdata_alloc((char *)header, nn);
1556 + new->stash_len = nn;
1558 + /* Don't resend this. */
1559 + daemon->srv_save = NULL;
1562 + fd = server->sfd->fd;
1567 + if (server->addr.sa.sa_family == AF_INET6)
1569 + if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1570 + fd = new->rfd6->fd;
1575 + if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1576 + fd = new->rfd4->fd;
1582 - if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1583 - fd = new->rfd4->fd;
1584 + while (retry_send(sendto(fd, (char *)header, nn, 0,
1586 + sa_len(&server->addr))));
1587 + server->queries++;
1593 - while (retry_send(sendto(fd, (char *)header, nn, 0,
1595 - sa_len(&server->addr))));
1596 - server->queries++;
1604 - /* Ok, we reached far enough up the chain-of-trust that we can validate something.
1605 - Now wind back down, pulling back answers which wouldn't previously validate
1606 - and validate them with the new data. Note that if an answer needs multiple
1607 - keys to validate, we may find another key is needed, in which case we set off
1608 - down another branch of the tree. Once we get to the original answer
1609 - (FREC_DNSSEC_QUERY not set) and it validates, return it to the original requestor. */
1610 - while (forward->dependent)
1612 + /* Validated original answer, all done. */
1613 + if (!forward->dependent)
1616 + /* validated subsdiary query, (and cached result)
1617 + pop that and return to the previous query we were working on. */
1618 struct frec *prev = forward->dependent;
1621 forward->blocking_query = NULL; /* already gone */
1622 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1623 n = forward->stash_len;
1625 - if (status == STAT_SECURE)
1627 - if (forward->flags & FREC_DNSKEY_QUERY)
1628 - status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1629 - else if (forward->flags & FREC_DS_QUERY)
1631 - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1632 - /* Provably no DS, everything below is insecure, even if signatures are offered */
1633 - if (status == STAT_NO_DS)
1634 - /* We only cache sigs when we've validated a reply.
1635 - Avoid caching a reply with sigs if there's a vaildated break in the
1636 - DS chain, so we don't return replies from cache missing sigs. */
1637 - status = STAT_INSECURE_DS;
1638 - else if (status == STAT_NO_SIG)
1640 - if (option_bool(OPT_DNSSEC_NO_SIGN))
1642 - status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1643 - if (status == STAT_INSECURE)
1644 - status = STAT_INSECURE_DS;
1647 - status = STAT_INSECURE_DS;
1649 - else if (status == STAT_NO_NS)
1650 - status = STAT_BOGUS;
1652 - else if (forward->flags & FREC_CHECK_NOSIGN)
1654 - status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
1655 - if (status != STAT_NEED_KEY)
1656 - status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname);
1660 - status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL);
1661 - if (status == STAT_NO_SIG)
1663 - if (option_bool(OPT_DNSSEC_NO_SIGN))
1664 - status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1666 - status = STAT_INSECURE;
1670 - if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
1676 no_cache_dnssec = 0;
1678 - if (status == STAT_INSECURE_DS)
1680 - /* We only cache sigs when we've validated a reply.
1681 - Avoid caching a reply with sigs if there's a vaildated break in the
1682 - DS chain, so we don't return replies from cache missing sigs. */
1683 - status = STAT_INSECURE;
1684 - no_cache_dnssec = 1;
1687 if (status == STAT_TRUNCATED)
1688 header->hb3 |= HB3_TC;
1689 @@ -1062,7 +959,7 @@ void reply_query(int fd, int family, time_t now)
1691 char *result, *domain = "result";
1693 - if (forward->work_counter == 0)
1694 + if (status == STAT_ABANDONED)
1696 result = "ABANDONED";
1697 status = STAT_BOGUS;
1698 @@ -1072,7 +969,7 @@ void reply_query(int fd, int family, time_t now)
1700 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1701 domain = daemon->namebuff;
1704 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
1707 @@ -1415,315 +1312,49 @@ void receive_query(struct listener *listen, time_t now)
1712 -/* UDP: we've got an unsigned answer, return STAT_INSECURE if we can prove there's no DS
1713 - and therefore the answer shouldn't be signed, or STAT_BOGUS if it should be, or
1714 - STAT_NEED_DS_NEG and keyname if we need to do the query. */
1715 -static int send_check_sign(struct frec *forward, time_t now, struct dns_header *header, size_t plen,
1716 - char *name, char *keyname)
1718 - int status = dnssec_chase_cname(now, header, plen, name, keyname);
1720 - if (status != STAT_INSECURE)
1723 - /* Store the domain we're trying to check. */
1724 - forward->name_start = strlen(name);
1725 - forward->name_len = forward->name_start + 1;
1726 - if (!(forward->orig_domain = blockdata_alloc(name, forward->name_len)))
1727 - return STAT_BOGUS;
1729 - return do_check_sign(forward, 0, now, name, keyname);
1732 -/* We either have a a reply (header non-NULL, or we need to start by looking in the cache */
1733 -static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname)
1735 - /* get domain we're checking back from blockdata store, it's stored on the original query. */
1736 - while (forward->dependent && !forward->orig_domain)
1737 - forward = forward->dependent;
1739 - blockdata_retrieve(forward->orig_domain, forward->name_len, name);
1747 - struct crec *crecp;
1749 - /* Haven't received answer, see if in cache */
1750 - if (!(crecp = cache_find_by_name(NULL, &name[forward->name_start], now, F_DS)))
1752 - /* put name of DS record we're missing into keyname */
1753 - strcpy(keyname, &name[forward->name_start]);
1754 - /* and wait for reply to arrive */
1755 - return STAT_NEED_DS_NEG;
1758 - /* F_DNSSECOK misused in DS cache records to non-existance of NS record */
1759 - if (!(crecp->flags & F_NEG))
1760 - status = STAT_SECURE;
1761 - else if (crecp->flags & F_DNSSECOK)
1762 - status = STAT_NO_DS;
1764 - status = STAT_NO_NS;
1767 - /* Have entered non-signed part of DNS tree. */
1768 - if (status == STAT_NO_DS)
1769 - return forward->dependent ? STAT_INSECURE_DS : STAT_INSECURE;
1771 - if (status == STAT_BOGUS)
1772 - return STAT_BOGUS;
1774 - if (status == STAT_NO_SIG && *keyname != 0)
1776 - /* There is a validated CNAME chain that doesn't end in a DS record. Start
1777 - the search again in that domain. */
1778 - blockdata_free(forward->orig_domain);
1779 - forward->name_start = strlen(keyname);
1780 - forward->name_len = forward->name_start + 1;
1781 - if (!(forward->orig_domain = blockdata_alloc(keyname, forward->name_len)))
1782 - return STAT_BOGUS;
1784 - strcpy(name, keyname);
1785 - status = 0; /* force to cache when we iterate. */
1789 - /* There's a proven DS record, or we're within a zone, where there doesn't need
1790 - to be a DS record. Add a name and try again.
1791 - If we've already tried the whole name, then fail */
1793 - if (forward->name_start == 0)
1794 - return STAT_BOGUS;
1796 - for (p = &name[forward->name_start-2]; (*p != '.') && (p != name); p--);
1801 - forward->name_start = p - name;
1802 - status = 0; /* force to cache when we iterate. */
1806 -/* Move down from the root, until we find a signed non-existance of a DS, in which case
1807 - an unsigned answer is OK, or we find a signed DS, in which case there should be
1808 - a signature, and the answer is BOGUS */
1809 -static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, size_t plen, int class, char *name,
1810 - char *keyname, struct server *server, int *keycount)
1813 - unsigned char *packet, *payload;
1815 - int status, name_len;
1816 - struct blockdata *block;
1820 - /* Get first insecure entry in CNAME chain */
1821 - status = tcp_key_recurse(now, STAT_CHASE_CNAME, header, plen, class, name, keyname, server, keycount);
1822 - if (status == STAT_BOGUS)
1823 - return STAT_BOGUS;
1825 - if (!(packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16))))
1826 - return STAT_BOGUS;
1828 - payload = &packet[2];
1829 - header = (struct dns_header *)payload;
1830 - length = (u16 *)packet;
1832 - /* Stash the name away, since the buffer will be trashed when we recurse */
1833 - name_len = strlen(name) + 1;
1834 - name_start = name + name_len - 1;
1836 - if (!(block = blockdata_alloc(name, name_len)))
1839 - return STAT_BOGUS;
1844 - unsigned char c1, c2;
1845 - struct crec *crecp;
1847 - if (--(*keycount) == 0)
1850 - blockdata_free(block);
1851 - return STAT_BOGUS;
1854 - while ((crecp = cache_find_by_name(NULL, name_start, now, F_DS)))
1856 - if ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK))
1858 - /* Found a secure denial of DS - delegation is indeed insecure */
1860 - blockdata_free(block);
1861 - return STAT_INSECURE;
1864 - /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation.
1865 - Add another label and continue. */
1867 - if (name_start == name)
1870 - blockdata_free(block);
1871 - return STAT_BOGUS; /* run out of labels */
1875 - while (*name_start != '.' && name_start != name)
1877 - if (name_start != name)
1881 - /* Can't find it in the cache, have to send a query */
1883 - m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr, server->edns_pktsz);
1885 - *length = htons(m);
1887 - if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) &&
1888 - read_write(server->tcpfd, &c1, 1, 1) &&
1889 - read_write(server->tcpfd, &c2, 1, 1) &&
1890 - read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
1892 - m = (c1 << 8) | c2;
1894 - /* Note this trashes all three name workspaces */
1895 - status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount);
1897 - if (status == STAT_NO_DS)
1899 - /* Found a secure denial of DS - delegation is indeed insecure */
1901 - blockdata_free(block);
1902 - return STAT_INSECURE;
1905 - if (status == STAT_NO_SIG && *keyname != 0)
1907 - /* There is a validated CNAME chain that doesn't end in a DS record. Start
1908 - the search again in that domain. */
1909 - blockdata_free(block);
1910 - name_len = strlen(keyname) + 1;
1911 - name_start = name + name_len - 1;
1913 - if (!(block = blockdata_alloc(keyname, name_len)))
1914 - return STAT_BOGUS;
1916 - strcpy(name, keyname);
1920 - if (status == STAT_BOGUS)
1923 - blockdata_free(block);
1924 - return STAT_BOGUS;
1927 - /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation.
1928 - Add another label and continue. */
1930 - /* Get name we're checking back. */
1931 - blockdata_retrieve(block, name_len, name);
1933 - if (name_start == name)
1936 - blockdata_free(block);
1937 - return STAT_BOGUS; /* run out of labels */
1941 - while (*name_start != '.' && name_start != name)
1943 - if (name_start != name)
1950 - blockdata_free(block);
1951 - return STAT_BOGUS; /* run out of labels */
1956 static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
1957 int class, char *name, char *keyname, struct server *server, int *keycount)
1959 /* Recurse up the key heirarchy */
1961 + unsigned char *packet = NULL;
1963 + unsigned char *payload = NULL;
1964 + struct dns_header *new_header = NULL;
1965 + u16 *length = NULL;
1966 + unsigned char c1, c2;
1968 - /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1969 - if (--(*keycount) == 0)
1970 - return STAT_INSECURE;
1972 - if (status == STAT_NEED_KEY)
1973 - new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1974 - else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG)
1977 - new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1978 - if (status == STAT_NEED_DS)
1979 + /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
1980 + if (--(*keycount) == 0)
1981 + new_status = STAT_ABANDONED;
1982 + else if (status == STAT_NEED_KEY)
1983 + new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
1984 + else if (status == STAT_NEED_DS)
1985 + new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
1987 + new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
1989 + if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1992 + /* Can't validate because we need a key/DS whose name now in keyname.
1993 + Make query for same, and recurse to validate */
1996 - if (new_status == STAT_NO_DS)
1997 - new_status = STAT_INSECURE_DS;
1998 - if (new_status == STAT_NO_SIG)
2000 - if (option_bool(OPT_DNSSEC_NO_SIGN))
2002 - new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2003 - if (new_status == STAT_INSECURE)
2004 - new_status = STAT_INSECURE_DS;
2007 - new_status = STAT_INSECURE_DS;
2009 - else if (new_status == STAT_NO_NS)
2010 - new_status = STAT_BOGUS;
2011 + packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
2012 + payload = &packet[2];
2013 + new_header = (struct dns_header *)payload;
2014 + length = (u16 *)packet;
2017 - else if (status == STAT_CHASE_CNAME)
2018 - new_status = dnssec_chase_cname(now, header, n, name, keyname);
2021 - new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL);
2023 - if (new_status == STAT_NO_SIG)
2026 - if (option_bool(OPT_DNSSEC_NO_SIGN))
2027 - new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2029 - new_status = STAT_INSECURE;
2030 + new_status = STAT_ABANDONED;
2035 - /* Can't validate because we need a key/DS whose name now in keyname.
2036 - Make query for same, and recurse to validate */
2037 - if (new_status == STAT_NEED_DS || new_status == STAT_NEED_KEY)
2040 - unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
2041 - unsigned char *payload = &packet[2];
2042 - struct dns_header *new_header = (struct dns_header *)payload;
2043 - u16 *length = (u16 *)packet;
2044 - unsigned char c1, c2;
2047 - return STAT_INSECURE;
2051 m = dnssec_generate_query(new_header, ((char *) new_header) + 65536, keyname, class,
2052 new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
2054 @@ -1733,65 +1364,22 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
2055 !read_write(server->tcpfd, &c1, 1, 1) ||
2056 !read_write(server->tcpfd, &c2, 1, 1) ||
2057 !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
2058 - new_status = STAT_INSECURE;
2061 - m = (c1 << 8) | c2;
2063 - new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
2065 - if (new_status == STAT_SECURE)
2067 - /* Reached a validated record, now try again at this level.
2068 - Note that we may get ANOTHER NEED_* if an answer needs more than one key.
2069 - If so, go round again. */
2071 - if (status == STAT_NEED_KEY)
2072 - new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
2073 - else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG)
2075 - new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
2076 - if (status == STAT_NEED_DS)
2078 - if (new_status == STAT_NO_DS)
2079 - new_status = STAT_INSECURE_DS;
2080 - else if (new_status == STAT_NO_SIG)
2082 - if (option_bool(OPT_DNSSEC_NO_SIGN))
2084 - new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2085 - if (new_status == STAT_INSECURE)
2086 - new_status = STAT_INSECURE_DS;
2089 - new_status = STAT_INSECURE_DS;
2091 - else if (new_status == STAT_NO_NS)
2092 - new_status = STAT_BOGUS;
2095 - else if (status == STAT_CHASE_CNAME)
2096 - new_status = dnssec_chase_cname(now, header, n, name, keyname);
2099 - new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL);
2101 - if (new_status == STAT_NO_SIG)
2103 - if (option_bool(OPT_DNSSEC_NO_SIGN))
2104 - new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2106 - new_status = STAT_INSECURE;
2110 - if (new_status == STAT_NEED_DS || new_status == STAT_NEED_KEY)
2111 - goto another_tcp_key;
2113 + new_status = STAT_ABANDONED;
2117 + m = (c1 << 8) | c2;
2120 + new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
2122 + if (new_status != STAT_OK)
2132 @@ -2075,19 +1663,10 @@ unsigned char *tcp_request(int confd, time_t now,
2133 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled)
2135 int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
2136 - int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
2137 + int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
2138 char *result, *domain = "result";
2140 - if (status == STAT_INSECURE_DS)
2142 - /* We only cache sigs when we've validated a reply.
2143 - Avoid caching a reply with sigs if there's a vaildated break in the
2144 - DS chain, so we don't return replies from cache missing sigs. */
2145 - status = STAT_INSECURE;
2146 - no_cache_dnssec = 1;
2149 - if (keycount == 0)
2150 + if (status == STAT_ABANDONED)
2152 result = "ABANDONED";
2153 status = STAT_BOGUS;
2154 @@ -2179,7 +1758,6 @@ static struct frec *allocate_frec(time_t now)
2155 f->dependent = NULL;
2156 f->blocking_query = NULL;
2158 - f->orig_domain = NULL;
2160 daemon->frec_list = f;
2162 @@ -2248,12 +1826,6 @@ static void free_frec(struct frec *f)
2166 - if (f->orig_domain)
2168 - blockdata_free(f->orig_domain);
2169 - f->orig_domain = NULL;
2172 /* Anything we're waiting on is pointless now, too */
2173 if (f->blocking_query)
2174 free_frec(f->blocking_query);
2175 @@ -2281,14 +1853,23 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
2179 - if (difftime(now, f->time) >= 4*TIMEOUT)
2185 - if (!oldest || difftime(f->time, oldest->time) <= 0)
2188 + /* Don't free DNSSEC sub-queries here, as we may end up with
2189 + dangling references to them. They'll go when their "real" query
2191 + if (!f->dependent)
2194 + if (difftime(now, f->time) >= 4*TIMEOUT)
2201 + if (!oldest || difftime(f->time, oldest->time) <= 0)