001/* 002 * Copyright 2015-2024 the original author or authors 003 * 004 * This software is licensed under the Apache License, Version 2.0, 005 * the GNU Lesser General Public License version 2 or later ("LGPL") 006 * and the WTFPL. 007 * You may choose either license to govern your use of this software only 008 * upon the condition that you accept all of the terms of either 009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL. 010 */ 011package org.minidns.dnssec; 012 013import java.util.Collections; 014import java.util.List; 015 016import org.minidns.constants.DnssecConstants.DigestAlgorithm; 017import org.minidns.dnsmessage.Question; 018import org.minidns.dnsname.DnsName; 019import org.minidns.record.DNSKEY; 020import org.minidns.record.Data; 021import org.minidns.record.RRSIG; 022import org.minidns.record.Record; 023import org.minidns.record.Record.TYPE; 024 025public abstract class DnssecUnverifiedReason { 026 public abstract String getReasonString(); 027 028 @Override 029 public String toString() { 030 return getReasonString(); 031 } 032 033 @Override 034 public int hashCode() { 035 return getReasonString().hashCode(); 036 } 037 038 @Override 039 public boolean equals(Object obj) { 040 return obj instanceof DnssecUnverifiedReason && ((DnssecUnverifiedReason) obj).getReasonString().equals(getReasonString()); 041 } 042 043 public static class AlgorithmNotSupportedReason extends DnssecUnverifiedReason { 044 private final String algorithm; 045 private final TYPE type; 046 private final Record<? extends Data> record; 047 048 public AlgorithmNotSupportedReason(byte algorithm, TYPE type, Record<? extends Data> record) { 049 this.algorithm = Integer.toString(algorithm & 0xff); 050 this.type = type; 051 this.record = record; 052 } 053 054 @Override 055 public String getReasonString() { 056 return type.name() + " algorithm " + algorithm + " required to verify " + record.name + " is unknown or not supported by platform"; 057 } 058 } 059 060 public static class AlgorithmExceptionThrownReason extends DnssecUnverifiedReason { 061 private final int algorithmNumber; 062 private final String kind; 063 private final Exception reason; 064 private final Record<? extends Data> record; 065 066 public AlgorithmExceptionThrownReason(DigestAlgorithm algorithm, String kind, Record<? extends Data> record, Exception reason) { 067 this.algorithmNumber = algorithm.value; 068 this.kind = kind; 069 this.record = record; 070 this.reason = reason; 071 } 072 073 @Override 074 public String getReasonString() { 075 return kind + " algorithm " + algorithmNumber + " threw exception while verifying " + record.name + ": " + reason; 076 } 077 } 078 079 public static class ConflictsWithSep extends DnssecUnverifiedReason { 080 private final Record<DNSKEY> record; 081 082 public ConflictsWithSep(Record<DNSKEY> record) { 083 this.record = record; 084 } 085 086 @Override 087 public String getReasonString() { 088 return "Zone " + record.name.ace + " is in list of known SEPs, but DNSKEY from response mismatches!"; 089 } 090 } 091 092 public static class NoTrustAnchorReason extends DnssecUnverifiedReason { 093 private final DnsName zone; 094 095 public NoTrustAnchorReason(DnsName zone) { 096 this.zone = zone; 097 } 098 099 @Override 100 public String getReasonString() { 101 return "No trust anchor was found for zone " + zone + ". Try enabling DLV"; 102 } 103 } 104 105 public static class NoSecureEntryPointReason extends DnssecUnverifiedReason { 106 private final DnsName zone; 107 108 public NoSecureEntryPointReason(DnsName zone) { 109 this.zone = zone; 110 } 111 112 @Override 113 public String getReasonString() { 114 return "No secure entry point was found for zone " + zone; 115 } 116 } 117 118 public static class NoRootSecureEntryPointReason extends DnssecUnverifiedReason { 119 public NoRootSecureEntryPointReason() { 120 } 121 122 @Override 123 public String getReasonString() { 124 return "No secure entry point was found for the root zone (\"Did you forget to configure a root SEP?\")"; 125 } 126 } 127 128 public static class NoSignaturesReason extends DnssecUnverifiedReason { 129 private final Question question; 130 131 public NoSignaturesReason(Question question) { 132 this.question = question; 133 } 134 135 @Override 136 public String getReasonString() { 137 return "No signatures were attached to answer on question for " + question.type + " at " + question.name; 138 } 139 } 140 141 public static class NoActiveSignaturesReason extends DnssecUnverifiedReason { 142 private final Question question; 143 private final List<RRSIG> outdatedRrSigs; 144 145 public NoActiveSignaturesReason(Question question, List<RRSIG> outdatedRrSigs) { 146 this.question = question; 147 assert !outdatedRrSigs.isEmpty(); 148 this.outdatedRrSigs = Collections.unmodifiableList(outdatedRrSigs); 149 } 150 151 @Override 152 public String getReasonString() { 153 return "No currently active signatures were attached to answer on question for " + question.type + " at " + question.name; 154 } 155 156 public List<RRSIG> getOutdatedRrSigs() { 157 return outdatedRrSigs; 158 } 159 } 160 161 public static class NSECDoesNotMatchReason extends DnssecUnverifiedReason { 162 private final Question question; 163 private final Record<? extends Data> record; 164 165 public NSECDoesNotMatchReason(Question question, Record<? extends Data> record) { 166 this.question = question; 167 this.record = record; 168 } 169 170 @Override 171 public String getReasonString() { 172 return "NSEC " + record.name + " does nat match question for " + question.type + " at " + question.name; 173 } 174 } 175}