src/api2/config: check digest

This commit is contained in:
Dietmar Maurer 2020-01-15 12:27:05 +01:00
parent 347834df25
commit 002a191abf
6 changed files with 35 additions and 7 deletions

View File

@ -112,6 +112,10 @@ pub fn read_datastore(name: String) -> Result<Value, Error> {
optional: true, optional: true,
schema: datastore::DIR_NAME_SCHEMA, schema: datastore::DIR_NAME_SCHEMA,
}, },
digest: {
optional: true,
schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
},
}, },
}, },
)] )]
@ -120,12 +124,18 @@ pub fn update_datastore(
name: String, name: String,
comment: Option<String>, comment: Option<String>,
path: Option<String>, path: Option<String>,
digest: Option<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?; let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
// pass/compare digest // pass/compare digest
let (mut config, _digest) = datastore::config()?; let (mut config, expected_digest) = datastore::config()?;
if let Some(ref digest) = digest {
let digest = proxmox::tools::hex_to_digest(digest)?;
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
let mut data: datastore::DataStoreConfig = config.lookup("datastore", &name)?; let mut data: datastore::DataStoreConfig = config.lookup("datastore", &name)?;

View File

@ -118,6 +118,10 @@ pub fn read_remote(name: String) -> Result<Value, Error> {
optional: true, optional: true,
schema: remotes::REMOTE_PASSWORD_SCHEMA, schema: remotes::REMOTE_PASSWORD_SCHEMA,
}, },
digest: {
optional: true,
schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
},
}, },
}, },
)] )]
@ -128,12 +132,17 @@ pub fn update_remote(
host: Option<String>, host: Option<String>,
userid: Option<String>, userid: Option<String>,
password: Option<String>, password: Option<String>,
digest: Option<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let _lock = crate::tools::open_file_locked(remotes::REMOTES_CFG_LOCKFILE, std::time::Duration::new(10, 0))?; let _lock = crate::tools::open_file_locked(remotes::REMOTES_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
// pass/compare digest let (mut config, expected_digest) = remotes::config()?;
let (mut config, _digest) = remotes::config()?;
if let Some(ref digest) = digest {
let digest = proxmox::tools::hex_to_digest(digest)?;
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
let mut data: remotes::Remote = config.lookup("remote", &name)?; let mut data: remotes::Remote = config.lookup("remote", &name)?;

View File

@ -118,7 +118,7 @@ pub const ROUTER: Router = Router::new()
&ObjectSchema::new( &ObjectSchema::new(
"Returns DNS server IPs and sreach domain.", "Returns DNS server IPs and sreach domain.",
&sorted!([ &sorted!([
("digest", false, &PVE_CONFIG_DIGEST_SCHEMA), ("digest", false, &PROXMOX_CONFIG_DIGEST_SCHEMA),
("search", true, &SEARCH_DOMAIN_SCHEMA), ("search", true, &SEARCH_DOMAIN_SCHEMA),
("dns1", true, &FIRST_DNS_SERVER_SCHEMA), ("dns1", true, &FIRST_DNS_SERVER_SCHEMA),
("dns2", true, &SECOND_DNS_SERVER_SCHEMA), ("dns2", true, &SECOND_DNS_SERVER_SCHEMA),
@ -138,7 +138,7 @@ pub const ROUTER: Router = Router::new()
("dns1", true, &FIRST_DNS_SERVER_SCHEMA), ("dns1", true, &FIRST_DNS_SERVER_SCHEMA),
("dns2", true, &SECOND_DNS_SERVER_SCHEMA), ("dns2", true, &SECOND_DNS_SERVER_SCHEMA),
("dns3", true, &THIRD_DNS_SERVER_SCHEMA), ("dns3", true, &THIRD_DNS_SERVER_SCHEMA),
("digest", true, &PVE_CONFIG_DIGEST_SCHEMA), ("digest", true, &PROXMOX_CONFIG_DIGEST_SCHEMA),
]), ]),
) )
).protected(true) ).protected(true)

View File

@ -85,7 +85,7 @@ pub const PASSWORD_FORMAT: ApiStringFormat =
ApiStringFormat::Pattern(&PASSWORD_REGEX); ApiStringFormat::Pattern(&PASSWORD_REGEX);
pub const PVE_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(r#"\ pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(r#"\
Prevent changes if current configuration file has different SHA256 digest. Prevent changes if current configuration file has different SHA256 digest.
This can be used to prevent concurrent modifications. This can be used to prevent concurrent modifications.
"# "#

View File

@ -336,7 +336,6 @@ impl SectionConfig {
} }
} }
// cargo test test_section_config1 -- --nocapture // cargo test test_section_config1 -- --nocapture
#[test] #[test]
fn test_section_config1() { fn test_section_config1() {

View File

@ -428,6 +428,16 @@ pub fn join(data: &Vec<String>, sep: char) -> String {
list list
} }
/// Detect modified configuration files
///
/// This function fails with a resonable error message if checksums do not match.
pub fn detect_modified_configuration_file(digest1: &[u8;32], digest2: &[u8;32]) -> Result<(), Error> {
if digest1 != digest2 {
bail!("detected modified configuration - file changed by other user? Try again.");
}
Ok(())
}
/// normalize uri path /// normalize uri path
/// ///
/// Do not allow ".", "..", or hidden files ".XXXX" /// Do not allow ".", "..", or hidden files ".XXXX"