Skip to content

Commit

Permalink
🔧 Support <policy>
Browse files Browse the repository at this point in the history
  • Loading branch information
jokeyrhyme committed Nov 27, 2024
1 parent b9044b9 commit 8229c5a
Showing 1 changed file with 134 additions and 7 deletions.
141 changes: 134 additions & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub struct BusConfig {
/// The bus daemon will write its pid to the specified file.
pub pidfile: Option<PathBuf>,

pub policies: Vec<Policy>,

/// Adds a directory to search for .service files,
/// which tell the dbus-daemon how to start a program to provide a particular well-known bus name.
#[serde(default)]
Expand Down Expand Up @@ -92,6 +94,11 @@ impl TryFrom<Document> for BusConfig {
bc.listen.insert(s);
}
Element::Pidfile(p) => bc.pidfile = Some(p),
Element::Policy(pe) => {
if let Some(p) = OptionalPolicy::try_from(pe)? {
bc.policies.push(p);
}
}
Element::Servicedir(p) => {
bc.servicedir.push(p);
}
Expand Down Expand Up @@ -222,13 +229,6 @@ impl BusConfig {
}
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Type {
Session,
System,
}

#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
struct Document {
#[serde(rename = "$value", default)]
Expand All @@ -247,6 +247,7 @@ enum Element {
Listen(String),
Limit,
Pidfile(PathBuf),
Policy(PolicyElement),
Servicedir(PathBuf),
Servicehelper(PathBuf),
/// Requests a standard set of session service directories.
Expand Down Expand Up @@ -297,6 +298,90 @@ pub struct Limits {
pub reply_timeout: Duration,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Policy {
DefaultContext,
Group(String),
MandatoryContext,
User(String),
}
// TODO: implement Cmp/Ord to help stable-sort Policy values:
// DefaultContext < Group < User < MandatoryContext
type OptionalPolicy = Option<Policy>;
impl TryFrom<PolicyElement> for OptionalPolicy {
type Error = Error;

fn try_from(value: PolicyElement) -> Result<Self> {
match value {
PolicyElement {
at_console: Some(_),
context: None,
group: None,
user: None,
..
} => {
eprintln!(r#"warning: busd does not implement `<policy at_context="...">`"#);
Ok(None)
}
PolicyElement {
at_console: None,
context: Some(c),
group: None,
user: None,
..
} => Ok(Some(match c {
PolicyContext::Default => Policy::DefaultContext,
PolicyContext::Mandatory => Policy::MandatoryContext,
})),
PolicyElement {
at_console: None,
context: None,
group: Some(group),
user: None,
..
} => Ok(Some(Policy::Group(group))),
PolicyElement {
at_console: None,
context: None,
group: None,
user: Some(user),
..
} => Ok(Some(Policy::User(user))),
_ => Err(Error::msg(format!(
"policy contains conflicting attributes: {value:?}"
))),
}
}
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
enum PolicyContext {
Default,
Mandatory,
}

#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
struct PolicyElement {
#[serde(rename = "@at_console")]
at_console: Option<String>,
#[serde(rename = "@context")]
context: Option<PolicyContext>,
#[serde(rename = "@group")]
group: Option<String>,
// #[serde(rename = "$value", default)]
// rules: Vec<RuleElement>,
#[serde(rename = "@user")]
user: Option<String>,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Type {
Session,
System,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
struct TypeElement {
#[serde(rename = "$text")]
Expand Down Expand Up @@ -457,6 +542,48 @@ mod tests {
);
}

#[test]
fn bus_config_parse_with_policies_ok() {
let input = r#"<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy context="default">
<allow send_destination="*" eavesdrop="true"/>
<allow eavesdrop="true"/>
<allow own="*"/>
</policy>
<policy at_console="true">
<allow send_destination="org.freedesktop.DBus" send_interface="org.freedesktop.systemd1.Activator"/>
</policy>
<policy user="root">
<allow send_destination="org.freedesktop.DBus" send_interface="org.freedesktop.systemd1.Activator"/>
</policy>
<policy group="network">
<allow send_destination="org.freedesktop.Avahi"/>
<allow receive_sender="org.freedesktop.Avahi"/>
</policy>
<policy context="mandatory">
<deny send_destination="net.connman.iwd"/>
</policy>
</busconfig>
"#;

let busconfig = BusConfig::parse(input).expect("should parse XML input");

assert_eq!(
busconfig,
BusConfig {
policies: vec![
Policy::DefaultContext,
Policy::User(String::from("root")),
Policy::Group(String::from("network")),
Policy::MandatoryContext,
],
..Default::default()
}
);
}

#[test]
fn bus_config_parse_with_servicedir_and_standard_session_servicedirs_ok() {
let input = r#"<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
Expand Down

0 comments on commit 8229c5a

Please sign in to comment.