mod keyringsecret;
#[cfg(any(feature = "yubihsm-usb", feature = "yubihsm-http"))]
pub mod kms;
#[cfg(all(target_os = "linux", feature = "linux-secret-service"))]
pub mod linux;
#[cfg(all(target_os = "macos", feature = "macos-keychain"))]
pub mod macos;
#[cfg(feature = "file")]
pub mod sqlcipher;
#[cfg(all(target_os = "windows", feature = "windows-credentials"))]
pub mod windows;
#[cfg(any(feature = "yubihsm-usb", feature = "yubihsm-http"))]
pub mod yubihsm;
#[cfg(all(target_os = "macos", feature = "macos-keychain"))]
#[cfg_attr(docsrs, doc(cfg(all(target_os = "macos", feature = "macos-keychain"))))]
pub use self::macos::MacOsKeyRing as OsKeyRing;
#[cfg(all(target_os = "linux", feature = "linux-secret-service"))]
#[cfg_attr(
docsrs,
doc(cfg(all(target_os = "linux", feature = "linux-secret-service")))
)]
pub use self::linux::LinuxOsKeyRing as OsKeyRing;
#[cfg(all(target_os = "windows", feature = "windows-credentials"))]
#[cfg_attr(
docsrs,
doc(cfg(all(target_os = "windows", feature = "windows-credentials")))
)]
pub use self::windows::WindowsOsKeyRing as OsKeyRing;
use std::collections::BTreeMap;
pub type Result<T> = std::result::Result<T, crate::error::KeyRingError>;
pub use keyringsecret::*;
#[cfg(any(
all(target_os = "linux", feature = "linux-secret-service"),
all(target_os = "macos", feature = "macos-keychain"),
))]
use uzers::{get_current_username, get_effective_username};
#[cfg(any(
all(target_os = "macos", feature = "macos-keychain"),
all(target_os = "windows", feature = "windows-credentials"),
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
all(target_os = "macos", feature = "macos-keychain"),
all(target_os = "windows", feature = "windows-credentials"),
)))
)]
pub fn get_os_keyring(service: &str) -> Result<OsKeyRing> {
OsKeyRing::new(service)
}
#[cfg(all(target_os = "linux", feature = "linux-secret-service"))]
#[cfg_attr(
docsrs,
doc(cfg(all(target_os = "linux", feature = "linux-secret-service")))
)]
pub fn get_os_keyring(service: &str) -> Result<OsKeyRing<'_>> {
OsKeyRing::new(service)
}
#[cfg(not(any(
all(target_os = "macos", feature = "macos-keychain"),
all(target_os = "windows", feature = "windows-credentials"),
all(target_os = "linux", feature = "linux-secret-service"),
feature = "file",
feature = "yubihsm-usb",
feature = "yubihsm-http",
)))]
compile_error!("no keyring implementation is selected or available for this platform");
#[cfg(any(
all(target_os = "linux", feature = "linux-secret-service"),
all(target_os = "macos", feature = "macos-keychain"),
))]
fn get_username() -> String {
fn fallback_username() -> String {
whoami::username().unwrap_or_else(|_| String::from("unknown"))
}
fn get_current_user() -> String {
match get_current_username() {
Some(s) => s.into_string().unwrap_or_else(|_| fallback_username()),
None => fallback_username(),
}
}
match get_effective_username() {
Some(s) => s.into_string().unwrap_or_else(|_| get_current_user()),
None => get_current_user(),
}
}
#[cfg(feature = "file")]
pub const fn allows_file() -> bool {
true
}
#[cfg(not(feature = "file"))]
pub const fn allows_file() -> bool {
false
}
pub trait KeyRing: Send + Sync {
fn get_secret<S: AsRef<str>>(&mut self, id: S) -> Result<KeyRingSecret>;
fn set_secret<S: AsRef<str>, B: AsRef<[u8]>>(&mut self, id: S, secret: B) -> Result<()>;
fn delete_secret<S: AsRef<str>>(&mut self, id: S) -> Result<()>;
}
pub trait DynKeyRing: Send + Sync {
fn get_secret(&mut self, id: &str) -> Result<KeyRingSecret>;
fn set_secret(&mut self, id: &str, secret: &[u8]) -> Result<()>;
fn delete_secret(&mut self, id: &str) -> Result<()>;
}
impl<D: DynKeyRing> KeyRing for D {
fn get_secret<S: AsRef<str>>(&mut self, id: S) -> Result<KeyRingSecret> {
DynKeyRing::get_secret(self, id.as_ref())
}
fn set_secret<S: AsRef<str>, B: AsRef<[u8]>>(&mut self, id: S, secret: B) -> Result<()> {
DynKeyRing::set_secret(self, id.as_ref(), secret.as_ref())
}
fn delete_secret<S: AsRef<str>>(&mut self, id: S) -> Result<()> {
DynKeyRing::delete_secret(self, id.as_ref())
}
}
pub trait NewKeyRing: Sized {
fn new<S: AsRef<str>>(service: S) -> Result<Self>;
}
pub trait PeekableKeyRing {
fn peek_secret<S: AsRef<str>>(id: S) -> Result<Vec<(String, KeyRingSecret)>>;
}
pub trait ListKeyRing {
fn list_secrets() -> Result<Vec<BTreeMap<String, String>>>;
}
#[cfg(any(
all(target_os = "macos", feature = "macos-keychain"),
all(target_os = "linux", feature = "linux-secret-service"),
))]
pub(crate) fn parse_peek_criteria(id: &str) -> BTreeMap<String, String> {
let mut result = BTreeMap::new();
if !id.is_empty() {
for pair in id.split(',') {
let s = pair.split('=').collect::<Vec<&str>>();
result.insert(s[0].to_string(), s[1].to_string());
}
}
result
}