diff options
author | koverstreet <kent.overstreet@gmail.com> | 2024-05-30 19:56:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-30 19:56:27 -0400 |
commit | d42a09728051e3b3611fde927adf37c84589921c (patch) | |
tree | 763149408b7dd7481f7d5ad79a3c2b88d2e5b250 /src/commands | |
parent | de6e8ac23014b18795b08aad0e7a0b38323a49d3 (diff) | |
parent | 22495e0d31e5a440fe58039941a2f916aee6c89f (diff) |
Merge pull request #281 from tmuehlbacher/rewrite-rust-key-handling
Rewrite rust key handling
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/mount.rs | 83 |
1 files changed, 35 insertions, 48 deletions
diff --git a/src/commands/mount.rs b/src/commands/mount.rs index 474f58ff..49849aae 100644 --- a/src/commands/mount.rs +++ b/src/commands/mount.rs @@ -1,15 +1,19 @@ -use crate::key; -use crate::key::UnlockPolicy; +use std::{ + collections::HashMap, + ffi::{c_char, c_void, CString}, + io::{stdout, IsTerminal}, + path::{Path, PathBuf}, + {env, fs, str}, +}; + +use anyhow::{ensure, Result}; use bch_bindgen::{bcachefs, bcachefs::bch_sb_handle, opt_set, path_to_cstr}; use clap::Parser; use log::{debug, error, info, LevelFilter}; -use std::collections::HashMap; -use std::ffi::{c_char, c_void, CString}; -use std::io::{stdout, IsTerminal}; -use std::path::{Path, PathBuf}; -use std::{env, fs, str}; use uuid::Uuid; +use crate::key::{KeyHandle, Passphrase, UnlockPolicy}; + fn mount_inner( src: String, target: impl AsRef<std::path::Path>, @@ -231,7 +235,8 @@ pub struct Cli { #[arg( short = 'k', long = "key_location", - default_value = "ask", + value_enum, + default_value_t, verbatim_doc_comment )] unlock_policy: UnlockPolicy, @@ -303,11 +308,11 @@ fn devs_str_sbs_from_device( } } -fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { +fn cmd_mount_inner(opt: Cli) -> Result<()> { // Grab the udev information once let udev_info = udev_bcachefs_info()?; - let (devices, block_devices_to_mount) = if opt.dev.starts_with("UUID=") { + let (devices, sbs) = if opt.dev.starts_with("UUID=") { let uuid = opt.dev.replacen("UUID=", "", 1); devs_str_sbs_from_uuid(&udev_info, uuid)? } else if opt.dev.starts_with("OLD_BLKID_UUID=") { @@ -332,44 +337,26 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { } }; - if block_devices_to_mount.is_empty() { - Err(anyhow::anyhow!("No device found from specified parameters"))?; - } - - let key_name = CString::new(format!( - "bcachefs:{}", - block_devices_to_mount[0].sb().uuid() - )) - .unwrap(); - - // Check if the filesystem's master key is encrypted and we don't have a key - if unsafe { bcachefs::bch2_sb_is_encrypted_and_locked(block_devices_to_mount[0].sb) } - && !key::check_for_key(&key_name)? - { - // First by password_file, if available - let fallback_to_unlock_policy = if let Some(passphrase_file) = &opt.passphrase_file { - match key::read_from_passphrase_file( - &block_devices_to_mount[0], - passphrase_file.as_path(), - ) { - Ok(()) => { - // Decryption succeeded - false - } - Err(err) => { - // Decryption failed, fall back to unlock_policy - error!("Failed to decrypt using passphrase_file: {}", err); - true - } - } - } else { - // No passphrase_file specified, fall back to unlock_policy - true - }; - // If decryption by key_file was unsuccesful, prompt for passphrase (or follow key_policy) - if fallback_to_unlock_policy { - key::apply_key_unlocking_policy(&block_devices_to_mount[0], opt.unlock_policy)?; - }; + ensure!(!sbs.is_empty(), "No device(s) to mount specified"); + + let first_sb = sbs[0]; + let uuid = first_sb.sb().uuid(); + + if unsafe { bcachefs::bch2_sb_is_encrypted(first_sb.sb) } { + let _key_handle = KeyHandle::new_from_search(&uuid).or_else(|_| { + opt.passphrase_file + .map(|path| { + Passphrase::new_from_file(&first_sb, path) + .inspect_err(|e| { + error!( + "Failed to read passphrase from file, falling back to prompt: {}", + e + ) + }) + .and_then(|p| KeyHandle::new(&first_sb, &p)) + }) + .unwrap_or_else(|| opt.unlock_policy.apply(&first_sb)) + }); } if let Some(mountpoint) = opt.mountpoint { |