Skip to main content

mssql_tls/
error.rs

1//! TLS-related error types.
2
3use thiserror::Error;
4
5/// Errors that can occur during TLS operations.
6#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum TlsError {
9    /// TLS handshake failed.
10    #[error("TLS handshake failed: {0}")]
11    HandshakeFailed(String),
12
13    /// Certificate validation failed.
14    #[error("certificate validation failed: {0}")]
15    CertificateValidation(String),
16
17    /// Hostname verification failed.
18    #[error("hostname verification failed: expected {expected}, got {actual}")]
19    HostnameVerification {
20        /// Expected hostname.
21        expected: String,
22        /// Actual hostname from certificate.
23        actual: String,
24    },
25
26    /// Invalid certificate format.
27    #[error("invalid certificate: {0}")]
28    InvalidCertificate(String),
29
30    /// Invalid private key format.
31    #[error("invalid private key: {0}")]
32    InvalidPrivateKey(String),
33
34    /// TLS configuration error.
35    #[error("TLS configuration error: {0}")]
36    Configuration(String),
37
38    /// IO error during TLS operations.
39    #[error("IO error: {0}")]
40    Io(#[from] std::io::Error),
41
42    /// Rustls error.
43    #[error("rustls error: {0}")]
44    Rustls(#[from] rustls::Error),
45
46    /// Server requires encryption but client disabled it.
47    #[error("server requires encryption")]
48    EncryptionRequired,
49
50    /// Client requires encryption but server doesn't support it.
51    #[error("server does not support encryption")]
52    EncryptionNotSupported,
53
54    /// TDS 8.0 strict mode is required but not supported.
55    #[error("TDS 8.0 strict mode required")]
56    StrictModeRequired,
57
58    /// Connection closed during TLS negotiation.
59    #[error("connection closed during TLS negotiation")]
60    ConnectionClosed,
61}
62
63impl TlsError {
64    /// Check if this error is transient and may succeed on retry.
65    ///
66    /// IO errors and connection closures are transient. Certificate and
67    /// configuration errors are terminal.
68    #[must_use]
69    pub fn is_transient(&self) -> bool {
70        matches!(self, Self::Io(_) | Self::ConnectionClosed)
71    }
72
73    /// Check if this error is terminal and will never succeed on retry.
74    ///
75    /// Certificate validation failures, configuration errors, and encryption
76    /// mode mismatches are permanent.
77    #[must_use]
78    pub fn is_terminal(&self) -> bool {
79        !self.is_transient()
80    }
81}