D-Bus service activation and access control
dbus at lists.topphemmelig.net
Fri Jul 28 11:16:21 UTC 2017
I've started to look into the aspects of service activation as well as
tightening the access control for the brand new OpenVPN client. So back
from holidays, I've started pondering again and need to gain deeper
The current design so far consists of three "independent" executables,
all using the /system bus/. Independent in the sense of running with
separate PIDs and memory scopes; only communicating with each other via
a) configuration manager (bus name: net.openvpn.v3.configuration)
b) session manager (bus name: net.openvpn.v3.session)
c) client VPN process (bus name: net.openvpn.v3.be$PID)
To establish a connection, the unprivileged end user loads a
configuration file into the configuration manager, and retrieves a
unique object path for it. Then the user connects to the session
manager and calls a NewTunnel method and provides the configuration path.
The session manager registers a new session object and starts the client
VPN process with a token value. This client issues a signal to the
session manager with its bus name together with the token value. Which
then updates the session object with the correct backend details and
responds to the backend by calling a RegistrationComplete method in the
>From this point of, the end-user only "talks" to the session manager to
manage the backend client process. And it proxies signals from the
backend to processes listening to signals from the session manager.
This works quite well. And I have also managed to get the configuration
and session managers to be activated via D-Bus.
So to the questions :)
** System bus vs session bus coupled with D-Bus activation
There are two types of configuration files: System wide and user
specific. The system wide configurations are to be used by any user on
the system; while the user specific configurations should be isolated to
a particular user (uid).
What I wonder is if the session manager, being started via D-Bus
activation, can it connect to a user's session bus? And could this work
across users? This could enable running two different instances of the
configuration manager; session bus for user only configuration and
system bus for system wide configurations. When connecting to the
session manager for a user specific configuration it will require a
logged in user - so the session bus is expected to be available.
(The reason for having the configuration manager, is to ensure all data
loaded from various files are available without requiring the backend
client processes to load data from /home/johndoe/.cert - or similar
restricted file locations + interacting with PKCS#11/smartcards happens
via a user managed process)
** If system/session bus mixture approach is not viable
For user specific configurations, could one alternative approach be to
make use of the GCredentials API and "tag" configurations to a specific
user on the configuration object ... and deny access if an invalid
(read: unexpected) user attempts to access the configuration object?
And will this work when the session manager is activated on the system
bus by one user and accessed by another user? It is the session manager
which connects to the configuration manager when retrieving the
** Providing arguments to the D-Bus activated service
Is it possible to provide arguments during the activation of a service?
I'm working on reducing the privileges of the session manager. Currently
I've managed to execute the client backend process by fork()ing out a
process from the session manager running as the openvpn user. It
execve() /usr/bin/pkexec, which then starts the client backend as root.
I have a simple polkit policy allowing the openvpn user to allow this.
If the backends process could get the token value it needs to register
with the session manager, the backend client process could also be D-Bus
activated, with User=root. The token value does not need to be
transported as a command line argument, the communication channel is not
important in this case.
Another and far more complex solution could be that the backend client
processes are started without any arguments and issues a generic signal
to the session manager triggering the session manager to pass the needed
information. But this needs a very careful design to avoid race
conditions if many VPN tunnels are started in parallel; it requires the
session manager to much more carefully track which backend clients have
been started and whom have/have not completed the registration and
follow up on those. With the current design, the process is tied
directly to a session object at the fork() time.
More information about the dbus