]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/016-Major_rationalisation_of_DNSSEC_validation.patch
bird: New package
[ipfire-2.x.git] / src / patches / dnsmasq / 016-Major_rationalisation_of_DNSSEC_validation.patch
CommitLineData
fbcc3cb7
MF
1From 9a31b68b59adcac01016d4026d906b69c4216c01 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Tue, 15 Dec 2015 10:20:39 +0000
4Subject: [PATCH] Major rationalisation of DNSSEC validation.
5
6Much gnarly special-case code removed and replaced with correct
7general implementaion. Checking of zone-status moved to DNSSEC code,
8where it should be, vastly simplifying query-forwarding code.
9---
10 src/dnsmasq.h | 19 +-
11 src/dnssec.c | 926 ++++++++++++++++++++++++++++++---------------------------
12 src/forward.c | 741 ++++++++++-----------------------------------
13 3 files changed, 653 insertions(+), 1033 deletions(-)
14
15diff --git a/src/dnsmasq.h b/src/dnsmasq.h
16index f42acdb..023a1cf 100644
17--- a/src/dnsmasq.h
18+++ b/src/dnsmasq.h
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
24-#define STAT_NO_DS 9
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
29+#define STAT_OK 8
30+#define STAT_ABANDONED 9
31
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
41
42 #ifdef HAVE_DNSSEC
43 #define HASH_SIZE 20 /* SHA-1 digest size */
44@@ -626,9 +621,7 @@ struct frec {
45 #ifdef HAVE_DNSSEC
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;
51+ size_t stash_len;
52 struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
53 struct frec *blocking_query; /* Query which is blocking us. */
54 #endif
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);
66diff --git a/src/dnssec.c b/src/dnssec.c
67index b4dc14e..de7b335 100644
68--- a/src/dnssec.c
69+++ b/src/dnssec.c
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";
77+#endif
78 default: return NULL;
79 }
80 }
81@@ -592,30 +594,30 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
82 }
83 }
84
85-static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
86+static int expand_workspace(unsigned char ***wkspc, int *szp, int new)
87 {
88 unsigned char **p;
89- int new_sz = *sz;
90-
91- if (new_sz > new)
92+ int old = *szp;
93+
94+ if (old >= new+1)
95 return 1;
96
97 if (new >= 100)
98 return 0;
99
100- new_sz += 5;
101+ new += 5;
102
103- if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
104+ if (!(p = whine_malloc(new * sizeof(unsigned char **))))
105 return 0;
106
107- if (*wkspc)
108+ if (old != 0 && *wkspc)
109 {
110- memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
111+ memcpy(p, *wkspc, old * sizeof(unsigned char **));
112 free(*wkspc);
113 }
114
115 *wkspc = p;
116- *sz = new_sz;
117+ *szp = new;
118
119 return 1;
120 }
121@@ -706,47 +708,28 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
122 } while (swap);
123 }
124
125-/* Validate a single RRset (class, type, name) in the supplied DNS reply
126- Return code:
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)
134-
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;
138
139- name is unchanged on exit. keyname is used as workspace and trashed.
140-*/
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)
147 {
148- static unsigned char **rrset = NULL, **sigs = NULL;
149- static int rrset_sz = 0, sig_sz = 0;
150-
151+ static int rrset_sz = 0, sig_sz = 0;
152 unsigned char *p;
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);
157-
158- if (wildcard_out)
159- *wildcard_out = NULL;
160-
161+ int rrsetidx, sigidx, j, rdlen, res;
162+ int name_labels = count_labels(name); /* For 4035 5.3.2 check */
163+ int gotkey = 0;
164+
165 if (!(p = skip_questions(header, plen)))
166 return STAT_BOGUS;
167-
168- name_labels = count_labels(name); /* For 4035 5.3.2 check */
169
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);
173 j != 0; j--)
174 {
175 unsigned char *pstart, *pdata;
176- int stype, sclass;
177+ int stype, sclass, algo, type_covered, labels, sig_expiration, sig_inception;
178
179 pstart = p;
180
181@@ -762,14 +745,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
182 GETSHORT(rdlen, p);
183
184 if (!CHECK_LEN(header, p, plen, rdlen))
185- return STAT_BOGUS;
186+ return 0;
187
188 if (res == 1 && sclass == class)
189 {
190 if (stype == type)
191 {
192 if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
193- return STAT_BOGUS;
194+ return 0;
195
196 rrset[rrsetidx++] = pstart;
197 }
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)
200 {
201 if (rdlen < 18)
202- return STAT_BOGUS; /* bad packet */
203+ return 0; /* bad packet */
204
205 GETSHORT(type_covered, p);
206+ algo = *p++;
207+ labels = *p++;
208+ p += 4; /* orig_ttl */
209+ GETLONG(sig_expiration, p);
210+ GETLONG(sig_inception, p);
211+ p += 2; /* key_tag */
212
213- if (type_covered == type)
214+ if (gotkey)
215+ {
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)
218+ return 0;
219+ }
220+ else
221+ {
222+ gotkey = 1;
223+
224+ if (!extract_name(header, plen, &p, keyname, 1, 0))
225+ return 0;
226+
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. */
233+ if (*keyname != 0)
234+ {
235+ char *name_start;
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 */
239+ else
240+ return 0;
241+ }
242+ }
243+
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))
249 {
250 if (!expand_workspace(&sigs, &sig_sz, sigidx))
251- return STAT_BOGUS;
252+ return 0;
253
254 sigs[sigidx++] = pdata;
255 }
256@@ -794,17 +817,45 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
257 }
258
259 if (!ADD_RDLEN(header, p, plen, rdlen))
260- return STAT_BOGUS;
261+ return 0;
262 }
263
264- /* RRset empty */
265- if (rrsetidx == 0)
266- return STAT_INSECURE;
267+ *sigcnt = sigidx;
268+ *rrcnt = rrsetidx;
269+
270+ return 1;
271+}
272+
273+/* Validate a single RRset (class, type, name) in the supplied DNS reply
274+ Return code:
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)
281+
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.
284
285- /* no RRSIGs */
286- if (sigidx == 0)
287- return STAT_NO_SIG;
288+ name is unchanged on exit. keyname is used as workspace and trashed.
289+
290+ Call explore_rrset first to find and count RRs and sigs.
291+*/
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)
294+{
295+ unsigned char *p;
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);
300+
301+ if (wildcard_out)
302+ *wildcard_out = NULL;
303
304+ name_labels = count_labels(name); /* For 4035 5.3.2 check */
305+
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
310 algo = *p++;
311 labels = *p++;
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);
317
318 if (!extract_name(header, plen, &p, keyname, 1, 0))
319 return STAT_BOGUS;
320
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. */
327- if (*keyname != 0)
328- {
329- int failed = 0;
330-
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 */
334- else
335- {
336- failed = 1;
337- break;
338- }
339-
340- /* Bad sig, try another */
341- if (failed)
342- continue;
343- }
344-
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))
351 continue;
352-
353+
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.
360 return codes:
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
370 */
371 int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
372 {
373@@ -1001,23 +1025,6 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
374 return STAT_NEED_DS;
375 }
376
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;
380-
381- /* 4035 5.2
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)))
389- break;
390-
391- if (!recp1)
392- return STAT_INSECURE_DS;
393-
394 /* NOTE, we need to find ONE DNSKEY which matches the DS */
395 for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
396 {
397@@ -1070,7 +1077,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
398 void *ctx;
399 unsigned char *digest, *ds_digest;
400 const struct nettle_hash *hash;
401-
402+ int sigcnt, rrcnt;
403+
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
408
409 from_wire(name);
410
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)
421 {
422 valid = 1;
423 break;
424@@ -1112,7 +1124,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
425 {
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 */
430
431 GETSHORT(qtype, p);
432 GETSHORT(qclass, p);
433@@ -1198,7 +1210,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
434
435 /* commit cache insert. */
436 cache_end_insert();
437- return STAT_SECURE;
438+ return STAT_OK;
439 }
440
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
443
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
448+ cached too.
449 return codes:
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.
457 */
458
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)
462 val = STAT_BOGUS;
463 else
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 */
467
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
470
471 if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
472 val = STAT_BOGUS;
473-
474- /* If we return STAT_NO_SIG, name contains the name of the DS query */
475- if (val == STAT_NO_SIG)
476- return val;
477
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)))
483 {
484 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
485 return STAT_BOGUS;
486 }
487+
488+ if (val != STAT_SECURE)
489+ return val;
490
491 /* By here, the answer is proved secure, and a positive answer has been cached. */
492- if (val == STAT_SECURE && neganswer)
493+ if (neganswer)
494 {
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
498
499 cache_end_insert();
500
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");
503 }
504-
505- return nons ? STAT_NO_NS : STAT_NO_DS;
506 }
507
508- return val;
509+ return STAT_OK;
510 }
511
512+
513 /* 4034 6.1 */
514 static int hostname_cmp(const char *a, const char *b)
515 {
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);
518
519 if (nons)
520- *nons = 0;
521+ *nons = 1;
522
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 */
527
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)
530- *nons = 1;
531+ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
532+ *nons = 0;
533
534+ if (rdlen >= 2 && p[0] == 0)
535+ {
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)
539+ return STAT_BOGUS;
540+
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)
544+ return STAT_BOGUS;
545+ }
546+
547 while (rdlen >= 2)
548 {
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)
553 {
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;
557
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 */
561 GETSHORT(rdlen, p);
562 psave = p;
563- p += 4; /* algo, flags, iterations */
564+ p++; /* algo */
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
571 return 0;
572
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)
575- *nons = 1;
576+ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
577+ *nons = 0;
578
579+ if (rdlen >= 2 && p[0] == 0)
580+ {
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)
584+ return 0;
585+
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)
589+ return 0;
590+ }
591+
592 while (rdlen >= 2)
593 {
594 if (p[0] == type >> 8)
595 {
596 /* Does the NSEC3 say our type exists? */
597 if (offset < p[1] && (p[offset+2] & mask) != 0)
598- return STAT_BOGUS;
599+ return 0;
600
601 break; /* finshed checking */
602 }
603@@ -1643,7 +1683,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
604 rdlen -= p[1];
605 p += p[1];
606 }
607-
608+
609 return 1;
610 }
611 else if (rc < 0)
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)
616- return 1;
617+ {
618+ if ((flags & 0x01) && nons) /* opt out */
619+ *nons = 0;
620+
621+ return 1;
622+ }
623 }
624 else
625 {
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)
628- return 1;
629+ {
630+ if ((flags & 0x01) && nons) /* opt out */
631+ *nons = 0;
632+
633+ return 1;
634+ }
635 }
636 }
637 }
638+
639 return 0;
640 }
641
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;
644
645 if (nons)
646- *nons = 0;
647+ *nons = 1;
648
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
652
653 return STAT_SECURE;
654 }
655-
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 */
658+
659+/* Check signing status of name.
660+ returns:
661+ STAT_SECURE zone is signed.
662+ STAT_INSECURE zone proved unsigned.
663+ STAT_NEED_DS require DS record of name returned in keyname.
664+
665+ name returned unaltered.
666+*/
667+static int zone_status(char *name, int class, char *keyname, time_t now)
668+{
669+ int name_start = strlen(name);
670+ struct crec *crecp;
671+ char *p;
672+
673+ while (1)
674+ {
675+ strcpy(keyname, &name[name_start]);
676+
677+ if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS)))
678+ return STAT_NEED_DS;
679+ else
680+ do
681+ {
682+ if (crecp->uid == (unsigned int)class)
683+ {
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.
689+ */
690+ if (crecp->flags & F_NEG)
691+ {
692+ if (crecp->flags & F_DNSSECOK)
693+ return STAT_INSECURE; /* proved no DS here */
694+ }
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 */
697+ }
698+ }
699+ while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
700+
701+ if (name_start == 0)
702+ break;
703+
704+ for (p = &name[name_start-2]; (*p != '.') && (p != name); p--);
705+
706+ if (p != name)
707+ p++;
708+
709+ name_start = p - name;
710+ }
711+
712+ return STAT_SECURE;
713+}
714+
715+/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3)
716+ Return code:
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)
722+*/
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)
726 {
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;
733+
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;
737+ int nsec_type;
738
739 if (neganswer)
740 *neganswer = 0;
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;
744
745- qname = p1 = (unsigned char *)(header+1);
746+ p1 = (unsigned char *)(header+1);
747
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. */
751+
752+ if (!expand_workspace(&targets, &target_sz, 0))
753+ return STAT_BOGUS;
754+
755+ targets[0] = p1;
756+ targetidx = 1;
757+
758 if (!extract_name(header, plen, &p1, name, 1, 4))
759 return STAT_BOGUS;
760-
761+
762 GETSHORT(qtype, p1);
763 GETSHORT(qclass, p1);
764 ans_start = p1;
765-
766- if (qtype == T_ANY)
767- have_answer = 1;
768
769- /* Can't validate an RRISG query */
770+ /* Can't validate an RRSIG query */
771 if (qtype == T_RRSIG)
772 return STAT_INSECURE;
773-
774- cname_loop:
775- for (j = ntohs(header->ancount); j != 0; j--)
776- {
777- /* leave pointer to missing name in qname */
778-
779- if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
780- return STAT_BOGUS; /* bad packet */
781-
782- GETSHORT(type2, p1);
783- GETSHORT(class2, p1);
784- p1 += 4; /* TTL */
785- GETSHORT(rdlen2, p1);
786-
787- if (rc == 1 && qclass == class2)
788- {
789- /* Do we have an answer for the question? */
790- if (type2 == qtype)
791- {
792- have_answer = 1;
793- break;
794- }
795- else if (type2 == T_CNAME)
796- {
797- qname = p1;
798-
799- /* looped CNAMES */
800- if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
801- return STAT_BOGUS;
802-
803- p1 = ans_start;
804- goto cname_loop;
805- }
806- }
807-
808- if (!ADD_RDLEN(header, p1, plen, rdlen2))
809- return STAT_BOGUS;
810- }
811-
812- if (neganswer && !have_answer)
813- *neganswer = 1;
814
815- /* No data, therefore no sigs */
816- if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
817- {
818- *keyname = 0;
819- return STAT_NO_SIG;
820- }
821-
822+ if (qtype != T_CNAME)
823+ for (j = ntohs(header->ancount); j != 0; j--)
824+ {
825+ if (!(p1 = skip_name(p1, header, plen, 10)))
826+ return STAT_BOGUS; /* bad packet */
827+
828+ GETSHORT(type2, p1);
829+ p1 += 6; /* class, TTL */
830+ GETSHORT(rdlen2, p1);
831+
832+ if (type2 == T_CNAME)
833+ {
834+ if (!expand_workspace(&targets, &target_sz, targetidx))
835+ return STAT_BOGUS;
836+
837+ targets[targetidx++] = p1; /* pointer to target name */
838+ }
839+
840+ if (!ADD_RDLEN(header, p1, plen, rdlen2))
841+ return STAT_BOGUS;
842+ }
843+
844 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
845 {
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 */
849 if (j == i)
850 {
851- int ttl, keytag, algo, digest, type_covered;
852+ int ttl, keytag, algo, digest, type_covered, sigcnt, rrcnt;
853 unsigned char *psave;
854 struct all_addr a;
855 struct blockdata *key;
856@@ -1939,143 +2036,186 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
857 char *wildname;
858 int have_wildcard = 0;
859
860- rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
861-
862- if (rc == STAT_SECURE_WILDCARD)
863- {
864- have_wildcard = 1;
865-
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 */
872-
873- if (nsec_type == T_NSEC)
874- rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, NULL);
875- else
876- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
877- keyname, name, type1, wildname, NULL);
878-
879- if (rc != STAT_SECURE)
880- return rc;
881- }
882- else if (rc != STAT_SECURE)
883- {
884- if (class)
885- *class = class1; /* Class for DS or DNSKEY */
886+ if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
887+ return STAT_BOGUS;
888
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. */
891+ if (sigcnt == 0)
892+ {
893+ if (check_unsigned)
894 {
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. */
900- *keyname = 0;
901- else if (!extract_name(header, plen, &qname, keyname, 1, 0))
902- return STAT_BOGUS;
903+ rc = zone_status(name, class1, keyname, now);
904+ if (rc == STAT_SECURE)
905+ rc = STAT_BOGUS;
906+ if (class)
907+ *class = class1; /* Class for NEED_DS or NEED_DNSKEY */
908 }
909-
910+ else
911+ rc = STAT_INSECURE;
912+
913 return rc;
914 }
915
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)
923+ {
924+ /* Zone is insecure, don't need to validate RRset */
925+ if (class)
926+ *class = class1; /* Class for NEED_DS or NEED_DNSKEY */
927+ return rc;
928+ }
929+
930+ rc = validate_rrset(now, header, plen, class1, type1, sigcnt, rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
931
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)
934 {
935- if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
936- return STAT_BOGUS; /* bad packet */
937+ if (class)
938+ *class = class1; /* Class for DS or DNSKEY */
939+ return rc;
940+ }
941+ else
942+ {
943+ /* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
944+
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. */
948+
949+ for (j = 0; j <targetidx; j++)
950+ if ((p2 = targets[j]))
951+ {
952+ if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
953+ return STAT_BOGUS; /* bad packet */
954+
955+ if (class1 == qclass && rc == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
956+ targets[j] = NULL;
957+ }
958+
959+ if (rc == STAT_SECURE_WILDCARD)
960+ {
961+ have_wildcard = 1;
962
963- GETSHORT(type2, p2);
964- GETSHORT(class2, p2);
965- GETLONG(ttl, p2);
966- GETSHORT(rdlen2, p2);
967-
968- if (!CHECK_LEN(header, p2, plen, rdlen2))
969- return STAT_BOGUS; /* bad packet */
970-
971- if (class2 == class1 && rc == 1)
972- {
973- psave = p2;
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 */
980+
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. */
984
985- if (type1 == T_DS && type2 == T_DS)
986- {
987- if (rdlen2 < 4)
988- return STAT_BOGUS; /* bad packet */
989-
990- GETSHORT(keytag, p2);
991- algo = *p2++;
992- digest = *p2++;
993-
994- /* Cache needs to known class for DNSSEC stuff */
995- a.addr.dnssec.class = class2;
996-
997- if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
998- {
999- if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1000- blockdata_free(key);
1001- else
1002- {
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;
1010- }
1011- }
1012- }
1013- else if (type2 == T_RRSIG)
1014- {
1015- if (rdlen2 < 18)
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);
1019+ else
1020+ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
1021+ keyname, name, type1, wildname, NULL);
1022+
1023+ if (rc == STAT_BOGUS)
1024+ return rc;
1025+ }
1026+
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();
1030+
1031+ for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
1032+ {
1033+ if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1034+ return STAT_BOGUS; /* bad packet */
1035+
1036+ GETSHORT(type2, p2);
1037+ GETSHORT(class2, p2);
1038+ GETLONG(ttl, p2);
1039+ GETSHORT(rdlen2, p2);
1040+
1041+ if (!CHECK_LEN(header, p2, plen, rdlen2))
1042+ return STAT_BOGUS; /* bad packet */
1043+
1044+ if (class2 == class1 && rc == 1)
1045+ {
1046+ psave = p2;
1047
1048- GETSHORT(type_covered, p2);
1049-
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)
1055 {
1056- a.addr.dnssec.type = type_covered;
1057- a.addr.dnssec.class = class1;
1058+ if (rdlen2 < 4)
1059+ return STAT_BOGUS; /* bad packet */
1060
1061- algo = *p2++;
1062- p2 += 13; /* labels, orig_ttl, expiration, inception */
1063 GETSHORT(keytag, p2);
1064+ algo = *p2++;
1065+ digest = *p2++;
1066+
1067+ /* Cache needs to known class for DNSSEC stuff */
1068+ a.addr.dnssec.class = class2;
1069
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)))
1076 {
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);
1080 else
1081 {
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;
1094+ }
1095+ }
1096+ }
1097+ else if (type2 == T_RRSIG)
1098+ {
1099+ if (rdlen2 < 18)
1100+ return STAT_BOGUS; /* bad packet */
1101+
1102+ GETSHORT(type_covered, p2);
1103+
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))
1108+ {
1109+ a.addr.dnssec.type = type_covered;
1110+ a.addr.dnssec.class = class1;
1111+
1112+ algo = *p2++;
1113+ p2 += 13; /* labels, orig_ttl, expiration, inception */
1114+ GETSHORT(keytag, p2);
1115+
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)))
1121+ {
1122+ if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
1123+ blockdata_free(key);
1124+ else
1125+ {
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;
1131+ }
1132 }
1133 }
1134 }
1135+
1136+ p2 = psave;
1137 }
1138
1139- p2 = psave;
1140+ if (!ADD_RDLEN(header, p2, plen, rdlen2))
1141+ return STAT_BOGUS; /* bad packet */
1142 }
1143
1144- if (!ADD_RDLEN(header, p2, plen, rdlen2))
1145- return STAT_BOGUS; /* bad packet */
1146+ cache_end_insert();
1147 }
1148-
1149- cache_end_insert();
1150 }
1151 }
1152
1153@@ -2083,143 +2223,49 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
1154 return STAT_BOGUS;
1155 }
1156
1157- /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
1158- if (have_answer)
1159- return STAT_SECURE;
1160-
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)))
1164- {
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. */
1169- *keyname = 0;
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. */
1174- }
1175-
1176- /* Get name of missing answer */
1177- if (!extract_name(header, plen, &qname, name, 1, 0))
1178- return STAT_BOGUS;
1179-
1180- if (nsec_type == T_NSEC)
1181- return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons);
1182- else
1183- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons);
1184-}
1185-
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
1191-*/
1192-int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
1193-{
1194- unsigned char *p = (unsigned char *)(header+1);
1195- int type, class, qclass, rdlen, j, rc;
1196- int cname_count = CNAME_CHAIN;
1197- char *wildname;
1198-
1199- /* Get question */
1200- if (!extract_name(header, plen, &p, name, 1, 4))
1201- return STAT_BOGUS;
1202-
1203- p +=2; /* type */
1204- GETSHORT(qclass, p);
1205-
1206- while (1)
1207- {
1208- for (j = ntohs(header->ancount); j != 0; j--)
1209- {
1210- if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
1211- return STAT_BOGUS; /* bad packet */
1212-
1213- GETSHORT(type, p);
1214- GETSHORT(class, p);
1215- p += 4; /* TTL */
1216- GETSHORT(rdlen, p);
1217-
1218- /* Not target, loop */
1219- if (rc == 2 || qclass != class)
1220- {
1221- if (!ADD_RDLEN(header, p, plen, rdlen))
1222- return STAT_BOGUS;
1223- continue;
1224- }
1225-
1226- /* Got to end of CNAME chain. */
1227- if (type != T_CNAME)
1228- return STAT_INSECURE;
1229-
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);
1232-
1233- if (rc == STAT_SECURE_WILDCARD)
1234- {
1235- int nsec_type, nsec_count, i;
1236- unsigned char **nsecs;
1237-
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 */
1244-
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 */
1247-
1248- for (i = 0; i < nsec_count; i++)
1249- {
1250- unsigned char *p1 = nsecs[i];
1251-
1252- if (!extract_name(header, plen, &p1, daemon->workspacename, 1, 0))
1253- return STAT_BOGUS;
1254-
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]))
1259+ {
1260+ if (neganswer)
1261+ *neganswer = 1;
1262
1263- /* NSECs can't be wildcards. */
1264- if (rc == STAT_SECURE_WILDCARD)
1265- rc = STAT_BOGUS;
1266+ if (!extract_name(header, plen, &p2, name, 1, 10))
1267+ return STAT_BOGUS; /* bad packet */
1268+
1269+ /* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
1270
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)))
1275+ {
1276+ /* Empty DS without NSECS */
1277+ if (qtype == T_DS)
1278+ return STAT_BOGUS;
1279+ else
1280+ {
1281+ rc = zone_status(name, qclass, keyname, now);
1282+ if (rc != STAT_SECURE)
1283+ {
1284+ if (class)
1285+ *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
1286 return rc;
1287- }
1288-
1289- if (nsec_type == T_NSEC)
1290- rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type, NULL);
1291- else
1292- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename,
1293- keyname, name, type, wildname, NULL);
1294-
1295- if (rc != STAT_SECURE)
1296- return rc;
1297- }
1298-
1299- if (rc != STAT_SECURE)
1300- {
1301- if (rc == STAT_NO_SIG)
1302- rc = STAT_INSECURE;
1303- return rc;
1304- }
1305+ }
1306+
1307+ return STAT_BOGUS; /* signed zone, no NSECs */
1308+ }
1309+ }
1310
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;
1316-
1317- break;
1318- }
1319+ if (nsec_type == T_NSEC)
1320+ rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons);
1321+ else
1322+ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons);
1323
1324- /* End of CNAME chain */
1325- return STAT_INSECURE;
1326- }
1327+ if (rc != STAT_SECURE)
1328+ return rc;
1329+ }
1330+
1331+ return STAT_SECURE;
1332 }
1333
1334
1335diff --git a/src/forward.c b/src/forward.c
1336index b76a974..dd22a62 100644
1337--- a/src/forward.c
1338+++ b/src/forward.c
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);
1342
1343-#ifdef HAVE_DNSSEC
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);
1349-#endif
1350-
1351-
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)
1356 #ifdef HAVE_DNSSEC
1357 if (server && option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
1358 {
1359- int status;
1360+ int status = 0;
1361
1362 /* We've had a reply already, which we're validating. Ignore this duplicate */
1363 if (forward->blocking_query)
1364 return;
1365-
1366- if (header->hb3 & HB3_TC)
1367- {
1368- /* Truncated answer can't be validated.
1369+
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.
1374 */
1375- status = STAT_TRUNCATED;
1376- }
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)
1380- {
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)
1389- {
1390- if (option_bool(OPT_DNSSEC_NO_SIGN))
1391- {
1392- status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1393- if (status == STAT_INSECURE)
1394- status = STAT_INSECURE_DS;
1395- }
1396- else
1397- status = STAT_INSECURE_DS;
1398- }
1399- else if (status == STAT_NO_NS)
1400- status = STAT_BOGUS;
1401- }
1402- else if (forward->flags & FREC_CHECK_NOSIGN)
1403- {
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);
1407- }
1408- else
1409+ if (header->hb3 & HB3_TC)
1410+ status = STAT_TRUNCATED;
1411+
1412+ while (1)
1413 {
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)
1420 {
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);
1427 else
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);
1431 }
1432- }
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)
1436- {
1437- struct frec *new, *orig;
1438-
1439- /* Free any saved query */
1440- if (forward->stash)
1441- blockdata_free(forward->stash);
1442-
1443- /* Now save reply pending receipt of key data */
1444- if (!(forward->stash = blockdata_alloc((char *)header, n)))
1445- return;
1446- forward->stash_len = n;
1447
1448- anotherkey:
1449- /* Find the original query that started it all.... */
1450- for (orig = forward; orig->dependent; orig = orig->dependent);
1451-
1452- if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1453- status = STAT_INSECURE;
1454- else
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)
1458 {
1459- int fd;
1460- struct frec *next = new->next;
1461- *new = *forward; /* copy everything, then overwrite */
1462- new->next = next;
1463- new->blocking_query = NULL;
1464- new->sentto = server;
1465- new->rfd4 = NULL;
1466- new->orig_domain = NULL;
1467-#ifdef HAVE_IPV6
1468- new->rfd6 = NULL;
1469-#endif
1470- new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_CHECK_NOSIGN);
1471+ struct frec *new, *orig;
1472
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)
1477- {
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);
1481- }
1482- else
1483- {
1484- if (status == STAT_NEED_DS_NEG)
1485- new->flags |= FREC_CHECK_NOSIGN;
1486- else
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);
1490- }
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);
1500+
1501+ /* Now save reply pending receipt of key data */
1502+ if (!(forward->stash = blockdata_alloc((char *)header, n)))
1503 return;
1504-
1505- new->stash_len = nn;
1506+ forward->stash_len = n;
1507
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);
1512
1513- if (server->sfd)
1514- fd = server->sfd->fd;
1515+ if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
1516+ status = STAT_ABANDONED;
1517 else
1518 {
1519- fd = -1;
1520+ int fd;
1521+ struct frec *next = new->next;
1522+ *new = *forward; /* copy everything, then overwrite */
1523+ new->next = next;
1524+ new->blocking_query = NULL;
1525+ new->sentto = server;
1526+ new->rfd4 = NULL;
1527 #ifdef HAVE_IPV6
1528- if (server->addr.sa.sa_family == AF_INET6)
1529+ new->rfd6 = NULL;
1530+#endif
1531+ new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
1532+
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)
1537+ {
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);
1541+ }
1542+ else
1543 {
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);
1549 }
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;
1557+
1558+ /* Don't resend this. */
1559+ daemon->srv_save = NULL;
1560+
1561+ if (server->sfd)
1562+ fd = server->sfd->fd;
1563 else
1564+ {
1565+ fd = -1;
1566+#ifdef HAVE_IPV6
1567+ if (server->addr.sa.sa_family == AF_INET6)
1568+ {
1569+ if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
1570+ fd = new->rfd6->fd;
1571+ }
1572+ else
1573 #endif
1574+ {
1575+ if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
1576+ fd = new->rfd4->fd;
1577+ }
1578+ }
1579+
1580+ if (fd != -1)
1581 {
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,
1585+ &server->addr.sa,
1586+ sa_len(&server->addr))));
1587+ server->queries++;
1588 }
1589- }
1590-
1591- if (fd != -1)
1592- {
1593- while (retry_send(sendto(fd, (char *)header, nn, 0,
1594- &server->addr.sa,
1595- sa_len(&server->addr))));
1596- server->queries++;
1597- }
1598-
1599+ }
1600 return;
1601 }
1602- }
1603
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)
1611- {
1612+ /* Validated original answer, all done. */
1613+ if (!forward->dependent)
1614+ break;
1615+
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;
1619 free_frec(forward);
1620 forward = prev;
1621 forward->blocking_query = NULL; /* already gone */
1622 blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
1623 n = forward->stash_len;
1624-
1625- if (status == STAT_SECURE)
1626- {
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)
1630- {
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)
1639- {
1640- if (option_bool(OPT_DNSSEC_NO_SIGN))
1641- {
1642- status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1643- if (status == STAT_INSECURE)
1644- status = STAT_INSECURE_DS;
1645- }
1646- else
1647- status = STAT_INSECURE_DS;
1648- }
1649- else if (status == STAT_NO_NS)
1650- status = STAT_BOGUS;
1651- }
1652- else if (forward->flags & FREC_CHECK_NOSIGN)
1653- {
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);
1657- }
1658- else
1659- {
1660- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL);
1661- if (status == STAT_NO_SIG)
1662- {
1663- if (option_bool(OPT_DNSSEC_NO_SIGN))
1664- status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
1665- else
1666- status = STAT_INSECURE;
1667- }
1668- }
1669-
1670- if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
1671- goto anotherkey;
1672- }
1673 }
1674+
1675
1676 no_cache_dnssec = 0;
1677-
1678- if (status == STAT_INSECURE_DS)
1679- {
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;
1685- }
1686
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)
1690 {
1691 char *result, *domain = "result";
1692
1693- if (forward->work_counter == 0)
1694+ if (status == STAT_ABANDONED)
1695 {
1696 result = "ABANDONED";
1697 status = STAT_BOGUS;
1698@@ -1072,7 +969,7 @@ void reply_query(int fd, int family, time_t now)
1699
1700 if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
1701 domain = daemon->namebuff;
1702-
1703+
1704 log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
1705 }
1706
1707@@ -1415,315 +1312,49 @@ void receive_query(struct listener *listen, time_t now)
1708 }
1709
1710 #ifdef HAVE_DNSSEC
1711-
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)
1717-{
1718- int status = dnssec_chase_cname(now, header, plen, name, keyname);
1719-
1720- if (status != STAT_INSECURE)
1721- return status;
1722-
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;
1728-
1729- return do_check_sign(forward, 0, now, name, keyname);
1730-}
1731-
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)
1734-{
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;
1738-
1739- blockdata_retrieve(forward->orig_domain, forward->name_len, name);
1740-
1741- while (1)
1742- {
1743- char *p;
1744-
1745- if (status == 0)
1746- {
1747- struct crec *crecp;
1748-
1749- /* Haven't received answer, see if in cache */
1750- if (!(crecp = cache_find_by_name(NULL, &name[forward->name_start], now, F_DS)))
1751- {
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;
1756- }
1757-
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;
1763- else
1764- status = STAT_NO_NS;
1765- }
1766-
1767- /* Have entered non-signed part of DNS tree. */
1768- if (status == STAT_NO_DS)
1769- return forward->dependent ? STAT_INSECURE_DS : STAT_INSECURE;
1770-
1771- if (status == STAT_BOGUS)
1772- return STAT_BOGUS;
1773-
1774- if (status == STAT_NO_SIG && *keyname != 0)
1775- {
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;
1783-
1784- strcpy(name, keyname);
1785- status = 0; /* force to cache when we iterate. */
1786- continue;
1787- }
1788-
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 */
1792-
1793- if (forward->name_start == 0)
1794- return STAT_BOGUS;
1795-
1796- for (p = &name[forward->name_start-2]; (*p != '.') && (p != name); p--);
1797-
1798- if (p != name)
1799- p++;
1800-
1801- forward->name_start = p - name;
1802- status = 0; /* force to cache when we iterate. */
1803- }
1804-}
1805-
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)
1811-{
1812- size_t m;
1813- unsigned char *packet, *payload;
1814- u16 *length;
1815- int status, name_len;
1816- struct blockdata *block;
1817-
1818- char *name_start;
1819-
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;
1824-
1825- if (!(packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16))))
1826- return STAT_BOGUS;
1827-
1828- payload = &packet[2];
1829- header = (struct dns_header *)payload;
1830- length = (u16 *)packet;
1831-
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;
1835-
1836- if (!(block = blockdata_alloc(name, name_len)))
1837- {
1838- free(packet);
1839- return STAT_BOGUS;
1840- }
1841-
1842- while (1)
1843- {
1844- unsigned char c1, c2;
1845- struct crec *crecp;
1846-
1847- if (--(*keycount) == 0)
1848- {
1849- free(packet);
1850- blockdata_free(block);
1851- return STAT_BOGUS;
1852- }
1853-
1854- while ((crecp = cache_find_by_name(NULL, name_start, now, F_DS)))
1855- {
1856- if ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK))
1857- {
1858- /* Found a secure denial of DS - delegation is indeed insecure */
1859- free(packet);
1860- blockdata_free(block);
1861- return STAT_INSECURE;
1862- }
1863-
1864- /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation.
1865- Add another label and continue. */
1866-
1867- if (name_start == name)
1868- {
1869- free(packet);
1870- blockdata_free(block);
1871- return STAT_BOGUS; /* run out of labels */
1872- }
1873-
1874- name_start -= 2;
1875- while (*name_start != '.' && name_start != name)
1876- name_start--;
1877- if (name_start != name)
1878- name_start++;
1879- }
1880-
1881- /* Can't find it in the cache, have to send a query */
1882-
1883- m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr, server->edns_pktsz);
1884-
1885- *length = htons(m);
1886-
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))
1891- {
1892- m = (c1 << 8) | c2;
1893-
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);
1896-
1897- if (status == STAT_NO_DS)
1898- {
1899- /* Found a secure denial of DS - delegation is indeed insecure */
1900- free(packet);
1901- blockdata_free(block);
1902- return STAT_INSECURE;
1903- }
1904-
1905- if (status == STAT_NO_SIG && *keyname != 0)
1906- {
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;
1912-
1913- if (!(block = blockdata_alloc(keyname, name_len)))
1914- return STAT_BOGUS;
1915-
1916- strcpy(name, keyname);
1917- continue;
1918- }
1919-
1920- if (status == STAT_BOGUS)
1921- {
1922- free(packet);
1923- blockdata_free(block);
1924- return STAT_BOGUS;
1925- }
1926-
1927- /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation.
1928- Add another label and continue. */
1929-
1930- /* Get name we're checking back. */
1931- blockdata_retrieve(block, name_len, name);
1932-
1933- if (name_start == name)
1934- {
1935- free(packet);
1936- blockdata_free(block);
1937- return STAT_BOGUS; /* run out of labels */
1938- }
1939-
1940- name_start -= 2;
1941- while (*name_start != '.' && name_start != name)
1942- name_start--;
1943- if (name_start != name)
1944- name_start++;
1945- }
1946- else
1947- {
1948- /* IO failure */
1949- free(packet);
1950- blockdata_free(block);
1951- return STAT_BOGUS; /* run out of labels */
1952- }
1953- }
1954-}
1955-
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)
1958 {
1959 /* Recurse up the key heirarchy */
1960 int new_status;
1961+ unsigned char *packet = NULL;
1962+ size_t m;
1963+ unsigned char *payload = NULL;
1964+ struct dns_header *new_header = NULL;
1965+ u16 *length = NULL;
1966+ unsigned char c1, c2;
1967
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;
1971-
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)
1975+ while (1)
1976 {
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);
1986+ else
1987+ new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
1988+
1989+ if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
1990+ break;
1991+
1992+ /* Can't validate because we need a key/DS whose name now in keyname.
1993+ Make query for same, and recurse to validate */
1994+ if (!packet)
1995 {
1996- if (new_status == STAT_NO_DS)
1997- new_status = STAT_INSECURE_DS;
1998- if (new_status == STAT_NO_SIG)
1999- {
2000- if (option_bool(OPT_DNSSEC_NO_SIGN))
2001- {
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;
2005- }
2006- else
2007- new_status = STAT_INSECURE_DS;
2008- }
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;
2015 }
2016- }
2017- else if (status == STAT_CHASE_CNAME)
2018- new_status = dnssec_chase_cname(now, header, n, name, keyname);
2019- else
2020- {
2021- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL);
2022
2023- if (new_status == STAT_NO_SIG)
2024+ if (!packet)
2025 {
2026- if (option_bool(OPT_DNSSEC_NO_SIGN))
2027- new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2028- else
2029- new_status = STAT_INSECURE;
2030+ new_status = STAT_ABANDONED;
2031+ break;
2032 }
2033- }
2034-
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)
2038- {
2039- size_t m;
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;
2045-
2046- if (!packet)
2047- return STAT_INSECURE;
2048-
2049- another_tcp_key:
2050+
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);
2053
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;
2059- else
2060 {
2061- m = (c1 << 8) | c2;
2062-
2063- new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
2064-
2065- if (new_status == STAT_SECURE)
2066- {
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. */
2070-
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)
2074- {
2075- new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
2076- if (status == STAT_NEED_DS)
2077- {
2078- if (new_status == STAT_NO_DS)
2079- new_status = STAT_INSECURE_DS;
2080- else if (new_status == STAT_NO_SIG)
2081- {
2082- if (option_bool(OPT_DNSSEC_NO_SIGN))
2083- {
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;
2087- }
2088- else
2089- new_status = STAT_INSECURE_DS;
2090- }
2091- else if (new_status == STAT_NO_NS)
2092- new_status = STAT_BOGUS;
2093- }
2094- }
2095- else if (status == STAT_CHASE_CNAME)
2096- new_status = dnssec_chase_cname(now, header, n, name, keyname);
2097- else
2098- {
2099- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL);
2100-
2101- if (new_status == STAT_NO_SIG)
2102- {
2103- if (option_bool(OPT_DNSSEC_NO_SIGN))
2104- new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
2105- else
2106- new_status = STAT_INSECURE;
2107- }
2108- }
2109-
2110- if (new_status == STAT_NEED_DS || new_status == STAT_NEED_KEY)
2111- goto another_tcp_key;
2112- }
2113+ new_status = STAT_ABANDONED;
2114+ break;
2115 }
2116+
2117+ m = (c1 << 8) | c2;
2118
2119- free(packet);
2120+ new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
2121+
2122+ if (new_status != STAT_OK)
2123+ break;
2124 }
2125+
2126+ if (packet)
2127+ free(packet);
2128+
2129 return new_status;
2130 }
2131 #endif
2132@@ -2075,19 +1663,10 @@ unsigned char *tcp_request(int confd, time_t now,
2133 if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled)
2134 {
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";
2139-
2140- if (status == STAT_INSECURE_DS)
2141- {
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;
2147- }
2148
2149- if (keycount == 0)
2150+ if (status == STAT_ABANDONED)
2151 {
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;
2157 f->stash = NULL;
2158- f->orig_domain = NULL;
2159 #endif
2160 daemon->frec_list = f;
2161 }
2162@@ -2248,12 +1826,6 @@ static void free_frec(struct frec *f)
2163 f->stash = NULL;
2164 }
2165
2166- if (f->orig_domain)
2167- {
2168- blockdata_free(f->orig_domain);
2169- f->orig_domain = NULL;
2170- }
2171-
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)
2176 target = f;
2177 else
2178 {
2179- if (difftime(now, f->time) >= 4*TIMEOUT)
2180- {
2181- free_frec(f);
2182- target = f;
2183- }
2184-
2185- if (!oldest || difftime(f->time, oldest->time) <= 0)
2186- oldest = f;
2187+#ifdef HAVE_DNSSEC
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
2190+ is freed. */
2191+ if (!f->dependent)
2192+#endif
2193+ {
2194+ if (difftime(now, f->time) >= 4*TIMEOUT)
2195+ {
2196+ free_frec(f);
2197+ target = f;
2198+ }
2199+
2200+
2201+ if (!oldest || difftime(f->time, oldest->time) <= 0)
2202+ oldest = f;
2203+ }
2204 }
2205
2206 if (target)
2207--
22081.7.10.4
2209