Skip to content
Merged
Prev Previous commit
Next Next commit
Add intial support for EDE
  • Loading branch information
ibauersachs committed Dec 25, 2021
commit 407ab361d2494fc1c16518e0aaa1a5ee90af3821
64 changes: 47 additions & 17 deletions src/main/java/org/xbill/DNS/dnssec/DnsSecVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
import org.xbill.DNS.DNSKEYRecord;
import org.xbill.DNS.DNSSEC;
import org.xbill.DNS.DNSSEC.DNSSECException;
import org.xbill.DNS.DNSSEC.KeyMismatchException;
import org.xbill.DNS.DNSSEC.SignatureExpiredException;
import org.xbill.DNS.DNSSEC.SignatureNotYetValidException;
import org.xbill.DNS.ExtendedErrorCodeOption;
import org.xbill.DNS.RRSIGRecord;
import org.xbill.DNS.RRset;
import org.xbill.DNS.Record;
Expand Down Expand Up @@ -67,34 +71,52 @@ private List<DNSKEYRecord> findKey(RRset dnskeyRrset, RRSIGRecord signature) {
* if it did not verify (for any reason), and {@link SecurityStatus#UNCHECKED} if verification
* could not be completed (usually because the public key was not available).
*/
private SecurityStatus verifySignature(
private JustifiedSecStatus verifySignature(
SRRset rrset, RRSIGRecord sigrec, RRset keyRrset, Instant date) {
if (!rrset.getName().subdomain(keyRrset.getName())) {
log.debug("signer name is off-tree");
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.DNSSEC_BOGUS,
R.get("dnskey.key_offtree", keyRrset.getName(), rrset.getName()));
}

List<DNSKEYRecord> keys = this.findKey(keyRrset, sigrec);
if (keys.isEmpty()) {
log.trace("could not find appropriate key");
return SecurityStatus.BOGUS;
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.DNSKEY_MISSING,
R.get("dnskey.no_key", sigrec.getSigner()));
}

SecurityStatus status = SecurityStatus.UNCHECKED;
for (DNSKEYRecord key : keys) {
try {
if (!rrset.getName().subdomain(keyRrset.getName())) {
log.debug("signer name is off-tree");
status = SecurityStatus.BOGUS;
continue;
}

DNSSEC.verify(rrset, sigrec, key, date);
ValUtils.setCanonicalNsecOwner(rrset, sigrec);
return SecurityStatus.SECURE;
return new JustifiedSecStatus(SecurityStatus.SECURE, -1, null);
} catch (KeyMismatchException kme) {
return new JustifiedSecStatus(
SecurityStatus.BOGUS, ExtendedErrorCodeOption.DNSSEC_BOGUS, R.get("dnskey.no_match"));
} catch (SignatureExpiredException e) {
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.SIGNATURE_EXPIRED,
R.get("dnskey.expired"));
} catch (SignatureNotYetValidException e) {
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.SIGNATURE_NOT_YET_VALID,
R.get("dnskey.not_yet_valid"));
} catch (DNSSECException e) {
log.error(
"Failed to validate RRset {}/{}", rrset.getName(), Type.string(rrset.getType()), e);
status = SecurityStatus.BOGUS;
return new JustifiedSecStatus(
SecurityStatus.BOGUS, ExtendedErrorCodeOption.DNSSEC_BOGUS, R.get("dnskey.invalid"));
}
}

return status;
return new JustifiedSecStatus(SecurityStatus.UNCHECKED, -1, null);
}

/**
Expand All @@ -106,22 +128,30 @@ private SecurityStatus verifySignature(
* @param date The date against which to verify the rrset.
* @return SecurityStatus.SECURE if the rrest verified positively, SecurityStatus.BOGUS otherwise.
*/
public SecurityStatus verify(SRRset rrset, RRset keyRrset, Instant date) {
public JustifiedSecStatus verify(SRRset rrset, RRset keyRrset, Instant date) {
List<RRSIGRecord> sigs = rrset.sigs();
if (sigs.isEmpty()) {
log.info("RRset failed to verify due to lack of signatures");
return SecurityStatus.BOGUS;
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.RRSIGS_MISSING,
R.get("validate.bogus.missingsig"));
}

JustifiedSecStatus res =
new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.RRSIGS_MISSING,
R.get("validate.bogus.missingsig"));
for (RRSIGRecord sigrec : sigs) {
SecurityStatus res = this.verifySignature(rrset, sigrec, keyRrset, date);
if (res == SecurityStatus.SECURE) {
res = this.verifySignature(rrset, sigrec, keyRrset, date);
if (res.status == SecurityStatus.SECURE) {
return res;
}
}

log.info("RRset failed to verify: all signatures were BOGUS");
return SecurityStatus.BOGUS;
return res;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/xbill/DNS/dnssec/JustifiedSecStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
final class JustifiedSecStatus {
SecurityStatus status;
int edeReason;
String reason;

/**
Expand All @@ -16,8 +17,9 @@ final class JustifiedSecStatus {
* @param status The security status.
* @param reason The reason why the status was determined.
*/
JustifiedSecStatus(SecurityStatus status, String reason) {
JustifiedSecStatus(SecurityStatus status, int edeReason, String reason) {
this.status = status;
this.edeReason = edeReason;
this.reason = reason;
}

Expand All @@ -27,6 +29,6 @@ final class JustifiedSecStatus {
* @param response The response to which to apply this status.
*/
void applyToResponse(SMessage response) {
response.setStatus(this.status, this.reason);
response.setStatus(this.status, edeReason, this.reason);
}
}
23 changes: 17 additions & 6 deletions src/main/java/org/xbill/DNS/dnssec/KeyEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.ExtendedErrorCodeOption;
import org.xbill.DNS.Name;
import org.xbill.DNS.Record;
import org.xbill.DNS.Type;
Expand All @@ -20,6 +21,7 @@
callSuper = true,
of = {"badReason", "isEmpty"})
final class KeyEntry extends SRRset {
private int edeReason;
private String badReason;
private boolean isEmpty;

Expand Down Expand Up @@ -107,7 +109,8 @@ public boolean isGood() {
*
* @param reason The reason why this key entry is bad.
*/
public void setBadReason(String reason) {
public void setBadReason(int edeReason, String reason) {
this.edeReason = edeReason;
this.badReason = reason;
log.debug(this.badReason);
}
Expand All @@ -130,19 +133,27 @@ JustifiedSecStatus validateKeyFor(Name signerName) {
reason = R.get("validate.insecure_unsigned");
}

return new JustifiedSecStatus(SecurityStatus.INSECURE, reason);
return new JustifiedSecStatus(SecurityStatus.INSECURE, edeReason, reason);
}

if (this.isGood()) {
return new JustifiedSecStatus(SecurityStatus.BOGUS, R.get("validate.bogus.missingsig"));
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.RRSIGS_MISSING,
R.get("validate.bogus.missingsig"));
}

return new JustifiedSecStatus(SecurityStatus.BOGUS, R.get("validate.bogus", this.badReason));
return new JustifiedSecStatus(
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.DNSSEC_BOGUS,
R.get("validate.bogus", this.badReason));
}

if (this.isBad()) {
return new JustifiedSecStatus(
SecurityStatus.BOGUS, R.get("validate.bogus.badkey", this.getName(), this.badReason));
SecurityStatus.BOGUS,
ExtendedErrorCodeOption.DNSSEC_BOGUS,
R.get("validate.bogus.badkey", this.getName(), this.badReason));
}

if (this.isNull()) {
Expand All @@ -151,7 +162,7 @@ JustifiedSecStatus validateKeyFor(Name signerName) {
reason = R.get("validate.insecure");
}

return new JustifiedSecStatus(SecurityStatus.INSECURE, reason);
return new JustifiedSecStatus(SecurityStatus.INSECURE, edeReason, reason);
}

return null;
Expand Down
29 changes: 19 additions & 10 deletions src/main/java/org/xbill/DNS/dnssec/SMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.LinkedList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.ExtendedErrorCodeOption;
import org.xbill.DNS.Flags;
import org.xbill.DNS.Header;
import org.xbill.DNS.Message;
Expand Down Expand Up @@ -36,6 +37,7 @@ final class SMessage {
private final List<SRRset>[] sections;
private SecurityStatus securityStatus;
private String bogusReason;
private int edeReason = -1;

/**
* Creates a instance of this class.
Expand Down Expand Up @@ -181,8 +183,8 @@ public SecurityStatus getStatus() {
*
* @param status the new security status for this message.
*/
public void setStatus(SecurityStatus status) {
this.securityStatus = status;
public void setStatus(SecurityStatus status, int edeReason) {
setStatus(status, edeReason, null);
}

/**
Expand All @@ -191,12 +193,22 @@ public void setStatus(SecurityStatus status) {
* @param status the new security status for this message.
* @param reason Why this message's status is set as indicated.
*/
public void setStatus(SecurityStatus status, String reason) {
public void setStatus(SecurityStatus status, int edeReason, String reason) {
this.securityStatus = status;
this.edeReason = edeReason;
this.bogusReason = reason;
log.debug(this.bogusReason);
}

/**
* Sets the security status of this message to bogus and sets the reason.
*
* @param reason Why this message's status is bogus.
*/
public void setBogus(String reason) {
setStatus(SecurityStatus.BOGUS, ExtendedErrorCodeOption.DNSSEC_BOGUS, reason);
}

/**
* Gets the reason why this messages' status is bogus.
*
Expand All @@ -207,14 +219,11 @@ public String getBogusReason() {
}

/**
* Sets the security status of this message to bogus and sets the reason.
*
* @param reason Why this message's status is bogus.
* Gets the {@link org.xbill.DNS.ExtendedErrorCodeOption} reason why this messages' status is
* bogus.
*/
public void setBogus(String reason) {
this.setStatus(SecurityStatus.BOGUS);
this.bogusReason = reason;
log.debug(this.bogusReason);
public int getEdeReason() {
return this.edeReason;
}

/**
Expand Down
Loading