Merge branch 'master' of ssh://proxdev.maurer-it.com/rust/proxmox-backup
This commit is contained in:
@ -74,12 +74,14 @@ pub const ROLE_ADMIN: u64 = std::u64::MAX;
|
||||
pub const ROLE_NO_ACCESS: u64 = 0;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Audit can view configuration and status information, but not modify it.
|
||||
pub const ROLE_AUDIT: u64 = 0
|
||||
| PRIV_SYS_AUDIT
|
||||
| PRIV_DATASTORE_AUDIT;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Datastore.Admin can do anything on the datastore.
|
||||
pub const ROLE_DATASTORE_ADMIN: u64 = 0
|
||||
| PRIV_DATASTORE_AUDIT
|
||||
@ -90,6 +92,7 @@ pub const ROLE_DATASTORE_ADMIN: u64 = 0
|
||||
| PRIV_DATASTORE_PRUNE;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Datastore.Reader can read/verify datastore content and do restore
|
||||
pub const ROLE_DATASTORE_READER: u64 = 0
|
||||
| PRIV_DATASTORE_AUDIT
|
||||
@ -97,27 +100,32 @@ pub const ROLE_DATASTORE_READER: u64 = 0
|
||||
| PRIV_DATASTORE_READ;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Datastore.Backup can do backup and restore, but no prune.
|
||||
pub const ROLE_DATASTORE_BACKUP: u64 = 0
|
||||
| PRIV_DATASTORE_BACKUP;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Datastore.PowerUser can do backup, restore, and prune.
|
||||
pub const ROLE_DATASTORE_POWERUSER: u64 = 0
|
||||
| PRIV_DATASTORE_PRUNE
|
||||
| PRIV_DATASTORE_BACKUP;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Datastore.Audit can audit the datastore.
|
||||
pub const ROLE_DATASTORE_AUDIT: u64 = 0
|
||||
| PRIV_DATASTORE_AUDIT;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Remote.Audit can audit the remote
|
||||
pub const ROLE_REMOTE_AUDIT: u64 = 0
|
||||
| PRIV_REMOTE_AUDIT;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Remote.Admin can do anything on the remote.
|
||||
pub const ROLE_REMOTE_ADMIN: u64 = 0
|
||||
| PRIV_REMOTE_AUDIT
|
||||
@ -125,6 +133,7 @@ pub const ROLE_REMOTE_ADMIN: u64 = 0
|
||||
| PRIV_REMOTE_READ;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::identity_op)]
|
||||
/// Remote.SyncOperator can do read and prune on the remote.
|
||||
pub const ROLE_REMOTE_SYNC_OPERATOR: u64 = 0
|
||||
| PRIV_REMOTE_AUDIT
|
||||
@ -363,6 +372,7 @@ impl AclTreeNode {
|
||||
fn extract_group_roles(&self, _user: &Userid, leaf: bool) -> HashMap<String, bool> {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
#[allow(clippy::for_kv_map)]
|
||||
for (_group, roles) in &self.groups {
|
||||
let is_member = false; // fixme: check if user is member of the group
|
||||
if !is_member {
|
||||
@ -402,7 +412,7 @@ impl AclTreeNode {
|
||||
}
|
||||
|
||||
fn insert_group_role(&mut self, group: String, role: String, propagate: bool) {
|
||||
let map = self.groups.entry(group).or_insert_with(|| HashMap::new());
|
||||
let map = self.groups.entry(group).or_insert_with(HashMap::new);
|
||||
if role == ROLE_NAME_NO_ACCESS {
|
||||
map.clear();
|
||||
map.insert(role, propagate);
|
||||
@ -413,7 +423,7 @@ impl AclTreeNode {
|
||||
}
|
||||
|
||||
fn insert_user_role(&mut self, auth_id: Authid, role: String, propagate: bool) {
|
||||
let map = self.users.entry(auth_id).or_insert_with(|| HashMap::new());
|
||||
let map = self.users.entry(auth_id).or_insert_with(HashMap::new);
|
||||
if role == ROLE_NAME_NO_ACCESS {
|
||||
map.clear();
|
||||
map.insert(role, propagate);
|
||||
@ -435,7 +445,7 @@ impl AclTree {
|
||||
/// Iterates over the tree looking for a node matching `path`.
|
||||
pub fn find_node(&mut self, path: &str) -> Option<&mut AclTreeNode> {
|
||||
let path = split_acl_path(path);
|
||||
return self.get_node(&path);
|
||||
self.get_node(&path)
|
||||
}
|
||||
|
||||
fn get_node(&mut self, path: &[&str]) -> Option<&mut AclTreeNode> {
|
||||
@ -455,7 +465,7 @@ impl AclTree {
|
||||
node = node
|
||||
.children
|
||||
.entry(String::from(*comp))
|
||||
.or_insert_with(|| AclTreeNode::new());
|
||||
.or_insert_with(AclTreeNode::new);
|
||||
}
|
||||
node
|
||||
}
|
||||
@ -521,12 +531,12 @@ impl AclTree {
|
||||
if *propagate {
|
||||
role_ug_map1
|
||||
.entry(role)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.or_insert_with(BTreeSet::new)
|
||||
.insert(auth_id);
|
||||
} else {
|
||||
role_ug_map0
|
||||
.entry(role)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.or_insert_with(BTreeSet::new)
|
||||
.insert(auth_id);
|
||||
}
|
||||
}
|
||||
@ -538,12 +548,12 @@ impl AclTree {
|
||||
if *propagate {
|
||||
role_ug_map1
|
||||
.entry(role)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.or_insert_with(BTreeSet::new)
|
||||
.insert(group);
|
||||
} else {
|
||||
role_ug_map0
|
||||
.entry(role)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.or_insert_with(BTreeSet::new)
|
||||
.insert(group);
|
||||
}
|
||||
}
|
||||
@ -563,7 +573,7 @@ impl AclTree {
|
||||
});
|
||||
result_map
|
||||
.entry(item_list)
|
||||
.or_insert_with(|| BTreeSet::new())
|
||||
.or_insert_with(BTreeSet::new)
|
||||
.insert(item.to_string());
|
||||
}
|
||||
result_map
|
||||
@ -651,8 +661,7 @@ impl AclTree {
|
||||
if !ROLE_NAMES.contains_key(role) {
|
||||
bail!("unknown role '{}'", role);
|
||||
}
|
||||
if user_or_group.starts_with('@') {
|
||||
let group = &user_or_group[1..];
|
||||
if let Some(group) = user_or_group.strip_prefix('@') {
|
||||
node.insert_group_role(group.to_string(), role.to_string(), propagate);
|
||||
} else {
|
||||
node.insert_user_role(user_or_group.parse()?, role.to_string(), propagate);
|
||||
|
@ -98,7 +98,7 @@ impl CachedUserInfo {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn check_privs(
|
||||
|
@ -135,8 +135,8 @@ pub const DATASTORE_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.datastore.lck";
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(DATASTORE_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(DATASTORE_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let data = CONFIG.parse(DATASTORE_CFG_FILENAME, &content)?;
|
||||
|
@ -68,8 +68,8 @@ pub fn lock() -> Result<std::fs::File, Error> {
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(DRIVE_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(DRIVE_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let data = CONFIG.parse(DRIVE_CFG_FILENAME, &content)?;
|
||||
|
@ -43,8 +43,8 @@ fn init() -> SectionConfig {
|
||||
config
|
||||
}
|
||||
|
||||
pub const MEDIA_POOL_CFG_FILENAME: &'static str = "/etc/proxmox-backup/media-pool.cfg";
|
||||
pub const MEDIA_POOL_CFG_LOCKFILE: &'static str = "/etc/proxmox-backup/.media-pool.lck";
|
||||
pub const MEDIA_POOL_CFG_FILENAME: &str = "/etc/proxmox-backup/media-pool.cfg";
|
||||
pub const MEDIA_POOL_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.media-pool.lck";
|
||||
|
||||
pub fn lock() -> Result<std::fs::File, Error> {
|
||||
open_file_locked(MEDIA_POOL_CFG_LOCKFILE, std::time::Duration::new(10, 0), true)
|
||||
@ -52,8 +52,8 @@ pub fn lock() -> Result<std::fs::File, Error> {
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(MEDIA_POOL_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(MEDIA_POOL_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let data = CONFIG.parse(MEDIA_POOL_CFG_FILENAME, &content)?;
|
||||
|
@ -386,9 +386,9 @@ impl NetworkConfig {
|
||||
pub fn check_mtu(&self, parent_name: &str, child_name: &str) -> Result<(), Error> {
|
||||
|
||||
let parent = self.interfaces.get(parent_name)
|
||||
.ok_or(format_err!("check_mtu - missing parent interface '{}'", parent_name))?;
|
||||
.ok_or_else(|| format_err!("check_mtu - missing parent interface '{}'", parent_name))?;
|
||||
let child = self.interfaces.get(child_name)
|
||||
.ok_or(format_err!("check_mtu - missing child interface '{}'", child_name))?;
|
||||
.ok_or_else(|| format_err!("check_mtu - missing child interface '{}'", child_name))?;
|
||||
|
||||
let child_mtu = match child.mtu {
|
||||
Some(mtu) => mtu,
|
||||
@ -515,7 +515,7 @@ pub fn config() -> Result<(NetworkConfig, [u8;32]), Error> {
|
||||
Some(content) => content,
|
||||
None => {
|
||||
let content = proxmox::tools::fs::file_get_optional_contents(NETWORK_INTERFACES_FILENAME)?;
|
||||
content.unwrap_or(Vec::new())
|
||||
content.unwrap_or_default()
|
||||
}
|
||||
};
|
||||
|
||||
@ -577,8 +577,8 @@ pub fn complete_port_list(arg: &str, _param: &HashMap<String, String>) -> Vec<St
|
||||
Err(_) => return vec![],
|
||||
};
|
||||
|
||||
let arg = arg.clone().trim();
|
||||
let prefix = if let Some(idx) = arg.rfind(",") { &arg[..idx+1] } else { "" };
|
||||
let arg = arg.trim();
|
||||
let prefix = if let Some(idx) = arg.rfind(',') { &arg[..idx+1] } else { "" };
|
||||
ports.iter().map(|port| format!("{}{}", prefix, port)).collect()
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ pub static IPV4_REVERSE_MASK: &[&str] = &[
|
||||
lazy_static! {
|
||||
pub static ref IPV4_MASK_HASH_LOCALNET: HashMap<&'static str, u8> = {
|
||||
let mut map = HashMap::new();
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 8..32 {
|
||||
map.insert(IPV4_REVERSE_MASK[i], i as u8);
|
||||
}
|
||||
@ -61,22 +62,23 @@ lazy_static! {
|
||||
pub fn parse_cidr(cidr: &str) -> Result<(String, u8, bool), Error> {
|
||||
let (address, mask, is_v6) = parse_address_or_cidr(cidr)?;
|
||||
if let Some(mask) = mask {
|
||||
return Ok((address, mask, is_v6));
|
||||
Ok((address, mask, is_v6))
|
||||
} else {
|
||||
bail!("missing netmask in '{}'", cidr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_netmask(mask: u8, is_v6: bool) -> Result<(), Error> {
|
||||
if is_v6 {
|
||||
if !(mask >= 1 && mask <= 128) {
|
||||
bail!("IPv6 mask '{}' is out of range (1..128).", mask);
|
||||
}
|
||||
let (ver, min, max) = if is_v6 {
|
||||
("IPv6", 1, 128)
|
||||
} else {
|
||||
if !(mask > 0 && mask <= 32) {
|
||||
bail!("IPv4 mask '{}' is out of range (1..32).", mask);
|
||||
}
|
||||
("IPv4", 1, 32)
|
||||
};
|
||||
|
||||
if !(mask >= min && mask <= max) {
|
||||
bail!("{} mask '{}' is out of range ({}..{}).", ver, mask, min, max);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -97,18 +99,18 @@ pub fn parse_address_or_cidr(cidr: &str) -> Result<(String, Option<u8>, bool), E
|
||||
if let Some(mask) = caps.get(2) {
|
||||
let mask = u8::from_str_radix(mask.as_str(), 10)?;
|
||||
check_netmask(mask, false)?;
|
||||
return Ok((address.to_string(), Some(mask), false));
|
||||
Ok((address.to_string(), Some(mask), false))
|
||||
} else {
|
||||
return Ok((address.to_string(), None, false));
|
||||
Ok((address.to_string(), None, false))
|
||||
}
|
||||
} else if let Some(caps) = CIDR_V6_REGEX.captures(&cidr) {
|
||||
let address = &caps[1];
|
||||
if let Some(mask) = caps.get(2) {
|
||||
let mask = u8::from_str_radix(mask.as_str(), 10)?;
|
||||
check_netmask(mask, true)?;
|
||||
return Ok((address.to_string(), Some(mask), true));
|
||||
Ok((address.to_string(), Some(mask), true))
|
||||
} else {
|
||||
return Ok((address.to_string(), None, true));
|
||||
Ok((address.to_string(), None, true))
|
||||
}
|
||||
} else {
|
||||
bail!("invalid address/mask '{}'", cidr);
|
||||
|
@ -74,9 +74,9 @@ impl <R: BufRead> Lexer<R> {
|
||||
}
|
||||
|
||||
fn split_line(line: &str) -> VecDeque<(Token, String)> {
|
||||
if line.starts_with("#") {
|
||||
if let Some(comment) = line.strip_prefix('#') {
|
||||
let mut res = VecDeque::new();
|
||||
res.push_back((Token::Comment, line[1..].trim().to_string()));
|
||||
res.push_back((Token::Comment, comment.trim().to_string()));
|
||||
return res;
|
||||
}
|
||||
let mut list: VecDeque<(Token, String)> = line.split_ascii_whitespace().map(|text| {
|
||||
@ -114,14 +114,14 @@ impl <R: BufRead> Iterator for Lexer<R> {
|
||||
Some(ref mut cur_line) => {
|
||||
if cur_line.is_empty() {
|
||||
self.cur_line = None;
|
||||
return Some(Ok((Token::Newline, String::from("\n"))));
|
||||
Some(Ok((Token::Newline, String::from("\n"))))
|
||||
} else {
|
||||
let (token, text) = cur_line.pop_front().unwrap();
|
||||
return Some(Ok((token, text)));
|
||||
Some(Ok((token, text)))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return None;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ impl <R: BufRead> NetworkParser<R> {
|
||||
bail!("input error - {}", err);
|
||||
}
|
||||
Some(Ok((token, _))) => {
|
||||
return Ok(*token);
|
||||
Ok(*token)
|
||||
}
|
||||
None => {
|
||||
bail!("got unexpected end of stream (inside peek)");
|
||||
@ -44,7 +44,7 @@ impl <R: BufRead> NetworkParser<R> {
|
||||
}
|
||||
Some(Ok((token, text))) => {
|
||||
if token == Token::Newline { self.line_nr += 1; }
|
||||
return Ok((token, text));
|
||||
Ok((token, text))
|
||||
}
|
||||
None => {
|
||||
bail!("got unexpected end of stream (inside peek)");
|
||||
@ -215,12 +215,12 @@ impl <R: BufRead> NetworkParser<R> {
|
||||
Token::Comment => {
|
||||
let comment = self.eat(Token::Comment)?;
|
||||
if !address_family_v4 && address_family_v6 {
|
||||
let mut comments = interface.comments6.take().unwrap_or(String::new());
|
||||
let mut comments = interface.comments6.take().unwrap_or_default();
|
||||
if !comments.is_empty() { comments.push('\n'); }
|
||||
comments.push_str(&comment);
|
||||
interface.comments6 = Some(comments);
|
||||
} else {
|
||||
let mut comments = interface.comments.take().unwrap_or(String::new());
|
||||
let mut comments = interface.comments.take().unwrap_or_default();
|
||||
if !comments.is_empty() { comments.push('\n'); }
|
||||
comments.push_str(&comment);
|
||||
interface.comments = Some(comments);
|
||||
|
@ -92,8 +92,8 @@ pub const REMOTE_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.remote.lck";
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(REMOTE_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(REMOTE_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let data = CONFIG.parse(REMOTE_CFG_FILENAME, &content)?;
|
||||
|
@ -79,7 +79,7 @@ impl From<&SyncJobStatus> for SyncJobConfig {
|
||||
owner: job_status.owner.clone(),
|
||||
remote: job_status.remote.clone(),
|
||||
remote_store: job_status.remote_store.clone(),
|
||||
remove_vanished: job_status.remove_vanished.clone(),
|
||||
remove_vanished: job_status.remove_vanished,
|
||||
comment: job_status.comment.clone(),
|
||||
schedule: job_status.schedule.clone(),
|
||||
}
|
||||
@ -183,8 +183,8 @@ pub const SYNC_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.sync.lck";
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(SYNC_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(SYNC_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let data = CONFIG.parse(SYNC_CFG_FILENAME, &content)?;
|
||||
|
@ -53,7 +53,7 @@ pub struct EncryptionKeyInfo {
|
||||
}
|
||||
|
||||
pub fn compute_tape_key_fingerprint(key: &[u8; 32]) -> Result<Fingerprint, Error> {
|
||||
let crypt_config = CryptConfig::new(key.clone())?;
|
||||
let crypt_config = CryptConfig::new(*key)?;
|
||||
Ok(crypt_config.fingerprint())
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ pub fn insert_key(key: [u8;32], key_config: KeyConfig, force: bool) -> Result<()
|
||||
};
|
||||
|
||||
if !force {
|
||||
if let Some(_) = config_map.get(&fingerprint) {
|
||||
if config_map.get(&fingerprint).is_some() {
|
||||
bail!("encryption key '{}' already exists.", fingerprint);
|
||||
}
|
||||
}
|
||||
|
@ -1380,14 +1380,14 @@ impl std::str::FromStr for TfaResponse {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Error> {
|
||||
Ok(if s.starts_with("totp:") {
|
||||
TfaResponse::Totp(s[5..].to_string())
|
||||
} else if s.starts_with("u2f:") {
|
||||
TfaResponse::U2f(serde_json::from_str(&s[4..])?)
|
||||
} else if s.starts_with("webauthn:") {
|
||||
TfaResponse::Webauthn(serde_json::from_str(&s[9..])?)
|
||||
} else if s.starts_with("recovery:") {
|
||||
TfaResponse::Recovery(s[9..].to_string())
|
||||
Ok(if let Some(totp) = s.strip_prefix("totp:") {
|
||||
TfaResponse::Totp(totp.to_string())
|
||||
} else if let Some(u2f) = s.strip_prefix("u2f:") {
|
||||
TfaResponse::U2f(serde_json::from_str(u2f)?)
|
||||
} else if let Some(webauthn) = s.strip_prefix("webauthn:") {
|
||||
TfaResponse::Webauthn(serde_json::from_str(webauthn)?)
|
||||
} else if let Some(recovery) = s.strip_prefix("recovery:") {
|
||||
TfaResponse::Recovery(recovery.to_string())
|
||||
} else {
|
||||
bail!("invalid tfa response");
|
||||
})
|
||||
|
@ -157,8 +157,8 @@ pub const USER_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.user.lck";
|
||||
|
||||
pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
|
||||
|
||||
let content = proxmox::tools::fs::file_read_optional_string(USER_CFG_FILENAME)?;
|
||||
let content = content.unwrap_or(String::from(""));
|
||||
let content = proxmox::tools::fs::file_read_optional_string(USER_CFG_FILENAME)?
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let digest = openssl::sha::sha256(content.as_bytes());
|
||||
let mut data = CONFIG.parse(USER_CFG_FILENAME, &content)?;
|
||||
|
Reference in New Issue
Block a user