client: xdg usage: place() vs find()

place() is used when creating a file, as it will create
intermediate directories, only use it when actually placing
a new file.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-07-08 10:42:05 +02:00
parent 3bad3e6e52
commit b65390ebc9
3 changed files with 32 additions and 23 deletions

View File

@ -1,4 +1,4 @@
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Context, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use chrono::{Local, TimeZone, DateTime}; 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<Vec<u8>, Error>) -> Result<([u8;32], DateTime<Local>), Error> { pub fn load_and_decrypt_key(
path: &std::path::Path,
passphrase: &dyn Fn() -> Result<Vec<u8>, Error>,
) -> Result<([u8;32], DateTime<Local>), 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<Vec<u8>, Error>,
) -> Result<([u8;32], DateTime<Local>), Error> {
let raw = file_get_contents(&path)?; let raw = file_get_contents(&path)?;
let data = String::from_utf8(raw)?; let data = String::from_utf8(raw)?;

View File

@ -677,13 +677,13 @@ fn keyfile_parameters(param: &Value) -> Result<(Option<PathBuf>, CryptMode), Err
Ok(match (keyfile, crypt_mode) { Ok(match (keyfile, crypt_mode) {
// no parameters: // no parameters:
(None, None) => (key::optional_default_key_path()?, CryptMode::Encrypt), (None, None) => (key::find_default_encryption_key()?, CryptMode::Encrypt),
// just --crypt-mode=none // just --crypt-mode=none
(None, Some(CryptMode::None)) => (None, CryptMode::None), (None, Some(CryptMode::None)) => (None, CryptMode::None),
// just --crypt-mode other than 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"), None => bail!("--crypt-mode without --keyfile and no default key file available"),
Some(path) => (Some(path), crypt_mode), Some(path) => (Some(path), crypt_mode),
} }

View File

@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::{bail, Error}; use anyhow::{bail, format_err, Context, Error};
use chrono::{Local, TimeZone}; use chrono::{Local, TimeZone};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use xdg::BaseDirectories; use xdg::BaseDirectories;
@ -15,6 +15,8 @@ use proxmox_backup::backup::{
}; };
use proxmox_backup::tools; use proxmox_backup::tools;
pub const DEFAULT_ENCRYPTION_KEY_FILE_NAME: &str = "encryption-key.json";
pub fn master_pubkey_path() -> Result<PathBuf, Error> { pub fn master_pubkey_path() -> Result<PathBuf, Error> {
let base = BaseDirectories::with_prefix("proxmox-backup")?; let base = BaseDirectories::with_prefix("proxmox-backup")?;
@ -24,13 +26,19 @@ pub fn master_pubkey_path() -> Result<PathBuf, Error> {
Ok(path) Ok(path)
} }
pub fn default_encryption_key_path() -> Result<PathBuf, Error> { pub fn find_default_encryption_key() -> Result<Option<PathBuf>, Error> {
let base = BaseDirectories::with_prefix("proxmox-backup")?; 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 pub fn place_default_encryption_key() -> Result<PathBuf, Error> {
let path = base.place_config_file("encryption-key.json")?; BaseDirectories::with_prefix("proxmox-backup")
.map_err(Error::from)
Ok(path) .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<Vec<u8>, Error> { pub fn get_encryption_key_password() -> Result<Vec<u8>, Error> {
@ -53,16 +61,6 @@ pub fn get_encryption_key_password() -> Result<Vec<u8>, Error> {
bail!("no password input mechanism available"); 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<Option<PathBuf>, Error> {
let path = default_encryption_key_path()?;
Ok(if path.exists() {
Some(path)
} else {
None
})
}
#[api( #[api(
default: "scrypt", default: "scrypt",
)] )]
@ -103,7 +101,7 @@ impl Default for Kdf {
fn create(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> { fn create(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> {
let path = match path { let path = match path {
Some(path) => PathBuf::from(path), Some(path) => PathBuf::from(path),
None => default_encryption_key_path()?, None => place_default_encryption_key()?,
}; };
let kdf = kdf.unwrap_or_default(); let kdf = kdf.unwrap_or_default();
@ -160,7 +158,8 @@ fn create(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> {
fn change_passphrase(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> { fn change_passphrase(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> {
let path = match path { let path = match path {
Some(path) => PathBuf::from(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(); let kdf = kdf.unwrap_or_default();