mirror of
https://github.com/rustic-rs/rustic.git
synced 2025-10-26 11:18:51 +00:00
Merge pull request #161 from rustic-rs/password-options
Add global options --password and --password-command
This commit is contained in:
commit
093d6d2fd4
@ -1,7 +1,7 @@
|
||||
use std::fmt::Write;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -25,25 +25,43 @@ pub fn bytes(b: u64) -> String {
|
||||
ByteSize(b).to_string_as(true)
|
||||
}
|
||||
|
||||
pub async fn get_key(be: &impl ReadBackend, password_file: Option<PathBuf>) -> Result<Key> {
|
||||
match password_file {
|
||||
None => {
|
||||
for _i in 0..MAX_PASSWORD_RETRIES {
|
||||
let pass = prompt_password("enter repository password: ")?;
|
||||
if let Ok(key) = find_key_in_backend(be, &pass, None).await {
|
||||
ve1!("password is correct");
|
||||
pub async fn get_key(
|
||||
be: &impl ReadBackend,
|
||||
password: Option<&str>,
|
||||
password_file: Option<&Path>,
|
||||
password_command: Option<&str>,
|
||||
) -> Result<Key> {
|
||||
let password = match (password, password_file, password_command) {
|
||||
(Some(pwd), _, _) => Some(pwd.to_string()),
|
||||
(_, Some(file), _) => {
|
||||
let mut file = BufReader::new(File::open(file)?);
|
||||
Some(read_password_from_bufread(&mut file)?)
|
||||
}
|
||||
(_, _, Some(command)) => {
|
||||
let mut commands: Vec<_> = command.split(' ').collect();
|
||||
let output = Command::new(commands[0])
|
||||
.args(&mut commands[1..])
|
||||
.output()?;
|
||||
|
||||
let mut pwd = BufReader::new(&*output.stdout);
|
||||
Some(read_password_from_bufread(&mut pwd)?)
|
||||
}
|
||||
(None, None, None) => None,
|
||||
};
|
||||
|
||||
for _ in 0..MAX_PASSWORD_RETRIES {
|
||||
match &password {
|
||||
// if password is given, directly return the result of find_key_in_backend and don't retry
|
||||
Some(pass) => return find_key_in_backend(be, pass, None).await,
|
||||
None => {
|
||||
// TODO: Differentiate between wrong password and other error!
|
||||
if let Ok(key) =
|
||||
find_key_in_backend(be, &prompt_password("enter repository password: ")?, None)
|
||||
.await
|
||||
{
|
||||
return Ok(key);
|
||||
}
|
||||
}
|
||||
bail!("tried too often...aborting!");
|
||||
}
|
||||
Some(file) => {
|
||||
let mut file = BufReader::new(File::open(file)?);
|
||||
let pass = read_password_from_bufread(&mut file)?;
|
||||
if let Ok(key) = find_key_in_backend(be, &pass, None).await {
|
||||
ve1!("password is correct");
|
||||
return Ok(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
bail!("incorrect password!");
|
||||
|
||||
@ -52,6 +52,15 @@ struct Opts {
|
||||
)]
|
||||
repo_hot: Option<String>,
|
||||
|
||||
/// Password of the repository - WARNING: Using --password can reveal the password in the process list!
|
||||
#[clap(
|
||||
long,
|
||||
global = true,
|
||||
env = "RUSTIC_PASSWORD",
|
||||
help_heading = "GLOBAL OPTIONS"
|
||||
)]
|
||||
password: Option<String>,
|
||||
|
||||
/// File to read the password from
|
||||
#[clap(
|
||||
short,
|
||||
@ -59,10 +68,21 @@ struct Opts {
|
||||
global = true,
|
||||
parse(from_os_str),
|
||||
env = "RUSTIC_PASSWORD_FILE",
|
||||
help_heading = "GLOBAL OPTIONS"
|
||||
help_heading = "GLOBAL OPTIONS",
|
||||
conflicts_with = "password"
|
||||
)]
|
||||
password_file: Option<PathBuf>,
|
||||
|
||||
/// Command to read the password from
|
||||
#[clap(
|
||||
long,
|
||||
global = true,
|
||||
env = "RUSTIC_PASSWORD_COMMAND",
|
||||
help_heading = "GLOBAL OPTIONS",
|
||||
conflicts_with_all = &["password", "password-file"],
|
||||
)]
|
||||
password_command: Option<String>,
|
||||
|
||||
/// Increase verbosity (can be used multiple times)
|
||||
#[clap(
|
||||
long,
|
||||
@ -202,7 +222,16 @@ pub async fn execute() -> Result<()> {
|
||||
bail!("keys from repo and repo-hot do not match. Aborting.");
|
||||
}
|
||||
}
|
||||
let key = get_key(&be, args.password_file).await?;
|
||||
|
||||
let key = get_key(
|
||||
&be,
|
||||
args.password.as_deref(),
|
||||
args.password_file.as_deref(),
|
||||
args.password_command.as_deref(),
|
||||
)
|
||||
.await?;
|
||||
ve1!("password is correct.");
|
||||
|
||||
let dbe = DecryptBackend::new(&be, key.clone());
|
||||
let config: ConfigFile = dbe.get_file(&config_ids[0]).await?;
|
||||
match (config.is_hot == Some(true), be_hot.is_some()) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user