]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnssec.c
Blockdata fixes and tuning.
[people/ms/dnsmasq.git] / src / dnssec.c
CommitLineData
8d41ebd8 1/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
0fc2f313 2 and Copyright (c) 2012-2014 Simon Kelley
8d41ebd8
GB
3
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*/
e292e93d
GB
17
18#include "dnsmasq.h"
0fc2f313
SK
19
20#ifdef HAVE_DNSSEC
21
86bec2d3
SK
22#include <nettle/rsa.h>
23#include <nettle/dsa.h>
24#include <nettle/nettle-meta.h>
25#include <gmp.h>
c3e0b9b6 26
e292e93d
GB
27#define SERIAL_UNDEF -100
28#define SERIAL_EQ 0
29#define SERIAL_LT -1
30#define SERIAL_GT 1
31
86bec2d3
SK
32/* 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
0fc2f313
SK
226/* 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)
7f0485cf 235{
0fc2f313
SK
236 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;
7f0485cf
GB
258}
259
0fc2f313
SK
260/* Note: no compression allowed in input. */
261static void from_wire(char *name)
13e435eb 262{
0fc2f313
SK
263 unsigned char *l;
264 int len;
13e435eb 265
0fc2f313 266 for (l = (unsigned char *)name; *l != 0; l += len+1)
13e435eb 267 {
0fc2f313
SK
268 len = *l;
269 memmove(l, l+1, len);
270 l[len] = '.';
13e435eb 271 }
7f0485cf 272
0fc2f313 273 *(l-1) = 0;
13e435eb
GB
274}
275
5ada8885
SK
276/* 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
5f8e58f4
SK
291/* Implement RFC1982 wrapped compare for 32-bit numbers */
292static int serial_compare_32(unsigned long s1, unsigned long s2)
293{
294 if (s1 == s2)
295 return SERIAL_EQ;
0ca895f5 296
5f8e58f4
SK
297 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}
0852d76b 305
5f8e58f4
SK
306/* Check whether today/now is between date_start and date_end */
307static int check_date_range(unsigned long date_start, unsigned long date_end)
0852d76b 308{
5f8e58f4
SK
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}
f119ed38 315
5f8e58f4
SK
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,
5f8e58f4
SK
349 0, -1 /* wildcard/catchall */
350 };
351
352 u16 *p = rr_desc;
353
354 while (*p != type && *p != 0)
355 while (*p++ != (u16)-1);
f119ed38 356
5f8e58f4
SK
357 return p+1;
358}
0852d76b 359
5f8e58f4
SK
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)
371 return 0;
372
373 if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
374 /* domain-name, canonicalise */
375 return to_wire(buff);
376 else
377 {
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 }
0852d76b
GB
390}
391
5f8e58f4
SK
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)
c3e0b9b6 408{
5f8e58f4 409 int swap, quit, i;
0fc2f313 410
5f8e58f4
SK
411 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
1486a9c7 431 for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
5f8e58f4 432 {
1486a9c7
SK
433 if (left1 != 0)
434 memmove(buff1, buff1 + len1 - left1, left1);
435
5f8e58f4
SK
436 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
1486a9c7
SK
444 if (left2 != 0)
445 memmove(buff2, buff2 + len2 - left2, left2);
446
5f8e58f4
SK
447 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)
1486a9c7 456 left1 = len1 - len2, left2 = 0, len = len2;
5f8e58f4 457 else
1486a9c7 458 left2 = len2 - len1, left1 = 0, len = len1;
5f8e58f4 459
6fd6dacb 460 rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
5f8e58f4 461
4619d946 462 if (rc > 0 || (rc == 0 && quit && len1 > len2))
5f8e58f4
SK
463 {
464 unsigned char *tmp = rrset[i+1];
465 rrset[i+1] = rrset[i];
466 rrset[i] = tmp;
467 swap = quit = 1;
468 }
6fd6dacb
SK
469 else if (rc < 0)
470 quit = 1;
5f8e58f4
SK
471 }
472 }
473 } while (swap);
474}
c3e0b9b6 475
5f8e58f4
SK
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,
e7829aef 487 int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
5f8e58f4
SK
488{
489 static unsigned char **rrset = NULL, **sigs = NULL;
490 static int rrset_sz = 0, sig_sz = 0;
0fc2f313 491
5f8e58f4 492 unsigned char *p;
5ada8885 493 int rrsetidx, sigidx, res, rdlen, j, name_labels;
5f8e58f4
SK
494 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);
c3e0b9b6 497
5f8e58f4
SK
498 if (!(p = skip_questions(header, plen)))
499 return STAT_INSECURE;
c3e0b9b6 500
5ada8885
SK
501 name_labels = count_labels(name); /* For 4035 5.3.2 check */
502
e7829aef
SK
503 cache_start_insert(); /* RRSIGS */
504
5ada8885 505 /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
5f8e58f4
SK
506 for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
507 j != 0; j--)
508 {
509 unsigned char *pstart, *pdata;
e7829aef 510 int stype, sclass, ttl;
c3e0b9b6 511
5f8e58f4
SK
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);
e7829aef 519 GETLONG(ttl, p);
5f8e58f4
SK
520
521 pdata = p;
c3e0b9b6 522
5f8e58f4
SK
523 GETSHORT(rdlen, p);
524
e7829aef
SK
525 if (!CHECK_LEN(header, p, plen, rdlen))
526 return STAT_INSECURE;
527
5f8e58f4
SK
528 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 {
5ada8885
SK
554 if (rdlen < 18)
555 return STAT_INSECURE; /* bad packet */
556
557 GETSHORT(type_covered, p);
5ada8885 558
e7829aef 559 if (type_covered == type)
5ada8885
SK
560 {
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;
e7829aef
SK
580
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 ||
2d33bda2 584 type_covered == T_DNSKEY || type_covered == T_PTR)
e7829aef
SK
585 {
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 {
824202ef 597 crecp->uid = class;
e7829aef 598 crecp->addr.sig.keydata = block;
824202ef 599 crecp->addr.sig.keylen = rdlen;
e7829aef
SK
600 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 */
5f8e58f4
SK
608 }
609 }
610
611 if (!ADD_RDLEN(header, p, plen, rdlen))
612 return STAT_INSECURE;
613 }
c3e0b9b6 614
e7829aef
SK
615 cache_end_insert(); /* RRSIGS */
616
5f8e58f4
SK
617 /* 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 {
86bec2d3
SK
629 unsigned char *psav, *sig;
630 int i, wire_len, sig_len;
631 const struct nettle_hash *hash;
632 void *ctx;
633 unsigned char *digest;
5f8e58f4
SK
634 u32 nsigttl;
635
636 p = sigs[j];
5ada8885 637 GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
5f8e58f4
SK
638 psav = p;
639
5ada8885 640 p += 2; /* type_covered - already checked */
5f8e58f4
SK
641 algo = *p++;
642 labels = *p++;
643 GETLONG(orig_ttl, p);
e7829aef
SK
644 GETLONG(sig_expiration, p);
645 GETLONG(sig_inception, p);
5f8e58f4
SK
646 GETSHORT(key_tag, p);
647
5f8e58f4
SK
648 if (!extract_name(header, plen, &p, keyname, 1, 0))
649 return STAT_INSECURE;
650
e7829aef
SK
651 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
5f8e58f4
SK
657 /* 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
86bec2d3
SK
661 sig = p;
662 sig_len = rdlen - (p - psav);
e7829aef 663
5f8e58f4
SK
664 nsigttl = htonl(orig_ttl);
665
86bec2d3 666 hash->update(ctx, 18, psav);
5f8e58f4 667 wire_len = to_wire(keyname);
86bec2d3 668 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
5f8e58f4
SK
669 from_wire(keyname);
670
5f8e58f4
SK
671 for (i = 0; i < rrsetidx; ++i)
672 {
673 int seg;
674 unsigned char *end, *cp;
5ada8885 675 char *name_start = name;
5f8e58f4
SK
676 u16 len, *dp;
677
678 p = rrset[i];
679 if (!extract_name(header, plen, &p, name, 1, 10))
680 return STAT_INSECURE;
5ada8885
SK
681
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);
86bec2d3
SK
694 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);
5f8e58f4
SK
697
698 p += 8; /* skip class, type, ttl */
699 GETSHORT(rdlen, p);
5ada8885
SK
700 if (!CHECK_LEN(header, p, plen, rdlen))
701 return STAT_INSECURE;
702
5f8e58f4
SK
703 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);
86bec2d3 711 hash->update(ctx, 2, (unsigned char *)&len);
5f8e58f4
SK
712
713 /* Now canonicalise again and digest. */
714 cp = p;
715 dp = rr_desc;
716 while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
86bec2d3 717 hash->update(ctx, seg, (unsigned char *)name);
5f8e58f4 718 if (cp != end)
86bec2d3 719 hash->update(ctx, end - cp, cp);
5f8e58f4 720 }
86bec2d3
SK
721
722 hash->digest(ctx, hash->digest_size, digest);
723
5ada8885
SK
724 /* 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
5f8e58f4
SK
728 if (key)
729 {
730 if (algo_in == algo && keytag_in == key_tag &&
86bec2d3 731 verify(key, keylen, sig, sig_len, digest, algo))
5f8e58f4
SK
732 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))
51ea3ca2
SK
738 if (crecp->addr.key.algo == algo &&
739 crecp->addr.key.keytag == key_tag &&
824202ef
SK
740 crecp->uid == class &&
741 verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, algo))
5f8e58f4
SK
742 return STAT_SECURE;
743 }
744 }
745
746 return STAT_BOGUS;
747}
748
0fc2f313 749/* The DNS packet is expected to contain the answer to a DNSKEY query.
5f8e58f4 750 Leave name of query in name.
c3e0b9b6
SK
751 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.
0fc2f313
SK
755 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
c3e0b9b6
SK
758*/
759int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
760{
0fc2f313 761 unsigned char *psave, *p = (unsigned char *)(header+1);
c3e0b9b6 762 struct crec *crecp, *recp1;
0fc2f313 763 int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
c3e0b9b6 764 struct blockdata *key;
51ea3ca2 765 struct all_addr a;
c3e0b9b6 766
5f8e58f4
SK
767 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
c3e0b9b6
SK
774 GETSHORT(qtype, p);
775 GETSHORT(qclass, p);
776
0fc2f313 777 if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0)
c3e0b9b6
SK
778 return STAT_INSECURE;
779
0fc2f313
SK
780 /* 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
0fc2f313 787 /* NOTE, we need to find ONE DNSKEY which matches the DS */
e7829aef 788 for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--)
c3e0b9b6
SK
789 {
790 /* Ensure we have type, class TTL and length */
0fc2f313 791 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
c3e0b9b6
SK
792 return STAT_INSECURE; /* bad packet */
793
794 GETSHORT(qtype, p);
795 GETSHORT(qclass, p);
796 GETLONG(ttl, p);
797 GETSHORT(rdlen, p);
6f468103 798
0fc2f313
SK
799 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
800 return STAT_INSECURE; /* bad packet */
801
6f468103
SK
802 if (qclass != class || qtype != T_DNSKEY || rc == 2)
803 {
804 p += rdlen;
805 continue;
806 }
807
0fc2f313 808 psave = p;
c3e0b9b6 809
c3e0b9b6 810 GETSHORT(flags, p);
0fc2f313
SK
811 if (*p++ != 3)
812 return STAT_INSECURE;
c3e0b9b6 813 algo = *p++;
0fc2f313 814 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
e7829aef 815 key = NULL;
c3e0b9b6 816
e7829aef
SK
817 /* key must have zone key flag set */
818 if (flags & 0x100)
819 key = blockdata_alloc((char*)p, rdlen - 4);
c3e0b9b6 820
0fc2f313 821 p = psave;
e7829aef 822
0fc2f313
SK
823 if (!ADD_RDLEN(header, p, plen, rdlen))
824 return STAT_INSECURE; /* bad packet */
c3e0b9b6 825
e7829aef
SK
826 /* No zone key flag or malloc failure */
827 if (!key)
0fc2f313
SK
828 continue;
829
830 for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
86bec2d3
SK
831 {
832 void *ctx;
833 unsigned char *digest, *ds_digest;
834 const struct nettle_hash *hash;
835
51ea3ca2
SK
836 if (recp1->addr.ds.algo == algo &&
837 recp1->addr.ds.keytag == keytag &&
824202ef 838 recp1->uid == class &&
51ea3ca2 839 (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
86bec2d3 840 hash_init(hash, &ctx, &digest))
0fc2f313 841
86bec2d3
SK
842 {
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
824202ef
SK
853 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 &&
86bec2d3
SK
856 validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag))
857 {
86bec2d3 858 valid = 1;
86bec2d3
SK
859 break;
860 }
861 }
862 }
e7829aef 863 blockdata_free(key);
c3e0b9b6 864 }
c3e0b9b6 865
0fc2f313
SK
866 if (valid)
867 {
e7829aef
SK
868 /* 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
824202ef 914 recp1->addr.key.keylen = rdlen - 4;
e7829aef
SK
915 recp1->addr.key.keydata = key;
916 recp1->addr.key.algo = algo;
917 recp1->addr.key.keytag = keytag;
918 recp1->addr.key.flags = flags;
824202ef 919 recp1->uid = class;
e7829aef
SK
920 }
921
922 p = psave;
923 if (!ADD_RDLEN(header, p, plen, rdlen))
924 return STAT_INSECURE; /* bad packet */
925 }
926
0fc2f313
SK
927 /* 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;
c3e0b9b6 934}
0fc2f313 935
c3e0b9b6 936/* The DNS packet is expected to contain the answer to a DS query
0fc2f313 937 Leave name of DS query in name.
c3e0b9b6
SK
938 Put all DSs in the answer which are valid into the cache.
939 return codes:
0fc2f313 940 STAT_INSECURE bad packet, no DS in reply.
c3e0b9b6
SK
941 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{
51ea3ca2
SK
948 unsigned char *p = (unsigned char *)(header+1);
949 int qtype, qclass, val;
c3e0b9b6 950
5f8e58f4
SK
951 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
c3e0b9b6
SK
958 GETSHORT(qtype, p);
959 GETSHORT(qclass, p);
960
0fc2f313 961 if (qtype != T_DS || qclass != class || ntohs(header->ancount) == 0)
c3e0b9b6 962 return STAT_INSECURE;
0fc2f313 963
51ea3ca2
SK
964 val = dnssec_validate_reply(now, header, plen, name, keyname, NULL);
965
0fc2f313
SK
966 if (val == STAT_BOGUS)
967 log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
c3e0b9b6 968
51ea3ca2 969 return val;
c3e0b9b6
SK
970}
971
c5f4ec7d
SK
972/* 4034 6.1 */
973static int hostname_cmp(const char *a, const char *b)
974{
dbf72123
SK
975 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
c5f4ec7d
SK
981 while (1)
982 {
dbf72123
SK
983 while (sa != a && *(sa-1) != '.')
984 sa--;
c5f4ec7d 985
dbf72123
SK
986 while (sb != b && *(sb-1) != '.')
987 sb--;
988
989 ca = sa;
990 cb = sb;
991
992 while (1)
993 {
994 if (ca == ea)
995 {
996 if (cb == eb)
997 break;
998
999 return -1;
1000 }
c5f4ec7d 1001
dbf72123
SK
1002 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
979cdf9b 1013 if (ac < bc)
dbf72123
SK
1014 return -1;
1015 else if (ac != bc)
1016 return 1;
1017 }
c5f4ec7d 1018
dbf72123
SK
1019
1020 if (sa == a)
c5f4ec7d 1021 {
dbf72123
SK
1022 if (sb == b)
1023 return 0;
c5f4ec7d 1024
dbf72123 1025 return -1;
c5f4ec7d
SK
1026 }
1027
dbf72123
SK
1028 if (sb == b)
1029 return 1;
c5f4ec7d 1030
dbf72123
SK
1031 ea = sa--;
1032 eb = sb--;
c5f4ec7d
SK
1033 }
1034}
1035
1036
0fc2f313 1037/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
51ea3ca2 1038/* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
0fc2f313 1039int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class)
adca3e9c 1040{
0fc2f313
SK
1041 unsigned char *ans_start, *p1, *p2;
1042 int type1, class1, rdlen1, type2, class2, rdlen2;
c5f4ec7d 1043 int i, j, rc, have_nsec, have_nsec_equal, cname_count = 5;
adca3e9c 1044
c5f4ec7d 1045 if ((RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR) || ntohs(header->qdcount) != 1)
72ae2f3d 1046 return STAT_INSECURE;
c5f4ec7d 1047
0fc2f313
SK
1048 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++)
adca3e9c 1052 {
0fc2f313
SK
1053 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 */
51ea3ca2 1083 if (j == i)
0fc2f313 1084 {
51ea3ca2
SK
1085 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;
0744ca66 1100
51ea3ca2
SK
1101 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;
824202ef
SK
1132 crecp->uid = class2;
1133 crecp->addr.ds.keylen = rdlen2 - 4;
51ea3ca2
SK
1134 }
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 }
0fc2f313
SK
1145 }
1146 }
adca3e9c 1147
0fc2f313
SK
1148 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1149 return STAT_INSECURE;
adca3e9c
GB
1150 }
1151
c5f4ec7d
SK
1152 /* 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
51ea3ca2
SK
1162 /* Can't validate RRSIG query */
1163 if (type1 == T_RRSIG)
1164 return STAT_INSECURE;
1165
c5f4ec7d
SK
1166 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;
e292e93d
GB
1306}
1307
c3e0b9b6 1308
3471f181 1309/* Compute keytag (checksum to quickly index a key). See RFC4034 */
0fc2f313 1310int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
3471f181 1311{
75ffc9bf
GB
1312 if (alg == 1)
1313 {
1314 /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
1315 See RFC4034, Appendix B.1 */
0fc2f313 1316 return key[keylen-4] * 256 + key[keylen-3];
75ffc9bf
GB
1317 }
1318 else
1319 {
1320 unsigned long ac;
1321 int i;
1322
0fc2f313
SK
1323 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;
0304d28f 1328 }
3471f181 1329}
e292e93d 1330
5f8e58f4
SK
1331size_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
b5dbfd14 1336 querystr("dnssec-query", types, type);
5f8e58f4
SK
1337
1338 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);
e292e93d 1349
5f8e58f4
SK
1350 header->hb3 = HB3_RD;
1351 SET_OPCODE(header, QUERY);
5b3bf921
SK
1352 /* 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;
5f8e58f4
SK
1355
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}
8a9be9e4
SK
1367
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;
5f8e58f4 1376
8a9be9e4
SK
1377 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))
7d23a66f 1383 break; /* bad packet */
8a9be9e4
SK
1384
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))
7d23a66f 1392 break; /* bad packet */
8a9be9e4 1393 }
703c7ff4
SK
1394
1395 hash->digest(ctx, hash->digest_size, digest);
8a9be9e4
SK
1396 return digest;
1397}
1398
0fc2f313 1399#endif /* HAVE_DNSSEC */