Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add passphrase_file to mount options (refactored) #269

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bcachefs.8
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,12 @@ is the path where the filesystem should be mounted. If not set, then the filesys
but all steps preceding mounting the filesystem (e.g. asking for passphrase) will still be performed.
.Pp the options are as follows:
.Bl -tag -width Ds
.It Fl f , Fl -passphrase-file Ns = Ns Ar passphrase_file
Path to passphrase/key file
.sp
Precedes key_location/unlock_policy: if the filesystem can be decrypted by the specified passphrase
file, it is decrypted. (i.e. Regardless if "fail" is specified for key_location/unlock_policy.)
.El
.It Fl o Ar options
Mount options provided as a comma-separated list. See user guide for complete list.
.Bl -tag -width Ds -compact
Expand All @@ -393,6 +399,8 @@ Run fsck during mount
Fix errors without asking during fsck
.It Cm read_only
Mount in read only mode
.It Cm passphrase_file Ns = Ns Ar passphrase_file
Path to passphrase/key file
.It Cm version_upgrade
.El
.It Fl k , Fl -key-location Ns = Ns ( Cm fail | wait | ask )
Expand All @@ -408,6 +416,7 @@ prompt the user for password.
.El
.It Fl c , Fl -colorize Ns = Ns ( Cm true | false )
Force color on/off. Default: auto-detect TTY
.El
.It Fl v
Be verbose. Can be specified more than once.
.El
Expand Down
72 changes: 60 additions & 12 deletions src/commands/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,18 @@ fn devs_str_sbs_from_device(
}
}

fn parse_passphrase_file_from_mount_options(options: impl AsRef<str>) -> Option<PathBuf> {
options
.as_ref()
.split(',')
.fold(None, |_, next| match next {
x if x.starts_with("passphrase_file") => {
Some(PathBuf::from(x.split('=').nth(1).unwrap().to_string()))
}
_ => None,
})
}

fn cmd_mount_inner(opt: Cli) -> Result<()> {
// Grab the udev information once
let udev_info = udev_bcachefs_info()?;
Expand Down Expand Up @@ -338,18 +350,12 @@ fn cmd_mount_inner(opt: Cli) -> Result<()> {

if unsafe { bcachefs::bch2_sb_is_encrypted(first_sb.sb) } {
let _key_handle: KeyHandle = KeyHandle::new_from_search(&uuid).or_else(|_| {
opt.passphrase_file
.and_then(|path| match Passphrase::new_from_file(&first_sb, path) {
Ok(p) => Some(KeyHandle::new(&first_sb, &p)),
Err(e) => {
error!(
"Failed to read passphrase from file, falling back to prompt: {}",
e
);
None
}
})
.unwrap_or_else(|| opt.unlock_policy.apply(&first_sb))
attempt_unlock_master_key(
opt.passphrase_file,
&opt.options,
opt.unlock_policy,
first_sb,
)
})?;
}

Expand All @@ -373,6 +379,48 @@ fn cmd_mount_inner(opt: Cli) -> Result<()> {
}
}

fn attempt_unlock_master_key(
passphrase_file: Option<PathBuf>,
options: &String,
unlock_policy: UnlockPolicy,
first_sb: bch_sb_handle,
) -> Result<KeyHandle, anyhow::Error> {
// Unlock by key_file CLI option
passphrase_file
.and_then(
|path| match Passphrase::new_from_file(&first_sb, path.clone()) {
Ok(p) => Some(KeyHandle::new(&first_sb, &p)),
Err(e) => {
error!(
"Failed to read passphrase from path \"{}\". Error: {}",
path.display(),
e
);
None
}
},
)
// Unlock by key_file mount option
.unwrap_or_else(|| {
parse_passphrase_file_from_mount_options(options)
.and_then(|path: PathBuf| {
match Passphrase::new_from_file(&first_sb, path.clone()) {
Ok(p) => Some(KeyHandle::new(&first_sb, &p)),
Err(e) => {
error!(
"Failed to read passphrase from path \"{}\". Error: {}",
path.display(),
e
);
None
}
}
})
// Unlock by unlock policy
.unwrap_or_else(|| unlock_policy.apply(&first_sb))
})
}

pub fn mount(mut argv: Vec<String>, symlink_cmd: Option<&str>) -> i32 {
// If the bcachefs tool is being called as "bcachefs mount dev ..." (as opposed to via a
// symlink like "/usr/sbin/mount.bcachefs dev ...", then we need to pop the 0th argument
Expand Down