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 org.minidns.dnsmessage.DnsMessage; 014import org.minidns.dnsmessage.Question; 015import org.minidns.record.Data; 016import org.minidns.record.DelegatingDnssecRR; 017import org.minidns.record.Record; 018 019import java.io.IOException; 020import java.math.BigInteger; 021import java.security.spec.InvalidKeySpecException; 022import java.util.List; 023import java.util.Locale; 024 025public class DnssecValidationFailedException extends IOException { 026 private static final long serialVersionUID = 5413184667629832742L; 027 028 public DnssecValidationFailedException(Question question, String reason) { 029 super("Validation of request to " + question + " failed: " + reason); 030 } 031 032 public DnssecValidationFailedException(String message) { 033 super(message); 034 } 035 036 public DnssecValidationFailedException(String message, Throwable cause) { 037 super(message, cause); 038 } 039 040 public DnssecValidationFailedException(Record<? extends Data> record, String reason) { 041 super("Validation of record " + record + " failed: " + reason); 042 } 043 044 public DnssecValidationFailedException(List<Record<? extends Data>> records, String reason) { 045 super("Validation of " + records.size() + " " + records.get(0).type + " record" + (records.size() > 1 ? "s" : "") + " failed: " + reason); 046 } 047 048 public static class DataMalformedException extends DnssecValidationFailedException { 049 050 /** 051 * 052 */ 053 private static final long serialVersionUID = 1L; 054 055 private final byte[] data; 056 057 public DataMalformedException(IOException exception, byte[] data) { 058 super("Malformed data", exception); 059 this.data = data; 060 } 061 062 public DataMalformedException(String message, IOException exception, byte[] data) { 063 super(message, exception); 064 this.data = data; 065 } 066 067 public byte[] getData() { 068 return data; 069 } 070 } 071 072 public static class DnssecInvalidKeySpecException extends DnssecValidationFailedException { 073 074 /** 075 * 076 */ 077 private static final long serialVersionUID = 1L; 078 079 public DnssecInvalidKeySpecException(InvalidKeySpecException exception) { 080 super("Invalid key spec", exception); 081 } 082 083 public DnssecInvalidKeySpecException(String message, InvalidKeySpecException exception, byte[] data) { 084 super(message, exception); 085 } 086 087 } 088 089 public static class AuthorityDoesNotContainSoa extends DnssecValidationFailedException { 090 091 /** 092 * 093 */ 094 private static final long serialVersionUID = 1L; 095 096 private final DnsMessage response; 097 098 public AuthorityDoesNotContainSoa(DnsMessage response) { 099 super("Autority does not contain SOA"); 100 this.response = response; 101 } 102 103 public DnsMessage getResponse() { 104 return response; 105 } 106 } 107 108 public static final class DigestComparisonFailedException extends DnssecValidationFailedException { 109 110 /** 111 * 112 */ 113 private static final long serialVersionUID = 1L; 114 115 private final Record<? extends Data> record; 116 private final DelegatingDnssecRR ds; 117 private final byte[] digest; 118 private final String digestHex; 119 120 private DigestComparisonFailedException(String message, Record<? extends Data> record, DelegatingDnssecRR ds, byte[] digest, String digestHex) { 121 super(message); 122 this.record = record; 123 this.ds = ds; 124 this.digest = digest; 125 this.digestHex = digestHex; 126 } 127 128 public Record<? extends Data> getRecord() { 129 return record; 130 } 131 132 public DelegatingDnssecRR getDelegaticDnssecRr() { 133 return ds; 134 } 135 136 public byte[] getDigest() { 137 return digest.clone(); 138 } 139 140 public String getDigestHex() { 141 return digestHex; 142 } 143 144 public static DigestComparisonFailedException from(Record<? extends Data> record, DelegatingDnssecRR ds, byte[] digest) { 145 BigInteger digestBigInteger = new BigInteger(1, digest); 146 String digestHex = digestBigInteger.toString(16).toUpperCase(Locale.ROOT); 147 148 String message = "Digest for " + record + " does not match. Digest of delegating DNSSEC RR " + ds + " is '" 149 + ds.getDigestHex() + "' while we calculated '" + digestHex + "'"; 150 return new DigestComparisonFailedException(message, record, ds, digest, digestHex); 151 } 152 } 153}