]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/020-DNSSEC_validation_tweak.patch
kernel: update to 3.14.62
[ipfire-2.x.git] / src / patches / dnsmasq / 020-DNSSEC_validation_tweak.patch
1 From 2dbba34b2c1289a108f876c78b84889f2a93115d Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Wed, 16 Dec 2015 13:41:58 +0000
4 Subject: [PATCH] DNSSEC validation tweak.
5
6 A zone which has at least one key with an algorithm we don't
7 support should be considered as insecure.
8 ---
9 src/dnssec.c | 82 ++++++++++++++++++++++++++++++++++++++--------------------
10 1 file changed, 54 insertions(+), 28 deletions(-)
11
12 diff --git a/src/dnssec.c b/src/dnssec.c
13 index fa3eb81..dc563e0 100644
14 --- a/src/dnssec.c
15 +++ b/src/dnssec.c
16 @@ -763,10 +763,10 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
17 STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
18 STAT_NEED_DS need DS to complete validation (name is returned in keyname)
19
20 - if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
21 + If key is non-NULL, use that key, which has the algo and tag given in the params of those names,
22 otherwise find the key in the cache.
23
24 - name is unchanged on exit. keyname is used as workspace and trashed.
25 + Name is unchanged on exit. keyname is used as workspace and trashed.
26
27 Call explore_rrset first to find and count RRs and sigs.
28 */
29 @@ -919,6 +919,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
30 return STAT_BOGUS;
31 }
32
33 +
34 /* The DNS packet is expected to contain the answer to a DNSKEY query.
35 Put all DNSKEYs in the answer which are valid into the cache.
36 return codes:
37 @@ -1831,15 +1832,15 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
38
39 /* Check signing status of name.
40 returns:
41 - STAT_SECURE zone is signed.
42 - STAT_INSECURE zone proved unsigned.
43 - STAT_NEED_DS require DS record of name returned in keyname.
44 -
45 + STAT_SECURE zone is signed.
46 + STAT_INSECURE zone proved unsigned.
47 + STAT_NEED_DS require DS record of name returned in keyname.
48 + STAT_NEED_DNSKEY require DNSKEY record of name returned in keyname.
49 name returned unaltered.
50 */
51 static int zone_status(char *name, int class, char *keyname, time_t now)
52 {
53 - int name_start = strlen(name);
54 + int secure_ds, name_start = strlen(name);
55 struct crec *crecp;
56 char *p;
57
58 @@ -1850,27 +1851,52 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
59 if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS)))
60 return STAT_NEED_DS;
61 else
62 - do
63 - {
64 - if (crecp->uid == (unsigned int)class)
65 - {
66 - /* F_DNSSECOK misused in DS cache records to non-existance of NS record.
67 - F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here,
68 - but that's because there's no NS record either, ie this isn't the start
69 - of a zone. We only prove that the DNS tree below a node is unsigned when
70 - we prove that we're at a zone cut AND there's no DS record.
71 - */
72 - if (crecp->flags & F_NEG)
73 - {
74 - if (crecp->flags & F_DNSSECOK)
75 - return STAT_INSECURE; /* proved no DS here */
76 - }
77 - else if (!ds_digest_name(crecp->addr.ds.digest) || !algo_digest_name(crecp->addr.ds.algo))
78 - return STAT_INSECURE; /* algo we can't use - insecure */
79 - }
80 - }
81 - while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
82 -
83 + {
84 + secure_ds = 0;
85 +
86 + do
87 + {
88 + if (crecp->uid == (unsigned int)class)
89 + {
90 + /* F_DNSSECOK misused in DS cache records to non-existance of NS record.
91 + F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here,
92 + but that's because there's no NS record either, ie this isn't the start
93 + of a zone. We only prove that the DNS tree below a node is unsigned when
94 + we prove that we're at a zone cut AND there's no DS record.
95 + */
96 + if (crecp->flags & F_NEG)
97 + {
98 + if (crecp->flags & F_DNSSECOK)
99 + return STAT_INSECURE; /* proved no DS here */
100 + }
101 + else if (!ds_digest_name(crecp->addr.ds.digest) || !algo_digest_name(crecp->addr.ds.algo))
102 + return STAT_INSECURE; /* algo we can't use - insecure */
103 + else
104 + secure_ds = 1;
105 + }
106 + }
107 + while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
108 + }
109 +
110 + if (secure_ds)
111 + {
112 + /* We've found only DS records that attest to the DNSKEY RRset in the zone, so we believe
113 + that RRset is good. Furthermore the DNSKEY whose hash is proved by the DS record is
114 + one we can use. However the DNSKEY RRset may contain more than one key and
115 + one of the other keys may use an algorithm we don't support. If that's
116 + the case the zone is insecure for us. */
117 +
118 + if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
119 + return STAT_NEED_KEY;
120 +
121 + do
122 + {
123 + if (crecp->uid == (unsigned int)class && !algo_digest_name(crecp->addr.key.algo))
124 + return STAT_INSECURE;
125 + }
126 + while ((crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY)));
127 + }
128 +
129 if (name_start == 0)
130 break;
131
132 --
133 1.7.10.4
134