use of org.minidns.record.DNSKEY in project minidns by MiniDNS.
the class DNSSECClient method verifySecureEntryPoint.
private Set<UnverifiedReason> verifySecureEntryPoint(Question q, final Record<DNSKEY> sepRecord) throws IOException {
final DNSKEY dnskey = sepRecord.payloadData;
Set<UnverifiedReason> unverifiedReasons = new HashSet<>();
Set<UnverifiedReason> activeReasons = new HashSet<>();
if (knownSeps.containsKey(sepRecord.name)) {
if (dnskey.keyEquals(knownSeps.get(sepRecord.name))) {
return unverifiedReasons;
} else {
unverifiedReasons.add(new UnverifiedReason.ConflictsWithSep(sepRecord));
return unverifiedReasons;
}
}
// configured with one and we can abort stating the reason.
if (sepRecord.name.isRootLabel()) {
unverifiedReasons.add(new UnverifiedReason.NoRootSecureEntryPointReason());
return unverifiedReasons;
}
DelegatingDnssecRR delegation = null;
DNSSECMessage dsResp = queryDnssec(sepRecord.name, TYPE.DS);
if (dsResp == null) {
LOGGER.fine("There is no DS record for " + sepRecord.name + ", server gives no result");
} else {
unverifiedReasons.addAll(dsResp.getUnverifiedReasons());
for (Record<? extends Data> record : dsResp.answerSection) {
Record<DS> dsRecord = record.ifPossibleAs(DS.class);
if (dsRecord == null)
continue;
DS ds = dsRecord.payloadData;
if (dnskey.getKeyTag() == ds.keyTag) {
delegation = ds;
activeReasons = dsResp.getUnverifiedReasons();
break;
}
}
if (delegation == null) {
LOGGER.fine("There is no DS record for " + sepRecord.name + ", server gives empty result");
}
}
if (delegation == null && dlv != null && !dlv.isChildOf(sepRecord.name)) {
DNSSECMessage dlvResp = queryDnssec(DNSName.from(sepRecord.name, dlv), TYPE.DLV);
if (dlvResp != null) {
unverifiedReasons.addAll(dlvResp.getUnverifiedReasons());
for (Record<? extends Data> record : dlvResp.answerSection) {
Record<DLV> dlvRecord = record.ifPossibleAs(DLV.class);
if (dlvRecord == null)
continue;
if (sepRecord.payloadData.getKeyTag() == dlvRecord.payloadData.keyTag) {
LOGGER.fine("Found DLV for " + sepRecord.name + ", awesome.");
delegation = dlvRecord.payloadData;
activeReasons = dlvResp.getUnverifiedReasons();
break;
}
}
}
}
if (delegation != null) {
UnverifiedReason unverifiedReason = verifier.verify(sepRecord, delegation);
if (unverifiedReason != null) {
unverifiedReasons.add(unverifiedReason);
} else {
unverifiedReasons = activeReasons;
}
} else if (unverifiedReasons.isEmpty()) {
unverifiedReasons.add(new NoTrustAnchorReason(sepRecord.name.ace));
}
return unverifiedReasons;
}
use of org.minidns.record.DNSKEY in project minidns by MiniDNS.
the class DNSSECClient method verifySignedRecords.
private Set<UnverifiedReason> verifySignedRecords(Question q, RRSIG rrsig, List<Record<? extends Data>> records) throws IOException {
Set<UnverifiedReason> result = new HashSet<>();
DNSKEY dnskey = null;
if (rrsig.typeCovered == TYPE.DNSKEY) {
// Key must be present
for (Record<? extends Data> record : records) {
Record<DNSKEY> dnsKeyRecord = record.ifPossibleAs(DNSKEY.class);
if (dnsKeyRecord == null)
continue;
if (dnsKeyRecord.payloadData.getKeyTag() == rrsig.keyTag) {
dnskey = dnsKeyRecord.payloadData;
break;
}
}
} else if (q.type == TYPE.DS && rrsig.signerName.equals(q.name)) {
// We should not probe for the self signed DS negative response, as it will be an endless loop.
result.add(new NoTrustAnchorReason(q.name.ace));
return result;
} else {
DNSSECMessage dnskeyRes = queryDnssec(rrsig.signerName, TYPE.DNSKEY);
if (dnskeyRes == null) {
throw new DNSSECValidationFailedException(q, "There is no DNSKEY " + rrsig.signerName + ", but it is used");
}
result.addAll(dnskeyRes.getUnverifiedReasons());
for (Record<? extends Data> record : dnskeyRes.answerSection) {
Record<DNSKEY> dnsKeyRecord = record.ifPossibleAs(DNSKEY.class);
if (dnsKeyRecord == null)
continue;
if (dnsKeyRecord.payloadData.getKeyTag() == rrsig.keyTag) {
dnskey = dnsKeyRecord.payloadData;
}
}
}
if (dnskey == null) {
throw new DNSSECValidationFailedException(q, records.size() + " " + rrsig.typeCovered + " record(s) are signed using an unknown key.");
}
UnverifiedReason unverifiedReason = verifier.verify(records, rrsig, dnskey);
if (unverifiedReason != null) {
result.add(unverifiedReason);
}
return result;
}
use of org.minidns.record.DNSKEY in project minidns by MiniDNS.
the class DNSSECClient method verifyAnswer.
private Set<UnverifiedReason> verifyAnswer(DNSMessage dnsMessage) throws IOException {
Question q = dnsMessage.questions.get(0);
List<Record<? extends Data>> answers = dnsMessage.answerSection;
List<Record<? extends Data>> toBeVerified = dnsMessage.copyAnswers();
VerifySignaturesResult verifiedSignatures = verifySignatures(q, answers, toBeVerified);
Set<UnverifiedReason> result = verifiedSignatures.reasons;
if (!result.isEmpty()) {
return result;
}
// Keep SEPs separated, we only need one valid SEP.
boolean sepSignatureValid = false;
Set<UnverifiedReason> sepReasons = new HashSet<>();
for (Iterator<Record<? extends Data>> iterator = toBeVerified.iterator(); iterator.hasNext(); ) {
Record<DNSKEY> record = iterator.next().ifPossibleAs(DNSKEY.class);
if (record == null) {
continue;
}
// Verify all DNSKEYs as if it was a SEP. If we find a single SEP we are safe.
Set<UnverifiedReason> reasons = verifySecureEntryPoint(q, record);
if (reasons.isEmpty()) {
sepSignatureValid = true;
} else {
sepReasons.addAll(reasons);
}
if (!verifiedSignatures.sepSignaturePresent) {
LOGGER.finer("SEP key is not self-signed.");
}
iterator.remove();
}
if (verifiedSignatures.sepSignaturePresent && !sepSignatureValid) {
result.addAll(sepReasons);
}
if (verifiedSignatures.sepSignatureRequired && !verifiedSignatures.sepSignaturePresent) {
result.add(new NoSecureEntryPointReason(q.name.ace));
}
if (!toBeVerified.isEmpty()) {
if (toBeVerified.size() != answers.size()) {
throw new DNSSECValidationFailedException(q, "Only some records are signed!");
} else {
result.add(new NoSignaturesReason(q));
}
}
return result;
}
use of org.minidns.record.DNSKEY in project minidns by MiniDNS.
the class Verifier method verify.
public UnverifiedReason verify(Record<DNSKEY> dnskeyRecord, DelegatingDnssecRR ds) {
DNSKEY dnskey = dnskeyRecord.payloadData;
DigestCalculator digestCalculator = algorithmMap.getDsDigestCalculator(ds.digestType);
if (digestCalculator == null) {
return new AlgorithmNotSupportedReason(ds.digestTypeByte, ds.getType(), dnskeyRecord);
}
byte[] dnskeyData = dnskey.toByteArray();
byte[] dnskeyOwner = dnskeyRecord.name.getBytes();
byte[] combined = new byte[dnskeyOwner.length + dnskeyData.length];
System.arraycopy(dnskeyOwner, 0, combined, 0, dnskeyOwner.length);
System.arraycopy(dnskeyData, 0, combined, dnskeyOwner.length, dnskeyData.length);
byte[] digest;
try {
digest = digestCalculator.digest(combined);
} catch (Exception e) {
return new AlgorithmExceptionThrownReason(ds.digestType, "DS", dnskeyRecord, e);
}
if (!ds.digestEquals(digest)) {
throw new DNSSECValidationFailedException(dnskeyRecord, "SEP is not properly signed by parent DS!");
}
return null;
}
use of org.minidns.record.DNSKEY in project minidns by MiniDNS.
the class DNSSECClientTest method testNoSEPAtKSK.
@SuppressWarnings("unchecked")
@Test
public void testNoSEPAtKSK() throws IOException {
DNSKEY comKSK = dnskey(DNSKEY.FLAG_ZONE, algorithm, publicKey(algorithm, comPrivateKSK));
applyZones(client, signedRootZone(sign(rootKSK, "", rootPrivateKSK, algorithm, record("", rootKSK), record("", rootZSK)), sign(rootZSK, "", rootPrivateZSK, algorithm, record("com", ds("com", digestType, comKSK))), sign(rootZSK, "", rootPrivateZSK, algorithm, record("com", ns("ns.com"))), sign(rootZSK, "", rootPrivateZSK, algorithm, record("ns.com", a("1.1.1.1")))), signedZone("com", "ns.com", "1.1.1.1", sign(comKSK, "com", comPrivateKSK, algorithm, record("com", comKSK), record("com", comZSK)), sign(comZSK, "com", comPrivateZSK, algorithm, record("example.com", a("1.1.1.2")))));
DNSMessage message = client.query("example.com", Record.TYPE.A);
assertNotNull(message);
assertTrue(message.authenticData);
checkCorrectExampleMessage(message);
}
Aggregations