blob: 089d1a529041cb73dab867ebed4f7b0e4ef2f723 [file] [log] [blame]
Giovanni Bajo8d41ebd2012-05-05 00:48:12 +02001/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
Simon Kelley0fc2f312014-01-08 10:26:58 +00002 and Copyright (c) 2012-2014 Simon Kelley
Giovanni Bajo8d41ebd2012-05-05 00:48:12 +02003
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 dated June, 1991, or
7 (at your option) version 3 dated 29 June, 2007.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
Giovanni Bajoe292e932012-04-22 14:32:02 +020017
18#include "dnsmasq.h"
Simon Kelley0fc2f312014-01-08 10:26:58 +000019
20#ifdef HAVE_DNSSEC
21
Simon Kelley86bec2d2014-01-13 21:31:20 +000022#include <nettle/rsa.h>
23#include <nettle/dsa.h>
24#include <nettle/nettle-meta.h>
25#include <gmp.h>
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000026
Giovanni Bajoe292e932012-04-22 14:32:02 +020027#define SERIAL_UNDEF -100
28#define SERIAL_EQ 0
29#define SERIAL_LT -1
30#define SERIAL_GT 1
31
Simon Kelley86bec2d2014-01-13 21:31:20 +000032/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
33static char *ds_digest_name(int digest)
34{
35 switch (digest)
36 {
37 case 1: return "sha1";
38 case 2: return "sha256";
39 case 3: return "gosthash94";
40 case 4: return "sha384";
41 default: return NULL;
42 }
43}
44
45/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
46static char *algo_digest_name(int algo)
47{
48 switch (algo)
49 {
50 case 1: return "md5";
51 case 3: return "sha1";
52 case 5: return "sha1";
53 case 6: return "sha1";
54 case 7: return "sha1";
55 case 8: return "sha256";
56 case 10: return "sha512";
57 case 12: return "gosthash94";
58 case 13: return "sha256";
59 case 14: return "sha384";
60 default: return NULL;
61 }
62}
63
64/* Find pointer to correct hash function in nettle library */
65static const struct nettle_hash *hash_find(char *name)
66{
67 int i;
68
69 if (!name)
70 return NULL;
71
72 for (i = 0; nettle_hashes[i]; i++)
73 {
74 if (strcmp(nettle_hashes[i]->name, name) == 0)
75 return nettle_hashes[i];
76 }
77
78 return NULL;
79}
80
81/* expand ctx and digest memory allocations if necessary and init hash function */
82static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
83{
84 static void *ctx = NULL;
85 static unsigned char *digest = NULL;
86 static unsigned int ctx_sz = 0;
87 static unsigned int digest_sz = 0;
88
89 void *new;
90
91 if (ctx_sz < hash->context_size)
92 {
93 if (!(new = whine_malloc(hash->context_size)))
94 return 0;
95 if (ctx)
96 free(ctx);
97 ctx = new;
98 ctx_sz = hash->context_size;
99 }
100
101 if (digest_sz < hash->digest_size)
102 {
103 if (!(new = whine_malloc(hash->digest_size)))
104 return 0;
105 if (digest)
106 free(digest);
107 digest = new;
108 digest_sz = hash->digest_size;
109 }
110
111 *ctxp = ctx;
112 *digestp = digest;
113
114 hash->init(ctx);
115
116 return 1;
117}
118
119static int rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
120 unsigned char *digest, int algo)
121{
122 unsigned char *p;
123 size_t exp_len;
124
125 static struct rsa_public_key *key = NULL;
126 static mpz_t sig_mpz;
127
128 if (key == NULL)
129 {
130 if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
131 return 0;
132
133 nettle_rsa_public_key_init(key);
134 mpz_init(sig_mpz);
135 }
136
137 if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
138 return 0;
139
140 key_len--;
141 if ((exp_len = *p++) == 0)
142 {
143 GETSHORT(exp_len, p);
144 key_len -= 2;
145 }
146
147 if (exp_len >= key_len)
148 return 0;
149
150 key->size = key_len - exp_len;
151 mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
152 mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
153
154 mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
155
156 switch (algo)
157 {
158 case 1:
159 return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
160 case 5: case 7:
161 return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
162 case 8:
163 return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
164 case 10:
165 return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
166 }
167
168 return 0;
169}
170
171static int dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
172 unsigned char *digest, int algo)
173{
174 unsigned char *p;
175 unsigned int t;
176
177 static struct dsa_public_key *key = NULL;
178 static struct dsa_signature *sig_struct;
179
180 if (key == NULL)
181 {
182 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
183 !(key = whine_malloc(sizeof(struct dsa_public_key))))
184 return 0;
185
186 nettle_dsa_public_key_init(key);
187 nettle_dsa_signature_init(sig_struct);
188 }
189
190 if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
191 return 0;
192
193 t = *p++;
194
195 if (key_len < (213 + (t * 24)))
196 return 0;
197
198 mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
199 mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
200 mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
201 mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
202
203 mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
204 mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
205
206 (void)algo;
207
208 return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
209}
210
211static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
212 unsigned char *digest, int algo)
213{
214 switch (algo)
215 {
216 case 1: case 5: case 7: case 8: case 10:
217 return rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
218
219 case 3: case 6:
220 return dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
221 }
222
223 return 0;
224}
225
Simon Kelley0fc2f312014-01-08 10:26:58 +0000226/* Convert from presentation format to wire format, in place.
227 Also map UC -> LC.
228 Note that using extract_name to get presentation format
229 then calling to_wire() removes compression and maps case,
230 thus generating names in canonical form.
231 Calling to_wire followed by from_wire is almost an identity,
232 except that the UC remains mapped to LC.
233*/
234static int to_wire(char *name)
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200235{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000236 unsigned char *l, *p, term;
237 int len;
238
239 for (l = (unsigned char*)name; *l != 0; l = p)
240 {
241 for (p = l; *p != '.' && *p != 0; p++)
242 if (*p >= 'A' && *p <= 'Z')
243 *p = *p - 'A' + 'a';
244
245 term = *p;
246
247 if ((len = p - l) != 0)
248 memmove(l+1, l, len);
249 *l = len;
250
251 p++;
252
253 if (term == 0)
254 *p = 0;
255 }
256
257 return l + 1 - (unsigned char *)name;
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200258}
259
Simon Kelley0fc2f312014-01-08 10:26:58 +0000260/* Note: no compression allowed in input. */
261static void from_wire(char *name)
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200262{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000263 unsigned char *l;
264 int len;
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200265
Simon Kelley0fc2f312014-01-08 10:26:58 +0000266 for (l = (unsigned char *)name; *l != 0; l += len+1)
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200267 {
Simon Kelley0fc2f312014-01-08 10:26:58 +0000268 len = *l;
269 memmove(l, l+1, len);
270 l[len] = '.';
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200271 }
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200272
Simon Kelley0fc2f312014-01-08 10:26:58 +0000273 *(l-1) = 0;
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200274}
275
Simon Kelley5ada8882014-01-09 22:25:03 +0000276/* Input in presentation format */
277static int count_labels(char *name)
278{
279 int i;
280
281 if (*name == 0)
282 return 0;
283
284 for (i = 0; *name; name++)
285 if (*name == '.')
286 i++;
287
288 return i+1;
289}
290
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000291/* Implement RFC1982 wrapped compare for 32-bit numbers */
292static int serial_compare_32(unsigned long s1, unsigned long s2)
Giovanni Bajo0852d762012-04-28 03:49:24 +0200293{
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000294 if (s1 == s2)
295 return SERIAL_EQ;
Giovanni Bajo0852d762012-04-28 03:49:24 +0200296
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000297 if ((s1 < s2 && (s2 - s1) < (1UL<<31)) ||
298 (s1 > s2 && (s1 - s2) > (1UL<<31)))
299 return SERIAL_LT;
300 if ((s1 < s2 && (s2 - s1) > (1UL<<31)) ||
301 (s1 > s2 && (s1 - s2) < (1UL<<31)))
302 return SERIAL_GT;
303 return SERIAL_UNDEF;
304}
Giovanni Bajo0852d762012-04-28 03:49:24 +0200305
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000306/* Check whether today/now is between date_start and date_end */
307static int check_date_range(unsigned long date_start, unsigned long date_end)
308{
309 unsigned long curtime = time(0);
310
311 /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
312 return serial_compare_32(curtime, date_start) == SERIAL_GT
313 && serial_compare_32(curtime, date_end) == SERIAL_LT;
314}
315
316static u16 *get_desc(int type)
317{
318 /* List of RRtypes which include domains in the data.
319 0 -> domain
320 integer -> no of plain bytes
321 -1 -> end
322
323 zero is not a valid RRtype, so the final entry is returned for
324 anything which needs no mangling.
325 */
326
327 static u16 rr_desc[] =
328 {
329 T_NS, 0, -1,
330 T_MD, 0, -1,
331 T_MF, 0, -1,
332 T_CNAME, 0, -1,
333 T_SOA, 0, 0, -1,
334 T_MB, 0, -1,
335 T_MG, 0, -1,
336 T_MR, 0, -1,
337 T_PTR, 0, -1,
338 T_MINFO, 0, 0, -1,
339 T_MX, 2, 0, -1,
340 T_RP, 0, 0, -1,
341 T_AFSDB, 2, 0, -1,
342 T_RT, 2, 0, -1,
343 T_SIG, 18, 0, -1,
344 T_PX, 2, 0, 0, -1,
345 T_NXT, 0, -1,
346 T_KX, 2, 0, -1,
347 T_SRV, 6, 0, -1,
348 T_DNAME, 0, -1,
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000349 0, -1 /* wildcard/catchall */
350 };
351
352 u16 *p = rr_desc;
353
354 while (*p != type && *p != 0)
355 while (*p++ != (u16)-1);
356
357 return p+1;
358}
359
360/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
361 data, pointed to by *p, should be used raw. */
362static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff,
363 unsigned char **p, u16 **desc)
364{
365 int d = **desc;
366
367 (*desc)++;
368
369 /* No more data needs mangling */
370 if (d == (u16)-1)
Giovanni Bajof119ed32012-05-02 00:31:55 +0200371 return 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000372
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000373 if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
374 /* domain-name, canonicalise */
375 return to_wire(buff);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000376 else
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000377 {
378 /* plain data preceding a domain-name, don't run off the end of the data */
379 if ((end - *p) < d)
380 d = end - *p;
381
382 if (d != 0)
383 {
384 memcpy(buff, *p, d);
385 *p += d;
386 }
387
388 return d;
389 }
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000390}
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000391
392/* Bubble sort the RRset into the canonical order.
393 Note that the byte-streams from two RRs may get unsynced: consider
394 RRs which have two domain-names at the start and then other data.
395 The domain-names may have different lengths in each RR, but sort equal
396
397 ------------
398 |abcde|fghi|
399 ------------
400 |abcd|efghi|
401 ------------
402
403 leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
404*/
405
406static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
407 unsigned char **rrset, char *buff1, char *buff2)
408{
409 int swap, quit, i;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000410
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000411 do
412 {
413 for (swap = 0, i = 0; i < rrsetidx-1; i++)
414 {
415 int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
416 u16 *dp1, *dp2;
417 unsigned char *end1, *end2;
418 unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
419 unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
420
421 p1 += 8; /* skip class, type, ttl */
422 GETSHORT(rdlen1, p1);
423 end1 = p1 + rdlen1;
424
425 p2 += 8; /* skip class, type, ttl */
426 GETSHORT(rdlen2, p2);
427 end2 = p2 + rdlen2;
428
429 dp1 = dp2 = rr_desc;
430
Simon Kelley1486a9c2014-01-10 11:39:14 +0000431 for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000432 {
Simon Kelley1486a9c2014-01-10 11:39:14 +0000433 if (left1 != 0)
434 memmove(buff1, buff1 + len1 - left1, left1);
435
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000436 if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
437 {
438 quit = 1;
439 len1 = end1 - p1;
440 memcpy(buff1 + left1, p1, len1);
441 }
442 len1 += left1;
443
Simon Kelley1486a9c2014-01-10 11:39:14 +0000444 if (left2 != 0)
445 memmove(buff2, buff2 + len2 - left2, left2);
446
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000447 if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
448 {
449 quit = 1;
450 len2 = end2 - p2;
451 memcpy(buff2 + left2, p2, len2);
452 }
453 len2 += left2;
454
455 if (len1 > len2)
Simon Kelley1486a9c2014-01-10 11:39:14 +0000456 left1 = len1 - len2, left2 = 0, len = len2;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000457 else
Simon Kelley1486a9c2014-01-10 11:39:14 +0000458 left2 = len2 - len1, left1 = 0, len = len1;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000459
Simon Kelley6fd6dac2014-01-21 20:17:40 +0000460 rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000461
Simon Kelley4619d942014-01-16 19:53:06 +0000462 if (rc > 0 || (rc == 0 && quit && len1 > len2))
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000463 {
464 unsigned char *tmp = rrset[i+1];
465 rrset[i+1] = rrset[i];
466 rrset[i] = tmp;
467 swap = quit = 1;
468 }
Simon Kelley6fd6dac2014-01-21 20:17:40 +0000469 else if (rc < 0)
470 quit = 1;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000471 }
472 }
473 } while (swap);
474}
475
476/* Validate a single RRset (class, type, name) in the supplied DNS reply
477 Return code:
478 STAT_SECURE if it validates.
479 STAT_INSECURE can't validate (no RRSIG, bad packet).
480 STAT_BOGUS signature is wrong.
481 STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
482
483 if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
484 otherwise find the key in the cache.
485*/
486static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class,
Simon Kelleye7829ae2014-01-22 22:21:51 +0000487 int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000488{
489 static unsigned char **rrset = NULL, **sigs = NULL;
490 static int rrset_sz = 0, sig_sz = 0;
491
492 unsigned char *p;
Simon Kelley5ada8882014-01-09 22:25:03 +0000493 int rrsetidx, sigidx, res, rdlen, j, name_labels;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000494 struct crec *crecp = NULL;
495 int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
496 u16 *rr_desc = get_desc(type);
497
498 if (!(p = skip_questions(header, plen)))
499 return STAT_INSECURE;
500
Simon Kelley5ada8882014-01-09 22:25:03 +0000501 name_labels = count_labels(name); /* For 4035 5.3.2 check */
502
Simon Kelleye7829ae2014-01-22 22:21:51 +0000503 cache_start_insert(); /* RRSIGS */
504
Simon Kelley5ada8882014-01-09 22:25:03 +0000505 /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000506 for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
507 j != 0; j--)
508 {
509 unsigned char *pstart, *pdata;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000510 int stype, sclass, ttl;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000511
512 pstart = p;
513
514 if (!(res = extract_name(header, plen, &p, name, 0, 10)))
515 return STAT_INSECURE; /* bad packet */
516
517 GETSHORT(stype, p);
518 GETSHORT(sclass, p);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000519 GETLONG(ttl, p);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000520
521 pdata = p;
522
523 GETSHORT(rdlen, p);
524
Simon Kelleye7829ae2014-01-22 22:21:51 +0000525 if (!CHECK_LEN(header, p, plen, rdlen))
526 return STAT_INSECURE;
527
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000528 if (res == 1 && sclass == class)
529 {
530 if (stype == type)
531 {
532 if (rrsetidx == rrset_sz)
533 {
534 unsigned char **new;
535
536 /* expand */
537 if (!(new = whine_malloc((rrset_sz + 5) * sizeof(unsigned char **))))
538 return STAT_INSECURE;
539
540 if (rrset)
541 {
542 memcpy(new, rrset, rrset_sz * sizeof(unsigned char **));
543 free(rrset);
544 }
545
546 rrset = new;
547 rrset_sz += 5;
548 }
549 rrset[rrsetidx++] = pstart;
550 }
551
552 if (stype == T_RRSIG)
553 {
Simon Kelley5ada8882014-01-09 22:25:03 +0000554 if (rdlen < 18)
555 return STAT_INSECURE; /* bad packet */
556
557 GETSHORT(type_covered, p);
Simon Kelley5ada8882014-01-09 22:25:03 +0000558
Simon Kelleye7829ae2014-01-22 22:21:51 +0000559 if (type_covered == type)
Simon Kelley5ada8882014-01-09 22:25:03 +0000560 {
561 if (sigidx == sig_sz)
562 {
563 unsigned char **new;
564
565 /* expand */
566 if (!(new = whine_malloc((sig_sz + 5) * sizeof(unsigned char **))))
567 return STAT_INSECURE;
568
569 if (sigs)
570 {
571 memcpy(new, sigs, sig_sz * sizeof(unsigned char **));
572 free(sigs);
573 }
574
575 sigs = new;
576 sig_sz += 5;
577 }
578
579 sigs[sigidx++] = pdata;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000580
581 /* If it's a type we're going to cache, cache the RRISG too */
582 if (type_covered == T_A || type_covered == T_AAAA ||
583 type_covered == T_CNAME || type_covered == T_DS ||
Simon Kelley2d33bda2014-01-24 22:37:25 +0000584 type_covered == T_DNSKEY || type_covered == T_PTR)
Simon Kelleye7829ae2014-01-22 22:21:51 +0000585 {
586 struct all_addr a;
587 struct blockdata *block;
588 a.addr.dnssec.class = class;
589 a.addr.dnssec.type = type_covered;
590
591 algo = *p++;
592 p += 13; /* labels, orig_ttl, expiration, inception */
593 GETSHORT(key_tag, p);
594 if ((block = blockdata_alloc((char*)pdata + 2, rdlen)) &&
595 (crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
596 {
Simon Kelley824202e2014-01-23 20:59:46 +0000597 crecp->uid = class;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000598 crecp->addr.sig.keydata = block;
Simon Kelley824202e2014-01-23 20:59:46 +0000599 crecp->addr.sig.keylen = rdlen;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000600 crecp->addr.sig.keytag = key_tag;
601 crecp->addr.sig.type_covered = type_covered;
602 crecp->addr.sig.algo = algo;
603 }
604 }
605 }
606
607 p = pdata + 2; /* restore for ADD_RDLEN */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000608 }
609 }
610
611 if (!ADD_RDLEN(header, p, plen, rdlen))
612 return STAT_INSECURE;
613 }
614
Simon Kelleye7829ae2014-01-22 22:21:51 +0000615 cache_end_insert(); /* RRSIGS */
616
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000617 /* RRset empty, no RRSIGs */
618 if (rrsetidx == 0 || sigidx == 0)
619 return STAT_INSECURE;
620
621 /* Sort RRset records into canonical order.
622 Note that at this point keyname and name buffs are
623 unused, and used as workspace by the sort. */
624 sort_rrset(header, plen, rr_desc, rrsetidx, rrset, name, keyname);
625
626 /* Now try all the sigs to try and find one which validates */
627 for (j = 0; j <sigidx; j++)
628 {
Simon Kelley86bec2d2014-01-13 21:31:20 +0000629 unsigned char *psav, *sig;
630 int i, wire_len, sig_len;
631 const struct nettle_hash *hash;
632 void *ctx;
633 unsigned char *digest;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000634 u32 nsigttl;
635
636 p = sigs[j];
Simon Kelley5ada8882014-01-09 22:25:03 +0000637 GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000638 psav = p;
639
Simon Kelley5ada8882014-01-09 22:25:03 +0000640 p += 2; /* type_covered - already checked */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000641 algo = *p++;
642 labels = *p++;
643 GETLONG(orig_ttl, p);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000644 GETLONG(sig_expiration, p);
645 GETLONG(sig_inception, p);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000646 GETSHORT(key_tag, p);
647
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000648 if (!extract_name(header, plen, &p, keyname, 1, 0))
649 return STAT_INSECURE;
650
Simon Kelleye7829ae2014-01-22 22:21:51 +0000651 if (!check_date_range(sig_inception, sig_expiration) ||
652 labels > name_labels ||
653 !(hash = hash_find(algo_digest_name(algo))) ||
654 !hash_init(hash, &ctx, &digest))
655 continue;
656
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000657 /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
658 if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
659 return STAT_NEED_KEY;
660
Simon Kelley86bec2d2014-01-13 21:31:20 +0000661 sig = p;
662 sig_len = rdlen - (p - psav);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000663
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000664 nsigttl = htonl(orig_ttl);
665
Simon Kelley86bec2d2014-01-13 21:31:20 +0000666 hash->update(ctx, 18, psav);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000667 wire_len = to_wire(keyname);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000668 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000669 from_wire(keyname);
670
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000671 for (i = 0; i < rrsetidx; ++i)
672 {
673 int seg;
674 unsigned char *end, *cp;
Simon Kelley5ada8882014-01-09 22:25:03 +0000675 char *name_start = name;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000676 u16 len, *dp;
677
678 p = rrset[i];
679 if (!extract_name(header, plen, &p, name, 1, 10))
680 return STAT_INSECURE;
Simon Kelley5ada8882014-01-09 22:25:03 +0000681
682 /* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
683 if (labels < name_labels)
684 {
685 int k;
686 for (k = name_labels - labels; k != 0; k--)
687 while (*name_start != '.' && *name_start != 0)
688 name_start++;
689 name_start--;
690 *name_start = '*';
691 }
692
693 wire_len = to_wire(name_start);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000694 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
695 hash->update(ctx, 4, p); /* class and type */
696 hash->update(ctx, 4, (unsigned char *)&nsigttl);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000697
698 p += 8; /* skip class, type, ttl */
699 GETSHORT(rdlen, p);
Simon Kelley5ada8882014-01-09 22:25:03 +0000700 if (!CHECK_LEN(header, p, plen, rdlen))
701 return STAT_INSECURE;
702
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000703 end = p + rdlen;
704
705 /* canonicalise rdata and calculate length of same, use name buffer as workspace */
706 cp = p;
707 dp = rr_desc;
708 for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
709 len += end - cp;
710 len = htons(len);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000711 hash->update(ctx, 2, (unsigned char *)&len);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000712
713 /* Now canonicalise again and digest. */
714 cp = p;
715 dp = rr_desc;
716 while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
Simon Kelley86bec2d2014-01-13 21:31:20 +0000717 hash->update(ctx, seg, (unsigned char *)name);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000718 if (cp != end)
Simon Kelley86bec2d2014-01-13 21:31:20 +0000719 hash->update(ctx, end - cp, cp);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000720 }
Simon Kelley86bec2d2014-01-13 21:31:20 +0000721
722 hash->digest(ctx, hash->digest_size, digest);
723
Simon Kelley5ada8882014-01-09 22:25:03 +0000724 /* namebuff used for workspace above, restore to leave unchanged on exit */
725 p = (unsigned char*)(rrset[0]);
726 extract_name(header, plen, &p, name, 1, 0);
727
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000728 if (key)
729 {
730 if (algo_in == algo && keytag_in == key_tag &&
Simon Kelley86bec2d2014-01-13 21:31:20 +0000731 verify(key, keylen, sig, sig_len, digest, algo))
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000732 return STAT_SECURE;
733 }
734 else
735 {
736 /* iterate through all possible keys 4035 5.3.1 */
737 for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000738 if (crecp->addr.key.algo == algo &&
739 crecp->addr.key.keytag == key_tag &&
Simon Kelley824202e2014-01-23 20:59:46 +0000740 crecp->uid == class &&
741 verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, algo))
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000742 return STAT_SECURE;
743 }
744 }
745
746 return STAT_BOGUS;
747}
748
Simon Kelley0fc2f312014-01-08 10:26:58 +0000749/* The DNS packet is expected to contain the answer to a DNSKEY query.
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000750 Leave name of query in name.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000751 Put all DNSKEYs in the answer which are valid into the cache.
752 return codes:
753 STAT_INSECURE bad packet, no DNSKEYs in reply.
754 STAT_SECURE At least one valid DNSKEY found and in cache.
Simon Kelley0fc2f312014-01-08 10:26:58 +0000755 STAT_BOGUS No DNSKEYs found, which can be validated with DS,
756 or self-sign for DNSKEY RRset is not valid.
757 STAT_NEED_DS DS records to validate a key not found, name in keyname
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000758*/
759int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
760{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000761 unsigned char *psave, *p = (unsigned char *)(header+1);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000762 struct crec *crecp, *recp1;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000763 int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000764 struct blockdata *key;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000765 struct all_addr a;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000766
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000767 if (ntohs(header->qdcount) != 1 ||
768 !extract_name(header, plen, &p, name, 1, 4))
769 {
770 strcpy(name, "<none>");
771 return STAT_INSECURE;
772 }
773
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000774 GETSHORT(qtype, p);
775 GETSHORT(qclass, p);
776
Simon Kelley0fc2f312014-01-08 10:26:58 +0000777 if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0)
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000778 return STAT_INSECURE;
779
Simon Kelley0fc2f312014-01-08 10:26:58 +0000780 /* See if we have cached a DS record which validates this key */
781 if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
782 {
783 strcpy(keyname, name);
784 return STAT_NEED_DS;
785 }
786
Simon Kelley0fc2f312014-01-08 10:26:58 +0000787 /* NOTE, we need to find ONE DNSKEY which matches the DS */
Simon Kelleye7829ae2014-01-22 22:21:51 +0000788 for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000789 {
790 /* Ensure we have type, class TTL and length */
Simon Kelley0fc2f312014-01-08 10:26:58 +0000791 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000792 return STAT_INSECURE; /* bad packet */
793
794 GETSHORT(qtype, p);
795 GETSHORT(qclass, p);
796 GETLONG(ttl, p);
797 GETSHORT(rdlen, p);
Simon Kelley6f468102014-01-26 23:39:17 +0000798
Simon Kelley0fc2f312014-01-08 10:26:58 +0000799 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
800 return STAT_INSECURE; /* bad packet */
801
Simon Kelley6f468102014-01-26 23:39:17 +0000802 if (qclass != class || qtype != T_DNSKEY || rc == 2)
803 {
804 p += rdlen;
805 continue;
806 }
807
Simon Kelley0fc2f312014-01-08 10:26:58 +0000808 psave = p;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000809
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000810 GETSHORT(flags, p);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000811 if (*p++ != 3)
812 return STAT_INSECURE;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000813 algo = *p++;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000814 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000815 key = NULL;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000816
Simon Kelleye7829ae2014-01-22 22:21:51 +0000817 /* key must have zone key flag set */
818 if (flags & 0x100)
819 key = blockdata_alloc((char*)p, rdlen - 4);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000820
821 p = psave;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000822
Simon Kelley0fc2f312014-01-08 10:26:58 +0000823 if (!ADD_RDLEN(header, p, plen, rdlen))
824 return STAT_INSECURE; /* bad packet */
825
Simon Kelleye7829ae2014-01-22 22:21:51 +0000826 /* No zone key flag or malloc failure */
827 if (!key)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000828 continue;
829
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000830 for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
Simon Kelley86bec2d2014-01-13 21:31:20 +0000831 {
832 void *ctx;
833 unsigned char *digest, *ds_digest;
834 const struct nettle_hash *hash;
835
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000836 if (recp1->addr.ds.algo == algo &&
837 recp1->addr.ds.keytag == keytag &&
Simon Kelley824202e2014-01-23 20:59:46 +0000838 recp1->uid == class &&
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000839 (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
Simon Kelley86bec2d2014-01-13 21:31:20 +0000840 hash_init(hash, &ctx, &digest))
Simon Kelley0fc2f312014-01-08 10:26:58 +0000841
Simon Kelley86bec2d2014-01-13 21:31:20 +0000842 {
843 int wire_len = to_wire(name);
844
845 /* Note that digest may be different between DSs, so
846 we can't move this outside the loop. */
847 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
848 hash->update(ctx, (unsigned int)rdlen, psave);
849 hash->digest(ctx, hash->digest_size, digest);
850
851 from_wire(name);
852
Simon Kelley824202e2014-01-23 20:59:46 +0000853 if (recp1->addr.ds.keylen == (int)hash->digest_size &&
854 (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
855 memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
Simon Kelley86bec2d2014-01-13 21:31:20 +0000856 validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag))
857 {
Simon Kelley86bec2d2014-01-13 21:31:20 +0000858 valid = 1;
Simon Kelley86bec2d2014-01-13 21:31:20 +0000859 break;
860 }
861 }
862 }
Simon Kelleye7829ae2014-01-22 22:21:51 +0000863 blockdata_free(key);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000864 }
865
866 if (valid)
867 {
Simon Kelleye7829ae2014-01-22 22:21:51 +0000868 /* DNSKEY RRset determined to be OK, now cache it. */
869 cache_start_insert();
870
871 p = skip_questions(header, plen);
872
873 for (j = ntohs(header->ancount); j != 0; j--)
874 {
875 /* Ensure we have type, class TTL and length */
876 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
877 return STAT_INSECURE; /* bad packet */
878
879 GETSHORT(qtype, p);
880 GETSHORT(qclass, p);
881 GETLONG(ttl, p);
882 GETSHORT(rdlen, p);
883
884 if (qclass != class || qtype != T_DNSKEY || rc == 2)
885 {
886 if (ADD_RDLEN(header, p, plen, rdlen))
887 continue;
888
889 return STAT_INSECURE; /* bad packet */
890 }
891
892 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
893 return STAT_INSECURE; /* bad packet */
894
895 psave = p;
896
897 GETSHORT(flags, p);
898 if (*p++ != 3)
899 return STAT_INSECURE;
900 algo = *p++;
901 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
902
903 /* Cache needs to known class for DNSSEC stuff */
904 a.addr.dnssec.class = class;
905
906 if ((key = blockdata_alloc((char*)p, rdlen - 4)) &&
907 (recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
908 {
909 struct all_addr a;
910
911 a.addr.keytag = keytag;
912 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
913
Simon Kelley824202e2014-01-23 20:59:46 +0000914 recp1->addr.key.keylen = rdlen - 4;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000915 recp1->addr.key.keydata = key;
916 recp1->addr.key.algo = algo;
917 recp1->addr.key.keytag = keytag;
918 recp1->addr.key.flags = flags;
Simon Kelley824202e2014-01-23 20:59:46 +0000919 recp1->uid = class;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000920 }
921
922 p = psave;
923 if (!ADD_RDLEN(header, p, plen, rdlen))
924 return STAT_INSECURE; /* bad packet */
925 }
926
Simon Kelley0fc2f312014-01-08 10:26:58 +0000927 /* commit cache insert. */
928 cache_end_insert();
929 return STAT_SECURE;
930 }
931
932 log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
933 return STAT_BOGUS;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000934}
Simon Kelley0fc2f312014-01-08 10:26:58 +0000935
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000936/* The DNS packet is expected to contain the answer to a DS query
Simon Kelley0fc2f312014-01-08 10:26:58 +0000937 Leave name of DS query in name.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000938 Put all DSs in the answer which are valid into the cache.
939 return codes:
Simon Kelley0fc2f312014-01-08 10:26:58 +0000940 STAT_INSECURE bad packet, no DS in reply.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000941 STAT_SECURE At least one valid DS found and in cache.
942 STAT_BOGUS At least one DS found, which fails validation.
943 STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
944*/
945
946int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
947{
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000948 unsigned char *p = (unsigned char *)(header+1);
949 int qtype, qclass, val;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000950
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000951 if (ntohs(header->qdcount) != 1 ||
952 !extract_name(header, plen, &p, name, 1, 4))
953 {
954 strcpy(name, "<none>");
955 return STAT_INSECURE;
956 }
957
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000958 GETSHORT(qtype, p);
959 GETSHORT(qclass, p);
960
Simon Kelley0fc2f312014-01-08 10:26:58 +0000961 if (qtype != T_DS || qclass != class || ntohs(header->ancount) == 0)
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000962 return STAT_INSECURE;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000963
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000964 val = dnssec_validate_reply(now, header, plen, name, keyname, NULL);
965
Simon Kelley0fc2f312014-01-08 10:26:58 +0000966 if (val == STAT_BOGUS)
967 log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000968
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000969 return val;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000970}
971
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000972/* 4034 6.1 */
973static int hostname_cmp(const char *a, const char *b)
974{
Simon Kelleydbf72122014-01-21 14:28:02 +0000975 char *sa, *ea, *ca, *sb, *eb, *cb;
976 unsigned char ac, bc;
977
978 sa = ea = (char *)a + strlen(a);
979 sb = eb = (char *)b + strlen(b);
980
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000981 while (1)
982 {
Simon Kelleydbf72122014-01-21 14:28:02 +0000983 while (sa != a && *(sa-1) != '.')
984 sa--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000985
Simon Kelleydbf72122014-01-21 14:28:02 +0000986 while (sb != b && *(sb-1) != '.')
987 sb--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000988
Simon Kelleydbf72122014-01-21 14:28:02 +0000989 ca = sa;
990 cb = sb;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000991
Simon Kelleydbf72122014-01-21 14:28:02 +0000992 while (1)
Simon Kelleyc5f4ec72014-01-20 22:37:55 +0000993 {
Simon Kelleydbf72122014-01-21 14:28:02 +0000994 if (ca == ea)
995 {
996 if (cb == eb)
997 break;
998
999 return -1;
1000 }
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001001
Simon Kelleydbf72122014-01-21 14:28:02 +00001002 if (cb == eb)
1003 return 1;
1004
1005 ac = (unsigned char) *ca++;
1006 bc = (unsigned char) *cb++;
1007
1008 if (ac >= 'A' && ac <= 'Z')
1009 ac += 'a' - 'A';
1010 if (bc >= 'A' && bc <= 'Z')
1011 bc += 'a' - 'A';
1012
Simon Kelley979cdf92014-01-21 16:26:41 +00001013 if (ac < bc)
Simon Kelleydbf72122014-01-21 14:28:02 +00001014 return -1;
1015 else if (ac != bc)
1016 return 1;
1017 }
1018
1019
1020 if (sa == a)
1021 {
1022 if (sb == b)
1023 return 0;
1024
1025 return -1;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001026 }
1027
Simon Kelleydbf72122014-01-21 14:28:02 +00001028 if (sb == b)
1029 return 1;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001030
Simon Kelleydbf72122014-01-21 14:28:02 +00001031 ea = sa--;
1032 eb = sb--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001033 }
1034}
1035
1036
Simon Kelley0fc2f312014-01-08 10:26:58 +00001037/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001038/* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
Simon Kelley0fc2f312014-01-08 10:26:58 +00001039int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class)
Giovanni Bajoe292e932012-04-22 14:32:02 +02001040{
Simon Kelley0fc2f312014-01-08 10:26:58 +00001041 unsigned char *ans_start, *p1, *p2;
1042 int type1, class1, rdlen1, type2, class2, rdlen2;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001043 int i, j, rc, have_nsec, have_nsec_equal, cname_count = 5;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001044
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001045 if ((RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR) || ntohs(header->qdcount) != 1)
Simon Kelley72ae2f32014-01-19 09:54:16 +00001046 return STAT_INSECURE;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001047
Simon Kelley0fc2f312014-01-08 10:26:58 +00001048 if (!(ans_start = skip_questions(header, plen)))
1049 return STAT_INSECURE;
1050
1051 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
Giovanni Bajoe292e932012-04-22 14:32:02 +02001052 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001053 if (!extract_name(header, plen, &p1, name, 1, 10))
1054 return STAT_INSECURE; /* bad packet */
1055
1056 GETSHORT(type1, p1);
1057 GETSHORT(class1, p1);
1058 p1 += 4; /* TTL */
1059 GETSHORT(rdlen1, p1);
1060
1061 /* Don't try and validate RRSIGs! */
1062 if (type1 != T_RRSIG)
1063 {
1064 /* Check if we've done this RRset already */
1065 for (p2 = ans_start, j = 0; j < i; j++)
1066 {
1067 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1068 return STAT_INSECURE; /* bad packet */
1069
1070 GETSHORT(type2, p2);
1071 GETSHORT(class2, p2);
1072 p2 += 4; /* TTL */
1073 GETSHORT(rdlen2, p2);
1074
1075 if (type2 == type1 && class2 == class1 && rc == 1)
1076 break; /* Done it before: name, type, class all match. */
1077
1078 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1079 return STAT_INSECURE;
1080 }
1081
1082 /* Not done, validate now */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001083 if (j == i)
Simon Kelley0fc2f312014-01-08 10:26:58 +00001084 {
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001085 if ((rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0)) != STAT_SECURE)
1086 {
1087 if (class)
1088 *class = class1; /* Class for DS or DNSKEY */
1089 return rc;
1090 }
1091
1092 /* If we just validated a DS RRset, cache it */
1093 if (type1 == T_DS)
1094 {
1095 int ttl, keytag, algo, digest;
1096 unsigned char *psave;
1097 struct all_addr a;
1098 struct blockdata *key;
1099 struct crec *crecp;
Simon Kelley0744ca62014-01-25 16:40:15 +00001100
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001101 cache_start_insert();
1102
1103 for (p2 = ans_start, j = 0; j < ntohs(header->ancount) + ntohs(header->nscount); j++)
1104 {
1105 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1106 return STAT_INSECURE; /* bad packet */
1107
1108 GETSHORT(type2, p2);
1109 GETSHORT(class2, p2);
1110 GETLONG(ttl, p2);
1111 GETSHORT(rdlen2, p2);
1112
1113 if (type2 == T_DS && class2 == class1 && rc == 1)
1114 {
1115 psave = p2;
1116 GETSHORT(keytag, p2);
1117 algo = *p2++;
1118 digest = *p2++;
1119
1120 /* Cache needs to known class for DNSSEC stuff */
1121 a.addr.dnssec.class = class2;
1122
1123 if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)) &&
1124 (crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1125 {
1126 a.addr.keytag = keytag;
1127 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
1128 crecp->addr.ds.digest = digest;
1129 crecp->addr.ds.keydata = key;
1130 crecp->addr.ds.algo = algo;
1131 crecp->addr.ds.keytag = keytag;
Simon Kelley824202e2014-01-23 20:59:46 +00001132 crecp->uid = class2;
1133 crecp->addr.ds.keylen = rdlen2 - 4;
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001134 }
1135
1136 p2 = psave;
1137 }
1138
1139 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1140 return STAT_INSECURE; /* bad packet */
1141 }
1142
1143 cache_end_insert();
1144 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001145 }
1146 }
1147
1148 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1149 return STAT_INSECURE;
Giovanni Bajoe292e932012-04-22 14:32:02 +02001150 }
1151
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001152 /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
1153
1154 p1 = (unsigned char *)(header+1);
1155
1156 if (!extract_name(header, plen, &p1, name, 1, 4))
1157 return STAT_INSECURE;
1158
1159 GETSHORT(type1, p1);
1160 GETSHORT(class1, p1);
1161
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001162 /* Can't validate RRSIG query */
1163 if (type1 == T_RRSIG)
1164 return STAT_INSECURE;
1165
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001166 cname_loop:
1167 for (j = ntohs(header->ancount); j != 0; j--)
1168 {
1169 if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
1170 return STAT_INSECURE; /* bad packet */
1171
1172 GETSHORT(type2, p1);
1173 GETSHORT(class2, p1);
1174 p1 += 4; /* TTL */
1175 GETSHORT(rdlen2, p1);
1176
1177 if (rc == 1 && class1 == class2)
1178 {
1179 /* Do we have an answer for the question? */
1180 if (type1 == type2)
1181 return RCODE(header) == NXDOMAIN ? STAT_INSECURE : STAT_SECURE;
1182 else if (type2 == T_CNAME)
1183 {
1184 /* looped CNAMES */
1185 if (!cname_count-- ||
1186 !extract_name(header, plen, &p1, name, 1, 0) ||
1187 !(p1 = skip_questions(header, plen)))
1188 return STAT_INSECURE;
1189
1190 goto cname_loop;
1191 }
1192 }
1193
1194 if (!ADD_RDLEN(header, p1, plen, rdlen2))
1195 return STAT_INSECURE;
1196 }
1197
1198 /* NXDOMAIN or NODATA reply, look for NSEC records to support that.
1199 At this point, p1 points to the start of the auth section.
1200 Use keyname as workspace */
1201 for (have_nsec = 0, have_nsec_equal = 0, p2 = NULL, rdlen2 = 0, j = ntohs(header->nscount); j != 0; j--)
1202 {
1203 unsigned char *nsec_start = p1;
1204 if (!extract_name(header, plen, &p1, keyname, 1, 10))
1205 return STAT_INSECURE; /* bad packet */
1206
1207 GETSHORT(type2, p1);
1208 GETSHORT(class2, p1);
1209 p1 += 4; /* TTL */
1210 GETSHORT(rdlen1, p1);
1211
1212 if (class1 == class2 && type2 == T_NSEC)
1213 {
1214 have_nsec = 1;
1215 rc = hostname_cmp(name, keyname);
1216
1217 if (rc >= 0)
1218 {
1219 if (p2)
1220 {
1221 unsigned char *psave = p2;
1222 /* new NSEC is smaller than name,
1223 is it bigger than previous one? */
1224
1225 /* get previous one into name buffer */
1226 if (!extract_name(header, plen, &psave, name, 1, 0))
1227 return STAT_INSECURE; /* bad packet */
1228
1229 if (hostname_cmp(name, keyname) < 0)
1230 {
1231 p2 = nsec_start;
1232 rdlen2 = rdlen1;
1233 }
1234
1235 /* restore query name */
1236 psave = (unsigned char *)(header+1);
1237 if (!extract_name(header, plen, &psave, name, 1, 0))
1238 return STAT_INSECURE;
1239 }
1240 else
1241 {
1242 /* There was no previous best candidate */
1243 p2 = nsec_start;
1244 rdlen2 = rdlen1;
1245 }
1246 }
1247
1248 if (rc == 0)
1249 have_nsec_equal = 1;
1250 }
1251
1252 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1253 return STAT_INSECURE;
1254 }
1255
1256
1257 if (p2)
1258 {
1259 unsigned char *psave;
1260 p2 = skip_name(p2, header, plen, 0);
1261 p2 += 10; /* type, class, ttl, rdlen */
1262 psave = p2;
1263 extract_name(header, plen, &p2, keyname, 1, 0);
1264 rdlen2 -= p2 - psave;
1265 }
1266
1267 /* At this point, have_nsec is set if there's at least one NSEC
1268 have_nsec_equal is set if there's an NSEC with the same name as the query;
1269 p2 points to the type bit maps of the biggest NSEC smaller than or equal to the query
1270 or NULL if the query is smaller than all of them.
1271 Keyname holds the next domain name for that NSEC.
1272 rdlen2 is the length of the bitmap field */
1273
1274
1275 if (RCODE(header) == NOERROR && have_nsec_equal)
1276 {
1277 int offset = (type1 & 0xff) >> 3;
1278 int mask = 0x80 >> (type1 & 0x07);
1279
1280 while (rdlen2 >= 2)
1281 {
1282 if (p2[0] == type1 >> 8)
1283 {
1284 /* Does the NSEC say our type exists? */
1285 if (offset < p2[1] &&
1286 (p2[offset+2] & mask) != 0)
1287 return STAT_INSECURE;
1288
1289 break; /* finshed checking */
1290 }
1291
1292 rdlen2 -= p2[1];
1293 p2 += p2[1];
1294 }
1295
1296 return STAT_SECURE;
1297 }
1298
1299 if (RCODE(header) == NXDOMAIN && have_nsec)
1300 {
1301 if (!p2 || hostname_cmp(name, keyname) < 0)
1302 return STAT_SECURE; /* Before the first, or in a proven gap */
1303 }
1304
1305 return STAT_INSECURE;
Giovanni Bajoadca3e92012-04-25 17:46:53 +02001306}
1307
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001308
Giovanni Bajo3471f182012-04-25 17:49:16 +02001309/* Compute keytag (checksum to quickly index a key). See RFC4034 */
Simon Kelley0fc2f312014-01-08 10:26:58 +00001310int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
Giovanni Bajo3471f182012-04-25 17:49:16 +02001311{
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02001312 if (alg == 1)
1313 {
1314 /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
1315 See RFC4034, Appendix B.1 */
Simon Kelley0fc2f312014-01-08 10:26:58 +00001316 return key[keylen-4] * 256 + key[keylen-3];
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02001317 }
1318 else
1319 {
1320 unsigned long ac;
1321 int i;
Giovanni Bajo3471f182012-04-25 17:49:16 +02001322
Simon Kelley0fc2f312014-01-08 10:26:58 +00001323 ac = ((htons(flags) >> 8) | ((htons(flags) << 8) & 0xff00)) + 0x300 + alg;
1324 for (i = 0; i < keylen; ++i)
1325 ac += (i & 1) ? key[i] : key[i] << 8;
1326 ac += (ac >> 16) & 0xffff;
1327 return ac & 0xffff;
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02001328 }
Giovanni Bajo3471f182012-04-25 17:49:16 +02001329}
1330
Simon Kelley5f8e58f2014-01-09 17:31:19 +00001331size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
1332{
1333 unsigned char *p;
1334 char types[20];
1335
Simon Kelleyb5dbfd12014-01-25 18:19:51 +00001336 querystr("dnssec-query", types, type);
Giovanni Bajo0304d282012-05-02 03:29:52 +02001337
Simon Kelley5f8e58f2014-01-09 17:31:19 +00001338 if (addr->sa.sa_family == AF_INET)
1339 log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
1340#ifdef HAVE_IPV6
1341 else
1342 log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
1343#endif
1344
1345 header->qdcount = htons(1);
1346 header->ancount = htons(0);
1347 header->nscount = htons(0);
1348 header->arcount = htons(0);
1349
1350 header->hb3 = HB3_RD;
1351 SET_OPCODE(header, QUERY);
Simon Kelley5b3bf922014-01-25 17:03:07 +00001352 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
1353 this allows it to select auth servers when one is returning bad data. */
1354 header->hb4 = option_bool(OPT_DNSSEC_DEBUG) ? HB4_CD : 0;
Simon Kelley5f8e58f2014-01-09 17:31:19 +00001355
1356 /* ID filled in later */
1357
1358 p = (unsigned char *)(header+1);
1359
1360 p = do_rfc1035_name(p, name);
1361 *p++ = 0;
1362 PUTSHORT(type, p);
1363 PUTSHORT(class, p);
1364
1365 return add_do_bit(header, p - (unsigned char *)header, end);
1366}
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001367
1368unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
1369{
1370 int q;
1371 unsigned int len;
1372 unsigned char *p = (unsigned char *)(header+1);
1373 const struct nettle_hash *hash;
1374 void *ctx;
1375 unsigned char *digest;
Simon Kelley5f8e58f2014-01-09 17:31:19 +00001376
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001377 if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
1378 return NULL;
1379
1380 for (q = ntohs(header->qdcount); q != 0; q--)
1381 {
1382 if (!extract_name(header, plen, &p, name, 1, 4))
Simon Kelley7d23a662014-01-26 09:33:21 +00001383 break; /* bad packet */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001384
1385 len = to_wire(name);
1386 hash->update(ctx, len, (unsigned char *)name);
1387 /* CRC the class and type as well */
1388 hash->update(ctx, 4, p);
1389
1390 p += 4;
1391 if (!CHECK_LEN(header, p, plen, 0))
Simon Kelley7d23a662014-01-26 09:33:21 +00001392 break; /* bad packet */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001393 }
Simon Kelley703c7ff2014-01-25 23:46:23 +00001394
1395 hash->digest(ctx, hash->digest_size, digest);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00001396 return digest;
1397}
1398
Simon Kelley0fc2f312014-01-08 10:26:58 +00001399#endif /* HAVE_DNSSEC */