#[cfg(target_os = "macos")]
mod macos_auth;
#[cfg(all(
any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"),
feature = "lockscreen"
))]
mod pam_auth;
mod pin_auth;
mod stub_auth;
#[cfg(target_os = "windows")]
mod windows_auth;
pub use pin_auth::{MAX_PIN_LENGTH, MIN_PIN_LENGTH, PinAuthenticator, secure_clear};
use crate::app::config_manager::LockscreenAuthMode;
#[derive(Debug, Clone, PartialEq)]
pub enum AuthResult {
Success,
Failure(String),
SystemError(String),
}
pub trait Authenticator: Send + Sync {
fn is_available(&self) -> bool;
fn authenticate(&self, username: &str, password: &str) -> AuthResult;
fn get_current_username(&self) -> Option<String>;
#[allow(dead_code)]
fn system_name(&self) -> &'static str;
}
pub const fn is_os_auth_compiled() -> bool {
cfg!(all(
feature = "lockscreen",
any(
target_os = "linux",
target_os = "macos",
target_os = "windows",
target_os = "freebsd",
target_os = "netbsd"
)
))
}
pub fn is_os_auth_available() -> bool {
if !is_os_auth_compiled() {
return false;
}
#[cfg(all(
any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"),
feature = "lockscreen"
))]
{
if let Ok(auth) = pam_auth::PamAuthenticator::new() {
return auth.is_available();
}
}
#[cfg(target_os = "macos")]
{
if let Ok(auth) = macos_auth::MacOsAuthenticator::new() {
return auth.is_available();
}
}
#[cfg(target_os = "windows")]
{
if let Ok(auth) = windows_auth::WindowsAuthenticator::new() {
return auth.is_available();
}
}
false
}
pub fn create_authenticator_with_mode(
mode: LockscreenAuthMode,
pin_hash: Option<&str>,
salt: Option<&str>,
) -> Box<dyn Authenticator> {
match mode {
LockscreenAuthMode::Pin => {
if let (Some(hash), Some(s)) = (pin_hash, salt) {
if let Ok(auth) = PinAuthenticator::new(hash.to_string(), s.to_string()) {
return Box::new(auth);
}
}
Box::new(stub_auth::StubAuthenticator::new())
}
LockscreenAuthMode::OsAuth => create_authenticator(),
}
}
pub fn create_authenticator() -> Box<dyn Authenticator> {
#[cfg(all(
any(target_os = "linux", target_os = "freebsd", target_os = "netbsd"),
feature = "lockscreen"
))]
{
if let Ok(auth) = pam_auth::PamAuthenticator::new() {
if auth.is_available() {
return Box::new(auth);
}
}
}
#[cfg(target_os = "macos")]
{
if let Ok(auth) = macos_auth::MacOsAuthenticator::new() {
if auth.is_available() {
return Box::new(auth);
}
}
}
#[cfg(target_os = "windows")]
{
if let Ok(auth) = windows_auth::WindowsAuthenticator::new() {
if auth.is_available() {
return Box::new(auth);
}
}
}
Box::new(stub_auth::StubAuthenticator::new())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_authenticator() {
let auth = create_authenticator();
let _ = auth.system_name();
}
#[test]
fn test_get_username() {
let auth = create_authenticator();
let username = auth.get_current_username();
let _ = username;
}
}