zbus/fdo/
dbus.rs

1//! D-Bus standard interfaces.
2//!
3//! The D-Bus specification defines the message bus messages and some standard interfaces that may
4//! be useful across various D-Bus applications. This module provides their proxy.
5
6use enumflags2::{BitFlags, bitflags};
7use serde::{Deserialize, Serialize};
8use serde_repr::{Deserialize_repr, Serialize_repr};
9use std::collections::HashMap;
10use zbus_names::{
11    BusName, OwnedBusName, OwnedInterfaceName, OwnedUniqueName, UniqueName, WellKnownName,
12};
13#[cfg(unix)]
14use zvariant::OwnedFd;
15use zvariant::{DeserializeDict, Optional, SerializeDict, Type};
16
17use super::Result;
18use crate::{OwnedGuid, proxy};
19
20/// The flags used by the [`DBusProxy::request_name`] method.
21///
22/// The default flags (returned by [`BitFlags::default`]) are `AllowReplacement`, `ReplaceExisting`,
23/// and `DoNotQueue`.
24#[bitflags(default = AllowReplacement | ReplaceExisting | DoNotQueue)]
25#[repr(u32)]
26#[derive(Type, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
27pub enum RequestNameFlags {
28    /// If an application A specifies this flag and succeeds in becoming the owner of the name, and
29    /// another application B later calls [`DBusProxy::request_name`] with the `ReplaceExisting`
30    /// flag, then application A will lose ownership and receive a `org.freedesktop.DBus.NameLost`
31    /// signal, and application B will become the new owner. If `AllowReplacement` is not specified
32    /// by application A, or `ReplaceExisting` is not specified by application B, then application
33    /// B will not replace application A as the owner.
34    AllowReplacement = 0x01,
35    /// Try to replace the current owner if there is one. If this flag is not set the application
36    /// will only become the owner of the name if there is no current owner. If this flag is set,
37    /// the application will replace the current owner if the current owner specified
38    /// `AllowReplacement`.
39    ReplaceExisting = 0x02,
40    /// Without this flag, if an application requests a name that is already owned, the
41    /// application will be placed in a queue to own the name when the current owner gives it
42    /// up. If this flag is given, the application will not be placed in the queue; the
43    /// request for the name will simply fail. This flag also affects behavior when an
44    /// application is replaced as name owner; by default the application moves back into the
45    /// waiting queue, unless this flag was provided when the application became the name
46    /// owner.
47    DoNotQueue = 0x04,
48}
49
50/// The return code of the [`DBusProxy::request_name`] method.
51#[repr(u32)]
52#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
53pub enum RequestNameReply {
54    /// The caller is now the primary owner of the name, replacing any previous owner. Either the
55    /// name had no owner before, or the caller specified [`RequestNameFlags::ReplaceExisting`] and
56    /// the current owner specified [`RequestNameFlags::AllowReplacement`].
57    PrimaryOwner = 0x01,
58    /// The name already had an owner, [`RequestNameFlags::DoNotQueue`] was not specified, and
59    /// either the current owner did not specify [`RequestNameFlags::AllowReplacement`] or the
60    /// requesting application did not specify [`RequestNameFlags::ReplaceExisting`].
61    InQueue = 0x02,
62    /// The name already had an owner, [`RequestNameFlags::DoNotQueue`] was specified, and either
63    /// [`RequestNameFlags::AllowReplacement`] was not specified by the current owner, or
64    /// [`RequestNameFlags::ReplaceExisting`] was not specified by the requesting application.
65    Exists = 0x03,
66    /// The application trying to request ownership of a name is already the owner of it.
67    AlreadyOwner = 0x04,
68}
69
70impl std::fmt::Display for RequestNameReply {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        match self {
73            Self::PrimaryOwner => write!(f, "PrimaryOwner"),
74            Self::InQueue => write!(f, "InQueue"),
75            Self::Exists => write!(f, "Exists"),
76            Self::AlreadyOwner => write!(f, "AlreadyOwner"),
77        }
78    }
79}
80
81/// The return code of the [`DBusProxy::release_name`] method.
82#[repr(u32)]
83#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
84pub enum ReleaseNameReply {
85    /// The caller has released their claim on the given name. Either the caller was the primary
86    /// owner of the name, and the name is now unused or taken by somebody waiting in the queue for
87    /// the name, or the caller was waiting in the queue for the name and has now been removed from
88    /// the queue.
89    Released = 0x01,
90    /// The given name does not exist on this bus.
91    NonExistent = 0x02,
92    /// The caller was not the primary owner of this name, and was also not waiting in the queue to
93    /// own this name.
94    NotOwner = 0x03,
95}
96
97impl std::fmt::Display for ReleaseNameReply {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        match self {
100            Self::Released => write!(f, "Released"),
101            Self::NonExistent => write!(f, "NonExistent"),
102            Self::NotOwner => write!(f, "NotOwner"),
103        }
104    }
105}
106
107/// The return code of the [`DBusProxy::start_service_by_name`] method.
108///
109/// In zbus 6.0, this will become the return type of `start_service_by_name`.
110/// For now, it's provided separately with a `TryFrom<u32>` implementation
111/// to avoid breaking changes in the API.
112#[repr(u32)]
113#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
114pub enum StartServiceReply {
115    /// The service was successfully started.
116    Success = 0x01,
117    /// The service was already running.
118    AlreadyRunning = 0x02,
119}
120
121impl std::fmt::Display for StartServiceReply {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        match self {
124            Self::Success => write!(f, "Success"),
125            Self::AlreadyRunning => write!(f, "AlreadyRunning"),
126        }
127    }
128}
129
130// FIXME: When releasing 6.0, use StartServiceReply directly in start_service_by_name instead
131impl TryFrom<u32> for StartServiceReply {
132    type Error = super::Error;
133
134    fn try_from(value: u32) -> Result<Self> {
135        match value {
136            0x01 => Ok(StartServiceReply::Success),
137            0x02 => Ok(StartServiceReply::AlreadyRunning),
138            _ => Err(super::Error::ZBus(crate::Error::InvalidReply)),
139        }
140    }
141}
142
143/// Credentials of a process connected to a bus server.
144///
145/// If unable to determine certain credentials (for instance, because the process is not on the same
146/// machine as the bus daemon, or because this version of the bus daemon does not support a
147/// particular security framework), or if the values of those credentials cannot be represented as
148/// documented here, then those credentials are omitted.
149///
150/// **Note**: unknown keys, in particular those with "." that are not from the specification, will
151/// be ignored. Use your own implementation or contribute your keys here, or in the specification.
152#[derive(Debug, Default, DeserializeDict, PartialEq, Eq, SerializeDict, Type)]
153#[zvariant(signature = "a{sv}")]
154pub struct ConnectionCredentials {
155    #[zvariant(rename = "UnixUserID")]
156    pub(crate) unix_user_id: Option<u32>,
157
158    #[zvariant(rename = "UnixGroupIDs")]
159    pub(crate) unix_group_ids: Option<Vec<u32>>,
160
161    #[cfg(unix)]
162    #[zvariant(rename = "ProcessFD")]
163    pub(crate) process_fd: Option<OwnedFd>,
164
165    #[zvariant(rename = "ProcessID")]
166    pub(crate) process_id: Option<u32>,
167
168    #[zvariant(rename = "WindowsSID")]
169    pub(crate) windows_sid: Option<String>,
170
171    #[zvariant(rename = "LinuxSecurityLabel")]
172    pub(crate) linux_security_label: Option<Vec<u8>>,
173}
174
175impl ConnectionCredentials {
176    /// The numeric Unix user ID, as defined by POSIX.
177    pub fn unix_user_id(&self) -> Option<u32> {
178        self.unix_user_id
179    }
180
181    /// The numeric Unix group IDs (including both the primary group and the supplementary groups),
182    /// as defined by POSIX, in numerically sorted order. This array is either complete or absent:
183    /// if the message bus is able to determine some but not all of the caller's groups, or if one
184    /// of the groups is not representable in a UINT32, it must not add this credential to the
185    /// dictionary.
186    pub fn unix_group_ids(&self) -> Option<&Vec<u32>> {
187        self.unix_group_ids.as_ref()
188    }
189
190    /// Same as [`ConnectionCredentials::unix_group_ids`], but consumes `self` and returns the group
191    /// IDs Vec.
192    pub fn into_unix_group_ids(self) -> Option<Vec<u32>> {
193        self.unix_group_ids
194    }
195
196    /// A file descriptor pinning the process, on platforms that have this concept. On Linux, the
197    /// SO_PEERPIDFD socket option is a suitable implementation. This is safer to use to identify
198    /// a process than the ProcessID, as the latter is subject to re-use attacks, while the FD
199    /// cannot be recycled. If the original process no longer exists the FD will no longer be
200    /// resolvable.
201    #[cfg(unix)]
202    pub fn process_fd(&self) -> Option<&OwnedFd> {
203        self.process_fd.as_ref()
204    }
205
206    /// The numeric process ID, on platforms that have this concept. On Unix, this is the process ID
207    /// defined by POSIX.
208    pub fn process_id(&self) -> Option<u32> {
209        self.process_id
210    }
211
212    /// The Windows security identifier in its string form, e.g.
213    /// `S-1-5-21-3623811015-3361044348-30300820-1013` for a domain or local computer user or
214    /// "S-1-5-18` for the LOCAL_SYSTEM user.
215    pub fn windows_sid(&self) -> Option<&String> {
216        self.windows_sid.as_ref()
217    }
218
219    /// Same as [`ConnectionCredentials::windows_sid`], but consumes `self` and returns the SID
220    /// string.
221    pub fn into_windows_sid(self) -> Option<String> {
222        self.windows_sid
223    }
224
225    /// On Linux systems, the security label that would result from the SO_PEERSEC getsockopt call.
226    /// The array contains the non-zero bytes of the security label in an unspecified
227    /// ASCII-compatible encoding, followed by a single zero byte.
228    ///
229    /// For example, the SELinux context `system_u:system_r:init_t:s0` (a string of length 27) would
230    /// be encoded as 28 bytes ending with `':', 's', '0', '\x00'`
231    ///
232    /// On SELinux systems this is the SELinux context, as output by `ps -Z` or `ls -Z`. Typical
233    /// values might include `system_u:system_r:init_t:s0`,
234    /// `unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023`, or
235    /// `unconfined_u:unconfined_r:chrome_sandbox_t:s0-s0:c0.c1023`.
236    ///
237    /// On Smack systems, this is the Smack label. Typical values might include `_`, `*`, `User`,
238    /// `System` or `System::Shared`.
239    ///
240    /// On AppArmor systems, this is the AppArmor context, a composite string encoding the AppArmor
241    /// label (one or more profiles) and the enforcement mode. Typical values might include
242    /// `unconfined`, `/usr/bin/firefox (enforce)` or `user1 (complain)`.
243    pub fn linux_security_label(&self) -> Option<&Vec<u8>> {
244        self.linux_security_label.as_ref()
245    }
246
247    /// Same as [`ConnectionCredentials::linux_security_label`], but consumes `self` and returns
248    /// the security label bytes.
249    pub fn into_linux_security_label(self) -> Option<Vec<u8>> {
250        self.linux_security_label
251    }
252
253    /// Set the numeric Unix user ID, as defined by POSIX.
254    pub fn set_unix_user_id(mut self, unix_user_id: u32) -> Self {
255        self.unix_user_id = Some(unix_user_id);
256
257        self
258    }
259
260    /// Add a numeric Unix group ID.
261    ///
262    /// See [`ConnectionCredentials::unix_group_ids`] for more information.
263    pub fn add_unix_group_id(mut self, unix_group_id: u32) -> Self {
264        self.unix_group_ids
265            .get_or_insert_with(Vec::new)
266            .push(unix_group_id);
267
268        self
269    }
270
271    /// Set the process FD, on platforms that have this concept
272    #[cfg(unix)]
273    pub fn set_process_fd(mut self, process_fd: OwnedFd) -> Self {
274        self.process_fd = Some(process_fd);
275
276        self
277    }
278
279    /// Set the numeric process ID, on platforms that have this concept.
280    ///
281    /// See [`ConnectionCredentials::process_id`] for more information.
282    pub fn set_process_id(mut self, process_id: u32) -> Self {
283        self.process_id = Some(process_id);
284
285        self
286    }
287
288    /// Set the Windows security identifier in its string form.
289    pub fn set_windows_sid(mut self, windows_sid: String) -> Self {
290        self.windows_sid = Some(windows_sid);
291
292        self
293    }
294
295    /// Set the Linux security label.
296    ///
297    /// See [`ConnectionCredentials::linux_security_label`] for more information.
298    pub fn set_linux_security_label(mut self, linux_security_label: Vec<u8>) -> Self {
299        self.linux_security_label = Some(linux_security_label);
300
301        self
302    }
303}
304
305/// Proxy for the `org.freedesktop.DBus` interface.
306#[proxy(
307    default_service = "org.freedesktop.DBus",
308    default_path = "/org/freedesktop/DBus",
309    interface = "org.freedesktop.DBus"
310)]
311pub trait DBus {
312    /// Adds a match rule to match messages going through the message bus
313    #[zbus(name = "AddMatch")]
314    fn add_match_rule(&self, rule: crate::MatchRule<'_>) -> Result<()>;
315
316    /// Returns auditing data used by Solaris ADT, in an unspecified binary format.
317    fn get_adt_audit_session_data(&self, bus_name: BusName<'_>) -> Result<Vec<u8>>;
318
319    /// Returns as many credentials as possible for the process connected to the server.
320    fn get_connection_credentials(&self, bus_name: BusName<'_>) -> Result<ConnectionCredentials>;
321
322    /// Returns the security context used by SELinux, in an unspecified format.
323    #[zbus(name = "GetConnectionSELinuxSecurityContext")]
324    fn get_connection_selinux_security_context(&self, bus_name: BusName<'_>) -> Result<Vec<u8>>;
325
326    /// Returns the Unix process ID of the process connected to the server.
327    #[zbus(name = "GetConnectionUnixProcessID")]
328    fn get_connection_unix_process_id(&self, bus_name: BusName<'_>) -> Result<u32>;
329
330    /// Returns the Unix user ID of the process connected to the server.
331    fn get_connection_unix_user(&self, bus_name: BusName<'_>) -> Result<u32>;
332
333    /// Gets the unique ID of the bus.
334    fn get_id(&self) -> Result<OwnedGuid>;
335
336    /// Returns the unique connection name of the primary owner of the name given.
337    fn get_name_owner(&self, name: BusName<'_>) -> Result<OwnedUniqueName>;
338
339    /// Returns the unique name assigned to the connection.
340    fn hello(&self) -> Result<OwnedUniqueName>;
341
342    /// Returns a list of all names that can be activated on the bus.
343    fn list_activatable_names(&self) -> Result<Vec<OwnedBusName>>;
344
345    /// Returns a list of all currently-owned names on the bus.
346    fn list_names(&self) -> Result<Vec<OwnedBusName>>;
347
348    /// List the connections currently queued for a bus name.
349    fn list_queued_owners(&self, name: WellKnownName<'_>) -> Result<Vec<OwnedUniqueName>>;
350
351    /// Checks if the specified name exists (currently has an owner).
352    fn name_has_owner(&self, name: BusName<'_>) -> Result<bool>;
353
354    /// Ask the message bus to release the method caller's claim to the given name.
355    fn release_name(&self, name: WellKnownName<'_>) -> Result<ReleaseNameReply>;
356
357    /// Reload server configuration.
358    fn reload_config(&self) -> Result<()>;
359
360    /// Removes the first rule that matches.
361    #[zbus(name = "RemoveMatch")]
362    fn remove_match_rule(&self, rule: crate::MatchRule<'_>) -> Result<()>;
363
364    /// Ask the message bus to assign the given name to the method caller.
365    fn request_name(
366        &self,
367        name: WellKnownName<'_>,
368        flags: BitFlags<RequestNameFlags>,
369    ) -> Result<RequestNameReply>;
370
371    /// Tries to launch the executable associated with a name (service
372    /// activation), as an explicit request.
373    fn start_service_by_name(&self, name: WellKnownName<'_>, flags: u32) -> Result<u32>;
374
375    /// This method adds to or modifies that environment when activating services.
376    fn update_activation_environment(&self, environment: HashMap<&str, &str>) -> Result<()>;
377
378    /// This signal indicates that the owner of a name has
379    /// changed. It's also the signal to use to detect the appearance
380    /// of new names on the bus.
381    #[zbus(signal)]
382    fn name_owner_changed(
383        &self,
384        name: BusName<'_>,
385        old_owner: Optional<UniqueName<'_>>,
386        new_owner: Optional<UniqueName<'_>>,
387    );
388
389    /// This signal is sent to a specific application when it loses ownership of a name.
390    #[zbus(signal)]
391    fn name_lost(&self, name: BusName<'_>);
392
393    /// This signal is sent to a specific application when it gains ownership of a name.
394    #[zbus(signal)]
395    fn name_acquired(&self, name: BusName<'_>);
396
397    /// This property lists abstract “features” provided by the message bus, and can be used by
398    /// clients to detect the capabilities of the message bus with which they are communicating.
399    #[zbus(property)]
400    fn features(&self) -> Result<Vec<String>>;
401
402    /// This property lists interfaces provided by the `/org/freedesktop/DBus` object, and can be
403    /// used by clients to detect the capabilities of the message bus with which they are
404    /// communicating. Unlike the standard Introspectable interface, querying this property does not
405    /// require parsing XML. This property was added in version 1.11.x of the reference
406    /// implementation of the message bus.
407    ///
408    /// The standard `org.freedesktop.DBus` and `org.freedesktop.DBus.Properties` interfaces are not
409    /// included in the value of this property, because their presence can be inferred from the fact
410    /// that a method call on `org.freedesktop.DBus.Properties` asking for properties of
411    /// `org.freedesktop.DBus` was successful. The standard `org.freedesktop.DBus.Peer` and
412    /// `org.freedesktop.DBus.Introspectable` interfaces are not included in the value of this
413    /// property either, because they do not indicate features of the message bus implementation.
414    #[zbus(property)]
415    fn interfaces(&self) -> Result<Vec<OwnedInterfaceName>>;
416}
417
418#[cfg(test)]
419mod test {
420    use super::*;
421
422    #[test]
423    fn request_name_flags_default() {
424        let flags = BitFlags::<RequestNameFlags>::default();
425        assert!(flags.contains(RequestNameFlags::AllowReplacement));
426        assert!(flags.contains(RequestNameFlags::ReplaceExisting));
427        assert!(flags.contains(RequestNameFlags::DoNotQueue));
428    }
429}