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