Skip to main content

keyring_manager/
error.rs

1#[cfg(target_os = "linux")]
2use dbus_secret_service::Error as SsError;
3#[cfg(target_os = "macos")]
4use security_framework::base::Error as SfError;
5use std::fmt;
6use std::string::FromUtf8Error;
7
8#[cfg(target_os = "ios")]
9pub type OSStatus = i32;
10pub type Result<T> = ::std::result::Result<T, KeyringError>;
11
12/// An error from a keyring backend operation.
13#[derive(Debug)]
14pub enum KeyringError {
15    /// Filesystem error from the insecure file backend.
16    IoError(std::io::Error),
17    /// macOS keychain error.
18    #[cfg(target_os = "macos")]
19    MacOsKeychainError(SfError),
20    /// iOS keychain error (OSStatus code).
21    #[cfg(target_os = "ios")]
22    IOSKeychainError(OSStatus),
23    /// Linux Secret Service error.
24    #[cfg(target_os = "linux")]
25    SecretServiceError(SsError),
26    /// Windows credential vault error, carrying the `GetLastError` code.
27    #[cfg(target_os = "windows")]
28    WindowsVaultError(u32),
29    /// Android keystore error.
30    #[cfg(target_os = "android")]
31    AndroidKeystoreError(String),
32    /// No keyring backend is available on this platform.
33    NoBackendFound,
34    /// No value is stored for the requested key.
35    NoPasswordFound,
36    /// The store is locked, or absence could not be proven because the store is locked. Any stored
37    /// value is intact; retry once the device is unlocked. Never treat this as absence: a caller
38    /// that reprovisions on absence would overwrite a secret it could not read.
39    Locked,
40    /// The active backend does not implement this operation (e.g. key enumeration on an OS keychain).
41    Unsupported,
42    /// A stored value was not valid UTF-8.
43    Parse(FromUtf8Error),
44    /// Any other error, carrying a message.
45    Generic(String),
46}
47
48impl fmt::Display for KeyringError {
49    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50        match self {
51            KeyringError::IoError(ref err) => write!(f, "Keyring IO error: {}", err),
52            #[cfg(target_os = "macos")]
53            KeyringError::MacOsKeychainError(ref err) => {
54                write!(f, "MacOS keychain Error: {}", err)
55            }
56            #[cfg(target_os = "ios")]
57            KeyringError::IOSKeychainError(ref err) => {
58                write!(f, "iOS keychain Error: {}", err)
59            }
60            #[cfg(target_os = "linux")]
61            KeyringError::SecretServiceError(ref err) => write!(f, "Secret service error: {}", err),
62            #[cfg(target_os = "windows")]
63            KeyringError::WindowsVaultError(code) => {
64                write!(f, "Windows vault error: {}", code)
65            }
66            #[cfg(target_os = "android")]
67            KeyringError::AndroidKeystoreError(s) => {
68                write!(f, "Android keystore error: {}", s)
69            }
70            KeyringError::NoBackendFound => write!(f, "Keyring error: No Backend Found"),
71            KeyringError::NoPasswordFound => write!(f, "Keyring error: No Password Found"),
72            KeyringError::Locked => write!(f, "Keyring error: Store Locked"),
73            KeyringError::Unsupported => {
74                write!(f, "Keyring error: Operation Unsupported by backend")
75            }
76            KeyringError::Parse(ref err) => write!(f, "Keyring parse error: {}", err),
77            KeyringError::Generic(ref err) => write!(f, "Keyring generic error: {}", err),
78        }
79    }
80}
81
82impl std::error::Error for KeyringError {
83    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
84        match *self {
85            KeyringError::IoError(ref err) => Some(err),
86            #[cfg(target_os = "linux")]
87            KeyringError::SecretServiceError(ref err) => Some(err),
88            #[cfg(target_os = "macos")]
89            KeyringError::MacOsKeychainError(ref err) => Some(err),
90            _ => None,
91        }
92    }
93}
94
95impl From<std::io::Error> for KeyringError {
96    fn from(err: std::io::Error) -> KeyringError {
97        KeyringError::IoError(err)
98    }
99}
100
101#[cfg(target_os = "linux")]
102impl From<SsError> for KeyringError {
103    fn from(err: SsError) -> KeyringError {
104        KeyringError::SecretServiceError(err)
105    }
106}
107
108#[cfg(target_os = "macos")]
109impl From<SfError> for KeyringError {
110    fn from(err: SfError) -> KeyringError {
111        KeyringError::MacOsKeychainError(err)
112    }
113}
114
115#[cfg(target_os = "ios")]
116impl From<OSStatus> for KeyringError {
117    fn from(err: OSStatus) -> KeyringError {
118        KeyringError::IOSKeychainError(err)
119    }
120}
121
122impl From<FromUtf8Error> for KeyringError {
123    fn from(err: FromUtf8Error) -> KeyringError {
124        KeyringError::Parse(err)
125    }
126}
127
128impl From<String> for KeyringError {
129    fn from(err: String) -> KeyringError {
130        KeyringError::Generic(err)
131    }
132}