blob: 6639188b298f4e16c7aadf495757fb5ea2f4f4dd [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>
Simon Kelleyc152dc82014-02-19 18:14:33 +000024#ifndef NO_NETTLE_ECC
25# include <nettle/ecdsa.h>
26# include <nettle/ecc-curve.h>
27#endif
Simon Kelley86bec2d2014-01-13 21:31:20 +000028#include <nettle/nettle-meta.h>
29#include <gmp.h>
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000030
Giovanni Bajoe292e932012-04-22 14:32:02 +020031#define SERIAL_UNDEF -100
32#define SERIAL_EQ 0
33#define SERIAL_LT -1
34#define SERIAL_GT 1
35
Simon Kelley86bec2d2014-01-13 21:31:20 +000036/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
37static char *ds_digest_name(int digest)
38{
39 switch (digest)
40 {
41 case 1: return "sha1";
42 case 2: return "sha256";
43 case 3: return "gosthash94";
44 case 4: return "sha384";
45 default: return NULL;
46 }
47}
48
49/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
50static char *algo_digest_name(int algo)
51{
52 switch (algo)
53 {
54 case 1: return "md5";
55 case 3: return "sha1";
56 case 5: return "sha1";
57 case 6: return "sha1";
58 case 7: return "sha1";
59 case 8: return "sha256";
60 case 10: return "sha512";
61 case 12: return "gosthash94";
62 case 13: return "sha256";
63 case 14: return "sha384";
64 default: return NULL;
65 }
66}
67
68/* Find pointer to correct hash function in nettle library */
69static const struct nettle_hash *hash_find(char *name)
70{
71 int i;
72
73 if (!name)
74 return NULL;
75
76 for (i = 0; nettle_hashes[i]; i++)
77 {
78 if (strcmp(nettle_hashes[i]->name, name) == 0)
79 return nettle_hashes[i];
80 }
81
82 return NULL;
83}
84
85/* expand ctx and digest memory allocations if necessary and init hash function */
86static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
87{
88 static void *ctx = NULL;
89 static unsigned char *digest = NULL;
90 static unsigned int ctx_sz = 0;
91 static unsigned int digest_sz = 0;
92
93 void *new;
94
95 if (ctx_sz < hash->context_size)
96 {
97 if (!(new = whine_malloc(hash->context_size)))
98 return 0;
99 if (ctx)
100 free(ctx);
101 ctx = new;
102 ctx_sz = hash->context_size;
103 }
104
105 if (digest_sz < hash->digest_size)
106 {
107 if (!(new = whine_malloc(hash->digest_size)))
108 return 0;
109 if (digest)
110 free(digest);
111 digest = new;
112 digest_sz = hash->digest_size;
113 }
114
115 *ctxp = ctx;
116 *digestp = digest;
117
118 hash->init(ctx);
119
120 return 1;
121}
122
123static int rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
124 unsigned char *digest, int algo)
125{
126 unsigned char *p;
127 size_t exp_len;
128
129 static struct rsa_public_key *key = NULL;
130 static mpz_t sig_mpz;
131
132 if (key == NULL)
133 {
134 if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
135 return 0;
136
137 nettle_rsa_public_key_init(key);
138 mpz_init(sig_mpz);
139 }
140
141 if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
142 return 0;
143
144 key_len--;
145 if ((exp_len = *p++) == 0)
146 {
147 GETSHORT(exp_len, p);
148 key_len -= 2;
149 }
150
151 if (exp_len >= key_len)
152 return 0;
153
154 key->size = key_len - exp_len;
155 mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
156 mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
157
158 mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
159
160 switch (algo)
161 {
162 case 1:
163 return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
164 case 5: case 7:
165 return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
166 case 8:
167 return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
168 case 10:
169 return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
170 }
171
172 return 0;
173}
174
175static int dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
176 unsigned char *digest, int algo)
177{
178 unsigned char *p;
179 unsigned int t;
180
181 static struct dsa_public_key *key = NULL;
182 static struct dsa_signature *sig_struct;
183
184 if (key == NULL)
185 {
186 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
187 !(key = whine_malloc(sizeof(struct dsa_public_key))))
188 return 0;
189
190 nettle_dsa_public_key_init(key);
191 nettle_dsa_signature_init(sig_struct);
192 }
193
194 if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
195 return 0;
196
197 t = *p++;
198
199 if (key_len < (213 + (t * 24)))
200 return 0;
Simon Kelleyebe95a82014-02-13 14:56:10 +0000201
Simon Kelley86bec2d2014-01-13 21:31:20 +0000202 mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
203 mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
204 mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
205 mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
206
207 mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
208 mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
209
210 (void)algo;
Simon Kelleyebe95a82014-02-13 14:56:10 +0000211
Simon Kelley86bec2d2014-01-13 21:31:20 +0000212 return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
213}
214
Simon Kelleyc152dc82014-02-19 18:14:33 +0000215#ifndef NO_NETTLE_ECC
216static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
217 unsigned char *sig, size_t sig_len,
Simon Kelleyebe95a82014-02-13 14:56:10 +0000218 unsigned char *digest, size_t digest_len, int algo)
219{
220 unsigned char *p;
221 unsigned int t;
222 struct ecc_point *key;
223
224 static struct ecc_point *key_256 = NULL, *key_384 = NULL;
225 static mpz_t x, y;
226 static struct dsa_signature *sig_struct;
227
228 if (!sig_struct)
229 {
230 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
231 return 0;
232
233 nettle_dsa_signature_init(sig_struct);
234 mpz_init(x);
235 mpz_init(y);
236 }
237
238 switch (algo)
239 {
240 case 13:
241 if (!key_256)
242 {
243 if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
244 return 0;
245
246 nettle_ecc_point_init(key_256, &nettle_secp_256r1);
247 }
248
249 key = key_256;
250 t = 32;
251 break;
252
253 case 14:
254 if (!key_384)
255 {
256 if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
257 return 0;
258
259 nettle_ecc_point_init(key_384, &nettle_secp_384r1);
260 }
261
262 key = key_384;
263 t = 48;
264 break;
265
266 default:
267 return 0;
268 }
269
270 if (sig_len != 2*t || key_len != 2*t ||
271 (p = blockdata_retrieve(key_data, key_len, NULL)))
272 return 0;
273
274 mpz_import(x, t , 1, 1, 0, 0, p);
275 mpz_import(y, t , 1, 1, 0, 0, p + t);
276
277 if (!ecc_point_set(key, x, y))
278 return 0;
279
280 mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
281 mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
282
283 return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
284}
Simon Kelleyc152dc82014-02-19 18:14:33 +0000285#endif
286
Simon Kelley86bec2d2014-01-13 21:31:20 +0000287static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
Simon Kelleyebe95a82014-02-13 14:56:10 +0000288 unsigned char *digest, size_t digest_len, int algo)
Simon Kelley86bec2d2014-01-13 21:31:20 +0000289{
Simon Kelley7b1eae42014-02-20 13:43:28 +0000290 (void)digest_len;
291
Simon Kelley86bec2d2014-01-13 21:31:20 +0000292 switch (algo)
293 {
294 case 1: case 5: case 7: case 8: case 10:
295 return rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
296
297 case 3: case 6:
298 return dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
Simon Kelleyc152dc82014-02-19 18:14:33 +0000299
300#ifndef NO_NETTLE_ECC
Simon Kelleyebe95a82014-02-13 14:56:10 +0000301 case 13: case 14:
302 return dnsmasq_ecdsa_verify(key_data, key_len, sig, sig_len, digest, digest_len, algo);
Simon Kelleyc152dc82014-02-19 18:14:33 +0000303#endif
304 }
Simon Kelley86bec2d2014-01-13 21:31:20 +0000305
306 return 0;
307}
308
Simon Kelley0fc2f312014-01-08 10:26:58 +0000309/* Convert from presentation format to wire format, in place.
310 Also map UC -> LC.
311 Note that using extract_name to get presentation format
312 then calling to_wire() removes compression and maps case,
313 thus generating names in canonical form.
314 Calling to_wire followed by from_wire is almost an identity,
315 except that the UC remains mapped to LC.
316*/
317static int to_wire(char *name)
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200318{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000319 unsigned char *l, *p, term;
320 int len;
321
322 for (l = (unsigned char*)name; *l != 0; l = p)
323 {
324 for (p = l; *p != '.' && *p != 0; p++)
325 if (*p >= 'A' && *p <= 'Z')
326 *p = *p - 'A' + 'a';
327
328 term = *p;
329
330 if ((len = p - l) != 0)
331 memmove(l+1, l, len);
332 *l = len;
333
334 p++;
335
336 if (term == 0)
337 *p = 0;
338 }
339
340 return l + 1 - (unsigned char *)name;
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200341}
342
Simon Kelley0fc2f312014-01-08 10:26:58 +0000343/* Note: no compression allowed in input. */
344static void from_wire(char *name)
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200345{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000346 unsigned char *l;
347 int len;
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200348
Simon Kelley0fc2f312014-01-08 10:26:58 +0000349 for (l = (unsigned char *)name; *l != 0; l += len+1)
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200350 {
Simon Kelley0fc2f312014-01-08 10:26:58 +0000351 len = *l;
352 memmove(l, l+1, len);
353 l[len] = '.';
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200354 }
Giovanni Bajo7f0485c2012-04-28 12:59:49 +0200355
Simon Kelleye3f14552014-03-01 17:58:28 +0000356 if ((char *)l != name)
Simon Kelleybd9b3cf2014-03-01 16:12:28 +0000357 *(l-1) = 0;
Giovanni Bajo13e435e2012-04-27 03:19:40 +0200358}
359
Simon Kelley5ada8882014-01-09 22:25:03 +0000360/* Input in presentation format */
361static int count_labels(char *name)
362{
363 int i;
364
365 if (*name == 0)
366 return 0;
367
368 for (i = 0; *name; name++)
369 if (*name == '.')
370 i++;
371
372 return i+1;
373}
374
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000375/* Implement RFC1982 wrapped compare for 32-bit numbers */
376static int serial_compare_32(unsigned long s1, unsigned long s2)
Giovanni Bajo0852d762012-04-28 03:49:24 +0200377{
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000378 if (s1 == s2)
379 return SERIAL_EQ;
Giovanni Bajo0852d762012-04-28 03:49:24 +0200380
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000381 if ((s1 < s2 && (s2 - s1) < (1UL<<31)) ||
382 (s1 > s2 && (s1 - s2) > (1UL<<31)))
383 return SERIAL_LT;
384 if ((s1 < s2 && (s2 - s1) > (1UL<<31)) ||
385 (s1 > s2 && (s1 - s2) < (1UL<<31)))
386 return SERIAL_GT;
387 return SERIAL_UNDEF;
388}
Giovanni Bajo0852d762012-04-28 03:49:24 +0200389
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000390/* Check whether today/now is between date_start and date_end */
391static int check_date_range(unsigned long date_start, unsigned long date_end)
392{
393 unsigned long curtime = time(0);
394
395 /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
396 return serial_compare_32(curtime, date_start) == SERIAL_GT
397 && serial_compare_32(curtime, date_end) == SERIAL_LT;
398}
399
400static u16 *get_desc(int type)
401{
402 /* List of RRtypes which include domains in the data.
403 0 -> domain
404 integer -> no of plain bytes
405 -1 -> end
406
407 zero is not a valid RRtype, so the final entry is returned for
408 anything which needs no mangling.
409 */
410
411 static u16 rr_desc[] =
412 {
413 T_NS, 0, -1,
414 T_MD, 0, -1,
415 T_MF, 0, -1,
416 T_CNAME, 0, -1,
417 T_SOA, 0, 0, -1,
418 T_MB, 0, -1,
419 T_MG, 0, -1,
420 T_MR, 0, -1,
421 T_PTR, 0, -1,
422 T_MINFO, 0, 0, -1,
423 T_MX, 2, 0, -1,
424 T_RP, 0, 0, -1,
425 T_AFSDB, 2, 0, -1,
426 T_RT, 2, 0, -1,
427 T_SIG, 18, 0, -1,
428 T_PX, 2, 0, 0, -1,
429 T_NXT, 0, -1,
430 T_KX, 2, 0, -1,
431 T_SRV, 6, 0, -1,
432 T_DNAME, 0, -1,
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000433 0, -1 /* wildcard/catchall */
434 };
435
436 u16 *p = rr_desc;
437
438 while (*p != type && *p != 0)
439 while (*p++ != (u16)-1);
440
441 return p+1;
442}
443
444/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
445 data, pointed to by *p, should be used raw. */
446static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff,
447 unsigned char **p, u16 **desc)
448{
449 int d = **desc;
450
451 (*desc)++;
452
453 /* No more data needs mangling */
454 if (d == (u16)-1)
Giovanni Bajof119ed32012-05-02 00:31:55 +0200455 return 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000456
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000457 if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
458 /* domain-name, canonicalise */
459 return to_wire(buff);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000460 else
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000461 {
462 /* plain data preceding a domain-name, don't run off the end of the data */
463 if ((end - *p) < d)
464 d = end - *p;
465
466 if (d != 0)
467 {
468 memcpy(buff, *p, d);
469 *p += d;
470 }
471
472 return d;
473 }
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000474}
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000475
Simon Kelley613ad152014-02-25 23:02:28 +0000476static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
477{
478 unsigned char **p;
479 int new_sz = *sz;
480
481 if (new_sz > new)
482 return 1;
483
484 if (new >= 100)
485 return 0;
486
487 new_sz += 5;
488
489 if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
490 return 0;
491
492 if (*wkspc)
493 {
494 memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
495 free(*wkspc);
496 }
497
498 *wkspc = p;
499 *sz = new_sz;
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000500
501 return 1;
Simon Kelley613ad152014-02-25 23:02:28 +0000502}
503
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000504/* Bubble sort the RRset into the canonical order.
505 Note that the byte-streams from two RRs may get unsynced: consider
506 RRs which have two domain-names at the start and then other data.
507 The domain-names may have different lengths in each RR, but sort equal
508
509 ------------
510 |abcde|fghi|
511 ------------
512 |abcd|efghi|
513 ------------
514
515 leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
516*/
517
518static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
519 unsigned char **rrset, char *buff1, char *buff2)
520{
521 int swap, quit, i;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000522
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000523 do
524 {
525 for (swap = 0, i = 0; i < rrsetidx-1; i++)
526 {
527 int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
528 u16 *dp1, *dp2;
529 unsigned char *end1, *end2;
Simon Kelley5107ace2014-02-23 10:48:32 +0000530 /* Note that these have been determined to be OK previously,
531 so we don't need to check for NULL return here. */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000532 unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
533 unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
534
535 p1 += 8; /* skip class, type, ttl */
536 GETSHORT(rdlen1, p1);
537 end1 = p1 + rdlen1;
538
539 p2 += 8; /* skip class, type, ttl */
540 GETSHORT(rdlen2, p2);
541 end2 = p2 + rdlen2;
542
543 dp1 = dp2 = rr_desc;
544
Simon Kelley1486a9c2014-01-10 11:39:14 +0000545 for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000546 {
Simon Kelley1486a9c2014-01-10 11:39:14 +0000547 if (left1 != 0)
548 memmove(buff1, buff1 + len1 - left1, left1);
549
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000550 if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
551 {
552 quit = 1;
553 len1 = end1 - p1;
554 memcpy(buff1 + left1, p1, len1);
555 }
556 len1 += left1;
557
Simon Kelley1486a9c2014-01-10 11:39:14 +0000558 if (left2 != 0)
559 memmove(buff2, buff2 + len2 - left2, left2);
560
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000561 if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
562 {
563 quit = 1;
564 len2 = end2 - p2;
565 memcpy(buff2 + left2, p2, len2);
566 }
567 len2 += left2;
568
569 if (len1 > len2)
Simon Kelley1486a9c2014-01-10 11:39:14 +0000570 left1 = len1 - len2, left2 = 0, len = len2;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000571 else
Simon Kelley1486a9c2014-01-10 11:39:14 +0000572 left2 = len2 - len1, left1 = 0, len = len1;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000573
Simon Kelley6fd6dac2014-01-21 20:17:40 +0000574 rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000575
Simon Kelley4619d942014-01-16 19:53:06 +0000576 if (rc > 0 || (rc == 0 && quit && len1 > len2))
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000577 {
578 unsigned char *tmp = rrset[i+1];
579 rrset[i+1] = rrset[i];
580 rrset[i] = tmp;
581 swap = quit = 1;
582 }
Simon Kelley6fd6dac2014-01-21 20:17:40 +0000583 else if (rc < 0)
584 quit = 1;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000585 }
586 }
587 } while (swap);
588}
589
590/* Validate a single RRset (class, type, name) in the supplied DNS reply
591 Return code:
592 STAT_SECURE if it validates.
Simon Kelley5107ace2014-02-23 10:48:32 +0000593 STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000594 STAT_NO_SIG no RRsigs found.
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000595 STAT_INSECURE can't validate (no RRSIG, bad packet).
596 STAT_BOGUS signature is wrong.
597 STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
598
599 if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
600 otherwise find the key in the cache.
Simon Kelley5107ace2014-02-23 10:48:32 +0000601
602 name is unchanged on exit. keyname is used as workspace and trashed.
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000603*/
604static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class,
Simon Kelleye7829ae2014-01-22 22:21:51 +0000605 int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000606{
607 static unsigned char **rrset = NULL, **sigs = NULL;
608 static int rrset_sz = 0, sig_sz = 0;
609
610 unsigned char *p;
Simon Kelley5ada8882014-01-09 22:25:03 +0000611 int rrsetidx, sigidx, res, rdlen, j, name_labels;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000612 struct crec *crecp = NULL;
613 int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
614 u16 *rr_desc = get_desc(type);
615
616 if (!(p = skip_questions(header, plen)))
617 return STAT_INSECURE;
618
Simon Kelley5ada8882014-01-09 22:25:03 +0000619 name_labels = count_labels(name); /* For 4035 5.3.2 check */
620
621 /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000622 for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
623 j != 0; j--)
624 {
625 unsigned char *pstart, *pdata;
Simon Kelleyb98d22c2014-02-04 16:57:25 +0000626 int stype, sclass;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000627
628 pstart = p;
629
630 if (!(res = extract_name(header, plen, &p, name, 0, 10)))
631 return STAT_INSECURE; /* bad packet */
632
633 GETSHORT(stype, p);
634 GETSHORT(sclass, p);
Simon Kelleyb98d22c2014-02-04 16:57:25 +0000635 p += 4; /* TTL */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000636
637 pdata = p;
638
639 GETSHORT(rdlen, p);
640
Simon Kelleye7829ae2014-01-22 22:21:51 +0000641 if (!CHECK_LEN(header, p, plen, rdlen))
642 return STAT_INSECURE;
643
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000644 if (res == 1 && sclass == class)
645 {
646 if (stype == type)
647 {
Simon Kelley613ad152014-02-25 23:02:28 +0000648 if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
649 return STAT_INSECURE;
650
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000651 rrset[rrsetidx++] = pstart;
652 }
653
654 if (stype == T_RRSIG)
655 {
Simon Kelley613ad152014-02-25 23:02:28 +0000656 if (rdlen < 18)
657 return STAT_INSECURE; /* bad packet */
658
659 GETSHORT(type_covered, p);
660
661 if (type_covered == type)
662 {
663 if (!expand_workspace(&sigs, &sig_sz, sigidx))
664 return STAT_INSECURE;
665
666 sigs[sigidx++] = pdata;
667 }
668
669 p = pdata + 2; /* restore for ADD_RDLEN */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000670 }
671 }
Simon Kelley613ad152014-02-25 23:02:28 +0000672
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000673 if (!ADD_RDLEN(header, p, plen, rdlen))
674 return STAT_INSECURE;
675 }
676
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000677 /* RRset empty */
678 if (rrsetidx == 0)
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000679 return STAT_INSECURE;
Simon Kelley00a5b5d2014-02-28 18:10:55 +0000680
681 /* no RRSIGs */
682 if (sigidx == 0)
683 return STAT_NO_SIG;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000684
685 /* Sort RRset records into canonical order.
Simon Kelleyd3873802014-02-23 16:20:46 +0000686 Note that at this point keyname and daemon->workspacename buffs are
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000687 unused, and used as workspace by the sort. */
Simon Kelleyd3873802014-02-23 16:20:46 +0000688 sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000689
690 /* Now try all the sigs to try and find one which validates */
691 for (j = 0; j <sigidx; j++)
692 {
Simon Kelleyd3873802014-02-23 16:20:46 +0000693 unsigned char *psav, *sig, *digest;
Simon Kelley86bec2d2014-01-13 21:31:20 +0000694 int i, wire_len, sig_len;
695 const struct nettle_hash *hash;
696 void *ctx;
Simon Kelleyd3873802014-02-23 16:20:46 +0000697 char *name_start;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000698 u32 nsigttl;
699
700 p = sigs[j];
Simon Kelley5ada8882014-01-09 22:25:03 +0000701 GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000702 psav = p;
703
Simon Kelley5ada8882014-01-09 22:25:03 +0000704 p += 2; /* type_covered - already checked */
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000705 algo = *p++;
706 labels = *p++;
707 GETLONG(orig_ttl, p);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000708 GETLONG(sig_expiration, p);
709 GETLONG(sig_inception, p);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000710 GETSHORT(key_tag, p);
711
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000712 if (!extract_name(header, plen, &p, keyname, 1, 0))
713 return STAT_INSECURE;
Simon Kelleyd3873802014-02-23 16:20:46 +0000714
715 /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
716 the name of the zone containing the RRset. We can't tell that
717 for certain, but we can check that the RRset name is equal to
718 or encloses the signers name, which should be enough to stop
719 an attacker using signatures made with the key of an unrelated
720 zone he controls. Note that the root key is always allowed. */
721 if (*keyname != 0)
722 {
723 int failed = 0;
724
725 for (name_start = name; !hostname_isequal(name_start, keyname); )
726 if ((name_start = strchr(name_start, '.')))
727 name_start++; /* chop a label off and try again */
728 else
729 {
730 failed = 1;
731 break;
732 }
733
734 /* Bad sig, try another */
735 if (failed)
736 continue;
737 }
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000738
Simon Kelleyd3873802014-02-23 16:20:46 +0000739 /* Other 5.3.1 checks */
Simon Kelleye7829ae2014-01-22 22:21:51 +0000740 if (!check_date_range(sig_inception, sig_expiration) ||
741 labels > name_labels ||
742 !(hash = hash_find(algo_digest_name(algo))) ||
743 !hash_init(hash, &ctx, &digest))
744 continue;
745
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000746 /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
747 if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
748 return STAT_NEED_KEY;
749
Simon Kelley86bec2d2014-01-13 21:31:20 +0000750 sig = p;
751 sig_len = rdlen - (p - psav);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000752
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000753 nsigttl = htonl(orig_ttl);
754
Simon Kelley86bec2d2014-01-13 21:31:20 +0000755 hash->update(ctx, 18, psav);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000756 wire_len = to_wire(keyname);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000757 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000758 from_wire(keyname);
759
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000760 for (i = 0; i < rrsetidx; ++i)
761 {
762 int seg;
763 unsigned char *end, *cp;
764 u16 len, *dp;
Simon Kelleyd3873802014-02-23 16:20:46 +0000765
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000766 p = rrset[i];
767 if (!extract_name(header, plen, &p, name, 1, 10))
768 return STAT_INSECURE;
Simon Kelley5ada8882014-01-09 22:25:03 +0000769
Simon Kelleyd3873802014-02-23 16:20:46 +0000770 name_start = name;
771
Simon Kelley5ada8882014-01-09 22:25:03 +0000772 /* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
773 if (labels < name_labels)
774 {
775 int k;
776 for (k = name_labels - labels; k != 0; k--)
777 while (*name_start != '.' && *name_start != 0)
778 name_start++;
779 name_start--;
780 *name_start = '*';
781 }
782
783 wire_len = to_wire(name_start);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000784 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
785 hash->update(ctx, 4, p); /* class and type */
786 hash->update(ctx, 4, (unsigned char *)&nsigttl);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000787
788 p += 8; /* skip class, type, ttl */
789 GETSHORT(rdlen, p);
Simon Kelley5ada8882014-01-09 22:25:03 +0000790 if (!CHECK_LEN(header, p, plen, rdlen))
791 return STAT_INSECURE;
792
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000793 end = p + rdlen;
794
795 /* canonicalise rdata and calculate length of same, use name buffer as workspace */
796 cp = p;
797 dp = rr_desc;
798 for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
799 len += end - cp;
800 len = htons(len);
Simon Kelley86bec2d2014-01-13 21:31:20 +0000801 hash->update(ctx, 2, (unsigned char *)&len);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000802
803 /* Now canonicalise again and digest. */
804 cp = p;
805 dp = rr_desc;
806 while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
Simon Kelley86bec2d2014-01-13 21:31:20 +0000807 hash->update(ctx, seg, (unsigned char *)name);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000808 if (cp != end)
Simon Kelley86bec2d2014-01-13 21:31:20 +0000809 hash->update(ctx, end - cp, cp);
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000810 }
Simon Kelley86bec2d2014-01-13 21:31:20 +0000811
812 hash->digest(ctx, hash->digest_size, digest);
813
Simon Kelley5ada8882014-01-09 22:25:03 +0000814 /* namebuff used for workspace above, restore to leave unchanged on exit */
815 p = (unsigned char*)(rrset[0]);
816 extract_name(header, plen, &p, name, 1, 0);
817
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000818 if (key)
819 {
820 if (algo_in == algo && keytag_in == key_tag &&
Simon Kelleyebe95a82014-02-13 14:56:10 +0000821 verify(key, keylen, sig, sig_len, digest, hash->digest_size, algo))
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000822 return STAT_SECURE;
823 }
824 else
825 {
826 /* iterate through all possible keys 4035 5.3.1 */
827 for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000828 if (crecp->addr.key.algo == algo &&
829 crecp->addr.key.keytag == key_tag &&
Simon Kelley824202e2014-01-23 20:59:46 +0000830 crecp->uid == class &&
Simon Kelleyebe95a82014-02-13 14:56:10 +0000831 verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
Simon Kelley5107ace2014-02-23 10:48:32 +0000832 return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000833 }
834 }
835
836 return STAT_BOGUS;
837}
838
Simon Kelley0fc2f312014-01-08 10:26:58 +0000839/* The DNS packet is expected to contain the answer to a DNSKEY query.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000840 Put all DNSKEYs in the answer which are valid into the cache.
841 return codes:
842 STAT_INSECURE bad packet, no DNSKEYs in reply.
843 STAT_SECURE At least one valid DNSKEY found and in cache.
Simon Kelley0fc2f312014-01-08 10:26:58 +0000844 STAT_BOGUS No DNSKEYs found, which can be validated with DS,
845 or self-sign for DNSKEY RRset is not valid.
846 STAT_NEED_DS DS records to validate a key not found, name in keyname
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000847*/
848int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
849{
Simon Kelley0fc2f312014-01-08 10:26:58 +0000850 unsigned char *psave, *p = (unsigned char *)(header+1);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000851 struct crec *crecp, *recp1;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000852 int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000853 struct blockdata *key;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000854 struct all_addr a;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000855
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000856 if (ntohs(header->qdcount) != 1 ||
857 !extract_name(header, plen, &p, name, 1, 4))
Simon Kelley8d718cb2014-02-03 16:27:37 +0000858 return STAT_INSECURE;
Simon Kelley5f8e58f2014-01-09 17:31:19 +0000859
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000860 GETSHORT(qtype, p);
861 GETSHORT(qclass, p);
862
Simon Kelley0fc2f312014-01-08 10:26:58 +0000863 if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0)
Simon Kelleyf01d7be2014-02-24 20:20:00 +0000864 return STAT_BOGUS;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000865
Simon Kelleyb8eac192014-02-27 14:30:03 +0000866 /* See if we have cached a DS record which validates this key */
Simon Kelley0fc2f312014-01-08 10:26:58 +0000867 if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
868 {
869 strcpy(keyname, name);
870 return STAT_NEED_DS;
871 }
Simon Kelleyb8eac192014-02-27 14:30:03 +0000872
873 /* If we've cached that DS provably doesn't exist, result must be INSECURE */
874 if (crecp->flags & F_NEG)
875 return STAT_INSECURE;
876
Simon Kelley0fc2f312014-01-08 10:26:58 +0000877 /* NOTE, we need to find ONE DNSKEY which matches the DS */
Simon Kelleye7829ae2014-01-22 22:21:51 +0000878 for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000879 {
880 /* Ensure we have type, class TTL and length */
Simon Kelley0fc2f312014-01-08 10:26:58 +0000881 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000882 return STAT_INSECURE; /* bad packet */
883
884 GETSHORT(qtype, p);
885 GETSHORT(qclass, p);
886 GETLONG(ttl, p);
887 GETSHORT(rdlen, p);
Simon Kelley6f468102014-01-26 23:39:17 +0000888
Simon Kelley0fc2f312014-01-08 10:26:58 +0000889 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
890 return STAT_INSECURE; /* bad packet */
891
Simon Kelley6f468102014-01-26 23:39:17 +0000892 if (qclass != class || qtype != T_DNSKEY || rc == 2)
893 {
894 p += rdlen;
895 continue;
896 }
897
Simon Kelley0fc2f312014-01-08 10:26:58 +0000898 psave = p;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000899
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000900 GETSHORT(flags, p);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000901 if (*p++ != 3)
Simon Kelleyf01d7be2014-02-24 20:20:00 +0000902 return STAT_BOGUS;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000903 algo = *p++;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000904 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
Simon Kelleye7829ae2014-01-22 22:21:51 +0000905 key = NULL;
Simon Kelley0fc2f312014-01-08 10:26:58 +0000906
Simon Kelleye7829ae2014-01-22 22:21:51 +0000907 /* key must have zone key flag set */
908 if (flags & 0x100)
909 key = blockdata_alloc((char*)p, rdlen - 4);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000910
911 p = psave;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000912
Simon Kelley0fc2f312014-01-08 10:26:58 +0000913 if (!ADD_RDLEN(header, p, plen, rdlen))
Simon Kelley8d718cb2014-02-03 16:27:37 +0000914 {
915 if (key)
916 blockdata_free(key);
917 return STAT_INSECURE; /* bad packet */
918 }
919
Simon Kelleye7829ae2014-01-22 22:21:51 +0000920 /* No zone key flag or malloc failure */
921 if (!key)
Simon Kelley0fc2f312014-01-08 10:26:58 +0000922 continue;
923
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +0000924 for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
Simon Kelley86bec2d2014-01-13 21:31:20 +0000925 {
926 void *ctx;
927 unsigned char *digest, *ds_digest;
928 const struct nettle_hash *hash;
929
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000930 if (recp1->addr.ds.algo == algo &&
931 recp1->addr.ds.keytag == keytag &&
Simon Kelley824202e2014-01-23 20:59:46 +0000932 recp1->uid == class &&
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000933 (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
Simon Kelley86bec2d2014-01-13 21:31:20 +0000934 hash_init(hash, &ctx, &digest))
Simon Kelley0fc2f312014-01-08 10:26:58 +0000935
Simon Kelley86bec2d2014-01-13 21:31:20 +0000936 {
937 int wire_len = to_wire(name);
938
939 /* Note that digest may be different between DSs, so
940 we can't move this outside the loop. */
941 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
942 hash->update(ctx, (unsigned int)rdlen, psave);
943 hash->digest(ctx, hash->digest_size, digest);
944
945 from_wire(name);
946
Simon Kelley824202e2014-01-23 20:59:46 +0000947 if (recp1->addr.ds.keylen == (int)hash->digest_size &&
948 (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
949 memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
Simon Kelleyf6a2b792014-02-01 14:54:26 +0000950 validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE)
Simon Kelley86bec2d2014-01-13 21:31:20 +0000951 {
Simon Kelley86bec2d2014-01-13 21:31:20 +0000952 valid = 1;
Simon Kelley86bec2d2014-01-13 21:31:20 +0000953 break;
954 }
955 }
956 }
Simon Kelleye7829ae2014-01-22 22:21:51 +0000957 blockdata_free(key);
Simon Kelley0fc2f312014-01-08 10:26:58 +0000958 }
959
960 if (valid)
961 {
Simon Kelley8d718cb2014-02-03 16:27:37 +0000962 /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
Simon Kelleye7829ae2014-01-22 22:21:51 +0000963 cache_start_insert();
964
965 p = skip_questions(header, plen);
966
967 for (j = ntohs(header->ancount); j != 0; j--)
968 {
969 /* Ensure we have type, class TTL and length */
970 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
971 return STAT_INSECURE; /* bad packet */
972
973 GETSHORT(qtype, p);
974 GETSHORT(qclass, p);
975 GETLONG(ttl, p);
976 GETSHORT(rdlen, p);
Simon Kelley8d718cb2014-02-03 16:27:37 +0000977
978 if (!CHECK_LEN(header, p, plen, rdlen))
Simon Kelleye7829ae2014-01-22 22:21:51 +0000979 return STAT_INSECURE; /* bad packet */
Simon Kelleye7829ae2014-01-22 22:21:51 +0000980
Simon Kelley8d718cb2014-02-03 16:27:37 +0000981 if (qclass == class && rc == 1)
Simon Kelleye7829ae2014-01-22 22:21:51 +0000982 {
Simon Kelley8d718cb2014-02-03 16:27:37 +0000983 psave = p;
Simon Kelleye7829ae2014-01-22 22:21:51 +0000984
Simon Kelley8d718cb2014-02-03 16:27:37 +0000985 if (qtype == T_DNSKEY)
986 {
987 if (rdlen < 4)
988 return STAT_INSECURE; /* bad packet */
989
990 GETSHORT(flags, p);
991 if (*p++ != 3)
Simon Kelleyf01d7be2014-02-24 20:20:00 +0000992 return STAT_BOGUS;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000993 algo = *p++;
994 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
995
996 /* Cache needs to known class for DNSSEC stuff */
997 a.addr.dnssec.class = class;
998
999 if ((key = blockdata_alloc((char*)p, rdlen - 4)))
1000 {
1001 if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
1002 blockdata_free(key);
1003 else
1004 {
1005 a.addr.keytag = keytag;
1006 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
1007
1008 recp1->addr.key.keylen = rdlen - 4;
1009 recp1->addr.key.keydata = key;
1010 recp1->addr.key.algo = algo;
1011 recp1->addr.key.keytag = keytag;
1012 recp1->addr.key.flags = flags;
Simon Kelley8d718cb2014-02-03 16:27:37 +00001013 }
1014 }
1015 }
1016 else if (qtype == T_RRSIG)
1017 {
1018 /* RRSIG, cache if covers DNSKEY RRset */
1019 if (rdlen < 18)
1020 return STAT_INSECURE; /* bad packet */
1021
1022 GETSHORT(type_covered, p);
1023
1024 if (type_covered == T_DNSKEY)
1025 {
1026 a.addr.dnssec.class = class;
1027 a.addr.dnssec.type = type_covered;
1028
1029 algo = *p++;
1030 p += 13; /* labels, orig_ttl, expiration, inception */
1031 GETSHORT(keytag, p);
1032 if ((key = blockdata_alloc((char*)psave, rdlen)))
1033 {
1034 if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
1035 blockdata_free(key);
1036 else
1037 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001038 crecp->addr.sig.keydata = key;
1039 crecp->addr.sig.keylen = rdlen;
1040 crecp->addr.sig.keytag = keytag;
1041 crecp->addr.sig.type_covered = type_covered;
1042 crecp->addr.sig.algo = algo;
1043 }
1044 }
1045 }
1046 }
Simon Kelleye7829ae2014-01-22 22:21:51 +00001047
Simon Kelley8d718cb2014-02-03 16:27:37 +00001048 p = psave;
Simon Kelleye7829ae2014-01-22 22:21:51 +00001049 }
Simon Kelley8d718cb2014-02-03 16:27:37 +00001050
Simon Kelleye7829ae2014-01-22 22:21:51 +00001051 if (!ADD_RDLEN(header, p, plen, rdlen))
1052 return STAT_INSECURE; /* bad packet */
1053 }
1054
Simon Kelley0fc2f312014-01-08 10:26:58 +00001055 /* commit cache insert. */
1056 cache_end_insert();
1057 return STAT_SECURE;
1058 }
1059
1060 log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
1061 return STAT_BOGUS;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001062}
Simon Kelley0fc2f312014-01-08 10:26:58 +00001063
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001064/* The DNS packet is expected to contain the answer to a DS query
1065 Put all DSs in the answer which are valid into the cache.
1066 return codes:
Simon Kelleyb8eac192014-02-27 14:30:03 +00001067 STAT_INSECURE bad packet, no DS in reply, proven no DS in reply.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001068 STAT_SECURE At least one valid DS found and in cache.
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001069 STAT_NO_DS It's proved there's no DS here.
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001070 STAT_BOGUS At least one DS found, which fails validation.
1071 STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
1072*/
1073
1074int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
1075{
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001076 unsigned char *p = (unsigned char *)(header+1);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001077 int qtype, qclass, val, i, neganswer;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001078
Simon Kelley5f8e58f2014-01-09 17:31:19 +00001079 if (ntohs(header->qdcount) != 1 ||
Simon Kelleyb8eac192014-02-27 14:30:03 +00001080 !(p = skip_name(p, header, plen, 4)))
Simon Kelley8d718cb2014-02-03 16:27:37 +00001081 return STAT_INSECURE;
1082
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001083 GETSHORT(qtype, p);
1084 GETSHORT(qclass, p);
1085
Simon Kelleyb47b04c2014-02-25 23:13:28 +00001086 if (qtype != T_DS || qclass != class)
1087 val = STAT_BOGUS;
1088 else
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001089 val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer);
1090
1091 if (val == STAT_NO_SIG)
1092 val = STAT_INSECURE;
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001093
Simon Kelleyb8eac192014-02-27 14:30:03 +00001094 p = (unsigned char *)(header+1);
1095 extract_name(header, plen, &p, name, 1, 4);
1096 p += 4; /* qtype, qclass */
1097
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001098 if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
1099 return STAT_INSECURE;
1100
Simon Kelley0fc2f312014-01-08 10:26:58 +00001101 if (val == STAT_BOGUS)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001102 log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
Simon Kelleyb47b04c2014-02-25 23:13:28 +00001103
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001104 if ((val == STAT_SECURE || val == STAT_INSECURE) && neganswer)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001105 {
Simon Kelley14db4212014-03-01 15:35:50 +00001106 int rdlen, flags = F_FORWARD | F_DS | F_NEG;
Simon Kelleyb8eac192014-02-27 14:30:03 +00001107 unsigned long ttl, minttl = ULONG_MAX;
1108 struct all_addr a;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001109
1110 if (RCODE(header) == NXDOMAIN)
1111 flags |= F_NXDOMAIN;
1112
1113 if (val == STAT_SECURE)
1114 flags |= F_DNSSECOK;
Simon Kelleyb8eac192014-02-27 14:30:03 +00001115
1116 for (i = ntohs(header->nscount); i != 0; i--)
1117 {
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001118 if (!(p = skip_name(p, header, plen, 0)))
Simon Kelleyb8eac192014-02-27 14:30:03 +00001119 return STAT_INSECURE;
1120
1121 GETSHORT(qtype, p);
1122 GETSHORT(qclass, p);
1123 GETLONG(ttl, p);
1124 GETSHORT(rdlen, p);
1125
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001126 if (!CHECK_LEN(header, p, plen, rdlen))
Simon Kelleyb8eac192014-02-27 14:30:03 +00001127 return STAT_INSECURE; /* bad packet */
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001128
1129 if (qclass != class || qtype != T_SOA)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001130 {
1131 p += rdlen;
1132 continue;
1133 }
1134
1135 if (ttl < minttl)
1136 minttl = ttl;
1137
1138 /* MNAME */
1139 if (!(p = skip_name(p, header, plen, 0)))
1140 return STAT_INSECURE;
1141 /* RNAME */
1142 if (!(p = skip_name(p, header, plen, 20)))
1143 return STAT_INSECURE;
1144 p += 16; /* SERIAL REFRESH RETRY EXPIRE */
1145
1146 GETLONG(ttl, p); /* minTTL */
1147 if (ttl < minttl)
1148 minttl = ttl;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001149
1150 break;
Simon Kelleyb8eac192014-02-27 14:30:03 +00001151 }
1152
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001153 if (i != 0)
1154 {
1155 cache_start_insert();
1156
1157 a.addr.dnssec.class = class;
1158 cache_insert(name, &a, now, ttl, flags);
1159
1160 cache_end_insert();
1161 }
Simon Kelleyb8eac192014-02-27 14:30:03 +00001162
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001163 return (val == STAT_SECURE) ? STAT_NO_DS : STAT_INSECURE;
Simon Kelleyb8eac192014-02-27 14:30:03 +00001164 }
1165
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001166 return val;
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +00001167}
1168
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001169/* 4034 6.1 */
1170static int hostname_cmp(const char *a, const char *b)
1171{
Simon Kelleydbf72122014-01-21 14:28:02 +00001172 char *sa, *ea, *ca, *sb, *eb, *cb;
1173 unsigned char ac, bc;
1174
1175 sa = ea = (char *)a + strlen(a);
1176 sb = eb = (char *)b + strlen(b);
1177
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001178 while (1)
1179 {
Simon Kelleydbf72122014-01-21 14:28:02 +00001180 while (sa != a && *(sa-1) != '.')
1181 sa--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001182
Simon Kelleydbf72122014-01-21 14:28:02 +00001183 while (sb != b && *(sb-1) != '.')
1184 sb--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001185
Simon Kelleydbf72122014-01-21 14:28:02 +00001186 ca = sa;
1187 cb = sb;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001188
Simon Kelleydbf72122014-01-21 14:28:02 +00001189 while (1)
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001190 {
Simon Kelleydbf72122014-01-21 14:28:02 +00001191 if (ca == ea)
1192 {
1193 if (cb == eb)
1194 break;
1195
1196 return -1;
1197 }
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001198
Simon Kelleydbf72122014-01-21 14:28:02 +00001199 if (cb == eb)
1200 return 1;
1201
1202 ac = (unsigned char) *ca++;
1203 bc = (unsigned char) *cb++;
1204
1205 if (ac >= 'A' && ac <= 'Z')
1206 ac += 'a' - 'A';
1207 if (bc >= 'A' && bc <= 'Z')
1208 bc += 'a' - 'A';
1209
Simon Kelley979cdf92014-01-21 16:26:41 +00001210 if (ac < bc)
Simon Kelleydbf72122014-01-21 14:28:02 +00001211 return -1;
1212 else if (ac != bc)
1213 return 1;
1214 }
1215
1216
1217 if (sa == a)
1218 {
1219 if (sb == b)
1220 return 0;
1221
1222 return -1;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001223 }
1224
Simon Kelleydbf72122014-01-21 14:28:02 +00001225 if (sb == b)
1226 return 1;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001227
Simon Kelleydbf72122014-01-21 14:28:02 +00001228 ea = sa--;
1229 eb = sb--;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001230 }
1231}
1232
Simon Kelley5107ace2014-02-23 10:48:32 +00001233/* Find all the NSEC or NSEC3 records in a reply.
1234 return an array of pointers to them. */
1235static int find_nsec_records(struct dns_header *header, size_t plen, unsigned char ***nsecsetp, int *nsecsetl, int class_reqd)
1236{
1237 static unsigned char **nsecset = NULL;
1238 static int nsecset_sz = 0;
1239
1240 int type_found = -1;
1241 unsigned char *p = skip_questions(header, plen);
1242 int type, class, rdlen, i, nsecs_found;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001243
Simon Kelley5107ace2014-02-23 10:48:32 +00001244 /* Move to NS section */
1245 if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
1246 return 0;
1247
1248 for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
1249 {
1250 unsigned char *pstart = p;
1251
1252 if (!(p = skip_name(p, header, plen, 10)))
1253 return 0;
1254
1255 GETSHORT(type, p);
1256 GETSHORT(class, p);
1257 p += 4; /* TTL */
1258 GETSHORT(rdlen, p);
1259
1260 if (class == class_reqd && (type == T_NSEC || type == T_NSEC3))
1261 {
1262 /* No mixed NSECing 'round here, thankyouverymuch */
1263 if (type_found == T_NSEC && type == T_NSEC3)
1264 return 0;
1265 if (type_found == T_NSEC3 && type == T_NSEC)
1266 return 0;
1267
1268 type_found = type;
1269
Simon Kelley613ad152014-02-25 23:02:28 +00001270 if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
1271 return 0;
1272
Simon Kelley5107ace2014-02-23 10:48:32 +00001273 nsecset[nsecs_found++] = pstart;
1274 }
Simon Kelley613ad152014-02-25 23:02:28 +00001275
Simon Kelley5107ace2014-02-23 10:48:32 +00001276 if (!ADD_RDLEN(header, p, plen, rdlen))
1277 return 0;
1278 }
1279
1280 *nsecsetp = nsecset;
1281 *nsecsetl = nsecs_found;
1282
1283 return type_found;
1284}
1285
Simon Kelley24187532014-02-24 21:46:44 +00001286static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
Simon Kelley5107ace2014-02-23 10:48:32 +00001287 char *workspace1, char *workspace2, char *name, int type)
1288{
1289 int i, rc, rdlen;
1290 unsigned char *p, *psave;
1291 int offset = (type & 0xff) >> 3;
1292 int mask = 0x80 >> (type & 0x07);
1293
1294 /* Find NSEC record that proves name doesn't exist */
1295 for (i = 0; i < nsec_count; i++)
1296 {
1297 p = nsecs[i];
1298 if (!extract_name(header, plen, &p, workspace1, 1, 10))
1299 return STAT_INSECURE;
1300 p += 8; /* class, type, TTL */
1301 GETSHORT(rdlen, p);
1302 psave = p;
1303 if (!extract_name(header, plen, &p, workspace2, 1, 10))
1304 return STAT_INSECURE;
1305
1306 rc = hostname_cmp(workspace1, name);
1307
1308 if (rc == 0)
1309 {
Simon Kelleyf01d7be2014-02-24 20:20:00 +00001310 /* 4035 para 5.4. Last sentence */
1311 if (type == T_NSEC || type == T_RRSIG)
1312 return STAT_SECURE;
1313
Simon Kelley5107ace2014-02-23 10:48:32 +00001314 /* NSEC with the same name as the RR we're testing, check
1315 that the type in question doesn't appear in the type map */
1316 rdlen -= p - psave;
1317 /* rdlen is now length of type map, and p points to it */
1318
1319 while (rdlen >= 2)
1320 {
1321 if (!CHECK_LEN(header, p, plen, rdlen))
1322 return STAT_INSECURE;
1323
1324 if (p[0] == type >> 8)
1325 {
1326 /* Does the NSEC say our type exists? */
Simon Kelleya857daa2014-02-24 21:01:09 +00001327 if (offset < p[1] && (p[offset+2] & mask) != 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001328 return STAT_BOGUS;
1329
1330 break; /* finshed checking */
1331 }
1332
1333 rdlen -= p[1];
1334 p += p[1];
1335 }
1336
1337 return STAT_SECURE;
1338 }
1339 else if (rc == -1)
1340 {
1341 /* Normal case, name falls between NSEC name and next domain name,
1342 wrap around case, name falls between NSEC name (rc == -1) and end */
1343 if (hostname_cmp(workspace2, name) == 1 || hostname_cmp(workspace1, workspace2) == 1)
1344 return STAT_SECURE;
1345 }
1346 else
1347 {
1348 /* wrap around case, name falls between start and next domain name */
1349 if (hostname_cmp(workspace1, workspace2) == 1 && hostname_cmp(workspace2, name) == 1)
1350 return STAT_SECURE;
1351 }
1352 }
1353
1354 return STAT_BOGUS;
1355}
1356
1357/* return digest length, or zero on error */
1358static int hash_name(char *in, unsigned char **out, struct nettle_hash const *hash,
1359 unsigned char *salt, int salt_len, int iterations)
1360{
1361 void *ctx;
1362 unsigned char *digest;
1363 int i;
1364
1365 if (!hash_init(hash, &ctx, &digest))
1366 return 0;
1367
1368 hash->update(ctx, to_wire(in), (unsigned char *)in);
1369 hash->update(ctx, salt_len, salt);
1370 hash->digest(ctx, hash->digest_size, digest);
1371
1372 for(i = 0; i < iterations; i++)
1373 {
1374 hash->update(ctx, hash->digest_size, digest);
1375 hash->update(ctx, salt_len, salt);
1376 hash->digest(ctx, hash->digest_size, digest);
1377 }
1378
1379 from_wire(in);
1380
1381 *out = digest;
1382 return hash->digest_size;
1383}
1384
1385/* Decode base32 to first "." or end of string */
1386static int base32_decode(char *in, unsigned char *out)
1387{
Simon Kelleya857daa2014-02-24 21:01:09 +00001388 int oc, on, c, mask, i;
Simon Kelley5107ace2014-02-23 10:48:32 +00001389 unsigned char *p = out;
1390
Simon Kelleya857daa2014-02-24 21:01:09 +00001391 for (c = *in, oc = 0, on = 0; c != 0 && c != '.'; c = *++in)
Simon Kelley5107ace2014-02-23 10:48:32 +00001392 {
Simon Kelley5107ace2014-02-23 10:48:32 +00001393 if (c >= '0' && c <= '9')
1394 c -= '0';
1395 else if (c >= 'a' && c <= 'v')
1396 c -= 'a', c += 10;
1397 else if (c >= 'A' && c <= 'V')
1398 c -= 'A', c += 10;
1399 else
1400 return 0;
1401
1402 for (mask = 0x10, i = 0; i < 5; i++)
1403 {
Simon Kelleya857daa2014-02-24 21:01:09 +00001404 if (c & mask)
1405 oc |= 1;
1406 mask = mask >> 1;
1407 if (((++on) & 7) == 0)
1408 *p++ = oc;
1409 oc = oc << 1;
Simon Kelley5107ace2014-02-23 10:48:32 +00001410 }
1411 }
1412
1413 if ((on & 7) != 0)
1414 return 0;
1415
1416 return p - out;
1417}
1418
Simon Kelley24187532014-02-24 21:46:44 +00001419static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
Simon Kelley5107ace2014-02-23 10:48:32 +00001420 char *workspace1, char *workspace2, char *name, int type)
1421{
Simon Kelleya857daa2014-02-24 21:01:09 +00001422 unsigned char *salt, *p, *digest;
1423 int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0;
Simon Kelley5107ace2014-02-23 10:48:32 +00001424 struct nettle_hash const *hash;
1425 char *closest_encloser, *next_closest, *wildcard;
1426
1427 /* Look though the NSEC3 records to find the first one with
1428 an algorithm we support (currently only algo == 1).
1429
1430 Take the algo, iterations, and salt of that record
1431 as the ones we're going to use, and prune any
1432 that don't match. */
1433
1434 for (i = 0; i < nsec_count; i++)
1435 {
1436 if (!(p = skip_name(nsecs[i], header, plen, 15)))
1437 return STAT_INSECURE; /* bad packet */
1438
1439 p += 10; /* type, class, TTL, rdlen */
1440 algo = *p++;
1441
1442 if (algo == 1)
1443 break; /* known algo */
1444 }
1445
1446 /* No usable NSEC3s */
1447 if (i == nsec_count)
1448 return STAT_BOGUS;
1449
1450 p++; /* flags */
1451 GETSHORT (iterations, p);
1452 salt_len = *p++;
1453 salt = p;
1454 if (!CHECK_LEN(header, salt, plen, salt_len))
1455 return STAT_INSECURE; /* bad packet */
1456
1457 /* Now prune so we only have NSEC3 records with same iterations, salt and algo */
1458 for (i = 0; i < nsec_count; i++)
1459 {
1460 unsigned char *nsec3p = nsecs[i];
1461 int this_iter;
1462
1463 nsecs[i] = NULL; /* Speculative, will be restored if OK. */
1464
1465 if (!(p = skip_name(nsec3p, header, plen, 15)))
1466 return STAT_INSECURE; /* bad packet */
1467
1468 p += 10; /* type, class, TTL, rdlen */
1469
1470 if (*p++ != algo)
1471 continue;
1472
1473 p++; /* flags */
1474
Simon Kelleya857daa2014-02-24 21:01:09 +00001475 GETSHORT(this_iter, p);
Simon Kelley5107ace2014-02-23 10:48:32 +00001476 if (this_iter != iterations)
1477 continue;
1478
1479 if (salt_len != *p++)
1480 continue;
1481
1482 if (!CHECK_LEN(header, p, plen, salt_len))
1483 return STAT_INSECURE; /* bad packet */
1484
1485 if (memcmp(p, salt, salt_len) != 0)
1486 continue;
1487
1488 /* All match, put the pointer back */
1489 nsecs[i] = nsec3p;
1490 }
1491
1492 /* Algo is checked as 1 above */
1493 if (!(hash = hash_find("sha1")))
1494 return STAT_INSECURE;
1495
1496 /* Now, we need the "closest encloser NSEC3" */
1497 closest_encloser = name;
1498 next_closest = NULL;
1499
1500 do
1501 {
1502 if (*closest_encloser == '.')
1503 closest_encloser++;
1504
Simon Kelleya857daa2014-02-24 21:01:09 +00001505 if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001506 return STAT_INSECURE;
1507
1508 for (i = 0; i < nsec_count; i++)
1509 if ((p = nsecs[i]))
1510 {
Simon Kelley5107ace2014-02-23 10:48:32 +00001511 if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
Simon Kelleya857daa2014-02-24 21:01:09 +00001512 !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
Simon Kelley5107ace2014-02-23 10:48:32 +00001513 return STAT_INSECURE;
1514
Simon Kelleya857daa2014-02-24 21:01:09 +00001515 if (digest_len == base32_len &&
1516 memcmp(digest, workspace2, digest_len) == 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001517 break; /* Gotit */
1518 }
1519
1520 if (i != nsec_count)
1521 break;
1522
1523 next_closest = closest_encloser;
1524 }
1525 while ((closest_encloser = strchr(closest_encloser, '.')));
1526
1527 /* No usable NSEC3s */
1528 if (i == nsec_count)
1529 return STAT_BOGUS;
1530
1531 if (!next_closest)
1532 {
1533 /* We found an NSEC3 whose hashed name exactly matches the query, so
1534 Now we just need to check the type map. p points to the RR data for the record. */
Simon Kelleya857daa2014-02-24 21:01:09 +00001535 int rdlen;
Simon Kelley5107ace2014-02-23 10:48:32 +00001536 unsigned char *psave;
1537 int offset = (type & 0xff) >> 3;
1538 int mask = 0x80 >> (type & 0x07);
1539
1540 p += 8; /* class, type, TTL */
1541 GETSHORT(rdlen, p);
1542 psave = p;
1543 p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */
1544 hash_len = *p++;
1545 if (!CHECK_LEN(header, p, plen, hash_len))
1546 return STAT_INSECURE; /* bad packet */
1547 p += hash_len;
1548 rdlen -= p - psave;
1549
1550 while (rdlen >= 2)
1551 {
1552 if (!CHECK_LEN(header, p, plen, rdlen))
1553 return STAT_INSECURE;
1554
1555 if (p[0] == type >> 8)
1556 {
Simon Kelleya857daa2014-02-24 21:01:09 +00001557 /* Does the NSEC3 say our type exists? */
1558 if (offset < p[1] && (p[offset+2] & mask) != 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001559 return STAT_BOGUS;
1560
1561 break; /* finshed checking */
1562 }
1563
1564 rdlen -= p[1];
1565 p += p[1];
1566 }
1567
1568 return STAT_SECURE;
1569 }
1570
Simon Kelley24187532014-02-24 21:46:44 +00001571 /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
Simon Kelleya857daa2014-02-24 21:01:09 +00001572 if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001573 return STAT_INSECURE;
1574
1575 for (i = 0; i < nsec_count; i++)
1576 if ((p = nsecs[i]))
1577 {
Simon Kelleya857daa2014-02-24 21:01:09 +00001578 if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
1579 !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
Simon Kelley5107ace2014-02-23 10:48:32 +00001580 return STAT_INSECURE;
1581
1582 p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
1583 hash_len = *p++; /* p now points to next hashed name */
1584
1585 if (!CHECK_LEN(header, p, plen, hash_len))
1586 return STAT_INSECURE;
1587
Simon Kelleya857daa2014-02-24 21:01:09 +00001588 if (digest_len == base32_len && hash_len == base32_len)
Simon Kelley5107ace2014-02-23 10:48:32 +00001589 {
Simon Kelleya857daa2014-02-24 21:01:09 +00001590 if (memcmp(workspace2, digest, digest_len) <= 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001591 {
1592 /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
1593 wrap around case, name-hash falls between NSEC3 name-hash and end */
Simon Kelleya857daa2014-02-24 21:01:09 +00001594 if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001595 return STAT_SECURE;
1596 }
1597 else
1598 {
1599 /* wrap around case, name falls between start and next domain name */
Simon Kelleya857daa2014-02-24 21:01:09 +00001600 if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001601 return STAT_SECURE;
1602 }
1603 }
1604 }
1605
1606 /* Finally, check that there's no seat of wildcard synthesis */
1607 if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
1608 return STAT_BOGUS;
1609
1610 wildcard--;
1611 *wildcard = '*';
1612
Simon Kelleya857daa2014-02-24 21:01:09 +00001613 if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001614 return STAT_INSECURE;
1615
1616 for (i = 0; i < nsec_count; i++)
1617 if ((p = nsecs[i]))
1618 {
Simon Kelley5107ace2014-02-23 10:48:32 +00001619 if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
Simon Kelleya857daa2014-02-24 21:01:09 +00001620 !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
Simon Kelley5107ace2014-02-23 10:48:32 +00001621 return STAT_INSECURE;
1622
1623 p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
1624 hash_len = *p++; /* p now points to next hashed name */
1625
1626 if (!CHECK_LEN(header, p, plen, hash_len))
1627 return STAT_INSECURE;
1628
Simon Kelleya857daa2014-02-24 21:01:09 +00001629 if (digest_len == base32_len && hash_len == base32_len)
Simon Kelley5107ace2014-02-23 10:48:32 +00001630 {
Simon Kelleya857daa2014-02-24 21:01:09 +00001631 if (memcmp(workspace2, digest, digest_len) <= 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001632 {
1633 /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
1634 wrap around case, name-hash falls between NSEC3 name-hash and end */
Simon Kelleya857daa2014-02-24 21:01:09 +00001635 if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001636 return STAT_SECURE;
1637 }
1638 else
1639 {
1640 /* wrap around case, name falls between start and next domain name */
Simon Kelleya857daa2014-02-24 21:01:09 +00001641 if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
Simon Kelley5107ace2014-02-23 10:48:32 +00001642 return STAT_SECURE;
1643 }
1644 }
1645 }
1646
1647 return STAT_BOGUS;
1648}
1649
Simon Kelley0fc2f312014-01-08 10:26:58 +00001650/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001651/* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001652int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer)
Giovanni Bajoe292e932012-04-22 14:32:02 +02001653{
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001654 unsigned char *ans_start, *qname, *p1, *p2, **nsecs;
1655 int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype;
Simon Kelley5107ace2014-02-23 10:48:32 +00001656 int i, j, rc, nsec_count, cname_count = 10;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001657 int nsec_type = 0, have_answer = 0;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001658
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001659 if (neganswer)
1660 *neganswer = 0;
1661
Simon Kelleye3ec15a2014-02-13 16:56:30 +00001662 if (RCODE(header) == SERVFAIL)
1663 return STAT_BOGUS;
1664
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001665 if ((RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR) || ntohs(header->qdcount) != 1)
Simon Kelley72ae2f32014-01-19 09:54:16 +00001666 return STAT_INSECURE;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001667
1668 qname = p1 = (unsigned char *)(header+1);
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001669
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001670 if (!extract_name(header, plen, &p1, name, 1, 4))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001671 return STAT_INSECURE;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001672
1673 GETSHORT(qtype, p1);
1674 GETSHORT(qclass, p1);
1675 ans_start = p1;
1676
1677 /* Can't validate an RRISG query */
1678 if (qtype == T_RRSIG)
1679 return STAT_INSECURE;
1680
1681 cname_loop:
1682 for (j = ntohs(header->ancount); j != 0; j--)
1683 {
1684 /* leave pointer to missing name in qname */
1685
1686 if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
1687 return STAT_INSECURE; /* bad packet */
1688
1689 GETSHORT(type2, p1);
1690 GETSHORT(class2, p1);
1691 p1 += 4; /* TTL */
1692 GETSHORT(rdlen2, p1);
1693
1694 if (rc == 1 && qclass == class2)
1695 {
1696 /* Do we have an answer for the question? */
1697 if (type2 == qtype)
1698 {
1699 have_answer = 1;
1700 break;
1701 }
1702 else if (type2 == T_CNAME)
1703 {
1704 qname = p1;
1705
1706 /* looped CNAMES */
1707 if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
1708 return STAT_INSECURE;
1709
1710 p1 = ans_start;
1711 goto cname_loop;
1712 }
1713 }
1714
1715 if (!ADD_RDLEN(header, p1, plen, rdlen2))
1716 return STAT_INSECURE;
1717 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001718
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001719 if (neganswer && !have_answer)
1720 *neganswer = 1;
Simon Kelley05756102014-03-01 18:07:57 +00001721
1722 /* No data, therefore no sigs */
1723 if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
1724 return STAT_NO_SIG;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001725
Simon Kelley0fc2f312014-01-08 10:26:58 +00001726 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
Giovanni Bajoe292e932012-04-22 14:32:02 +02001727 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001728 if (!extract_name(header, plen, &p1, name, 1, 10))
1729 return STAT_INSECURE; /* bad packet */
1730
1731 GETSHORT(type1, p1);
1732 GETSHORT(class1, p1);
1733 p1 += 4; /* TTL */
1734 GETSHORT(rdlen1, p1);
1735
1736 /* Don't try and validate RRSIGs! */
1737 if (type1 != T_RRSIG)
1738 {
1739 /* Check if we've done this RRset already */
1740 for (p2 = ans_start, j = 0; j < i; j++)
1741 {
1742 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1743 return STAT_INSECURE; /* bad packet */
1744
1745 GETSHORT(type2, p2);
1746 GETSHORT(class2, p2);
1747 p2 += 4; /* TTL */
1748 GETSHORT(rdlen2, p2);
1749
1750 if (type2 == type1 && class2 == class1 && rc == 1)
1751 break; /* Done it before: name, type, class all match. */
1752
1753 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1754 return STAT_INSECURE;
1755 }
1756
1757 /* Not done, validate now */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001758 if (j == i)
Simon Kelley0fc2f312014-01-08 10:26:58 +00001759 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001760 int ttl, keytag, algo, digest, type_covered;
1761 unsigned char *psave;
1762 struct all_addr a;
1763 struct blockdata *key;
1764 struct crec *crecp;
1765
Simon Kelley5107ace2014-02-23 10:48:32 +00001766 rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0);
1767
1768 if (rc == STAT_SECURE_WILDCARD)
1769 {
1770 /* An attacker replay a wildcard answer with a different
Simon Kelleya857daa2014-02-24 21:01:09 +00001771 answer and overlay a genuine RR. To prove this
Simon Kelley5107ace2014-02-23 10:48:32 +00001772 hasn't happened, the answer must prove that
Simon Kelleya857daa2014-02-24 21:01:09 +00001773 the gennuine record doesn't exist. Check that here. */
Simon Kelley5107ace2014-02-23 10:48:32 +00001774 if (!nsec_type)
1775 {
1776 nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1);
1777
1778 if (nsec_type == 0)
1779 return STAT_INSECURE; /* Bad packet */
1780 if (nsec_type == -1)
1781 return STAT_BOGUS; /* No NSECs */
1782 }
1783
1784 if (nsec_type == T_NSEC)
Simon Kelley24187532014-02-24 21:46:44 +00001785 rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
Simon Kelley5107ace2014-02-23 10:48:32 +00001786 else
Simon Kelley24187532014-02-24 21:46:44 +00001787 rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
Simon Kelley5107ace2014-02-23 10:48:32 +00001788
1789 if (rc != STAT_SECURE)
1790 return rc;
1791 }
1792 else if (rc != STAT_SECURE)
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001793 {
1794 if (class)
1795 *class = class1; /* Class for DS or DNSKEY */
1796 return rc;
1797 }
Simon Kelley5107ace2014-02-23 10:48:32 +00001798
Simon Kelley8d718cb2014-02-03 16:27:37 +00001799 /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
1800 cache_start_insert();
1801
1802 for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001803 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001804 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1805 return STAT_INSECURE; /* bad packet */
1806
1807 GETSHORT(type2, p2);
1808 GETSHORT(class2, p2);
1809 GETLONG(ttl, p2);
1810 GETSHORT(rdlen2, p2);
1811
1812 if (!CHECK_LEN(header, p2, plen, rdlen2))
1813 return STAT_INSECURE; /* bad packet */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001814
Simon Kelley8d718cb2014-02-03 16:27:37 +00001815 if (class2 == class1 && rc == 1)
1816 {
1817 psave = p2;
1818
1819 if (type1 == T_DS && type2 == T_DS)
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001820 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001821 if (rdlen2 < 4)
1822 return STAT_INSECURE; /* bad packet */
1823
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001824 GETSHORT(keytag, p2);
1825 algo = *p2++;
1826 digest = *p2++;
1827
1828 /* Cache needs to known class for DNSSEC stuff */
1829 a.addr.dnssec.class = class2;
1830
Simon Kelley8d718cb2014-02-03 16:27:37 +00001831 if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001832 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001833 if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1834 blockdata_free(key);
1835 else
1836 {
1837 a.addr.keytag = keytag;
1838 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
1839 crecp->addr.ds.digest = digest;
1840 crecp->addr.ds.keydata = key;
1841 crecp->addr.ds.algo = algo;
1842 crecp->addr.ds.keytag = keytag;
Simon Kelley8d718cb2014-02-03 16:27:37 +00001843 crecp->addr.ds.keylen = rdlen2 - 4;
1844 }
1845 }
1846 }
1847 else if (type2 == T_RRSIG)
1848 {
1849 if (rdlen2 < 18)
1850 return STAT_INSECURE; /* bad packet */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001851
Simon Kelley8d718cb2014-02-03 16:27:37 +00001852 GETSHORT(type_covered, p2);
1853
1854 if (type_covered == type1 &&
1855 (type_covered == T_A || type_covered == T_AAAA ||
1856 type_covered == T_CNAME || type_covered == T_DS ||
1857 type_covered == T_DNSKEY || type_covered == T_PTR))
1858 {
1859 a.addr.dnssec.type = type_covered;
Simon Kelleyc8ca33f2014-02-10 10:35:42 +00001860 a.addr.dnssec.class = class1;
Simon Kelley8d718cb2014-02-03 16:27:37 +00001861
1862 algo = *p2++;
1863 p2 += 13; /* labels, orig_ttl, expiration, inception */
1864 GETSHORT(keytag, p2);
1865
1866 if ((key = blockdata_alloc((char*)psave, rdlen2)))
1867 {
1868 if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
1869 blockdata_free(key);
1870 else
1871 {
Simon Kelley8d718cb2014-02-03 16:27:37 +00001872 crecp->addr.sig.keydata = key;
1873 crecp->addr.sig.keylen = rdlen2;
1874 crecp->addr.sig.keytag = keytag;
1875 crecp->addr.sig.type_covered = type_covered;
1876 crecp->addr.sig.algo = algo;
1877 }
1878 }
1879 }
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001880 }
1881
Simon Kelley8d718cb2014-02-03 16:27:37 +00001882 p2 = psave;
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001883 }
1884
Simon Kelley8d718cb2014-02-03 16:27:37 +00001885 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1886 return STAT_INSECURE; /* bad packet */
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001887 }
Simon Kelley8d718cb2014-02-03 16:27:37 +00001888
1889 cache_end_insert();
Simon Kelley0fc2f312014-01-08 10:26:58 +00001890 }
1891 }
1892
1893 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1894 return STAT_INSECURE;
Giovanni Bajoe292e932012-04-22 14:32:02 +02001895 }
1896
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001897 /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001898 if (have_answer)
1899 return STAT_SECURE;
1900
Simon Kelley5107ace2014-02-23 10:48:32 +00001901 /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
Simon Kelley5107ace2014-02-23 10:48:32 +00001902 /* First marshall the NSEC records, if we've not done it previously */
1903 if (!nsec_type)
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001904 {
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001905 nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass);
Simon Kelley5107ace2014-02-23 10:48:32 +00001906
1907 if (nsec_type == 0)
1908 return STAT_INSECURE; /* Bad packet */
1909 if (nsec_type == -1)
1910 return STAT_BOGUS; /* No NSECs */
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001911 }
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001912
1913 /* Get name of missing answer */
1914 if (!extract_name(header, plen, &qname, name, 1, 0))
1915 return STAT_INSECURE;
Simon Kelleyc5f4ec72014-01-20 22:37:55 +00001916
Simon Kelley5107ace2014-02-23 10:48:32 +00001917 if (nsec_type == T_NSEC)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001918 return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
Simon Kelley5107ace2014-02-23 10:48:32 +00001919 else
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001920 return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
Giovanni Bajoadca3e92012-04-25 17:46:53 +02001921}
1922
Simon Kelley00a5b5d2014-02-28 18:10:55 +00001923/* Chase the CNAME chain in the packet until the first record which _doesn't validate.
1924 Needed for proving answer in unsigned space.
1925 Return STAT_NEED_*
1926 STAT_BOGUS - error
1927 STAT_INSECURE - name of first non-secure record in name
1928*/
1929int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
1930{
1931 unsigned char *p = (unsigned char *)(header+1);
1932 int type, class, qtype, qclass, rdlen, j, rc;
1933 int cname_count = 10;
1934
1935 /* Get question */
1936 if (!extract_name(header, plen, &p, name, 1, 4))
1937 return STAT_BOGUS;
1938
1939 GETSHORT(qtype, p);
1940 GETSHORT(qclass, p);
1941
1942 while (1)
1943 {
1944 for (j = ntohs(header->ancount); j != 0; j--)
1945 {
1946 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
1947 return STAT_BOGUS; /* bad packet */
1948
1949 GETSHORT(type, p);
1950 GETSHORT(class, p);
1951 p += 4; /* TTL */
1952 GETSHORT(rdlen, p);
1953
1954 /* Not target, loop */
1955 if (rc == 2 || qclass != class)
1956 {
1957 if (!ADD_RDLEN(header, p, plen, rdlen))
1958 return STAT_BOGUS;
1959 continue;
1960 }
1961
1962 /* Got to end of CNAME chain. */
1963 if (type != T_CNAME)
1964 return STAT_INSECURE;
1965
1966 /* validate CNAME chain, return if insecure or need more data */
1967 rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0);
1968 if (rc != STAT_SECURE)
1969 {
1970 if (rc == STAT_NO_SIG)
1971 rc = STAT_INSECURE;
1972 return rc;
1973 }
1974
1975 /* Loop down CNAME chain/ */
1976 if (!cname_count-- ||
1977 !extract_name(header, plen, &p, name, 1, 0) ||
1978 !(p = skip_questions(header, plen)))
1979 return STAT_BOGUS;
1980
1981 break;
1982 }
1983
1984 /* End of CNAME chain */
1985 return STAT_INSECURE;
1986 }
1987}
1988
1989
Giovanni Bajo3471f182012-04-25 17:49:16 +02001990/* Compute keytag (checksum to quickly index a key). See RFC4034 */
Simon Kelley0fc2f312014-01-08 10:26:58 +00001991int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
Giovanni Bajo3471f182012-04-25 17:49:16 +02001992{
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02001993 if (alg == 1)
1994 {
1995 /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
1996 See RFC4034, Appendix B.1 */
Simon Kelley0fc2f312014-01-08 10:26:58 +00001997 return key[keylen-4] * 256 + key[keylen-3];
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02001998 }
1999 else
2000 {
Simon Kelley1633e302014-02-10 16:42:46 +00002001 unsigned long ac = flags + 0x300 + alg;
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02002002 int i;
Giovanni Bajo3471f182012-04-25 17:49:16 +02002003
Simon Kelley0fc2f312014-01-08 10:26:58 +00002004 for (i = 0; i < keylen; ++i)
2005 ac += (i & 1) ? key[i] : key[i] << 8;
Simon Kelley1633e302014-02-10 16:42:46 +00002006
Simon Kelley0fc2f312014-01-08 10:26:58 +00002007 ac += (ac >> 16) & 0xffff;
2008 return ac & 0xffff;
Giovanni Bajo75ffc9b2012-05-02 19:58:06 +02002009 }
Giovanni Bajo3471f182012-04-25 17:49:16 +02002010}
2011
Simon Kelley5f8e58f2014-01-09 17:31:19 +00002012size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
2013{
2014 unsigned char *p;
Simon Kelley610e7822014-02-06 14:45:17 +00002015 char *types = querystr("dnssec-query", type);
Giovanni Bajo0304d282012-05-02 03:29:52 +02002016
Simon Kelley5f8e58f2014-01-09 17:31:19 +00002017 if (addr->sa.sa_family == AF_INET)
2018 log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
2019#ifdef HAVE_IPV6
2020 else
2021 log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
2022#endif
2023
2024 header->qdcount = htons(1);
2025 header->ancount = htons(0);
2026 header->nscount = htons(0);
2027 header->arcount = htons(0);
2028
2029 header->hb3 = HB3_RD;
2030 SET_OPCODE(header, QUERY);
Simon Kelley5b3bf922014-01-25 17:03:07 +00002031 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
2032 this allows it to select auth servers when one is returning bad data. */
2033 header->hb4 = option_bool(OPT_DNSSEC_DEBUG) ? HB4_CD : 0;
Simon Kelley5f8e58f2014-01-09 17:31:19 +00002034
2035 /* ID filled in later */
2036
2037 p = (unsigned char *)(header+1);
2038
2039 p = do_rfc1035_name(p, name);
2040 *p++ = 0;
2041 PUTSHORT(type, p);
2042 PUTSHORT(class, p);
2043
2044 return add_do_bit(header, p - (unsigned char *)header, end);
2045}
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002046
Simon Kelley613ad152014-02-25 23:02:28 +00002047/* Go through a domain name, find "pointers" and fix them up based on how many bytes
2048 we've chopped out of the packet, or check they don't point into an elided part. */
2049static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
2050{
2051 unsigned char *ansp = *namep;
2052
2053 while(1)
2054 {
2055 unsigned int label_type;
2056
2057 if (!CHECK_LEN(header, ansp, plen, 1))
2058 return 0;
2059
2060 label_type = (*ansp) & 0xc0;
2061
2062 if (label_type == 0xc0)
2063 {
2064 /* pointer for compression. */
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002065 unsigned int offset;
2066 int i;
Simon Kelley613ad152014-02-25 23:02:28 +00002067 unsigned char *p;
2068
2069 if (!CHECK_LEN(header, ansp, plen, 2))
2070 return 0;
2071
2072 offset = ((*ansp++) & 0x3f) << 8;
2073 offset |= *ansp++;
2074
2075 p = offset + (unsigned char *)header;
2076
2077 for (i = 0; i < rr_count; i++)
2078 if (p < rrs[i])
2079 break;
2080 else
2081 if (i & 1)
2082 offset -= rrs[i] - rrs[i-1];
2083
2084 /* does the pointer end up in an elided RR? */
2085 if (i & 1)
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002086 return 0;
Simon Kelley613ad152014-02-25 23:02:28 +00002087
2088 /* No, scale the pointer */
2089 if (fixup)
2090 {
2091 ansp -= 2;
2092 *ansp++ = (offset >> 8) | 0xc0;
2093 *ansp++ = offset & 0xff;
2094 }
2095 break;
2096 }
2097 else if (label_type == 0x80)
2098 return 0; /* reserved */
2099 else if (label_type == 0x40)
2100 {
2101 /* Extended label type */
2102 unsigned int count;
2103
2104 if (!CHECK_LEN(header, ansp, plen, 2))
2105 return 0;
2106
2107 if (((*ansp++) & 0x3f) != 1)
2108 return 0; /* we only understand bitstrings */
2109
2110 count = *(ansp++); /* Bits in bitstring */
2111
2112 if (count == 0) /* count == 0 means 256 bits */
2113 ansp += 32;
2114 else
2115 ansp += ((count-1)>>3)+1;
2116 }
2117 else
2118 { /* label type == 0 Bottom six bits is length */
2119 unsigned int len = (*ansp++) & 0x3f;
2120
2121 if (!ADD_RDLEN(header, ansp, plen, len))
2122 return 0;
2123
2124 if (len == 0)
2125 break; /* zero length label marks the end. */
2126 }
2127 }
2128
2129 *namep = ansp;
2130
2131 return 1;
2132}
2133
2134/* Go through RRs and check or fixup the domain names contained within */
2135static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
2136{
2137 int i, type, class, rdlen;
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002138 unsigned char *pp;
Simon Kelley613ad152014-02-25 23:02:28 +00002139
2140 for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
2141 {
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002142 pp = p;
2143
2144 if (!(p = skip_name(p, header, plen, 10)))
2145 return 0;
Simon Kelley613ad152014-02-25 23:02:28 +00002146
2147 GETSHORT(type, p);
2148 GETSHORT(class, p);
2149 p += 4; /* TTL */
2150 GETSHORT(rdlen, p);
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002151
Simon Kelley613ad152014-02-25 23:02:28 +00002152 if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
2153 {
Simon Kelley00a5b5d2014-02-28 18:10:55 +00002154 /* fixup name of RR */
2155 if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
2156 return 0;
2157
Simon Kelley613ad152014-02-25 23:02:28 +00002158 if (class == C_IN)
2159 {
2160 u16 *d;
Simon Kelley14db4212014-03-01 15:35:50 +00002161
2162 for (pp = p, d = get_desc(type); *d != (u16)-1; d++)
Simon Kelley613ad152014-02-25 23:02:28 +00002163 {
2164 if (*d != 0)
2165 pp += *d;
2166 else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
2167 return 0;
2168 }
2169 }
2170 }
2171
2172 if (!ADD_RDLEN(header, p, plen, rdlen))
2173 return 0;
2174 }
2175
2176 return 1;
2177}
2178
2179
2180size_t filter_rrsigs(struct dns_header *header, size_t plen)
2181{
2182 static unsigned char **rrs;
2183 static int rr_sz = 0;
2184
2185 unsigned char *p = (unsigned char *)(header+1);
2186 int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns;
2187
2188 if (ntohs(header->qdcount) != 1 ||
2189 !(p = skip_name(p, header, plen, 4)))
2190 return plen;
2191
2192 GETSHORT(qtype, p);
2193 GETSHORT(qclass, p);
2194
2195 /* First pass, find pointers to start and end of all the records we wish to elide:
2196 records added for DNSSEC, unless explicity queried for */
2197 for (rr_found = 0, chop_ns = 0, chop_an = 0, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
2198 {
2199 unsigned char *pstart = p;
2200 int type, class;
2201
2202 if (!(p = skip_name(p, header, plen, 10)))
2203 return plen;
2204
2205 GETSHORT(type, p);
2206 GETSHORT(class, p);
2207 p += 4; /* TTL */
2208 GETSHORT(rdlen, p);
2209
2210 if ((type == T_NSEC || type == T_NSEC3 || type == T_RRSIG) &&
2211 (type != qtype || class != qclass))
2212 {
2213 if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
2214 return plen;
2215
2216 rrs[rr_found++] = pstart;
2217
2218 if (!ADD_RDLEN(header, p, plen, rdlen))
2219 return plen;
2220
2221 rrs[rr_found++] = p;
2222
2223 if (i < ntohs(header->ancount))
2224 chop_an++;
2225 else
2226 chop_ns++;
2227 }
2228 else if (!ADD_RDLEN(header, p, plen, rdlen))
2229 return plen;
2230 }
2231
2232 /* Nothing to do. */
2233 if (rr_found == 0)
2234 return plen;
2235
2236 /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
2237 point to records we're going to elide. This is theoretically possible, but unlikely. If
2238 it happens, we give up and leave the answer unchanged. */
2239 p = (unsigned char *)(header+1);
2240
2241 /* question first */
2242 if (!check_name(&p, header, plen, 0, rrs, rr_found))
2243 return plen;
2244 p += 4; /* qclass, qtype */
2245
2246 /* Now answers and NS */
2247 if (!check_rrs(p, header, plen, 0, rrs, rr_found))
2248 return plen;
2249
2250 /* Third pass, elide records */
2251 for (p = rrs[0], i = 1; i < rr_found; i += 2)
2252 {
2253 unsigned char *start = rrs[i];
2254 unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
2255
2256 memmove(p, start, end-start);
2257 p += end-start;
2258 }
2259
2260 plen = p - (unsigned char *)header;
2261 header->ancount = htons(ntohs(header->ancount) - chop_an);
2262 header->nscount = htons(ntohs(header->nscount) - chop_ns);
2263
2264 /* Fourth pass, fix up pointers in the remaining records */
2265 p = (unsigned char *)(header+1);
2266
2267 check_name(&p, header, plen, 1, rrs, rr_found);
2268 p += 4; /* qclass, qtype */
2269
2270 check_rrs(p, header, plen, 1, rrs, rr_found);
2271
2272 return plen;
2273}
2274
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002275unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
2276{
2277 int q;
2278 unsigned int len;
2279 unsigned char *p = (unsigned char *)(header+1);
2280 const struct nettle_hash *hash;
2281 void *ctx;
2282 unsigned char *digest;
Simon Kelley5f8e58f2014-01-09 17:31:19 +00002283
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002284 if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
2285 return NULL;
2286
2287 for (q = ntohs(header->qdcount); q != 0; q--)
2288 {
2289 if (!extract_name(header, plen, &p, name, 1, 4))
Simon Kelley7d23a662014-01-26 09:33:21 +00002290 break; /* bad packet */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002291
2292 len = to_wire(name);
2293 hash->update(ctx, len, (unsigned char *)name);
2294 /* CRC the class and type as well */
2295 hash->update(ctx, 4, p);
2296
2297 p += 4;
2298 if (!CHECK_LEN(header, p, plen, 0))
Simon Kelley7d23a662014-01-26 09:33:21 +00002299 break; /* bad packet */
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002300 }
Simon Kelley703c7ff2014-01-25 23:46:23 +00002301
2302 hash->digest(ctx, hash->digest_size, digest);
Simon Kelley8a9be9e2014-01-25 23:17:21 +00002303 return digest;
2304}
2305
Simon Kelley0fc2f312014-01-08 10:26:58 +00002306#endif /* HAVE_DNSSEC */