tor_keymgr/
err.rs

1//! An error type for the `tor-keymgr` crate.
2
3use tor_error::HasKind;
4
5use dyn_clone::DynClone;
6use tor_persist::slug::BadSlug;
7
8use std::error::Error as StdError;
9use std::fmt;
10use std::sync::Arc;
11
12use crate::KeyPathError;
13
14/// An Error type for this crate.
15#[derive(thiserror::Error, Debug, Clone)]
16#[non_exhaustive]
17pub enum Error {
18    /// Detected keustore corruption.
19    #[error("{0}")]
20    Corruption(#[from] KeystoreCorruptionError),
21
22    /// An opaque error returned by a [`Keystore`](crate::Keystore).
23    #[error("{0}")]
24    Keystore(#[from] Arc<dyn KeystoreError>),
25
26    /// An error returned when the [`KeyMgr`](crate::KeyMgr) is asked to generate a key that already exists.
27    ///
28    /// Note that because there is no locking of the keystore,
29    /// this situation is not reliably detected
30    /// in the presence of concurrent tasks trying to generate the same key.
31    ///
32    /// So this error is provided to help the human user,
33    /// but mustn't be relied on for correctness.
34    #[error("Key already exists")]
35    KeyAlreadyExists,
36
37    /// Error coming from the tor-key-forgecrate
38    #[error("{0}")]
39    KeyForge(#[from] tor_key_forge::Error),
40
41    /// An error caused by an invalid certificate.
42    #[error("{0}")]
43    InvalidCert(#[from] tor_key_forge::InvalidCertError),
44
45    /// An internal error.
46    #[error("Internal error")]
47    Bug(#[from] tor_error::Bug),
48}
49
50/// An error returned by a [`Keystore`](crate::Keystore).
51pub trait KeystoreError:
52    HasKind + StdError + DynClone + fmt::Debug + fmt::Display + Send + Sync + 'static
53{
54}
55
56impl HasKind for Error {
57    fn kind(&self) -> tor_error::ErrorKind {
58        use tor_error::ErrorKind as EK;
59        use Error as E;
60
61        match self {
62            E::Keystore(e) => e.kind(),
63            E::Corruption(_) => EK::KeystoreCorrupted,
64            E::KeyAlreadyExists => EK::BadApiUsage, // TODO: not strictly right
65            E::KeyForge(_) => EK::BadApiUsage,
66            E::InvalidCert(_) => EK::BadApiUsage, // TODO: not strictly right
67            E::Bug(e) => e.kind(),
68        }
69    }
70}
71
72/// An error caused by a syntactically invalid [`ArtiPath`](crate::ArtiPath).
73///
74/// The `ArtiPath` is not in the legal syntax: it contains bad characters,
75/// or a syntactically invalid components.
76///
77/// (Does not include any errors arising from paths which are invalid
78/// *for the particular key*.)
79#[derive(thiserror::Error, Debug, Clone)]
80#[error("Invalid ArtiPath")]
81#[non_exhaustive]
82pub enum ArtiPathSyntaxError {
83    /// One of the path slugs was invalid.
84    #[error("{0}")]
85    Slug(#[from] BadSlug),
86
87    /// An internal error.
88    #[error("Internal error")]
89    Bug(#[from] tor_error::Bug),
90}
91
92/// An error caused by keystore corruption.
93#[derive(thiserror::Error, Debug, Clone)]
94#[error("Keystore corruption")]
95#[non_exhaustive]
96pub enum KeystoreCorruptionError {
97    /// A keystore contains a key that has an invalid [`KeyPath`](crate::KeyPath).
98    #[error("{0}")]
99    KeyPath(#[from] KeyPathError),
100
101    /// Missing certificate for key.
102    #[error("Missing certificate for key")]
103    MissingCertificate,
104
105    /// Missing the subject key of a certificate we own.
106    #[error("Subject key of certificate not found")]
107    MissingSubjectKey,
108
109    /// Missing signing key for certificate.
110    #[error("Missing signing key for certificate")]
111    MissingSigningKey,
112}
113
114/// An error that happens when we encounter an unknown key type.
115#[derive(thiserror::Error, PartialEq, Eq, Debug, Clone)]
116#[error("unknown key type: arti_extension={arti_extension}")]
117pub struct UnknownKeyTypeError {
118    /// The extension used for keys of this type in an Arti keystore.
119    pub(crate) arti_extension: String,
120}
121
122#[cfg(test)]
123mod tests {
124    // @@ begin test lint list maintained by maint/add_warning @@
125    #![allow(clippy::bool_assert_comparison)]
126    #![allow(clippy::clone_on_copy)]
127    #![allow(clippy::dbg_macro)]
128    #![allow(clippy::mixed_attributes_style)]
129    #![allow(clippy::print_stderr)]
130    #![allow(clippy::print_stdout)]
131    #![allow(clippy::single_char_pattern)]
132    #![allow(clippy::unwrap_used)]
133    #![allow(clippy::unchecked_duration_subtraction)]
134    #![allow(clippy::useless_vec)]
135    #![allow(clippy::needless_pass_by_value)]
136    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
137    use super::*;
138    use tor_error::ErrorKind;
139
140    #[derive(Debug, Copy, Clone, PartialEq, thiserror::Error)]
141    #[error("The source of a test error")]
142    struct TestErrorSource;
143
144    #[derive(Debug, Clone, thiserror::Error)]
145    #[error("A test error")]
146    struct TestError(#[from] TestErrorSource);
147
148    impl KeystoreError for TestError {}
149
150    impl HasKind for TestError {
151        fn kind(&self) -> ErrorKind {
152            ErrorKind::Other
153        }
154    }
155
156    #[test]
157    fn error_source() {
158        let e: Error = (Arc::new(TestError(TestErrorSource)) as Arc<dyn KeystoreError>).into();
159
160        assert_eq!(
161            e.source().unwrap().to_string(),
162            TestError(TestErrorSource).to_string()
163        );
164    }
165}