Save SSH passwords in Windows Credential Manager and auto-type at prompt
This commit is contained in:
parent
872fb0e80e
commit
1c243b3f3f
11 changed files with 538 additions and 38 deletions
46
src-tauri/src/creds.rs
Normal file
46
src-tauri/src/creds.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//! Saved SSH-host credentials. Backed by Windows Credential Manager via
|
||||
//! `keyring-core` + `windows-native-keyring-store` — passwords are DPAPI-
|
||||
//! encrypted at rest and scoped to the user account. Never written to
|
||||
//! disk in plaintext, never logged, never sent to the frontend.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use keyring_core::{Entry, Error as KeyringError};
|
||||
|
||||
const SERVICE: &str = "tiletopia";
|
||||
|
||||
fn target_for(host_id: &str) -> String {
|
||||
format!("ssh-host:{host_id}")
|
||||
}
|
||||
|
||||
fn entry(host_id: &str) -> Result<Entry> {
|
||||
Entry::new(SERVICE, &target_for(host_id))
|
||||
.with_context(|| format!("create keyring entry for {host_id}"))
|
||||
}
|
||||
|
||||
pub fn set(host_id: &str, password: &str) -> Result<()> {
|
||||
entry(host_id)?
|
||||
.set_password(password)
|
||||
.with_context(|| format!("write credential for {host_id}"))
|
||||
}
|
||||
|
||||
pub fn get(host_id: &str) -> Result<Option<String>> {
|
||||
match entry(host_id)?.get_password() {
|
||||
Ok(p) => Ok(Some(p)),
|
||||
Err(KeyringError::NoEntry) => Ok(None),
|
||||
Err(e) => Err(anyhow::Error::from(e)
|
||||
.context(format!("read credential for {host_id}"))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(host_id: &str) -> Result<()> {
|
||||
match entry(host_id)?.delete_credential() {
|
||||
Ok(()) => Ok(()),
|
||||
Err(KeyringError::NoEntry) => Ok(()),
|
||||
Err(e) => Err(anyhow::Error::from(e)
|
||||
.context(format!("delete credential for {host_id}"))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has(host_id: &str) -> bool {
|
||||
matches!(get(host_id), Ok(Some(_)))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue