diff --git a/src/backup/key_derivation.rs b/src/backup/key_derivation.rs index 37d4688b..7dd23e67 100644 --- a/src/backup/key_derivation.rs +++ b/src/backup/key_derivation.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, format_err, Error}; +use anyhow::{bail, format_err, Context, Error}; use serde::{Deserialize, Serialize}; use chrono::{Local, TimeZone, DateTime}; @@ -146,8 +146,18 @@ pub fn encrypt_key_with_passphrase( }) } -pub fn load_and_decrypt_key(path: &std::path::Path, passphrase: &dyn Fn() -> Result, Error>) -> Result<([u8;32], DateTime), Error> { +pub fn load_and_decrypt_key( + path: &std::path::Path, + passphrase: &dyn Fn() -> Result, Error>, +) -> Result<([u8;32], DateTime), Error> { + do_load_and_decrypt_key(path, passphrase) + .with_context(|| format!("failed to load decryption key from {:?}", path)) +} +fn do_load_and_decrypt_key( + path: &std::path::Path, + passphrase: &dyn Fn() -> Result, Error>, +) -> Result<([u8;32], DateTime), Error> { let raw = file_get_contents(&path)?; let data = String::from_utf8(raw)?; diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index 30dba8cd..7bd82e78 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -677,13 +677,13 @@ fn keyfile_parameters(param: &Value) -> Result<(Option, CryptMode), Err Ok(match (keyfile, crypt_mode) { // no parameters: - (None, None) => (key::optional_default_key_path()?, CryptMode::Encrypt), + (None, None) => (key::find_default_encryption_key()?, CryptMode::Encrypt), // just --crypt-mode=none (None, Some(CryptMode::None)) => (None, CryptMode::None), // just --crypt-mode other than none - (None, Some(crypt_mode)) => match key::optional_default_key_path()? { + (None, Some(crypt_mode)) => match key::find_default_encryption_key()? { None => bail!("--crypt-mode without --keyfile and no default key file available"), Some(path) => (Some(path), crypt_mode), } diff --git a/src/bin/proxmox_backup_client/key.rs b/src/bin/proxmox_backup_client/key.rs index 95487dfa..05d0a28d 100644 --- a/src/bin/proxmox_backup_client/key.rs +++ b/src/bin/proxmox_backup_client/key.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use anyhow::{bail, Error}; +use anyhow::{bail, format_err, Context, Error}; use chrono::{Local, TimeZone}; use serde::{Deserialize, Serialize}; use xdg::BaseDirectories; @@ -15,6 +15,8 @@ use proxmox_backup::backup::{ }; use proxmox_backup::tools; +pub const DEFAULT_ENCRYPTION_KEY_FILE_NAME: &str = "encryption-key.json"; + pub fn master_pubkey_path() -> Result { let base = BaseDirectories::with_prefix("proxmox-backup")?; @@ -24,13 +26,19 @@ pub fn master_pubkey_path() -> Result { Ok(path) } -pub fn default_encryption_key_path() -> Result { - let base = BaseDirectories::with_prefix("proxmox-backup")?; +pub fn find_default_encryption_key() -> Result, Error> { + BaseDirectories::with_prefix("proxmox-backup") + .map(|base| base.find_config_file(DEFAULT_ENCRYPTION_KEY_FILE_NAME)) + .with_context(|| "error searching for default encryption key file") +} - // usually $HOME/.config/proxmox-backup/encryption-key.json - let path = base.place_config_file("encryption-key.json")?; - - Ok(path) +pub fn place_default_encryption_key() -> Result { + BaseDirectories::with_prefix("proxmox-backup") + .map_err(Error::from) + .and_then(|base| { + base.place_config_file(DEFAULT_ENCRYPTION_KEY_FILE_NAME).map_err(Error::from) + }) + .with_context(|| "failed to place default encryption key file in xdg home") } pub fn get_encryption_key_password() -> Result, Error> { @@ -53,16 +61,6 @@ pub fn get_encryption_key_password() -> Result, Error> { bail!("no password input mechanism available"); } -/// Convenience helper to get the default key file path only if it exists. -pub fn optional_default_key_path() -> Result, Error> { - let path = default_encryption_key_path()?; - Ok(if path.exists() { - Some(path) - } else { - None - }) -} - #[api( default: "scrypt", )] @@ -103,7 +101,7 @@ impl Default for Kdf { fn create(kdf: Option, path: Option) -> Result<(), Error> { let path = match path { Some(path) => PathBuf::from(path), - None => default_encryption_key_path()?, + None => place_default_encryption_key()?, }; let kdf = kdf.unwrap_or_default(); @@ -160,7 +158,8 @@ fn create(kdf: Option, path: Option) -> Result<(), Error> { fn change_passphrase(kdf: Option, path: Option) -> Result<(), Error> { let path = match path { Some(path) => PathBuf::from(path), - None => default_encryption_key_path()?, + None => find_default_encryption_key()? + .ok_or_else(|| format_err!("no encryption file provided and no default file found"))?, }; let kdf = kdf.unwrap_or_default();