1use ans_types::{BadgeStatus, CryptoError, ParseError};
4use thiserror::Error;
5
6#[derive(Debug, Error)]
8#[non_exhaustive]
9pub enum AnsError {
10 #[error("DNS error: {0}")]
12 Dns(#[from] DnsError),
13
14 #[error("Transparency log error: {0}")]
16 TransparencyLog(#[from] TlogError),
17
18 #[error("Certificate error: {0}")]
20 Certificate(#[from] CryptoError),
21
22 #[error("Verification error: {0}")]
24 Verification(#[from] VerificationError),
25
26 #[error("Parse error: {0}")]
28 Parse(#[from] ParseError),
29}
30
31pub type AnsResult<T> = Result<T, AnsError>;
33
34#[derive(Debug, Error, Clone)]
36#[non_exhaustive]
37pub enum DnsError {
38 #[error("DNS record not found (NXDOMAIN) for {fqdn}")]
40 NotFound {
41 fqdn: String,
43 },
44
45 #[error("DNS lookup failed for {fqdn}: {reason}")]
47 LookupFailed {
48 fqdn: String,
50 reason: String,
52 },
53
54 #[error("DNS query timed out for {fqdn}")]
56 Timeout {
57 fqdn: String,
59 },
60
61 #[error("DNSSEC validation failed for {fqdn}")]
63 DnssecFailed {
64 fqdn: String,
66 },
67
68 #[error("Invalid badge TXT record format: {record}")]
70 InvalidFormat {
71 record: String,
73 },
74
75 #[error("DNS resolver error: {0}")]
77 ResolverError(String),
78}
79
80#[derive(Debug)]
85pub struct HttpError {
86 inner: reqwest::Error,
87}
88
89impl std::fmt::Display for HttpError {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 self.inner.fmt(f)
92 }
93}
94
95impl std::error::Error for HttpError {
96 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
97 self.inner.source()
98 }
99}
100
101impl From<reqwest::Error> for HttpError {
102 fn from(err: reqwest::Error) -> Self {
103 Self { inner: err }
104 }
105}
106
107#[derive(Debug, Error)]
115#[non_exhaustive]
116pub enum TlogError {
117 #[error("HTTP request failed: {0}")]
119 HttpError(#[from] HttpError),
120
121 #[error("Badge not found at {url}")]
123 NotFound {
124 url: String,
126 },
127
128 #[error("Invalid badge response: {0}")]
130 InvalidResponse(String),
131
132 #[error("Transparency log service unavailable")]
134 ServiceUnavailable,
135
136 #[error("Invalid URL: {0}")]
138 InvalidUrl(String),
139
140 #[error("Invalid header: {0}")]
142 InvalidHeader(String),
143
144 #[error("Untrusted badge domain: {domain}")]
146 UntrustedDomain {
147 domain: String,
149 trusted: Vec<String>,
151 },
152}
153
154#[derive(Debug, Error, Clone)]
156#[non_exhaustive]
157pub enum VerificationError {
158 #[error("Badge status {status:?} is not valid for connections")]
160 InvalidStatus {
161 status: BadgeStatus,
163 },
164
165 #[error("Fingerprint mismatch: expected {expected}, got {actual}")]
167 FingerprintMismatch {
168 expected: String,
170 actual: String,
172 },
173
174 #[error("Hostname mismatch: expected {expected}, got {actual}")]
176 HostnameMismatch {
177 expected: String,
179 actual: String,
181 },
182
183 #[error("ANS name mismatch: expected {expected}, got {actual}")]
185 AnsNameMismatch {
186 expected: String,
188 actual: String,
190 },
191
192 #[error("No matching badge found for version {version}")]
194 NoMatchingBadge {
195 version: String,
197 },
198
199 #[error("Certificate does not chain to trusted CA")]
201 UntrustedCertificate,
202
203 #[error("DANE verification failed: {0}")]
205 DaneVerificationFailed(DaneError),
206
207 #[error("Multiple verification errors: {errors:?}")]
209 Multiple {
210 errors: Vec<Self>,
212 },
213
214 #[error("Configuration error: {0}")]
216 Configuration(String),
217}
218
219#[derive(Debug, Error, Clone)]
221#[non_exhaustive]
222pub enum DaneError {
223 #[error("No TLSA records found for {fqdn}:{port}")]
225 NoTlsaRecords {
226 fqdn: String,
228 port: u16,
230 },
231
232 #[error("TLSA fingerprint mismatch: certificate not bound to DNS")]
234 FingerprintMismatch,
235
236 #[error("DNSSEC validation failed for {fqdn}")]
238 DnssecValidationFailed {
239 fqdn: String,
241 },
242
243 #[error("DNSSEC required but not present for {fqdn}")]
245 DnssecNotPresent {
246 fqdn: String,
248 },
249
250 #[error("Invalid TLSA record: {reason}")]
252 InvalidRecord {
253 reason: String,
255 },
256
257 #[error("DNS error during TLSA lookup: {0}")]
259 DnsError(#[from] DnsError),
260}