1 From d64c81fff7faf4392b688223ef3a617c5c07e7dc Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Tue, 15 Dec 2015 16:11:06 +0000
4 Subject: [PATCH] Move code which caches DS records to a more logical place.
7 src/dnssec.c | 179 +++++++++++++++++++++++++++++-----------------------------
8 1 file changed, 90 insertions(+), 89 deletions(-)
10 diff --git a/src/dnssec.c b/src/dnssec.c
11 index 1ae03a6..359231f 100644
14 @@ -1204,7 +1204,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
15 int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
17 unsigned char *p = (unsigned char *)(header+1);
18 - int qtype, qclass, val, i, neganswer, nons;
19 + int qtype, qclass, rc, i, neganswer, nons;
20 + int aclass, atype, rdlen;
24 if (ntohs(header->qdcount) != 1 ||
25 !(p = skip_name(p, header, plen, 4)))
26 @@ -1214,40 +1217,100 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
29 if (qtype != T_DS || qclass != class)
33 - val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
34 + rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
35 /* Note dnssec_validate_reply() will have cached positive answers */
37 - if (val == STAT_INSECURE)
40 + if (rc == STAT_INSECURE)
43 p = (unsigned char *)(header+1);
44 extract_name(header, plen, &p, name, 1, 4);
45 p += 4; /* qtype, qclass */
47 - if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
50 /* If the key needed to validate the DS is on the same domain as the DS, we'll
51 loop getting nowhere. Stop that now. This can happen of the DS answer comes
52 from the DS's zone, and not the parent zone. */
53 - if (val == STAT_BOGUS || (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
54 + if (rc == STAT_BOGUS || (rc == STAT_NEED_KEY && hostname_isequal(name, keyname)))
56 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
60 - if (val != STAT_SECURE)
63 - /* By here, the answer is proved secure, and a positive answer has been cached. */
65 + if (rc != STAT_SECURE)
70 - int rdlen, flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
71 - unsigned long ttl, minttl = ULONG_MAX;
73 + cache_start_insert();
75 + for (i = 0; i < ntohs(header->ancount); i++)
77 + if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
78 + return STAT_BOGUS; /* bad packet */
81 + GETSHORT(aclass, p);
85 + if (!CHECK_LEN(header, p, plen, rdlen))
86 + return STAT_BOGUS; /* bad packet */
88 + if (aclass == class && atype == T_DS && rc == 1)
90 + int algo, digest, keytag;
91 + unsigned char *psave = p;
92 + struct blockdata *key;
96 + return STAT_BOGUS; /* bad packet */
98 + GETSHORT(keytag, p);
102 + /* Cache needs to known class for DNSSEC stuff */
103 + a.addr.dnssec.class = class;
105 + if ((key = blockdata_alloc((char*)p, rdlen - 4)))
107 + if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
109 + blockdata_free(key);
114 + a.addr.keytag = keytag;
115 + log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
116 + crecp->addr.ds.digest = digest;
117 + crecp->addr.ds.keydata = key;
118 + crecp->addr.ds.algo = algo;
119 + crecp->addr.ds.keytag = keytag;
120 + crecp->addr.ds.keylen = rdlen - 4;
126 + if (!ADD_RDLEN(header, p, plen, rdlen))
127 + return STAT_BOGUS; /* bad packet */
130 + cache_end_insert();
135 + int flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
136 + unsigned long minttl = ULONG_MAX;
138 + if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
141 if (RCODE(header) == NXDOMAIN)
144 @@ -1261,20 +1324,20 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
145 if (!(p = skip_name(p, header, plen, 0)))
148 - GETSHORT(qtype, p);
149 - GETSHORT(qclass, p);
150 + GETSHORT(atype, p);
151 + GETSHORT(aclass, p);
156 if (!CHECK_LEN(header, p, plen, rdlen))
157 return STAT_BOGUS; /* bad packet */
159 - if (qclass != class || qtype != T_SOA)
161 + if (aclass != class || atype != T_SOA)
171 @@ -1306,7 +1369,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
172 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS");
180 @@ -2001,11 +2064,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
181 /* Not done, validate now */
184 - int ttl, keytag, algo, digest, sigcnt, rrcnt;
185 - unsigned char *psave;
187 - struct blockdata *key;
188 - struct crec *crecp;
192 if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
193 @@ -2032,6 +2091,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
194 Can't overwrite name here. */
195 strcpy(daemon->workspacename, keyname);
196 rc = zone_status(daemon->workspacename, class1, keyname, now);
198 if (rc != STAT_SECURE)
200 /* Zone is insecure, don't need to validate RRset */
201 @@ -2088,65 +2148,6 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
202 if (rc == STAT_BOGUS)
206 - /* If we just validated a DS RRset, cache it */
207 - /* Also note if the RRset is the answer to the question, or the target of a CNAME */
208 - cache_start_insert();
210 - for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
212 - if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
213 - return STAT_BOGUS; /* bad packet */
215 - GETSHORT(type2, p2);
216 - GETSHORT(class2, p2);
218 - GETSHORT(rdlen2, p2);
220 - if (!CHECK_LEN(header, p2, plen, rdlen2))
221 - return STAT_BOGUS; /* bad packet */
223 - if (class2 == class1 && rc == 1)
227 - if (type1 == T_DS && type2 == T_DS)
230 - return STAT_BOGUS; /* bad packet */
232 - GETSHORT(keytag, p2);
236 - /* Cache needs to known class for DNSSEC stuff */
237 - a.addr.dnssec.class = class2;
239 - if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
241 - if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
242 - blockdata_free(key);
245 - a.addr.keytag = keytag;
246 - log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
247 - crecp->addr.ds.digest = digest;
248 - crecp->addr.ds.keydata = key;
249 - crecp->addr.ds.algo = algo;
250 - crecp->addr.ds.keytag = keytag;
251 - crecp->addr.ds.keylen = rdlen2 - 4;
259 - if (!ADD_RDLEN(header, p2, plen, rdlen2))
260 - return STAT_BOGUS; /* bad packet */
263 - cache_end_insert();