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}