diff --git a/src/config.rs b/src/config.rs index 32c87f6..0b1f1e0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -76,6 +76,15 @@ pub struct Config { pub user: Option, } +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum Destination { + #[serde(rename = "*")] + Any, + Name(String), + Prefix(String), +} + impl TryFrom for Config { type Error = Error; @@ -297,6 +306,10 @@ impl TryFrom for OptionalOperation { .map(i8::from) .sum(); + if value.send_destination.is_some() && value.send_destination_prefix.is_some() { + return Err(Error::msg(format!("send_destination_prefix cannot be combined with the send_destination in the same rule: {value:?}"))); + } + if operations_count > 1 { return Err(Error::msg(format!("do not mix rule attributes for connect, own, receive, and/or send operations in the same rule: {value:?}"))); } @@ -534,8 +547,7 @@ pub type Rule = (Access, Operation); #[derive(Clone, Debug, Deserialize, PartialEq)] pub struct SendOperation { pub broadcast: Option, - pub destination: String, - pub destination_prefix: String, + pub destination: Option, pub error: String, pub interface: String, pub max_fds: u32, @@ -547,8 +559,7 @@ impl Default for SendOperation { fn default() -> Self { Self { broadcast: None, - destination: String::from("*"), - destination_prefix: String::default(), + destination: None, error: String::from("*"), interface: String::from("*"), max_fds: u32::MAX, @@ -560,10 +571,27 @@ impl Default for SendOperation { } impl From for SendOperation { fn from(value: RuleAttributes) -> Self { + let destination = match value { + RuleAttributes { + send_destination: Some(some), + send_destination_prefix: None, + .. + } if some == "*" => Some(Destination::Any), + RuleAttributes { + send_destination: Some(some), + send_destination_prefix: None, + .. + } => Some(Destination::Name(some)), + RuleAttributes { + send_destination: None, + send_destination_prefix: Some(some), + .. + } => Some(Destination::Prefix(some)), + _ => None, + }; Self { broadcast: value.send_broadcast, - destination: value.send_destination.unwrap_or(String::from("*")), - destination_prefix: value.send_destination_prefix.unwrap_or_default(), + destination, error: value.send_error.unwrap_or(String::from("*")), interface: value.send_interface.unwrap_or(String::from("*")), max_fds: value.max_fds.unwrap_or(u32::MAX), @@ -769,7 +797,6 @@ mod tests { - + @@ -810,8 +837,9 @@ mod tests { Access::Allow, Operation::Send(SendOperation { broadcast: Some(true), - destination: String::from("org.freedesktop.DBus"), - destination_prefix: String::from("org.freedesktop"), + destination: Some(Destination::Name(String::from( + "org.freedesktop.DBus" + ))), error: String::from("something bad"), interface: String::from("org.freedesktop.systemd1.Activator"), max_fds: 128, @@ -840,7 +868,9 @@ mod tests { ( Access::Allow, Operation::Send(SendOperation { - destination: String::from("org.freedesktop.Avahi"), + destination: Some(Destination::Prefix(String::from( + "org.freedesktop" + ))), ..Default::default() }) ), @@ -858,7 +888,7 @@ mod tests { Policy::MandatoryContext(vec![( Access::Deny, Operation::Send(SendOperation { - destination: String::from("net.connman.iwd"), + destination: Some(Destination::Name(String::from("net.connman.iwd"))), ..Default::default() }) ),]), @@ -902,7 +932,7 @@ mod tests { Access::Allow, // `eavesdrop="true"` is dropped, keep other attributes Operation::Send(SendOperation { - destination: String::from("*"), + destination: Some(Destination::Any), ..Default::default() }) ), @@ -915,7 +945,9 @@ mod tests { ( Access::Allow, Operation::Send(SendOperation { - destination: String::from("org.gnome.DisplayManager"), + destination: Some(Destination::Name(String::from( + "org.gnome.DisplayManager" + ))), interface: String::from("org.gnome.DisplayManager.Manager"), // `member=... is dropped` ..Default::default() @@ -929,6 +961,21 @@ mod tests { ); } + #[should_panic] + #[test] + fn bus_config_parse_with_policies_with_send_destination_and_send_destination_prefix_error() { + let input = r#" + + + + + + "#; + + Config::parse(input).expect("should parse XML input"); + } + #[should_panic] #[test] fn bus_config_parse_with_policies_with_send_and_receive_attributes_error() {