]> git.proxmox.com Git - proxmox.git/blob - src/error.rs
bcfaed08dbf02890471c48dce8cda6136a840cd4
[proxmox.git] / src / error.rs
1 //! The `Error` type and some ACME error constants for reference.
2
3 use std::fmt;
4
5 use openssl::error::ErrorStack as SslErrorStack;
6
7 /// The ACME error string for a "bad nonce" error.
8 pub const BAD_NONCE: &str = "urn:ietf:params:acme:error:badNonce";
9
10 /// The ACME error string for a "user action required" error.
11 pub const USER_ACTION_REQUIRED: &str = "urn:ietf:params:acme:error:userActionRequired";
12
13 /// Error types returned by this crate.
14 #[derive(Debug)]
15 #[must_use = "unused errors have no effect"]
16 pub enum Error {
17 /// A `badNonce` API response. The request should be retried with the new nonce received along
18 /// with this response.
19 BadNonce,
20
21 /// A `userActionRequired` API response. Typically this means there was a change to the ToS and
22 /// the user has to agree to the new terms.
23 UserActionRequired(String),
24
25 /// Other error repsonses from the Acme API not handled specially.
26 Api(crate::request::ErrorResponse),
27
28 /// The Acme API behaved unexpectedly.
29 InvalidApi(String),
30
31 /// Tried to use an `Account` or `AccountCreator` without a private key.
32 MissingKey,
33
34 /// Tried to create an `Account` without providing a single contact info.
35 MissingContactInfo,
36
37 /// Tried to use an empty `Order`.
38 EmptyOrder,
39
40 /// A raw `openssl::PKey` containing an unsupported key was passed.
41 UnsupportedKeyType,
42
43 /// A raw `openssl::PKey` or `openssl::EcKey` with an unsupported curve was passed.
44 UnsupportedGroup,
45
46 /// Failed to parse the account data returned by the API upon account creation.
47 BadAccountData(String),
48
49 /// Failed to parse the order data returned by the API from a new-order request.
50 BadOrderData(String),
51
52 /// An openssl error occurred during a crypto operation.
53 RawSsl(SslErrorStack),
54
55 /// An openssl error occurred during a crypto operation.
56 /// With some textual context.
57 Ssl(&'static str, SslErrorStack),
58
59 /// An otherwise uncaught serde error happened.
60 Json(serde_json::Error),
61
62 /// Can be used by the user for textual error messages without having to downcast to regular
63 /// acme errors.
64 Custom(String),
65
66 /// If built with the `client` feature, this is where general ureq/network errors end up.
67 /// This is usually a `ureq::Error`, however in order to provide an API which is not
68 /// feature-dependent, this variant is always present and contains a boxed `dyn Error`.
69 HttpClient(Box<dyn std::error::Error + Send + Sync + 'static>),
70
71 /// If built with the `client` feature, this is where client specific errors which are not from
72 /// errors forwarded from `ureq` end up.
73 Client(String),
74
75 /// A non-openssl error occurred while building data for the CSR.
76 Csr(String),
77 }
78
79 impl Error {
80 /// Create an `Error` from a custom text.
81 pub fn custom<T: std::fmt::Display>(s: T) -> Self {
82 Error::Custom(s.to_string())
83 }
84
85 /// Convenience method to check if this error represents a bad nonce error in which case the
86 /// request needs to be re-created using a new nonce.
87 pub fn is_bad_nonce(&self) -> bool {
88 matches!(self, Error::BadNonce)
89 }
90 }
91
92 impl std::error::Error for Error {}
93
94 impl fmt::Display for Error {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 match self {
97 Error::Api(err) => match err.detail.as_deref() {
98 Some(detail) => write!(f, "{}: {}", err.ty, detail),
99 None => fmt::Display::fmt(&err.ty, f),
100 },
101 Error::InvalidApi(err) => write!(f, "Acme Server API misbehaved: {}", err),
102 Error::BadNonce => f.write_str("bad nonce, please retry with a new nonce"),
103 Error::UserActionRequired(err) => write!(f, "user action required: {}", err),
104 Error::MissingKey => f.write_str("cannot build an account without a key"),
105 Error::MissingContactInfo => f.write_str("account requires contact info"),
106 Error::EmptyOrder => f.write_str("cannot make an empty order"),
107 Error::UnsupportedKeyType => f.write_str("unsupported key type"),
108 Error::UnsupportedGroup => f.write_str("unsupported EC group"),
109 Error::BadAccountData(err) => {
110 write!(f, "bad response to account query or creation: {}", err)
111 }
112 Error::BadOrderData(err) => {
113 write!(f, "bad response to new-order query or creation: {}", err)
114 }
115 Error::RawSsl(err) => fmt::Display::fmt(err, f),
116 Error::Ssl(context, err) => {
117 write!(f, "{}: {}", context, err)
118 }
119 Error::Json(err) => fmt::Display::fmt(err, f),
120 Error::Custom(err) => fmt::Display::fmt(err, f),
121 Error::HttpClient(err) => fmt::Display::fmt(err, f),
122 Error::Client(err) => fmt::Display::fmt(err, f),
123 Error::Csr(err) => fmt::Display::fmt(err, f),
124 }
125 }
126 }
127
128 impl From<SslErrorStack> for Error {
129 fn from(e: SslErrorStack) -> Self {
130 Error::RawSsl(e)
131 }
132 }
133
134 impl From<serde_json::Error> for Error {
135 fn from(e: serde_json::Error) -> Self {
136 Error::Json(e)
137 }
138 }
139
140 impl From<crate::request::ErrorResponse> for Error {
141 fn from(e: crate::request::ErrorResponse) -> Self {
142 Error::Api(e)
143 }
144 }