rocket/mtls/
error.rs

1use std::fmt;
2use std::num::NonZeroUsize;
3
4use crate::mtls::x509::{self, nom};
5
6/// An error returned by the [`Certificate`](crate::mtls::Certificate) guard.
7///
8/// To retrieve this error in a handler, use an `mtls::Result<Certificate>`
9/// guard type:
10///
11/// ```rust
12/// # extern crate rocket;
13/// # use rocket::get;
14/// use rocket::mtls::{self, Certificate};
15///
16/// #[get("/auth")]
17/// fn auth(cert: mtls::Result<Certificate<'_>>) {
18///     match cert {
19///         Ok(cert) => { /* do something with the client cert */ },
20///         Err(e) => { /* do something with the error */ },
21///     }
22/// }
23/// ```
24#[derive(Debug, Clone)]
25#[non_exhaustive]
26pub enum Error {
27    /// The certificate chain presented by the client had no certificates.
28    Empty,
29    /// The certificate contained neither a subject nor a subjectAlt extension.
30    NoSubject,
31    /// There is no subject and the subjectAlt is not marked as critical.
32    NonCriticalSubjectAlt,
33    /// An error occurred while parsing the certificate.
34    Parse(x509::X509Error),
35    /// The certificate parsed partially but is incomplete.
36    ///
37    /// If `Some(n)`, then `n` more bytes were expected. Otherwise, the number
38    /// of expected bytes is unknown.
39    Incomplete(Option<NonZeroUsize>),
40    /// The certificate contained `.0` bytes of trailing data.
41    Trailing(usize),
42}
43
44impl fmt::Display for Error {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Error::Parse(e) => write!(f, "parse error: {}", e),
48            Error::Incomplete(_) => write!(f, "incomplete certificate data"),
49            Error::Trailing(n) => write!(f, "found {} trailing bytes", n),
50            Error::Empty => write!(f, "empty certificate chain"),
51            Error::NoSubject => write!(f, "empty subject without subjectAlt"),
52            Error::NonCriticalSubjectAlt => write!(f, "empty subject without critical subjectAlt"),
53        }
54    }
55}
56
57impl From<nom::Err<x509::X509Error>> for Error {
58    fn from(e: nom::Err<x509::X509Error>) -> Self {
59        match e {
60            nom::Err::Incomplete(nom::Needed::Unknown) => Error::Incomplete(None),
61            nom::Err::Incomplete(nom::Needed::Size(n)) => Error::Incomplete(Some(n)),
62            nom::Err::Error(e) | nom::Err::Failure(e) => Error::Parse(e),
63        }
64    }
65}
66
67impl std::error::Error for Error {
68    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69        match self {
70            Error::Parse(e) => Some(e),
71            _ => None
72        }
73    }
74}