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 (recreated) #266

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
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
48 changes: 33 additions & 15 deletions src/commands/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,16 @@ 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) -> anyhow::Result<()> {
// Grab the udev information once
let udev_info = udev_bcachefs_info()?;
Expand Down Expand Up @@ -361,21 +371,15 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
&& !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
}
}
let fallback_to_unlock_policy = if let Some(passphrase_file) = opt.passphrase_file {
// Unlock by passphrase_file specified by cli
debug!("Attempting to unlock the master key with the passphrase file specified by cli");
attempt_unlock_master_key_with_passphrase_file(&block_devices_to_mount[0], passphrase_file)
} else if let Some(passphrase_file) = parse_passphrase_file_from_mount_options(&opt.options) {
// Unlock by passphrase_file specified by mount options
debug!("Attempting to unlock the master key with the passphrase_file specified in the mount options");
attempt_unlock_master_key_with_passphrase_file(&block_devices_to_mount[0], passphrase_file)

} else {
// No passphrase_file specified, fall back to unlock_policy
true
Expand Down Expand Up @@ -405,6 +409,20 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
Ok(())
}

fn attempt_unlock_master_key_with_passphrase_file(block_device: &bch_sb_handle, passphrase_file: PathBuf) -> bool {
match key::read_from_passphrase_file(block_device, 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
}
}
}

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