From 765b810f759a194458030ea0c2c5f33c259c175f Mon Sep 17 00:00:00 2001 From: Ron Waldon-Howe Date: Tue, 12 Nov 2024 22:53:40 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Ignore=20rule=20attributes=20ign?= =?UTF-8?q?ored=20by=20`dbus-broker`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 --- src/config.rs | 192 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 167 insertions(+), 25 deletions(-) diff --git a/src/config.rs b/src/config.rs index 815211b..5ba0aa6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -309,8 +309,8 @@ pub struct Limits { pub enum Operation { Connect, Own, - Receive, - Send, + Receive(ReceiveOperation), + Send(SendOperation), } type OptionalOperation = Option; impl TryFrom for OptionalOperation { @@ -320,8 +320,7 @@ impl TryFrom for OptionalOperation { let has_connect = false; let has_own = value.own.is_some(); let has_send = value.send_destination.is_some(); - let has_receive = - value.receive_sender.is_some() || (!has_send && value.eavesdrop.is_some()); + let has_receive = value.receive_sender.is_some(); let operations_count: i8 = vec![has_connect, has_own, has_receive, has_send] .into_iter() @@ -337,9 +336,13 @@ impl TryFrom for OptionalOperation { } else if has_own { Ok(Some(Operation::Own)) } else if has_receive { - Ok(Some(Operation::Receive)) + Ok(Some(Operation::Receive(ReceiveOperation { + sender: value.receive_sender.unwrap_or(String::from("*")), + }))) } else if has_send { - Ok(Some(Operation::Send)) + Ok(Some(Operation::Send(SendOperation { + destination: value.send_destination.unwrap_or(String::from("*")), + }))) } else { Err(Error::msg(format!("rule must specify supported attributes for connect, own, receive, or send operations: {value:?}"))) } @@ -433,16 +436,87 @@ struct PolicyElement { user: Option, } +#[derive(Clone, Debug, Default, PartialEq)] +pub struct ReceiveOperation { + pub sender: String, +} + type OptionalRule = Option; impl TryFrom for OptionalRule { type Error = Error; fn try_from(value: RuleElement) -> std::result::Result { match value { - RuleElement::Allow(attrs) => match OptionalOperation::try_from(attrs)? { - Some(some) => Ok(Some((Access::Allow, some))), - None => Ok(None), - }, + RuleElement::Allow(RuleAttributes { + eavesdrop: Some(true), + group: None, + own: None, + receive_sender: None, + receive_requested_reply: None, + send_destination: None, + send_requested_reply: None, + user: None, + }) => { + // see: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 + eprintln!( + r#"warning: eavesdropping is deprecated and ignored: ``"# + ); + Ok(None) + } + RuleElement::Allow( + RuleAttributes { + receive_requested_reply: Some(false), + .. + } + | RuleAttributes { + send_requested_reply: Some(false), + .. + }, + ) => { + // see: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 + eprintln!( + "warning: explicit policies on replies and errors are deprecated and ignored: ` { + if attrs.eavesdrop == Some(true) { + // see: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 + eprintln!( + r#"warning: eavesdropping is deprecated and ignored: ` Ok(Some((Access::Allow, some))), + None => Ok(None), + } + } + RuleElement::Deny(RuleAttributes { + eavesdrop: Some(true), + .. + }) => { + // see: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 + eprintln!( + r#"warning: eavesdropping is deprecated and ignored: ` { + // see: https://github.com/dbus2/busd/pull/146#issuecomment-2408429760 + eprintln!( + "warning: explicit policies on replies and errors are deprecated and ignored: ` match OptionalOperation::try_from(attrs)? { Some(some) => Ok(Some((Access::Deny, some))), None => Ok(None), @@ -467,15 +541,19 @@ pub type Rule = (Access, Operation); #[derive(Clone, Debug, Default, Deserialize, PartialEq)] struct RuleAttributes { #[serde(rename = "@eavesdrop")] - eavesdrop: Option, + eavesdrop: Option, #[serde(rename = "@group")] group: Option, #[serde(rename = "@own")] own: Option, #[serde(rename = "@receive_sender")] receive_sender: Option, + #[serde(rename = "@receive_requested_reply")] + receive_requested_reply: Option, #[serde(rename = "@send_destination")] send_destination: Option, + #[serde(rename = "@send_requested_reply")] + send_requested_reply: Option, #[serde(rename = "@user")] user: Option, } @@ -487,6 +565,11 @@ enum RuleElement { Deny(RuleAttributes), } +#[derive(Clone, Debug, Default, PartialEq)] +pub struct SendOperation { + pub destination: String, +} + #[derive(Clone, Debug, Deserialize, PartialEq)] #[serde(rename_all = "lowercase")] pub enum Type { @@ -660,13 +743,8 @@ mod tests { "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> - - - - - @@ -686,23 +764,87 @@ mod tests { busconfig, BusConfig { policies: vec![ - Policy::DefaultContext(vec![ - (Access::Allow, Operation::Send), - (Access::Allow, Operation::Receive), - (Access::Allow, Operation::Own), - ]), + Policy::DefaultContext(vec![(Access::Allow, Operation::Own),]), Policy::User( - vec![(Access::Allow, Operation::Send),], + vec![( + Access::Allow, + Operation::Send(SendOperation { + destination: String::from("org.freedesktop.DBus") + }) + ),], String::from("root") ), Policy::Group( vec![ - (Access::Allow, Operation::Send), - (Access::Allow, Operation::Receive), + ( + Access::Allow, + Operation::Send(SendOperation { + destination: String::from("org.freedesktop.Avahi") + }) + ), + ( + Access::Allow, + Operation::Receive(ReceiveOperation { + sender: String::from("org.freedesktop.Avahi") + }) + ), ], String::from("network") ), - Policy::MandatoryContext(vec![(Access::Deny, Operation::Send),]), + Policy::MandatoryContext(vec![( + Access::Deny, + Operation::Send(SendOperation { + destination: String::from("net.connman.iwd") + }) + ),]), + ], + ..Default::default() + } + ); + } + + #[test] + fn bus_config_parse_with_policies_with_ignored_rules_and_rule_attributes_ok() { + let input = r#" + + + + + + + + + + + + + + + "#; + + let busconfig = BusConfig::parse(input).expect("should parse XML input"); + + assert_eq!( + busconfig, + BusConfig { + policies: vec![ + Policy::DefaultContext(vec![ + ( + Access::Allow, + // `eavesdrop="true"` is dropped, keep other attributes + Operation::Send(SendOperation { + destination: String::from("*") + }) + ), + // `` has nothing left after dropping eavesdrop + // `` is completely ignored ], ..Default::default() }