src/bin/proxmox-backup-client.rs - key API: pass kdf parameter
Allow to store keys without password.
This commit is contained in:
parent
9b06db4563
commit
181f097af9
@ -57,13 +57,44 @@ impl KeyDerivationConfig {
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct KeyConfig {
|
||||
kdf: Option<KeyDerivationConfig>,
|
||||
pub kdf: Option<KeyDerivationConfig>,
|
||||
#[serde(with = "proxmox::tools::serde::date_time_as_rfc3339")]
|
||||
created: DateTime<Local>,
|
||||
pub created: DateTime<Local>,
|
||||
#[serde(with = "proxmox::tools::serde::bytes_as_base64")]
|
||||
data: Vec<u8>,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
pub fn store_key_config(
|
||||
path: &std::path::Path,
|
||||
replace: bool,
|
||||
key_config: KeyConfig,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let data = serde_json::to_string(&key_config)?;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
try_block!({
|
||||
if replace {
|
||||
let mode = nix::sys::stat::Mode::S_IRUSR | nix::sys::stat::Mode::S_IWUSR;
|
||||
crate::tools::file_set_contents(&path, data.as_bytes(), Some(mode))?;
|
||||
} else {
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.mode(0o0600)
|
||||
.create_new(true)
|
||||
.open(&path)?;
|
||||
|
||||
file.write_all(data.as_bytes())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}).map_err(|err: Error| format_err!("Unable to create file {:?} - {}", path, err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn store_key_with_passphrase(
|
||||
path: &std::path::Path,
|
||||
@ -104,37 +135,11 @@ pub fn store_key_with_passphrase(
|
||||
|
||||
let created = Local.timestamp(Local::now().timestamp(), 0);
|
||||
|
||||
|
||||
let key_config = KeyConfig {
|
||||
store_key_config(path, replace, KeyConfig {
|
||||
kdf: Some(kdf),
|
||||
created,
|
||||
data: enc_data,
|
||||
};
|
||||
|
||||
let data = serde_json::to_string(&key_config)?;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
try_block!({
|
||||
if replace {
|
||||
let mode = nix::sys::stat::Mode::S_IRUSR | nix::sys::stat::Mode::S_IWUSR;
|
||||
crate::tools::file_set_contents(&path, data.as_bytes(), Some(mode))?;
|
||||
} else {
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.mode(0o0600)
|
||||
.create_new(true)
|
||||
.open(&path)?;
|
||||
|
||||
file.write_all(data.as_bytes())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}).map_err(|err: Error| format_err!("Unable to create file {:?} - {}", path, err))?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_and_decrtypt_key(path: &std::path::Path, passphrase: fn() -> Result<Vec<u8>, Error>) -> Result<Vec<u8>, Error> {
|
||||
|
@ -812,18 +812,34 @@ fn key_create(
|
||||
let path = tools::required_string_param(¶m, "path")?;
|
||||
let path = PathBuf::from(path);
|
||||
|
||||
// always read from tty
|
||||
let kdf = param["kdf"].as_str().unwrap_or("scrypt");
|
||||
|
||||
let key = proxmox::sys::linux::random_data(32)?;
|
||||
|
||||
if kdf == "scrypt" {
|
||||
// always read passphrase from tty
|
||||
if !crate::tools::tty::stdin_isatty() {
|
||||
bail!("unable to read passphrase - no tty");
|
||||
}
|
||||
|
||||
let password = crate::tools::tty::read_password("Encryption Key Password: ")?;
|
||||
|
||||
let key = proxmox::sys::linux::random_data(32)?;
|
||||
|
||||
store_key_with_passphrase(&path, &key, &password, false)?;
|
||||
|
||||
Ok(Value::Null)
|
||||
} else if kdf == "none" {
|
||||
let created = Local.timestamp(Local::now().timestamp(), 0);
|
||||
|
||||
store_key_config(&path, false, KeyConfig {
|
||||
kdf: None,
|
||||
created,
|
||||
data: key,
|
||||
})?;
|
||||
|
||||
Ok(Value::Null)
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -836,6 +852,8 @@ fn key_change_passphrase(
|
||||
let path = tools::required_string_param(¶m, "path")?;
|
||||
let path = PathBuf::from(path);
|
||||
|
||||
let kdf = param["kdf"].as_str().unwrap_or("scrypt");
|
||||
|
||||
// we need a TTY to query the new password
|
||||
if !crate::tools::tty::stdin_isatty() {
|
||||
bail!("unable to change passphrase - no tty");
|
||||
@ -843,6 +861,8 @@ fn key_change_passphrase(
|
||||
|
||||
let key = load_and_decrtypt_key(&path, get_encryption_key_password)?;
|
||||
|
||||
if kdf == "scrypt" {
|
||||
|
||||
let new_pw = String::from_utf8(crate::tools::tty::read_password("New Password: ")?)?;
|
||||
let verify_pw = String::from_utf8(crate::tools::tty::read_password("Verify Password: ")?)?;
|
||||
|
||||
@ -857,16 +877,38 @@ fn key_change_passphrase(
|
||||
store_key_with_passphrase(&path, &key, new_pw.as_bytes(), true)?;
|
||||
|
||||
Ok(Value::Null)
|
||||
} else if kdf == "none" {
|
||||
// fixme: keep original creation time, add modified timestamp ??
|
||||
let created = Local.timestamp(Local::now().timestamp(), 0);
|
||||
|
||||
store_key_config(&path, true, KeyConfig {
|
||||
kdf: None,
|
||||
created,
|
||||
data: key,
|
||||
})?;
|
||||
|
||||
Ok(Value::Null)
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
fn key_mgmt_cli() -> CliCommandMap {
|
||||
|
||||
let kdf_schema: Arc<Schema> = Arc::new(
|
||||
StringSchema::new("Key derivation function. Choose 'none' to store the key unecrypted.")
|
||||
.format(Arc::new(ApiStringFormat::Enum(&["scrypt", "none"])))
|
||||
.default("scrypt")
|
||||
.into()
|
||||
);
|
||||
|
||||
// fixme: change-passphrase, import, export, list
|
||||
let key_create_cmd_def = CliCommand::new(
|
||||
ApiMethod::new(
|
||||
key_create,
|
||||
ObjectSchema::new("Create a new encryption key.")
|
||||
.required("path", StringSchema::new("File system path."))
|
||||
.optional("kdf", kdf_schema.clone())
|
||||
))
|
||||
.arg_param(vec!["path"])
|
||||
.completion_cb("path", tools::complete_file_name);
|
||||
@ -876,6 +918,7 @@ fn key_mgmt_cli() -> CliCommandMap {
|
||||
key_change_passphrase,
|
||||
ObjectSchema::new("Change the passphrase required to decrypt the key.")
|
||||
.required("path", StringSchema::new("File system path."))
|
||||
.optional("kdf", kdf_schema.clone())
|
||||
))
|
||||
.arg_param(vec!["path"])
|
||||
.completion_cb("path", tools::complete_file_name);
|
||||
|
Loading…
Reference in New Issue
Block a user