fix: authorize service calls through polkit #47
Loading…
Reference in a new issue
No description provided.
Delete branch "mysticalsoap/fix/dbus-policy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
#18: the shipped policy's
context="default"block allowssend_destination="org.aqomui.service", so any local user can invoke every method on the root service — includingcfgupdate(writes caller bytes to a root-owned file),change_ovpn_config(copies from caller-chosen paths), andconnect_to_server/import_thread(subprocess execution from untrusted dicts).Fix
Per-method polkit authorization, the pattern NetworkManager and friends use — the desktop user needs no group membership or any other setup:
systemd/org.aqomui.service.policy: new polkit actionorg.aqomui.service.manage, defaultsallow_active=yes/allow_inactive=no/allow_any=no— the user at an active local session is allowed, everyone else (SSH, other accounts) is refused. Headless use needs a polkit rule granting the action.aqomui_service.py: every D-Bus method exceptget_versionnow passes the bus sender torequire_authorization(), which asks polkitCheckAuthorization(no-interaction flags, so a denied caller fails immediately instead of hanging the single-threaded service on an auth prompt). Denials raiseorg.aqomui.service.NotAuthorized. Internal calls (sender=None) skip the check — the bus always sets the sender for external calls. If polkit itself is unreachable the service refuses rather than allows.systemd/org.aqomui.service.conf: the bus policy stays open by design so the service can identify callers — authorization lives in polkit now, and the conf says so in a comment.aqomui_gui.py/aqomui_cli.py: both first-party clients report aNotAuthorizeddenial cleanly (the GUI notifies; the CLI prints a one-line message and exits non-zero) instead of surfacing the raw D-Bus error / a traceback..policyfile and gains apolkitdep (already a de-facto dep — the GUI usespkexec); README documents the model and the headless caveat.An earlier revision of this branch used a dedicated
aqomuigroup in the bus policy instead; replaced wholesale after review discussion — polkit removes theusermod+ re-login friction and distinguishes the physically-present user from other local accounts, which a group can't.This is still only part of #18: server-side input validation (provider whitelisting, path canonicalization, the
setattrnamespace issue) remains open there.Related fixes (found along the way, technically out of scope)
aqomui-cli -tprintedSuccessfully disconnectedbefore it had actually issued the disconnect, so a failure (like the new deny) printed a false success followed by an error. The print now follows the call.Verification
python -W error::SyntaxWarning -m compileall aqomui/clean; CI runs pytest/ruff.policyfile validates against the local polkit DTD and matches theallow_activeshape of installed system actionsaqomui-cli -tdisconnects cleanly and connecting to a VPN through the app worksorg.aqomui.service.NotAuthorized: caller is not authorized for org.aqomui.service.manageCheckAuthorizationmarshaling (subject/details/flags typing) and theallow_activesemantics were also exercised directly against the host's live polkit daemonallow_active: a process with no login session (e.g. asystemd --userunit) owned by a user who has an active session is authorized — polkit's documented no-session fallback. That is the authorized user's own automation acting as themselves, not the cross-user / inactive-session case #18 is about, so it's intended rather than a gap.Refs #18
Assisted-by: claude-fable-5
fix: restrict the D-Bus policy to a dedicated aqomui groupto fix: authorize service calls through polkit334a970673207f9c4ad4207f9c4ad4c34c6b34df