Merge pull request #320 from WhatAmISupposedToPutHere/master

Ask for password via systemd-ask-password
This commit is contained in:
koverstreet 2024-08-02 09:33:46 -04:00 committed by GitHub
commit 6958dd8df2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 8 deletions

View File

@ -331,8 +331,9 @@ fn handle_unlock(cli: &Cli, sb: &bch_sb_handle) -> Result<KeyHandle> {
return Passphrase::new_from_file(path).and_then(|p| KeyHandle::new(sb, &p)); return Passphrase::new_from_file(path).and_then(|p| KeyHandle::new(sb, &p));
} }
KeyHandle::new_from_search(&sb.sb().uuid()) let uuid = sb.sb().uuid();
.or_else(|_| Passphrase::new().and_then(|p| KeyHandle::new(sb, &p))) KeyHandle::new_from_search(&uuid)
.or_else(|_| Passphrase::new(&uuid).and_then(|p| KeyHandle::new(sb, &p)))
} }
fn cmd_mount_inner(cli: &Cli) -> Result<()> { fn cmd_mount_inner(cli: &Cli) -> Result<()> {

View File

@ -7,7 +7,7 @@ use std::{
ptr, thread, ptr, thread,
time::Duration, time::Duration,
}; };
use std::process::{Command, Stdio};
use anyhow::{anyhow, ensure, Result}; use anyhow::{anyhow, ensure, Result};
use bch_bindgen::{ use bch_bindgen::{
bcachefs::{self, bch_key, bch_sb_handle}, bcachefs::{self, bch_key, bch_sb_handle},
@ -15,7 +15,7 @@ use bch_bindgen::{
keyutils::{self, keyctl_search}, keyutils::{self, keyctl_search},
}; };
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use log::info; use log::{debug, info};
use rustix::termios; use rustix::termios;
use uuid::Uuid; use uuid::Uuid;
use zeroize::{ZeroizeOnDrop, Zeroizing}; use zeroize::{ZeroizeOnDrop, Zeroizing};
@ -46,7 +46,7 @@ impl UnlockPolicy {
match self { match self {
Self::Fail => KeyHandle::new_from_search(&uuid), Self::Fail => KeyHandle::new_from_search(&uuid),
Self::Wait => Ok(KeyHandle::wait_for_unlock(&uuid)?), Self::Wait => Ok(KeyHandle::wait_for_unlock(&uuid)?),
Self::Ask => Passphrase::new_from_prompt().and_then(|p| KeyHandle::new(sb, &p)), Self::Ask => Passphrase::new_from_prompt(&uuid).and_then(|p| KeyHandle::new(sb, &p)),
Self::Stdin => Passphrase::new_from_stdin().and_then(|p| KeyHandle::new(sb, &p)), Self::Stdin => Passphrase::new_from_stdin().and_then(|p| KeyHandle::new(sb, &p)),
} }
} }
@ -142,16 +142,43 @@ impl Passphrase {
&self.0 &self.0
} }
pub fn new() -> Result<Self> { pub fn new(uuid: &Uuid) -> Result<Self> {
if stdin().is_terminal() { if stdin().is_terminal() {
Self::new_from_prompt() Self::new_from_prompt(uuid)
} else { } else {
Self::new_from_stdin() Self::new_from_stdin()
} }
} }
// The outer result represents a failure when trying to run systemd-ask-password,
// it is non-critical and will cause the password to be asked internally.
// The inner result represent a successful request that returned an error
// this one results in an error.
fn new_from_askpassword(uuid: &Uuid) -> Result<Result<Self>> {
let output = Command::new("systemd-ask-password")
.arg("--icon=drive-harddisk")
.arg(format!("--id=bcachefs:{}", uuid.as_hyphenated()))
.arg("-n")
.arg("Enter passphrase: ")
.stdin(Stdio::inherit())
.stderr(Stdio::inherit())
.output()?;
Ok(if output.status.success() {
match CString::new(output.stdout) {
Ok(cstr) => Ok(Self(cstr)),
Err(e) => Err(e.into())
}
} else {
Err(anyhow!("systemd-ask-password returned an error"))
})
}
// blocks indefinitely if no input is available on stdin // blocks indefinitely if no input is available on stdin
pub fn new_from_prompt() -> Result<Self> { pub fn new_from_prompt(uuid: &Uuid) -> Result<Self> {
match Self::new_from_askpassword(uuid) {
Ok(phrase) => return phrase,
Err(_) => debug!("Failed to start systemd-ask-password, doing the prompt ourselves"),
}
let old = termios::tcgetattr(stdin())?; let old = termios::tcgetattr(stdin())?;
let mut new = old.clone(); let mut new = old.clone();
new.local_modes.remove(termios::LocalModes::ECHO); new.local_modes.remove(termios::LocalModes::ECHO);