api: datastore: unify access checks

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Fabian Grünbichler 2022-05-09 17:14:32 +02:00 committed by Thomas Lamprecht
parent 133d718fe4
commit a724f5fd47
1 changed files with 103 additions and 168 deletions

View File

@ -77,30 +77,6 @@ fn get_group_note_path(
note_path note_path
} }
fn check_priv_or_backup_owner(
// FIXME: We could probably switch to pbs-datastore::BackupGroup here to replace all of store,
// ns and group.
store: &DataStore,
ns: &BackupNamespace,
group: &pbs_api_types::BackupGroup,
auth_id: &Authid,
required_privs: u64,
) -> Result<(), Error> {
let user_info = CachedUserInfo::new()?;
let privs = if ns.is_root() {
user_info.lookup_privs(auth_id, &["datastore", store.name()])
} else {
user_info.lookup_privs(auth_id, &["datastore", store.name(), &ns.to_string()])
};
if privs & required_privs == 0 {
let owner = store.get_owner(ns, group)?;
check_backup_owner(&owner, auth_id)?;
}
Ok(())
}
// TODO: move somewhere we can reuse it from (namespace has its own copy atm.) // TODO: move somewhere we can reuse it from (namespace has its own copy atm.)
fn get_ns_privs(store: &str, ns: &BackupNamespace, auth_id: &Authid) -> Result<u64, Error> { fn get_ns_privs(store: &str, ns: &BackupNamespace, auth_id: &Authid) -> Result<u64, Error> {
let user_info = CachedUserInfo::new()?; let user_info = CachedUserInfo::new()?;
@ -112,7 +88,7 @@ fn get_ns_privs(store: &str, ns: &BackupNamespace, auth_id: &Authid) -> Result<u
}) })
} }
// for asserting a base priv existence but also returning the prics for more fine grained checking // for asserting a base priv existence but also returning the privs for more fine grained checking
// locally // locally
fn get_ns_privs_checked( fn get_ns_privs_checked(
store: &str, store: &str,
@ -303,7 +279,7 @@ pub fn delete_group(
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -312,13 +288,10 @@ pub fn delete_group(
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
check_priv_or_backup_owner( if user_privs & PRIV_DATASTORE_MODIFY == 0 {
&datastore, let owner = datastore.get_owner(&backup_ns, &group)?;
&backup_ns, check_backup_owner(&owner, &auth_id)?;
&group, }
&auth_id,
PRIV_DATASTORE_MODIFY,
)?;
if !datastore.remove_backup_group(&backup_ns, &group)? { if !datastore.remove_backup_group(&backup_ns, &group)? {
bail!("group only partially deleted due to protected snapshots"); bail!("group only partially deleted due to protected snapshots");
@ -360,7 +333,7 @@ pub fn list_snapshot_files(
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -369,15 +342,12 @@ pub fn list_snapshot_files(
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
let snapshot = datastore.backup_dir(backup_ns, backup_dir)?; if user_privs & (PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_READ) == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
check_priv_or_backup_owner( let snapshot = datastore.backup_dir(backup_ns, backup_dir)?;
&datastore,
snapshot.backup_ns(),
snapshot.as_ref(),
&auth_id,
PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_READ,
)?;
let info = BackupInfo::new(snapshot)?; let info = BackupInfo::new(snapshot)?;
@ -418,7 +388,7 @@ pub fn delete_snapshot(
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -426,15 +396,13 @@ pub fn delete_snapshot(
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
let snapshot = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner( if user_privs & PRIV_DATASTORE_MODIFY == 0 {
&datastore, let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
snapshot.backup_ns(), check_backup_owner(&owner, &auth_id)?;
snapshot.as_ref(), }
&auth_id,
PRIV_DATASTORE_MODIFY, let snapshot = datastore.backup_dir(backup_ns, backup_dir)?;
)?;
snapshot.destroy(false)?; snapshot.destroy(false)?;
@ -770,12 +738,14 @@ pub fn verify(
) -> Result<Value, Error> { ) -> Result<Value, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_VERIFY | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_VERIFY | PRIV_DATASTORE_BACKUP,
)?; )?;
let owner_check_required = user_privs & PRIV_DATASTORE_VERIFY == 0;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
let ignore_verified = ignore_verified.unwrap_or(true); let ignore_verified = ignore_verified.unwrap_or(true);
@ -800,13 +770,10 @@ pub fn verify(
let dir = let dir =
datastore.backup_dir_from_parts(backup_ns, backup_type, backup_id, backup_time)?; datastore.backup_dir_from_parts(backup_ns, backup_type, backup_id, backup_time)?;
check_priv_or_backup_owner( if owner_check_required {
&datastore, let owner = datastore.get_owner(dir.backup_ns(), dir.as_ref())?;
dir.backup_ns(), check_backup_owner(&owner, &auth_id)?;
dir.as_ref(), }
&auth_id,
PRIV_DATASTORE_VERIFY,
)?;
backup_dir = Some(dir); backup_dir = Some(dir);
worker_type = "verify_snapshot"; worker_type = "verify_snapshot";
@ -821,13 +788,10 @@ pub fn verify(
); );
let group = pbs_api_types::BackupGroup::from((backup_type, backup_id)); let group = pbs_api_types::BackupGroup::from((backup_type, backup_id));
check_priv_or_backup_owner( if owner_check_required {
&datastore, let owner = datastore.get_owner(&backup_ns, &group)?;
&backup_ns, check_backup_owner(&owner, &auth_id)?;
&group, }
&auth_id,
PRIV_DATASTORE_VERIFY,
)?;
backup_group = Some(datastore.backup_group(backup_ns, group)); backup_group = Some(datastore.backup_group(backup_ns, group));
worker_type = "verify_group"; worker_type = "verify_group";
@ -868,14 +832,14 @@ pub fn verify(
)?; )?;
failed_dirs failed_dirs
} else { } else {
let privs = CachedUserInfo::new()?.lookup_privs(&auth_id, &["datastore", &store]); let owner = if owner_check_required {
let owner = if privs & PRIV_DATASTORE_VERIFY == 0 {
Some(auth_id) Some(auth_id)
} else { } else {
None None
}; };
// FIXME namespace missing here..
verify_all_backups( verify_all_backups(
&verify_worker, &verify_worker,
worker.upid(), worker.upid(),
@ -944,7 +908,7 @@ pub fn prune(
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -953,15 +917,12 @@ pub fn prune(
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
let group = datastore.backup_group(backup_ns, group); if user_privs & PRIV_DATASTORE_MODIFY == 0 {
let owner = datastore.get_owner(&backup_ns, &group)?;
check_backup_owner(&owner, &auth_id)?;
}
check_priv_or_backup_owner( let group = datastore.backup_group(backup_ns, group);
&datastore,
group.backup_ns(),
group.as_ref(),
&auth_id,
PRIV_DATASTORE_MODIFY,
)?;
let worker_id = format!("{}:{}", store, group); let worker_id = format!("{}:{}", store, group);
@ -1292,25 +1253,22 @@ pub fn download_file(
let store = required_string_param(&param, "store")?; let store = required_string_param(&param, "store")?;
let backup_ns = optional_ns_param(&param)?; let backup_ns = optional_ns_param(&param)?;
let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?; let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?;
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(store, Some(Operation::Read))?;
if user_privs & PRIV_DATASTORE_READ == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
let file_name = required_string_param(&param, "file-name")?.to_owned(); let file_name = required_string_param(&param, "file-name")?.to_owned();
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_READ,
)?;
println!( println!(
"Download {} from {} ({}/{})", "Download {} from {} ({}/{})",
file_name, store, backup_dir, file_name file_name, store, backup_dir, file_name
@ -1378,25 +1336,23 @@ pub fn download_file_decoded(
let store = required_string_param(&param, "store")?; let store = required_string_param(&param, "store")?;
let backup_ns = optional_ns_param(&param)?; let backup_ns = optional_ns_param(&param)?;
let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?; let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?;
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(store, Some(Operation::Read))?;
if user_privs & PRIV_DATASTORE_READ == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
let file_name = required_string_param(&param, "file-name")?.to_owned(); let file_name = required_string_param(&param, "file-name")?.to_owned();
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_READ,
)?;
let (manifest, files) = read_backup_index(&datastore, &backup_dir)?; let (manifest, files) = read_backup_index(&datastore, &backup_dir)?;
for file in files { for file in files {
if file.filename == file_name && file.crypt_mode == Some(CryptMode::Encrypt) { if file.filename == file_name && file.crypt_mode == Some(CryptMode::Encrypt) {
@ -1581,7 +1537,7 @@ pub fn catalog(
) -> Result<Vec<ArchiveEntry>, Error> { ) -> Result<Vec<ArchiveEntry>, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -1589,15 +1545,13 @@ pub fn catalog(
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner( if user_privs & PRIV_DATASTORE_READ == 0 {
&datastore, let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
backup_dir.backup_ns(), check_backup_owner(&owner, &auth_id)?;
backup_dir.as_ref(), }
&auth_id,
PRIV_DATASTORE_READ, let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
)?;
let file_name = CATALOG_NAME; let file_name = CATALOG_NAME;
@ -1667,27 +1621,25 @@ pub fn pxar_file_download(
let store = required_string_param(&param, "store")?; let store = required_string_param(&param, "store")?;
let backup_ns = optional_ns_param(&param)?; let backup_ns = optional_ns_param(&param)?;
let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?; let backup_dir: pbs_api_types::BackupDir = Deserialize::deserialize(&param)?;
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_READ | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
if user_privs & PRIV_DATASTORE_READ == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
let filepath = required_string_param(&param, "filepath")?.to_owned(); let filepath = required_string_param(&param, "filepath")?.to_owned();
let tar = param["tar"].as_bool().unwrap_or(false); let tar = param["tar"].as_bool().unwrap_or(false);
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_READ,
)?;
let mut components = base64::decode(&filepath)?; let mut components = base64::decode(&filepath)?;
if !components.is_empty() && components[0] == b'/' { if !components.is_empty() && components[0] == b'/' {
components.remove(0); components.remove(0);
@ -1878,7 +1830,7 @@ pub fn get_group_notes(
) -> Result<String, Error> { ) -> Result<String, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
@ -1886,13 +1838,10 @@ pub fn get_group_notes(
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
check_priv_or_backup_owner( if user_privs & PRIV_DATASTORE_AUDIT == 0 {
&datastore, let owner = datastore.get_owner(&backup_ns, &backup_group)?;
&backup_ns, check_backup_owner(&owner, &auth_id)?;
&backup_group, }
&auth_id,
PRIV_DATASTORE_AUDIT,
)?;
let note_path = get_group_note_path(&datastore, &backup_ns, &backup_group); let note_path = get_group_note_path(&datastore, &backup_ns, &backup_group);
Ok(file_read_optional_string(note_path)?.unwrap_or_else(|| "".to_owned())) Ok(file_read_optional_string(note_path)?.unwrap_or_else(|| "".to_owned()))
@ -1931,21 +1880,17 @@ pub fn set_group_notes(
) -> Result<(), Error> { ) -> Result<(), Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
if user_privs & PRIV_DATASTORE_MODIFY == 0 {
check_priv_or_backup_owner( let owner = datastore.get_owner(&backup_ns, &backup_group)?;
&datastore, check_backup_owner(&owner, &auth_id)?;
&backup_ns, }
&backup_group,
&auth_id,
PRIV_DATASTORE_MODIFY,
)?;
let note_path = get_group_note_path(&datastore, &backup_ns, &backup_group); let note_path = get_group_note_path(&datastore, &backup_ns, &backup_group);
replace_file(note_path, notes.as_bytes(), CreateOptions::new(), false)?; replace_file(note_path, notes.as_bytes(), CreateOptions::new(), false)?;
@ -1982,24 +1927,20 @@ pub fn get_notes(
) -> Result<String, Error> { ) -> Result<String, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
if user_privs & PRIV_DATASTORE_AUDIT == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_AUDIT,
)?;
let (manifest, _) = backup_dir.load_manifest()?; let (manifest, _) = backup_dir.load_manifest()?;
let notes = manifest.unprotected["notes"].as_str().unwrap_or(""); let notes = manifest.unprotected["notes"].as_str().unwrap_or("");
@ -2040,24 +1981,20 @@ pub fn set_notes(
) -> Result<(), Error> { ) -> Result<(), Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
if user_privs & PRIV_DATASTORE_MODIFY == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_MODIFY,
)?;
backup_dir backup_dir
.update_manifest(|manifest| { .update_manifest(|manifest| {
manifest.unprotected["notes"] = notes.into(); manifest.unprotected["notes"] = notes.into();
@ -2096,24 +2033,20 @@ pub fn get_protection(
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Read))?;
if user_privs & PRIV_DATASTORE_AUDIT == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_AUDIT,
)?;
Ok(backup_dir.is_protected()) Ok(backup_dir.is_protected())
} }
@ -2150,24 +2083,20 @@ pub fn set_protection(
) -> Result<(), Error> { ) -> Result<(), Error> {
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
get_ns_privs_checked( let user_privs = get_ns_privs_checked(
&store, &store,
&backup_ns, &backup_ns,
&auth_id, &auth_id,
PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP,
)?; )?;
let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?; let datastore = DataStore::lookup_datastore(&store, Some(Operation::Write))?;
if user_privs & PRIV_DATASTORE_MODIFY == 0 {
let owner = datastore.get_owner(&backup_ns, &backup_dir.group)?;
check_backup_owner(&owner, &auth_id)?;
}
let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?; let backup_dir = datastore.backup_dir(backup_ns, backup_dir)?;
check_priv_or_backup_owner(
&datastore,
backup_dir.backup_ns(),
backup_dir.as_ref(),
&auth_id,
PRIV_DATASTORE_MODIFY,
)?;
datastore.update_protection(&backup_dir, protected) datastore.update_protection(&backup_dir, protected)
} }
@ -2206,7 +2135,13 @@ pub fn set_backup_owner(
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
let backup_ns = backup_ns.unwrap_or_default(); let backup_ns = backup_ns.unwrap_or_default();
let privs = get_ns_privs(&store, &backup_ns, &auth_id)?;
let privs = get_ns_privs_checked(
&store,
&backup_ns,
&auth_id,
PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP,
)?;
let backup_group = datastore.backup_group(backup_ns, backup_group); let backup_group = datastore.backup_group(backup_ns, backup_group);
let allowed = if (privs & PRIV_DATASTORE_MODIFY) != 0 { let allowed = if (privs & PRIV_DATASTORE_MODIFY) != 0 {