Skip to content

Commit 821d1d2

Browse files
feat: configurable allow-list for dbus interfaces
1 parent 0402625 commit 821d1d2

10 files changed

Lines changed: 489 additions & 39 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ serde_json = "1"
5757
thiserror = "2.0.18"
5858
jiff = "0.2"
5959
tiny-skia = "0.11"
60+
toml = { version = "0.9", default-features = false, features = ["parse", "serde"] }
6061
tracing = { version = "0.1.44", features = [
6162
"max_level_debug",
6263
"release_max_level_info",

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ TARGET_BIN="$(DESTDIR)$(bindir)/$(BINARY)"
2525

2626
KEYBINDINGS_CONF="$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.Shortcuts/v1/defaults"
2727
TILING_EXCEPTIONS_CONF="$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.WindowRules/v1/tiling_exception_defaults"
28+
EI_CLIENTS_EXAMPLE="$(DESTDIR)$(sharedir)/doc/cosmic-comp/ei-clients.toml.example"
2829

2930
all: extract-vendor
3031
cargo build $(ARGS)
@@ -52,6 +53,7 @@ install:
5253
install -Dm0755 "$(CARGO_TARGET_DIR)/$(TARGET)/$(BINARY)" "$(TARGET_BIN)"
5354
install -Dm0644 "data/keybindings.ron" "$(KEYBINDINGS_CONF)"
5455
install -Dm0644 "data/tiling-exceptions.ron" "$(TILING_EXCEPTIONS_CONF)"
56+
install -Dm0644 "data/ei-clients.toml.example" "$(EI_CLIENTS_EXAMPLE)"
5557

5658
install-bare-session: install
5759
install -Dm0644 "data/cosmic.desktop" "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
@@ -61,7 +63,7 @@ install-bare-session: install
6163
install -Dm0755 "data/cosmic-service" "$(DESTDIR)/$(bindir)/cosmic-service"
6264

6365
uninstall:
64-
rm "$(TARGET_BIN)" "$(KEYBINDINGS_CONF)"
66+
rm "$(TARGET_BIN)" "$(KEYBINDINGS_CONF)" "$(EI_CLIENTS_EXAMPLE)"
6567

6668
uninstall-bare-session:
6769
rm "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"

data/ei-clients.toml.example

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Additional clients allowed on the compositor's D-Bus interfaces:
2+
#
3+
# [[ei.client]] "com.system76.CosmicComp.Ei" open an EI
4+
# (libei) sender socket, i.e. synthesize
5+
# keyboard, pointer and touch input.
6+
# [[a11y_keyboard_monitor.client]] "org.freedesktop.a11y.KeyboardMonitor"
7+
# observe and grab keys. Grant this only to
8+
# assistive tech you trust with every
9+
# keystroke typed in the session, passwords
10+
# included.
11+
#
12+
# Copy this file to a drop-in directory to activate it.
13+
# Use `install -m0644`. The compositor ignores a file left group-writable.
14+
# The compositor reads two drop-in directories, in this order:
15+
#
16+
# /usr/share/cosmic-comp/ei-clients.d/*.toml # for packages
17+
# /etc/cosmic-comp/ei-clients.d/*.toml # for local administration
18+
#
19+
# It applies the files in order of their file name across both directories. A
20+
# file in /etc replaces a file of the same name under /usr/share, so you can mask
21+
# a grant shipped by a package with an empty file of that name in /etc.
22+
#
23+
# The compositor picks up changes at start-up only.
24+
# Log out and back in after editing.
25+
#
26+
# The compositor always allows its own built-in clients, which need no entry
27+
# here: the XDG desktop portal implementation and the on-screen keyboard for
28+
# [ei], Orca for [a11y_keyboard_monitor]. Entries here add access. They cannot
29+
# narrow or remove a built-in.
30+
31+
# The compositor identifies a client by a well-known bus name it owns on the
32+
# session bus. The client must request that name before calling GetSenderSocket.
33+
[[ei.client]]
34+
bus_name = "org.example.MyRemoteTool"
35+
36+
# `device_types` limits what the client may ask for. Omit it and the client may
37+
# request every type. Valid values are "keyboard", "pointer" and "touchscreen".
38+
#
39+
# The client below can move the pointer, but cannot inject keystrokes.
40+
[[ei.client]]
41+
bus_name = "com.example.Kiosk"
42+
device_types = ["pointer"]
43+
44+
# You name a keyboard monitor the same way. There is no `device_types` here.
45+
# The interface carries no per-device policy, so a client watches every key
46+
# or nothing.
47+
[[a11y_keyboard_monitor.client]]
48+
bus_name = "org.example.MyScreenReader"

src/dbus/a11y_keyboard_monitor.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,9 @@ use std::{
1010
};
1111
use tracing::debug;
1212
use xkbcommon::xkb::Keysym;
13-
use zbus::{
14-
message::Header,
15-
names::{UniqueName, WellKnownName},
16-
object_server::SignalEmitter,
17-
};
18-
19-
use super::name_owners::NameOwners;
13+
use zbus::{message::Header, names::UniqueName, object_server::SignalEmitter};
2014

21-
static ALLOWED_NAMES: &[WellKnownName] = &[WellKnownName::from_static_str_unchecked(
22-
"org.gnome.Orca.KeyboardMonitor",
23-
)];
15+
use super::{client_allow_list::NameAllowList, name_owners::NameOwners};
2416

2517
// As defined in at-spi2-core
2618
const ATSPI_DEVICE_A11Y_MANAGER_VIRTUAL_MOD_START: u32 = 15;
@@ -76,19 +68,22 @@ pub struct A11yKeyboardMonitorState {
7668
active_virtual_mods: HashSet<Keysym>,
7769
conn: zbus::Connection,
7870
name_owners: NameOwners,
71+
allow_list: NameAllowList,
7972
}
8073

8174
impl A11yKeyboardMonitorState {
8275
pub async fn new(
8376
conn: &zbus::Connection,
8477
name_owners: &NameOwners,
8578
executor: &calloop::futures::Scheduler<()>,
79+
allow_list: NameAllowList,
8680
) -> zbus::Result<Self> {
8781
let clients = Arc::new(Mutex::new(Clients::default()));
8882

8983
let keyboard_monitor = KeyboardMonitor {
9084
clients: clients.clone(),
9185
name_owners: name_owners.clone(),
86+
allow_list: allow_list.clone(),
9287
};
9388
conn.object_server()
9489
.at("/org/freedesktop/a11y/Manager", keyboard_monitor)
@@ -101,6 +96,7 @@ impl A11yKeyboardMonitorState {
10196
active_virtual_mods: HashSet::new(),
10297
conn: conn.clone(),
10398
name_owners: name_owners.clone(),
99+
allow_list,
104100
})
105101
}
106102

@@ -188,22 +184,26 @@ impl A11yKeyboardMonitorState {
188184
pub fn refresh(&mut self) {
189185
// Remove clients and associated grabs when unique names are no longer
190186
// present on bus, or no longer hold approved name on bus.
191-
self.clients
192-
.lock()
193-
.unwrap()
194-
.0
195-
.retain(|k, _| self.name_owners.check_owner_no_poll(k, ALLOWED_NAMES))
187+
self.clients.lock().unwrap().0.retain(|k, _| {
188+
self.name_owners
189+
.check_owner_no_poll(k, self.allow_list.names())
190+
})
196191
}
197192
}
198193

199194
struct KeyboardMonitor {
200195
clients: Arc<Mutex<Clients>>,
201196
name_owners: NameOwners,
197+
allow_list: NameAllowList,
202198
}
203199

204200
impl KeyboardMonitor {
205201
async fn check_sender_allowed(&self, sender: &UniqueName<'_>) -> zbus::fdo::Result<()> {
206-
if self.name_owners.check_owner(sender, ALLOWED_NAMES).await {
202+
if self
203+
.name_owners
204+
.check_owner(sender, self.allow_list.names())
205+
.await
206+
{
207207
Ok(())
208208
} else {
209209
Err(zbus::fdo::Error::AccessDenied("Access denied".to_string()))

0 commit comments

Comments
 (0)