]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnssec.c
More DNSSEC cache readout.
[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 ||
584 type_covered == T_DNSKEY)
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);
798
0fc2f313 799 if (qclass != class || qtype != T_DNSKEY || rc == 2)
c3e0b9b6 800 {
0fc2f313
SK
801 if (ADD_RDLEN(header, p, plen, rdlen))
802 continue;
803
804 return STAT_INSECURE; /* bad packet */
c3e0b9b6
SK
805 }
806
0fc2f313
SK
807 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
808 return STAT_INSECURE; /* bad packet */
809
810 psave = p;
c3e0b9b6 811
c3e0b9b6 812 GETSHORT(flags, p);
0fc2f313
SK
813 if (*p++ != 3)
814 return STAT_INSECURE;
c3e0b9b6 815 algo = *p++;
0fc2f313 816 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
e7829aef 817 key = NULL;
c3e0b9b6 818
e7829aef
SK
819 /* key must have zone key flag set */
820 if (flags & 0x100)
821 key = blockdata_alloc((char*)p, rdlen - 4);
c3e0b9b6 822
0fc2f313 823 p = psave;
e7829aef 824
0fc2f313
SK
825 if (!ADD_RDLEN(header, p, plen, rdlen))
826 return STAT_INSECURE; /* bad packet */
c3e0b9b6 827
e7829aef
SK
828 /* No zone key flag or malloc failure */
829 if (!key)
0fc2f313
SK
830 continue;
831
832 for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
86bec2d3
SK
833 {
834 void *ctx;
835 unsigned char *digest, *ds_digest;
836 const struct nettle_hash *hash;
837
51ea3ca2
SK
838 if (recp1->addr.ds.algo == algo &&
839 recp1->addr.ds.keytag == keytag &&
824202ef 840 recp1->uid == class &&
51ea3ca2 841 (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
86bec2d3 842 hash_init(hash, &ctx, &digest))
0fc2f313 843
86bec2d3
SK
844 {
845 int wire_len = to_wire(name);
846
847 /* Note that digest may be different between DSs, so
848 we can't move this outside the loop. */
849 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
850 hash->update(ctx, (unsigned int)rdlen, psave);
851 hash->digest(ctx, hash->digest_size, digest);
852
853 from_wire(name);
854
824202ef
SK
855 if (recp1->addr.ds.keylen == (int)hash->digest_size &&
856 (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
857 memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
86bec2d3
SK
858 validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag))
859 {
86bec2d3 860 valid = 1;
86bec2d3
SK
861 break;
862 }
863 }
864 }
e7829aef 865 blockdata_free(key);
c3e0b9b6 866 }
c3e0b9b6 867
0fc2f313
SK
868 if (valid)
869 {
e7829aef
SK
870 /* DNSKEY RRset determined to be OK, now cache it. */
871 cache_start_insert();
872
873 p = skip_questions(header, plen);
874
875 for (j = ntohs(header->ancount); j != 0; j--)
876 {
877 /* Ensure we have type, class TTL and length */
878 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
879 return STAT_INSECURE; /* bad packet */
880
881 GETSHORT(qtype, p);
882 GETSHORT(qclass, p);
883 GETLONG(ttl, p);
884 GETSHORT(rdlen, p);
885
886 if (qclass != class || qtype != T_DNSKEY || rc == 2)
887 {
888 if (ADD_RDLEN(header, p, plen, rdlen))
889 continue;
890
891 return STAT_INSECURE; /* bad packet */
892 }
893
894 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
895 return STAT_INSECURE; /* bad packet */
896
897 psave = p;
898
899 GETSHORT(flags, p);
900 if (*p++ != 3)
901 return STAT_INSECURE;
902 algo = *p++;
903 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
904
905 /* Cache needs to known class for DNSSEC stuff */
906 a.addr.dnssec.class = class;
907
908 if ((key = blockdata_alloc((char*)p, rdlen - 4)) &&
909 (recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
910 {
911 struct all_addr a;
912
913 a.addr.keytag = keytag;
914 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
915
824202ef 916 recp1->addr.key.keylen = rdlen - 4;
e7829aef
SK
917 recp1->addr.key.keydata = key;
918 recp1->addr.key.algo = algo;
919 recp1->addr.key.keytag = keytag;
920 recp1->addr.key.flags = flags;
824202ef 921 recp1->uid = class;
e7829aef
SK
922 }
923
924 p = psave;
925 if (!ADD_RDLEN(header, p, plen, rdlen))
926 return STAT_INSECURE; /* bad packet */
927 }
928
0fc2f313
SK
929 /* commit cache insert. */
930 cache_end_insert();
931 return STAT_SECURE;
932 }
933
934 log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
935 return STAT_BOGUS;
c3e0b9b6 936}
0fc2f313 937
c3e0b9b6 938/* The DNS packet is expected to contain the answer to a DS query
0fc2f313 939 Leave name of DS query in name.
c3e0b9b6
SK
940 Put all DSs in the answer which are valid into the cache.
941 return codes:
0fc2f313 942 STAT_INSECURE bad packet, no DS in reply.
c3e0b9b6
SK
943 STAT_SECURE At least one valid DS found and in cache.
944 STAT_BOGUS At least one DS found, which fails validation.
945 STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
946*/
947
948int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
949{
51ea3ca2
SK
950 unsigned char *p = (unsigned char *)(header+1);
951 int qtype, qclass, val;
c3e0b9b6 952
5f8e58f4
SK
953 if (ntohs(header->qdcount) != 1 ||
954 !extract_name(header, plen, &p, name, 1, 4))
955 {
956 strcpy(name, "<none>");
957 return STAT_INSECURE;
958 }
959
c3e0b9b6
SK
960 GETSHORT(qtype, p);
961 GETSHORT(qclass, p);
962
0fc2f313 963 if (qtype != T_DS || qclass != class || ntohs(header->ancount) == 0)
c3e0b9b6 964 return STAT_INSECURE;
0fc2f313 965
51ea3ca2
SK
966 val = dnssec_validate_reply(now, header, plen, name, keyname, NULL);
967
0fc2f313
SK
968 if (val == STAT_BOGUS)
969 log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
c3e0b9b6 970
51ea3ca2 971 return val;
c3e0b9b6
SK
972}
973
c5f4ec7d
SK
974/* 4034 6.1 */
975static int hostname_cmp(const char *a, const char *b)
976{
dbf72123
SK
977 char *sa, *ea, *ca, *sb, *eb, *cb;
978 unsigned char ac, bc;
979
980 sa = ea = (char *)a + strlen(a);
981 sb = eb = (char *)b + strlen(b);
982
c5f4ec7d
SK
983 while (1)
984 {
dbf72123
SK
985 while (sa != a && *(sa-1) != '.')
986 sa--;
c5f4ec7d 987
dbf72123
SK
988 while (sb != b && *(sb-1) != '.')
989 sb--;
990
991 ca = sa;
992 cb = sb;
993
994 while (1)
995 {
996 if (ca == ea)
997 {
998 if (cb == eb)
999 break;
1000
1001 return -1;
1002 }
c5f4ec7d 1003
dbf72123
SK
1004 if (cb == eb)
1005 return 1;
1006
1007 ac = (unsigned char) *ca++;
1008 bc = (unsigned char) *cb++;
1009
1010 if (ac >= 'A' && ac <= 'Z')
1011 ac += 'a' - 'A';
1012 if (bc >= 'A' && bc <= 'Z')
1013 bc += 'a' - 'A';
1014
979cdf9b 1015 if (ac < bc)
dbf72123
SK
1016 return -1;
1017 else if (ac != bc)
1018 return 1;
1019 }
c5f4ec7d 1020
dbf72123
SK
1021
1022 if (sa == a)
c5f4ec7d 1023 {
dbf72123
SK
1024 if (sb == b)
1025 return 0;
c5f4ec7d 1026
dbf72123 1027 return -1;
c5f4ec7d
SK
1028 }
1029
dbf72123
SK
1030 if (sb == b)
1031 return 1;
c5f4ec7d 1032
dbf72123
SK
1033 ea = sa--;
1034 eb = sb--;
c5f4ec7d
SK
1035 }
1036}
1037
1038
0fc2f313 1039/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
51ea3ca2 1040/* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
0fc2f313 1041int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class)
adca3e9c 1042{
0fc2f313
SK
1043 unsigned char *ans_start, *p1, *p2;
1044 int type1, class1, rdlen1, type2, class2, rdlen2;
c5f4ec7d 1045 int i, j, rc, have_nsec, have_nsec_equal, cname_count = 5;
adca3e9c 1046
c5f4ec7d 1047 if ((RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR) || ntohs(header->qdcount) != 1)
72ae2f3d 1048 return STAT_INSECURE;
c5f4ec7d 1049
0fc2f313
SK
1050 if (!(ans_start = skip_questions(header, plen)))
1051 return STAT_INSECURE;
1052
1053 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
adca3e9c 1054 {
0fc2f313
SK
1055 if (!extract_name(header, plen, &p1, name, 1, 10))
1056 return STAT_INSECURE; /* bad packet */
1057
1058 GETSHORT(type1, p1);
1059 GETSHORT(class1, p1);
1060 p1 += 4; /* TTL */
1061 GETSHORT(rdlen1, p1);
1062
1063 /* Don't try and validate RRSIGs! */
1064 if (type1 != T_RRSIG)
1065 {
1066 /* Check if we've done this RRset already */
1067 for (p2 = ans_start, j = 0; j < i; j++)
1068 {
1069 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1070 return STAT_INSECURE; /* bad packet */
1071
1072 GETSHORT(type2, p2);
1073 GETSHORT(class2, p2);
1074 p2 += 4; /* TTL */
1075 GETSHORT(rdlen2, p2);
1076
1077 if (type2 == type1 && class2 == class1 && rc == 1)
1078 break; /* Done it before: name, type, class all match. */
1079
1080 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1081 return STAT_INSECURE;
1082 }
1083
1084 /* Not done, validate now */
51ea3ca2 1085 if (j == i)
0fc2f313 1086 {
51ea3ca2
SK
1087 if ((rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0)) != STAT_SECURE)
1088 {
1089 if (class)
1090 *class = class1; /* Class for DS or DNSKEY */
1091 return rc;
1092 }
1093
1094 /* If we just validated a DS RRset, cache it */
1095 if (type1 == T_DS)
1096 {
1097 int ttl, keytag, algo, digest;
1098 unsigned char *psave;
1099 struct all_addr a;
1100 struct blockdata *key;
1101 struct crec *crecp;
1102
1103 cache_start_insert();
1104
1105 for (p2 = ans_start, j = 0; j < ntohs(header->ancount) + ntohs(header->nscount); j++)
1106 {
1107 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
1108 return STAT_INSECURE; /* bad packet */
1109
1110 GETSHORT(type2, p2);
1111 GETSHORT(class2, p2);
1112 GETLONG(ttl, p2);
1113 GETSHORT(rdlen2, p2);
1114
1115 if (type2 == T_DS && class2 == class1 && rc == 1)
1116 {
1117 psave = p2;
1118 GETSHORT(keytag, p2);
1119 algo = *p2++;
1120 digest = *p2++;
1121
1122 /* Cache needs to known class for DNSSEC stuff */
1123 a.addr.dnssec.class = class2;
1124
1125 if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)) &&
1126 (crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
1127 {
1128 a.addr.keytag = keytag;
1129 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
1130 crecp->addr.ds.digest = digest;
1131 crecp->addr.ds.keydata = key;
1132 crecp->addr.ds.algo = algo;
1133 crecp->addr.ds.keytag = keytag;
824202ef
SK
1134 crecp->uid = class2;
1135 crecp->addr.ds.keylen = rdlen2 - 4;
51ea3ca2
SK
1136 }
1137
1138 p2 = psave;
1139 }
1140
1141 if (!ADD_RDLEN(header, p2, plen, rdlen2))
1142 return STAT_INSECURE; /* bad packet */
1143 }
1144
1145 cache_end_insert();
1146 }
0fc2f313
SK
1147 }
1148 }
adca3e9c 1149
0fc2f313
SK
1150 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1151 return STAT_INSECURE;
adca3e9c
GB
1152 }
1153
c5f4ec7d
SK
1154 /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
1155
1156 p1 = (unsigned char *)(header+1);
1157
1158 if (!extract_name(header, plen, &p1, name, 1, 4))
1159 return STAT_INSECURE;
1160
1161 GETSHORT(type1, p1);
1162 GETSHORT(class1, p1);
1163
51ea3ca2
SK
1164 /* Can't validate RRSIG query */
1165 if (type1 == T_RRSIG)
1166 return STAT_INSECURE;
1167
c5f4ec7d
SK
1168 cname_loop:
1169 for (j = ntohs(header->ancount); j != 0; j--)
1170 {
1171 if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
1172 return STAT_INSECURE; /* bad packet */
1173
1174 GETSHORT(type2, p1);
1175 GETSHORT(class2, p1);
1176 p1 += 4; /* TTL */
1177 GETSHORT(rdlen2, p1);
1178
1179 if (rc == 1 && class1 == class2)
1180 {
1181 /* Do we have an answer for the question? */
1182 if (type1 == type2)
1183 return RCODE(header) == NXDOMAIN ? STAT_INSECURE : STAT_SECURE;
1184 else if (type2 == T_CNAME)
1185 {
1186 /* looped CNAMES */
1187 if (!cname_count-- ||
1188 !extract_name(header, plen, &p1, name, 1, 0) ||
1189 !(p1 = skip_questions(header, plen)))
1190 return STAT_INSECURE;
1191
1192 goto cname_loop;
1193 }
1194 }
1195
1196 if (!ADD_RDLEN(header, p1, plen, rdlen2))
1197 return STAT_INSECURE;
1198 }
1199
1200 /* NXDOMAIN or NODATA reply, look for NSEC records to support that.
1201 At this point, p1 points to the start of the auth section.
1202 Use keyname as workspace */
1203 for (have_nsec = 0, have_nsec_equal = 0, p2 = NULL, rdlen2 = 0, j = ntohs(header->nscount); j != 0; j--)
1204 {
1205 unsigned char *nsec_start = p1;
1206 if (!extract_name(header, plen, &p1, keyname, 1, 10))
1207 return STAT_INSECURE; /* bad packet */
1208
1209 GETSHORT(type2, p1);
1210 GETSHORT(class2, p1);
1211 p1 += 4; /* TTL */
1212 GETSHORT(rdlen1, p1);
1213
1214 if (class1 == class2 && type2 == T_NSEC)
1215 {
1216 have_nsec = 1;
1217 rc = hostname_cmp(name, keyname);
1218
1219 if (rc >= 0)
1220 {
1221 if (p2)
1222 {
1223 unsigned char *psave = p2;
1224 /* new NSEC is smaller than name,
1225 is it bigger than previous one? */
1226
1227 /* get previous one into name buffer */
1228 if (!extract_name(header, plen, &psave, name, 1, 0))
1229 return STAT_INSECURE; /* bad packet */
1230
1231 if (hostname_cmp(name, keyname) < 0)
1232 {
1233 p2 = nsec_start;
1234 rdlen2 = rdlen1;
1235 }
1236
1237 /* restore query name */
1238 psave = (unsigned char *)(header+1);
1239 if (!extract_name(header, plen, &psave, name, 1, 0))
1240 return STAT_INSECURE;
1241 }
1242 else
1243 {
1244 /* There was no previous best candidate */
1245 p2 = nsec_start;
1246 rdlen2 = rdlen1;
1247 }
1248 }
1249
1250 if (rc == 0)
1251 have_nsec_equal = 1;
1252 }
1253
1254 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1255 return STAT_INSECURE;
1256 }
1257
1258
1259 if (p2)
1260 {
1261 unsigned char *psave;
1262 p2 = skip_name(p2, header, plen, 0);
1263 p2 += 10; /* type, class, ttl, rdlen */
1264 psave = p2;
1265 extract_name(header, plen, &p2, keyname, 1, 0);
1266 rdlen2 -= p2 - psave;
1267 }
1268
1269 /* At this point, have_nsec is set if there's at least one NSEC
1270 have_nsec_equal is set if there's an NSEC with the same name as the query;
1271 p2 points to the type bit maps of the biggest NSEC smaller than or equal to the query
1272 or NULL if the query is smaller than all of them.
1273 Keyname holds the next domain name for that NSEC.
1274 rdlen2 is the length of the bitmap field */
1275
1276
1277 if (RCODE(header) == NOERROR && have_nsec_equal)
1278 {
1279 int offset = (type1 & 0xff) >> 3;
1280 int mask = 0x80 >> (type1 & 0x07);
1281
1282 while (rdlen2 >= 2)
1283 {
1284 if (p2[0] == type1 >> 8)
1285 {
1286 /* Does the NSEC say our type exists? */
1287 if (offset < p2[1] &&
1288 (p2[offset+2] & mask) != 0)
1289 return STAT_INSECURE;
1290
1291 break; /* finshed checking */
1292 }
1293
1294 rdlen2 -= p2[1];
1295 p2 += p2[1];
1296 }
1297
1298 return STAT_SECURE;
1299 }
1300
1301 if (RCODE(header) == NXDOMAIN && have_nsec)
1302 {
1303 if (!p2 || hostname_cmp(name, keyname) < 0)
1304 return STAT_SECURE; /* Before the first, or in a proven gap */
1305 }
1306
1307 return STAT_INSECURE;
e292e93d
GB
1308}
1309
c3e0b9b6 1310
3471f181 1311/* Compute keytag (checksum to quickly index a key). See RFC4034 */
0fc2f313 1312int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
3471f181 1313{
75ffc9bf
GB
1314 if (alg == 1)
1315 {
1316 /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
1317 See RFC4034, Appendix B.1 */
0fc2f313 1318 return key[keylen-4] * 256 + key[keylen-3];
75ffc9bf
GB
1319 }
1320 else
1321 {
1322 unsigned long ac;
1323 int i;
1324
0fc2f313
SK
1325 ac = ((htons(flags) >> 8) | ((htons(flags) << 8) & 0xff00)) + 0x300 + alg;
1326 for (i = 0; i < keylen; ++i)
1327 ac += (i & 1) ? key[i] : key[i] << 8;
1328 ac += (ac >> 16) & 0xffff;
1329 return ac & 0xffff;
0304d28f 1330 }
3471f181 1331}
e292e93d 1332
5f8e58f4
SK
1333size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
1334{
1335 unsigned char *p;
1336 char types[20];
1337
1338 querystr("dnssec", types, type);
1339
1340 if (addr->sa.sa_family == AF_INET)
1341 log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
1342#ifdef HAVE_IPV6
1343 else
1344 log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
1345#endif
1346
1347 header->qdcount = htons(1);
1348 header->ancount = htons(0);
1349 header->nscount = htons(0);
1350 header->arcount = htons(0);
e292e93d 1351
5f8e58f4
SK
1352 header->hb3 = HB3_RD;
1353 SET_OPCODE(header, QUERY);
1354 header->hb4 = HB4_CD;
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}
1367
0fc2f313 1368#endif /* HAVE_DNSSEC */