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
    //
22
    // TODO: Should we expose the underlying MalformedPathError? The current
23
    // message "Key has invalid path" is too vague.
24
    #[error("Key has invalid path: {path}")]
25
    MalformedPath {
26
        /// The path of the key.
27
        path: PathBuf,
28
        /// The underlying error.
29
        #[source]
30
        err: MalformedPathError,
31
    },
32

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

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

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

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

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

            
76
    /// An internal error.
77
    #[error("Internal error")]
78
    Bug(#[from] tor_error::Bug),
79
}
80

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

            
93
    /// Found a key with no extension.
94
    #[error("no extension")]
95
    NoExtension,
96

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

            
102
impl KeystoreError for ArtiNativeKeystoreError {}
103

            
104
impl HasKind for ArtiNativeKeystoreError {
105
    fn kind(&self) -> ErrorKind {
106
        use ArtiNativeKeystoreError as KE;
107

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

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