1
//! An error type for the `tor-keymgr` crate.
2

            
3
use tor_error::HasKind;
4

            
5
use dyn_clone::DynClone;
6
use tor_persist::slug::BadSlug;
7

            
8
use std::error::Error as StdError;
9
use std::fmt;
10
use std::sync::Arc;
11

            
12
use crate::KeyPathError;
13

            
14
/// An Error type for this crate.
15
#[derive(thiserror::Error, Debug, Clone)]
16
#[non_exhaustive]
17
pub 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).
51
pub trait KeystoreError:
52
    HasKind + StdError + DynClone + fmt::Debug + fmt::Display + Send + Sync + 'static
53
{
54
}
55

            
56
impl HasKind for Error {
57
4
    fn kind(&self) -> tor_error::ErrorKind {
58
        use tor_error::ErrorKind as EK;
59
        use Error as E;
60

            
61
4
        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
4
            E::Bug(e) => e.kind(),
68
        }
69
4
    }
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]
82
pub 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]
96
pub 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}")]
117
pub 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)]
123
mod 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
}