mirror of
https://github.com/bitwarden/browser
synced 2026-02-11 05:53:42 +00:00
Clean up linux implementation
This commit is contained in:
@@ -42,62 +42,32 @@ impl Default for BiometricLockSystem {
|
||||
|
||||
impl super::BiometricTrait for BiometricLockSystem {
|
||||
async fn authenticate(&self, _hwnd: Vec<u8>, _message: String) -> Result<bool> {
|
||||
let connection = Connection::system().await?;
|
||||
let proxy = AuthorityProxy::new(&connection).await?;
|
||||
let subject = Subject::new_for_owner(std::process::id(), None, None)?;
|
||||
let details = std::collections::HashMap::new();
|
||||
let result = proxy
|
||||
.check_authorization(
|
||||
&subject,
|
||||
"com.bitwarden.Bitwarden.unlock",
|
||||
&details,
|
||||
CheckAuthorizationFlags::AllowUserInteraction.into(),
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(result) => Ok(result.is_authorized),
|
||||
Err(e) => {
|
||||
println!("polkit biometric error: {:?}", e);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
polkit_authenticate_bitwarden_policy().await
|
||||
}
|
||||
|
||||
async fn authenticate_available(&self) -> Result<bool> {
|
||||
let connection = Connection::system().await?;
|
||||
let proxy = AuthorityProxy::new(&connection).await?;
|
||||
let actions = proxy.enumerate_actions("en").await?;
|
||||
for action in actions {
|
||||
if action.action_id == "com.bitwarden.Bitwarden.unlock" {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
polkit_is_bitwarden_policy_available().await
|
||||
}
|
||||
|
||||
async fn enroll_persistent(&self, _user_id: &str, _key: &[u8]) -> Result<()> {
|
||||
// Not implemented
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn provide_key(&self, user_id: &str, key: &[u8]) {
|
||||
let mut secure_memory = self.secure_memory.lock().await;
|
||||
secure_memory.put(user_id.to_string(), key);
|
||||
self.secure_memory.lock().await.put(user_id.to_string(), key);
|
||||
}
|
||||
|
||||
async fn unlock(&self, user_id: &str, _hwnd: Vec<u8>) -> Result<Vec<u8>> {
|
||||
if !(self.authenticate(Vec::new(), "".to_string()).await?) {
|
||||
if !polkit_authenticate_bitwarden_policy().await? {
|
||||
return Err(anyhow!("Authentication failed"));
|
||||
}
|
||||
|
||||
let secure_memory = self.secure_memory.lock().await;
|
||||
secure_memory.get(user_id).ok_or(anyhow!("No key found"))
|
||||
self.secure_memory.lock().await.get(user_id).ok_or(anyhow!("No key found"))
|
||||
}
|
||||
|
||||
async fn unlock_available(&self, user_id: &str) -> Result<bool> {
|
||||
let secure_memory = self.secure_memory.lock().await;
|
||||
Ok(secure_memory.has(user_id))
|
||||
Ok(self.secure_memory.lock().await.has(user_id))
|
||||
}
|
||||
|
||||
async fn has_persistent(&self, _user_id: &str) -> Result<bool> {
|
||||
@@ -105,8 +75,59 @@ impl super::BiometricTrait for BiometricLockSystem {
|
||||
}
|
||||
|
||||
async fn unenroll(&self, user_id: &str) -> Result<(), anyhow::Error> {
|
||||
let mut secure_memory = self.secure_memory.lock().await;
|
||||
secure_memory.remove(user_id);
|
||||
self.secure_memory.lock().await.remove(user_id);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a polkit authorization against the bitwarden unlock policy. Note: This relies on no custom
|
||||
/// rules in the system skipping the authorization check, in which case this counts as UV / authentication.
|
||||
async fn polkit_authenticate_bitwarden_policy() -> Result<bool> {
|
||||
println!("[Polkit] Authenticating / performing UV");
|
||||
|
||||
let connection = Connection::system().await?;
|
||||
let proxy = AuthorityProxy::new(&connection).await?;
|
||||
let subject = Subject::new_for_owner(std::process::id(), None, None)?;
|
||||
let details = std::collections::HashMap::new();
|
||||
let authorization_result = proxy
|
||||
.check_authorization(
|
||||
&subject,
|
||||
"com.bitwarden.Bitwarden.unlock",
|
||||
&details,
|
||||
CheckAuthorizationFlags::AllowUserInteraction.into(),
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
|
||||
match authorization_result {
|
||||
Ok(result) => Ok(result.is_authorized),
|
||||
Err(e) => {
|
||||
eprintln!("[Polkit] Error performing authentication: {:?}", e);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn polkit_is_bitwarden_policy_available() -> Result<bool> {
|
||||
let connection = Connection::system().await?;
|
||||
let proxy = AuthorityProxy::new(&connection).await?;
|
||||
let actions = proxy.enumerate_actions("en").await?;
|
||||
for action in actions {
|
||||
if action.action_id == "com.bitwarden.Bitwarden.unlock" {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn test_polkit_authenticate() {
|
||||
let result = polkit_authenticate_bitwarden_policy().await;
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,10 @@ use crate::secure_memory::SecureMemoryStore;
|
||||
/// data is inaccessible to other user-mode processes, and even to root in most cases.
|
||||
/// If arbitrary data can be executed in the kernel, the data can still be retrieved:
|
||||
/// https://github.com/JonathonReinhart/nosecmem
|
||||
///
|
||||
/// Warning: There is a maximum amount of concurrent memfd_secret protected items. Only
|
||||
/// use this sparingly, or extend the implementation to use one secret + in-memory encryption,
|
||||
/// or to reserve a large protected area in which we allocate our items.
|
||||
pub(crate) struct MemfdSecretKVStore {
|
||||
map: HashMap<String, std::ptr::NonNull<[u8]>>,
|
||||
}
|
||||
@@ -103,6 +107,8 @@ mod tests {
|
||||
store.put(key.clone(), &value);
|
||||
assert!(store.has(&key), "Store should have key for size {}", size);
|
||||
assert_eq!(store.get(&key), Some(value), "Value mismatch for size {}", size);
|
||||
// The test will not pass when we don't remove the keys, because there is a limit of concurrent memfd_secret memory spaces.
|
||||
store.remove(&key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user