1
//! An error type for [`ArtiNativeKeystore`](crate::ArtiNativeKeystore).
2

            
3
use crate::keystore::fs_utils::FilesystemError;
4
use crate::raw::RawEntryId;
5
use crate::{ArtiPathSyntaxError, KeystoreError, UnknownKeyTypeError};
6
use tor_error::{ErrorKind, HasKind};
7
use tor_key_forge::{CertType, KeyType, SshKeyAlgorithm};
8

            
9
use std::path::PathBuf;
10
use std::sync::Arc;
11

            
12
/// An error returned by [`ArtiNativeKeystore`](crate::ArtiNativeKeystore)'s
13
/// [`Keystore`](crate::Keystore) implementation.
14
#[derive(thiserror::Error, Debug, Clone)]
15
pub(crate) enum ArtiNativeKeystoreError {
16
    /// An error that occurred while accessing the filesystem.
17
    #[error("{0}")]
18
    Filesystem(#[from] FilesystemError),
19

            
20
    /// Found a key with an invalid path.
21
    #[error("Key has invalid path: {path}")]
22
    MalformedPath {
23
        /// The path of the key.
24
        path: PathBuf,
25
        /// The underlying error.
26
        #[source]
27
        err: MalformedPathError,
28
    },
29

            
30
    /// An error due to encountering an unsupported [`KeyType`].
31
    #[error("{0}")]
32
    UnknownKeyType(#[from] UnknownKeyTypeError),
33

            
34
    /// Failed to parse an OpenSSH key.
35
    #[error("Failed to parse OpenSSH with type {key_type:?}")]
36
    SshKeyParse {
37
        /// The path of the malformed key.
38
        path: PathBuf,
39
        /// The type of key we were trying to fetch.
40
        key_type: KeyType,
41
        /// The underlying error.
42
        #[source]
43
        err: Arc<ssh_key::Error>,
44
    },
45

            
46
    /// The OpenSSH key we retrieved is of the wrong type.
47
    #[error("Unexpected OpenSSH key type: wanted {wanted_key_algo}, found {found_key_algo}")]
48
    UnexpectedSshKeyType {
49
        /// The path of the malformed key.
50
        path: PathBuf,
51
        /// The algorithm we expected the key to use.
52
        wanted_key_algo: SshKeyAlgorithm,
53
        /// The algorithm of the key we got.
54
        found_key_algo: SshKeyAlgorithm,
55
    },
56

            
57
    /// Failed to parse an OpenSSH key.
58
    #[error("Failed to parse cert with type {cert_type:?}")]
59
    CertParse {
60
        /// The path of the malformed key.
61
        path: PathBuf,
62
        /// The type of cert we were trying to fetch.
63
        cert_type: CertType,
64
        /// The underlying error.
65
        #[source]
66
        err: tor_bytes::Error,
67
    },
68

            
69
    /// Encountered a non-path `RawEntryId` variant.
70
    #[error("Raw entry {:?} not supported in an Arti keystore", _0)]
71
    UnsupportedRawEntry(RawEntryId),
72

            
73
    /// An internal error.
74
    #[error("Internal error")]
75
    Bug(#[from] tor_error::Bug),
76
}
77

            
78
/// The keystore contained a file whose name syntactically improper
79
///
80
/// Keys are supposed to have pathnames consisting of an `ArtiPath`
81
/// followed by a file extension.
82
///
83
/// See also [`KeyPathError`](crate::KeyPathError), which occurs at a higher level.
84
#[derive(thiserror::Error, Debug, Clone)]
85
pub(crate) enum MalformedPathError {
86
    /// Found a key with a non-UTF-8 path.
87
    #[error("the path is not valid UTF-8")]
88
    Utf8,
89

            
90
    /// Found a key with no extension.
91
    #[error("no extension")]
92
    NoExtension,
93

            
94
    /// The file path is not a valid [`ArtiPath`](crate::ArtiPath).
95
    #[error("not a valid ArtiPath")]
96
    InvalidArtiPath(ArtiPathSyntaxError),
97
}
98

            
99
impl KeystoreError for ArtiNativeKeystoreError {}
100

            
101
impl HasKind for ArtiNativeKeystoreError {
102
    fn kind(&self) -> ErrorKind {
103
        use ArtiNativeKeystoreError as KE;
104

            
105
        match self {
106
            KE::Filesystem(e) => e.kind(),
107
            KE::MalformedPath { .. } => ErrorKind::KeystoreAccessFailed,
108
            KE::UnknownKeyType(_) => ErrorKind::KeystoreAccessFailed,
109
            KE::SshKeyParse { .. } | KE::UnexpectedSshKeyType { .. } | KE::CertParse { .. } => {
110
                ErrorKind::KeystoreCorrupted
111
            }
112
            KE::UnsupportedRawEntry { .. } => ErrorKind::BadApiUsage,
113
            KE::Bug(e) => e.kind(),
114
        }
115
    }
116
}
117

            
118
impl From<ArtiNativeKeystoreError> for crate::Error {
119
38
    fn from(e: ArtiNativeKeystoreError) -> Self {
120
38
        crate::Error::Keystore(Arc::new(e))
121
38
    }
122
}