2121//! expected by dbus-broker, ensuring compatibility with the broker's policy engine.
2222
2323use crate :: error:: { self , Result } ;
24- use crate :: policy:: { Context , MessageType , Policy , Rule } ;
24+ use crate :: policy:: { Context , Policy , Rule } ;
2525use serde:: Serialize ;
2626use snafu:: ResultExt ;
2727use zvariant:: { Type , Value as ZVariantValue } ;
2828
29+ const DEFAULT_MAX_FDS : u64 = u64:: MAX ;
30+
2931/// Top-level policy structure that matches launcher's Dbus format. It is crucial that
3032/// the order of the fields remains like it is, otherwise the broker rejects the policy.
3133///
@@ -52,8 +54,8 @@ pub struct PolicyBatch {
5254 pub ( crate ) connect_verdict : bool ,
5355 pub ( crate ) connect_priority : u64 ,
5456 pub ( crate ) own_rules : Vec < OwnRecord > ,
55- pub ( crate ) send_rules : Vec < SendReceiveRecord > ,
56- pub ( crate ) recv_rules : Vec < SendReceiveRecord > ,
57+ pub ( crate ) send_rules : Vec < SendRecord > ,
58+ pub ( crate ) recv_rules : Vec < ReceiveRecord > ,
5759}
5860
5961/// Represents an Own Record in the actual dbus policy
@@ -67,23 +69,85 @@ pub struct OwnRecord {
6769 pub name : String ,
6870}
6971
70- /// Represents a Send Record in the actual dbus policy
72+ /// Represents a Send/Receive Record in the actual dbus policy
7173/// See:
7274/// https://github.com/bus1/dbus-broker/blob/b0db0890d1254477cf832e5f9f0a798360c80fd9/src/launch/policy.c#L877
73- #[ derive( Debug , Type , Serialize , Clone , ZVariantValue , Default ) ]
74- pub struct SendReceiveRecord {
75- pub verdict : bool ,
76- pub priority : u64 ,
77- pub name : String ,
78- pub path : String ,
79- pub interface : String ,
80- pub member : String ,
81- pub record_type : MessageType ,
82- pub broadcast : u32 ,
83- pub min_fds : u64 ,
84- pub max_fds : u64 ,
75+ macro_rules! impl_record {
76+ ( $record_type: ident, $rule_variant: path, [ $( ( $struct_field: ident, $rule_field: ident) ) ,* ] ) => {
77+ #[ derive( Debug , Type , Serialize , Clone , ZVariantValue ) ]
78+ pub struct $record_type {
79+ pub verdict: bool ,
80+ pub priority: u64 ,
81+ pub name: String ,
82+ pub path: String ,
83+ pub interface: String ,
84+ pub member: String ,
85+ pub record_type: crate :: policy:: MessageType ,
86+ pub broadcast: u32 ,
87+ pub min_fds: u64 ,
88+ pub max_fds: u64 ,
89+ }
90+
91+ impl Default for $record_type {
92+ fn default ( ) -> Self {
93+ Self {
94+ verdict: Default :: default ( ) ,
95+ priority: Default :: default ( ) ,
96+ name: Default :: default ( ) ,
97+ path: Default :: default ( ) ,
98+ interface: Default :: default ( ) ,
99+ member: Default :: default ( ) ,
100+ record_type: Default :: default ( ) ,
101+ broadcast: Default :: default ( ) ,
102+ min_fds: Default :: default ( ) ,
103+ max_fds: crate :: dbus_policy:: DEFAULT_MAX_FDS ,
104+ }
105+ }
106+ }
107+
108+ impl TryFrom <& Rule > for $record_type {
109+ type Error = crate :: error:: Error ;
110+
111+ fn try_from( rule: & Rule ) -> Result <Self > {
112+ match rule {
113+ $rule_variant {
114+ allow,
115+ priority,
116+ $( $rule_field, ) *
117+ ..
118+ } => Ok ( Self {
119+ verdict: * allow,
120+ priority: * priority,
121+ name: rule. name( ) ?,
122+ interface: rule. interface( ) ?,
123+ member: rule. member( ) ?,
124+ path: rule. path( ) ?,
125+ $( $struct_field: $rule_field. clone( ) , ) *
126+ ..Self :: default ( )
127+ } ) ,
128+ _ => error:: RuleToRecordSnafu {
129+ rule_type: format!( "{rule:?}" ) ,
130+ record_type: stringify!( $record_type) . to_string( ) ,
131+ }
132+ . fail( ) ,
133+ }
134+ }
135+ }
136+ } ;
85137}
86138
139+ impl_record ! (
140+ SendRecord ,
141+ Rule :: Send ,
142+ [ ( broadcast, send_broadcast) , ( record_type, send_type) ]
143+ ) ;
144+
145+ impl_record ! (
146+ ReceiveRecord ,
147+ Rule :: Receive ,
148+ [ ( broadcast, receive_broadcast) , ( record_type, receive_type) ]
149+ ) ;
150+
87151impl DbusPolicy {
88152 /// Builds a new DbusPolicy object using "system" as the only supported bus_type
89153 fn new ( ) -> Self {
@@ -221,63 +285,6 @@ impl TryFrom<&Rule> for OwnRecord {
221285 }
222286}
223287
224- impl TryFrom < & Rule > for SendReceiveRecord {
225- type Error = crate :: error:: Error ;
226-
227- fn try_from ( rule : & Rule ) -> Result < Self > {
228- match rule {
229- Rule :: Send {
230- allow,
231- send_destination,
232- send_path,
233- send_interface,
234- send_member,
235- send_type,
236- send_broadcast,
237- priority,
238- ..
239- } => Ok ( SendReceiveRecord {
240- verdict : * allow,
241- name : send_destination. clone ( ) ,
242- path : send_path. clone ( ) ,
243- interface : send_interface. clone ( ) ,
244- member : send_member. clone ( ) ,
245- record_type : * send_type,
246- broadcast : * send_broadcast,
247- priority : * priority,
248- ..SendReceiveRecord :: default ( )
249- } ) ,
250-
251- Rule :: Receive {
252- receive_sender,
253- receive_path,
254- receive_interface,
255- receive_member,
256- receive_type,
257- receive_broadcast,
258- allow,
259- priority,
260- ..
261- } => Ok ( SendReceiveRecord {
262- verdict : * allow,
263- name : receive_sender. clone ( ) ,
264- path : receive_path. clone ( ) ,
265- interface : receive_interface. clone ( ) ,
266- member : receive_member. clone ( ) ,
267- record_type : * receive_type,
268- broadcast : * receive_broadcast,
269- priority : * priority,
270- ..SendReceiveRecord :: default ( )
271- } ) ,
272- _ => error:: RuleToRecordSnafu {
273- rule_type : format ! ( "{rule:?}" ) ,
274- record_type : "SendRecord" . to_string ( ) ,
275- }
276- . fail ( ) ,
277- }
278- }
279- }
280-
281288#[ cfg( test) ]
282289mod tests {
283290 use super :: * ;
@@ -438,4 +445,42 @@ mod tests {
438445 let dbus_policy: DbusPolicy = policy. try_into ( ) . unwrap ( ) ;
439446 assert_eq ! ( dbus_policy. uid_entries[ 1 ] . 1 . send_rules. len( ) , 2 ) ;
440447 }
448+
449+ #[ test]
450+ fn test_wildcards_replaced_with_empty_string ( ) {
451+ let config_str = r#"
452+ [default]
453+ rules = [
454+ { allow = true, send_interface = "*", send_destination = "*", send_path = "*", send_member = "*" },
455+ ]
456+ "# ;
457+ let mut policy: Policy = toml:: from_str ( config_str) . unwrap ( ) ;
458+ policy. set_rule_priorities ( & mut 0u64 ) ;
459+ policy. prepare ( ) . unwrap ( ) ;
460+
461+ let dbus_policy: DbusPolicy = policy. try_into ( ) . unwrap ( ) ;
462+ assert_eq ! ( dbus_policy. uid_entries[ 0 ] . 1 . send_rules[ 0 ] . interface, "" ) ;
463+ assert_eq ! ( dbus_policy. uid_entries[ 0 ] . 1 . send_rules[ 0 ] . name, "" ) ;
464+ assert_eq ! ( dbus_policy. uid_entries[ 0 ] . 1 . send_rules[ 0 ] . member, "" ) ;
465+ assert_eq ! ( dbus_policy. uid_entries[ 0 ] . 1 . send_rules[ 0 ] . path, "" ) ;
466+ }
467+
468+ #[ test]
469+ fn test_max_fds_are_always_the_default ( ) {
470+ let config_str = r#"
471+ [default]
472+ rules = [
473+ { allow = true, send_interface = "*", send_destination = "*", send_path = "*", send_member = "*" },
474+ ]
475+ "# ;
476+ let mut policy: Policy = toml:: from_str ( config_str) . unwrap ( ) ;
477+ policy. set_rule_priorities ( & mut 0u64 ) ;
478+ policy. prepare ( ) . unwrap ( ) ;
479+
480+ let dbus_policy: DbusPolicy = policy. try_into ( ) . unwrap ( ) ;
481+ assert_eq ! (
482+ dbus_policy. uid_entries[ 0 ] . 1 . send_rules[ 0 ] . max_fds,
483+ DEFAULT_MAX_FDS
484+ ) ;
485+ }
441486}
0 commit comments