Skip to content

Commit 90abb2b

Browse files
committed
Prepare dnssec for EDE answers
1 parent 4f3b8c3 commit 90abb2b

File tree

8 files changed

+93
-42
lines changed

8 files changed

+93
-42
lines changed

src/main/java/org/xbill/DNS/ExtendedErrorCodeOption.java

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,31 +46,49 @@ public class ExtendedErrorCodeOption extends EDNSOption {
4646
static {
4747
codes.setMaximum(0xFFFF);
4848
codes.setPrefix("EDE");
49-
codes.add(OTHER, "Other");
50-
codes.add(UNSUPPORTED_DNSKEY_ALGORITHM, "Unsupported DNSKEY Algorithm");
51-
codes.add(UNSUPPORTED_DS_DIGEST_TYPE, "Unsupported DS Digest Type");
52-
codes.add(STALE_ANSWER, "Stale Answer");
53-
codes.add(FORGED_ANSWER, "Forged Answer");
54-
codes.add(DNSSEC_INDETERMINATE, "DNSSEC Indeterminate");
55-
codes.add(DNSSEC_BOGUS, "DNSSEC Bogus");
56-
codes.add(SIGNATURE_EXPIRED, "Signature Expired");
57-
codes.add(SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid");
58-
codes.add(DNSKEY_MISSING, "DNSKEY Missing");
59-
codes.add(RRSIGS_MISSING, "RRSIGs Missing");
60-
codes.add(NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set");
61-
codes.add(NSEC_MISSING, "NSEC Missing");
62-
codes.add(CACHED_ERROR, "Cached Error");
63-
codes.add(NOT_READY, "Not Ready");
64-
codes.add(BLOCKED, "Blocked");
65-
codes.add(CENSORED, "Censored");
66-
codes.add(FILTERED, "Filtered");
67-
codes.add(PROHIBITED, "Prohibited");
68-
codes.add(STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer");
69-
codes.add(NOT_AUTHORITATIVE, "Not Authoritative");
70-
codes.add(NOT_SUPPORTED, "Not Supported");
71-
codes.add(NO_REACHABLE_AUTHORITY, "No Reachable Authority");
72-
codes.add(NETWORK_ERROR, "Network Error");
73-
codes.add(INVALID_DATA, "Invalid Data");
49+
codes.add(OTHER, "OTHER");
50+
codes.add(UNSUPPORTED_DNSKEY_ALGORITHM, "UNSUPPORTED_DNSKEY_ALGORITHM");
51+
codes.add(UNSUPPORTED_DS_DIGEST_TYPE, "UNSUPPORTED_DS_DIGEST_TYPE");
52+
codes.add(STALE_ANSWER, "STALE_ANSWER");
53+
codes.add(FORGED_ANSWER, "FORGED_ANSWER");
54+
codes.add(DNSSEC_INDETERMINATE, "DNSSEC_INDETERMINATE");
55+
codes.add(DNSSEC_BOGUS, "DNSSEC_BOGUS");
56+
codes.add(SIGNATURE_EXPIRED, "SIGNATURE_EXPIRED");
57+
codes.add(SIGNATURE_NOT_YET_VALID, "SIGNATURE_NOT_YET_VALID");
58+
codes.add(DNSKEY_MISSING, "DNSKEY_MISSING");
59+
codes.add(RRSIGS_MISSING, "RRSIGS_MISSING");
60+
codes.add(NO_ZONE_KEY_BIT_SET, "NO_ZONE_KEY_BIT_SET");
61+
codes.add(NSEC_MISSING, "NSEC_MISSING");
62+
codes.add(CACHED_ERROR, "CACHED_ERROR");
63+
codes.add(NOT_READY, "NOT_READY");
64+
codes.add(BLOCKED, "BLOCKED");
65+
codes.add(CENSORED, "CENSORED");
66+
codes.add(FILTERED, "FILTERED");
67+
codes.add(PROHIBITED, "PROHIBITED");
68+
codes.add(STALE_NXDOMAIN_ANSWER, "STALE_NXDOMAIN_ANSWER");
69+
codes.add(NOT_AUTHORITATIVE, "NOT_AUTHORITATIVE");
70+
codes.add(NOT_SUPPORTED, "NOT_SUPPORTED");
71+
codes.add(NO_REACHABLE_AUTHORITY, "NO_REACHABLE_AUTHORITY");
72+
codes.add(NETWORK_ERROR, "NETWORK_ERROR");
73+
codes.add(INVALID_DATA, "INVALID_DATA");
74+
}
75+
76+
/**
77+
* Gets the text mnemonic corresponding to an EDE value.
78+
*
79+
* @since 3.5
80+
*/
81+
public static String text(int code) {
82+
return codes.getText(code);
83+
}
84+
85+
/**
86+
* Gets the numeric value corresponding to an EDE text mnemonic.
87+
*
88+
* @since 3.5
89+
*/
90+
public static int code(String text) {
91+
return codes.getValue(text);
7492
}
7593

7694
/** Creates an extended error code EDNS option. */

src/main/java/org/xbill/DNS/dnssec/KeyEntry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,14 @@ JustifiedSecStatus validateKeyFor(Name signerName) {
145145

146146
return new JustifiedSecStatus(
147147
SecurityStatus.BOGUS,
148-
ExtendedErrorCodeOption.DNSSEC_BOGUS,
148+
edeReason,
149149
R.get("validate.bogus", this.badReason));
150150
}
151151

152152
if (this.isBad()) {
153153
return new JustifiedSecStatus(
154154
SecurityStatus.BOGUS,
155-
ExtendedErrorCodeOption.DNSSEC_BOGUS,
155+
edeReason,
156156
R.get("validate.bogus.badkey", this.getName(), this.badReason));
157157
}
158158

src/main/java/org/xbill/DNS/dnssec/ValidatingResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ private KeyEntry dsResponseToKE(SMessage response, Message request, SRRset keyRr
967967
SRRset dsRrset = response.findAnswerRRset(qname, Type.DS, qclass);
968968
res = this.valUtils.verifySRRset(dsRrset, keyRrset, this.clock.instant());
969969
if (res.status != SecurityStatus.SECURE) {
970-
bogusKE.setBadReason(ExtendedErrorCodeOption.DNSSEC_BOGUS, R.get("failed.ds"));
970+
bogusKE.setBadReason(res.edeReason, res.reason);
971971
return bogusKE;
972972
}
973973

src/main/resources/messages.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dnskey.key_offtree=Key {0} for signature {1} is off tree
2323
dnskey.no_match=Key does not match signature
2424
dnskey.expired=Key exired
2525
dnskey.not_yet_valid=Key is not yet valid
26-
dnskey.invalid=Key does not verify signaure
26+
dnskey.invalid=Key does not verify signature
2727
failed.ds=DS rrset in DS response did not verify.
2828
failed.ds.cname=CNAME in DS response was not secure.
2929
ds.secure=CNAME validated, proof that DS does not exist.

src/test/java/org/xbill/DNS/dnssec/TestBase.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: BSD-3-Clause
22
package org.xbill.DNS.dnssec;
33

4+
import static org.junit.jupiter.api.Assertions.assertEquals;
45
import static org.junit.jupiter.api.Assertions.fail;
56
import static org.mockito.Mockito.mock;
67
import static org.mockito.Mockito.when;
@@ -245,14 +246,29 @@ protected String firstA(Message response) {
245246
}
246247

247248
protected int getEdeReason(Message m) {
248-
return Optional.ofNullable(m.getOPT())
249+
int edeReason = Optional.ofNullable(m.getOPT())
249250
.flatMap(
250251
opt ->
251252
opt.getOptions(Code.EDNS_EXTENDED_ERROR).stream()
252253
.filter(o -> o instanceof ExtendedErrorCodeOption)
253254
.findFirst()
254255
.map(o -> ((ExtendedErrorCodeOption) o).getErrorCode()))
255256
.orElse(-1);
257+
if (edeReason != -1) {
258+
assertEquals(getReason(m), getEdeText(m));
259+
}
260+
return edeReason;
261+
}
262+
263+
protected String getEdeText(Message m) {
264+
return Optional.ofNullable(m.getOPT())
265+
.flatMap(
266+
opt ->
267+
opt.getOptions(Code.EDNS_EXTENDED_ERROR).stream()
268+
.filter(o -> o instanceof ExtendedErrorCodeOption)
269+
.findFirst()
270+
.map(o -> ((ExtendedErrorCodeOption) o).getText()))
271+
.orElse(null);
256272
}
257273

258274
protected String getReason(Message m) {

src/test/java/org/xbill/DNS/dnssec/TestBogusReasonMessage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.io.IOException;
88
import org.junit.jupiter.api.Test;
9+
import org.xbill.DNS.ExtendedErrorCodeOption;
910
import org.xbill.DNS.Flags;
1011
import org.xbill.DNS.Message;
1112
import org.xbill.DNS.Rcode;
@@ -22,5 +23,6 @@ void testLongBogusReasonIsSplitCorrectly() throws IOException {
2223
assertEquals(
2324
"failed.nxdomain.authority:{ isc.org. 2962 IN NSEC [01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.isc.org. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY SPF] sigs: [NSEC 5 2 3600 20160706234032 20160606234032 13953 isc.org. fnOJeQG2vOwrERAPIqAenLOosbIBT7UvmxOV8Az2ExOhlGxP2CEqZEc5NPVbidq4oZC2kHyG7x31D6LBJXeXgOuanv+uqPNe9UIiUhdj+Egf8FEWIOKp8nxgjQGiGSNbQenWjeWoR91sReFEU+Pn7NPlEI072MzEESOT8oVucx8=] }",
2425
getReason(response));
26+
assertEquals(ExtendedErrorCodeOption.DNSSEC_BOGUS, getEdeReason(response));
2527
}
2628
}

src/test/java/org/xbill/DNS/dnssec/TestDNames.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.junit.jupiter.api.Test;
1212
import org.xbill.DNS.DClass;
1313
import org.xbill.DNS.DNAMERecord;
14+
import org.xbill.DNS.ExtendedErrorCodeOption;
1415
import org.xbill.DNS.Flags;
1516
import org.xbill.DNS.Lookup;
1617
import org.xbill.DNS.Message;
@@ -30,6 +31,7 @@ void testDNameToExistingIsValid() throws IOException {
3031
assertEquals(Rcode.NOERROR, response.getRcode());
3132
assertEquals(5, response.getSection(Section.ANSWER).size());
3233
assertNull(getReason(response));
34+
assertEquals(-1, getEdeReason(response));
3335
}
3436

3537
@Test
@@ -39,6 +41,7 @@ void testDNameToNoDataIsValid() throws IOException {
3941
assertEquals(Rcode.NOERROR, response.getRcode());
4042
assertEquals(3, response.getSection(Section.ANSWER).size());
4143
assertNull(getReason(response));
44+
assertEquals(-1, getEdeReason(response));
4245
}
4346

4447
@Test
@@ -47,6 +50,7 @@ void testDNameToNxDomainIsValid() throws IOException {
4750
assertTrue(response.getHeader().getFlag(Flags.AD), "AD flag must be set");
4851
assertEquals(Rcode.NXDOMAIN, response.getRcode());
4952
assertNull(getReason(response));
53+
assertEquals(-1, getEdeReason(response));
5054
}
5155

5256
@Test
@@ -61,6 +65,7 @@ void testDNameDirectQueryIsValid() throws IOException {
6165
assertEquals(Name.fromString("ingotronic.ch."), r.getTarget());
6266
}
6367
}
68+
assertEquals(-1, getEdeReason(response));
6469
}
6570

6671
@Test
@@ -74,6 +79,7 @@ void testDNameWithFakedCnameIsInvalid() throws IOException {
7479
assertFalse(response.getHeader().getFlag(Flags.AD), "AD flag must not be set");
7580
assertEquals(Rcode.SERVFAIL, response.getRcode());
7681
assertEquals("failed.synthesize.nomatch:www.isc.org.:www.ingotronic.ch.", getReason(response));
82+
assertEquals(ExtendedErrorCodeOption.DNSSEC_BOGUS, getEdeReason(response));
7783
}
7884

7985
@Test
@@ -92,6 +98,7 @@ void testDNameWithNoCnameIsValid() throws IOException {
9298
Record[] results = l.run();
9399
assertNotNull(results);
94100
assertTrue(results.length >= 1);
101+
assertEquals(-1, getEdeReason(response));
95102
}
96103

97104
@Test
@@ -105,6 +112,7 @@ void testDNameWithMultipleCnamesIsInvalid() throws IOException {
105112
assertFalse(response.getHeader().getFlag(Flags.AD), "AD flag must not be set");
106113
assertEquals(Rcode.SERVFAIL, response.getRcode());
107114
assertEquals("failed.synthesize.multiple", getReason(response));
115+
assertEquals(ExtendedErrorCodeOption.DNSSEC_BOGUS, getEdeReason(response));
108116
}
109117

110118
@Test
@@ -122,6 +130,7 @@ void testDNameWithTooLongCnameIsInvalid() throws IOException {
122130
assertFalse(response.getHeader().getFlag(Flags.AD), "AD flag must not be set");
123131
assertEquals(Rcode.SERVFAIL, response.getRcode());
124132
assertEquals("failed.synthesize.toolong", getReason(response));
133+
assertEquals(ExtendedErrorCodeOption.DNSSEC_BOGUS, getEdeReason(response));
125134
}
126135

127136
@Test
@@ -154,6 +163,7 @@ void testDNameInNsecIsUnderstood_Rfc6672_5_3_4_1() throws IOException {
154163
assertFalse(response.getHeader().getFlag(Flags.AD), "AD flag must not be set");
155164
assertEquals(Rcode.SERVFAIL, response.getRcode());
156165
assertEquals("failed.nxdomain.exists:www.alias.ingotronic.ch.", getReason(response));
166+
assertEquals(ExtendedErrorCodeOption.DNSSEC_BOGUS, getEdeReason(response));
157167
}
158168

159169
@Test
@@ -162,6 +172,7 @@ void testDNameToExternal() throws IOException {
162172
assertTrue(response.getHeader().getFlag(Flags.AD), "AD flag must be set");
163173
assertEquals(Rcode.NOERROR, response.getRcode());
164174
assertNull(getReason(response));
175+
assertEquals(-1, getEdeReason(response));
165176
}
166177

167178
@Test
@@ -170,5 +181,6 @@ void testDNameChain() throws IOException {
170181
assertTrue(response.getHeader().getFlag(Flags.AD), "AD flag must be set");
171182
assertEquals(Rcode.NOERROR, response.getRcode());
172183
assertNull(getReason(response));
184+
assertEquals(-1, getEdeReason(response));
173185
}
174186
}

src/test/java/org/xbill/DNS/dnssec/TestInvalid.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.time.Instant;
1111
import org.junit.jupiter.api.Test;
1212
import org.junit.jupiter.params.ParameterizedTest;
13+
import org.junit.jupiter.params.provider.CsvSource;
1314
import org.junit.jupiter.params.provider.ValueSource;
1415
import org.xbill.DNS.ARecord;
1516
import org.xbill.DNS.DClass;
1617
import org.xbill.DNS.DNSSEC.Algorithm;
18+
import org.xbill.DNS.ExtendedErrorCodeOption;
1719
import org.xbill.DNS.Flags;
1820
import org.xbill.DNS.Message;
1921
import org.xbill.DNS.Name;
@@ -24,22 +26,22 @@
2426
import org.xbill.DNS.Type;
2527

2628
class TestInvalid extends TestBase {
27-
@ParameterizedTest(name = "testInvalid_{arguments}")
28-
@ValueSource(
29-
strings = {
30-
"unknownalgorithm.dnssec",
31-
"sigexpired.dnssec",
32-
"bogussig.dnssec",
33-
"unknownalgorithm.nsec3",
34-
"sigexpired.nsec3",
35-
"bogussig.nsec3"
36-
})
29+
@ParameterizedTest(name = "testInvalid_{0}")
30+
@CsvSource({
31+
"bogussig.dnssec,dnskey.invalid,DNSSEC_BOGUS",
32+
"bogussig.nsec3,dnskey.invalid,DNSSEC_BOGUS",
33+
"sigexpired.dnssec,dnskey.expired,SIGNATURE_EXPIRED",
34+
"sigexpired.nsec3,dnskey.expired,SIGNATURE_EXPIRED",
35+
"unknownalgorithm.dnssec,failed.ds.noalg,UNSUPPORTED_DNSKEY_ALGORITHM",
36+
"unknownalgorithm.nsec3,failed.ds.noalg,UNSUPPORTED_DNSKEY_ALGORITHM",
37+
})
3738
@AlwaysOffline
38-
void testInvalid(String param) throws IOException {
39+
void testInvalid(String param, String dnssecReason, String edeMnemonic) throws IOException {
3940
Message response = resolver.send(createMessage(param + ".tjeb.nl./A"));
4041
assertFalse(response.getHeader().getFlag(Flags.AD), "AD flag must not be set");
4142
assertEquals(Rcode.SERVFAIL, response.getRcode());
42-
assertEquals("validate.bogus.badkey:" + param + ".tjeb.nl.:failed.ds", getReason(response));
43+
assertEquals("validate.bogus.badkey:" + param + ".tjeb.nl.:" + dnssecReason, getReason(response));
44+
assertEquals(ExtendedErrorCodeOption.code(edeMnemonic), getEdeReason(response));
4345
}
4446

4547
@Test
@@ -50,6 +52,7 @@ void testSignedBelowUnsignedBelowSigned() throws IOException {
5052
assertEquals(Rcode.NOERROR, response.getRcode());
5153
assertFalse(isEmptyAnswer(response));
5254
assertEquals("insecure.ds.nsec", getReason(response));
55+
assertEquals(-1, getEdeReason(response));
5356
}
5457

5558
@Test

0 commit comments

Comments
 (0)