D-Bus authentication and authorization
D-Bus isn't using the magic cookie file here; it's passing credentials over the UNIX domain socket (SCM_CREDENTIALS
).
The magic cookie file is only one of several D-Bus authentication mechanisms. D-Bus implements a SASL-compliant interface (see RFC4422) to support a wide range of authentication mechanisms. One of these mechanisms is called "EXTERNAL" auth, and it means that the transport channel itself should be used to guarantee authentication. At least in the case of D-Bus over UNIX sockets, this appears to be the first authentication mechanism that is tried.
From the D-Bus spec:
Special credentials-passing nul byte
Immediately after connecting to the server, the client must send a single nul byte. This byte may be accompanied by credentials information on some operating systems that use sendmsg() with SCM_CREDS or SCM_CREDENTIALS to pass credentials over UNIX domain sockets. However, the nul byte must be sent even on other kinds of socket, and even on operating systems that do not require a byte to be sent in order to transmit credentials. The text protocol described in this document begins after the single nul byte. If the first byte received from the client is not a nul byte, the server may disconnect that client.
A nul byte in any context other than the initial byte is an error; the protocol is ASCII-only.
The credentials sent along with the nul byte may be used with the SASL mechanism EXTERNAL.
If you strace an instance of dbus-daemon
, you can see that when you connect to it, it checks the credentials of the connecting user:
$ strace dbus-daemon --session --nofork
...
accept4(4, {sa_family=AF_LOCAL, NULL}, [2], SOCK_CLOEXEC) = 8
...
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\0", 1}], msg_controllen=0, msg_flags=0}, 0) = 1
getsockopt(8, SOL_SOCKET, SO_PEERCRED, {pid=6694, uid=1000, gid=1000}, [12]) = 0
So to answer your questions:
-
The D-Bus daemon is using your kernel-verified user ID to verify your identity. By using
socat
to proxy connections, you are letting anybody connect to the D-Bus daemon using your UID. -
If you try to connect directly to the socket from another UID, the daemon recognizes that the connecting UID is not a UID that is supposed to be allowed to connect. I believe the default is that only the daemon's own UID is allowed, but haven't formally verified that. You can allow other users, though: see the configuration files in
/etc/dbus-1/
, and alsoman dbus-daemon
. -
This is the D-Bus server replacing old/expired cookies with new ones. According to the DBUS_COOKIE_SHA1 section of the D-Bus spec, a cookie is stored along with its creation time, and the server is supposed to delete cookies that it decides are too old. Apparently the lifetime "can be fairly short".
Related videos on Youtube
Gilles 'SO- stop being evil'
Updated on September 18, 2022Comments
-
Gilles 'SO- stop being evil' over 1 year
I'm trying to set up remote access to D-Bus, and I don't understand how authentication and authorization are (not) working.
I have a D-Bus server listening on an abstract socket.
$ echo $DBUS_SESSION_BUS_ADDRESS unix:abstract=/tmp/dbus-g5sxxvDlmz,guid=49bd93b893fe40d83604952155190c31
I run
dbus-monitor
to watch what's going on. My test case isnotify-send hello
, which works when executed from the local machine.From another account on the same machine, I can't connect to that bus.
otheraccount$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-g5sxxvDlmz,guid=49bd93b893fe40d83604952155190c31 dbus-monitor Failed to open connection to session bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken. otheraccount$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-g5sxxvDlmz,guid=49bd93b893fe40d83604952155190c31 notify-send hello
After browsing the D-Bus specification, I copied
~/.dbus-keyrings/org_freedesktop_general
to the other account, but it doesn't help.I tried forwarding the D-Bus socket over TCP, inspired by schedar's Access D-Bus remotely using socat.
socat TCP-LISTEN:8004,reuseaddr,fork,range=127.0.0.1/32 ABSTRACT-CONNECT:/tmp/dbus-g5sxxvDlmz
I can connect to the TCP socket from my account.
DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=8004 notify-send hello
But not from the other account, neither with
dbus-monitor
nor withnotify-send
. Same error message fordbus-monitor
as above with the abstract socket;notify-send
now emits a trace:otheraccount$ DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=8004 notify-send hello ** (notify-send:2952): WARNING **: The connection is closed
Stracing reveals that this version of
notify-send
doesn't try to read the cookie file, so I understand why it wouldn't be able to connect.I also tried SSHing into another machine and forwarding the TCP connection.
ssh -R 8004:localhost:8004 remotehost
Surprisingly,
dbus-monitor
works without a cookie file! I can watch the D-Bus traffic from the remote host. I see a notice about eavesdropping in my localdbus-monitor
instance.remotehost$ DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=8004 dbus-monitor signal sender=org.freedesktop.DBus -> dest=:1.58 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired string ":1.58" method call sender=:1.58 -> dest=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch string "eavesdrop=true"
If I run
notify-send
on the local machine,dbus-monitor
on the remote host sees the notification. It's definitely reached a level of access that should require authentication.notify-send
complained about not finding a cookie. After copying the cookie file,notify-send
works from the remote machine.The local machine runs Debian wheezy. The remote machine runs FreeBSD 10.1.
I don't understand how D-Bus authentication and authorization work.
- Why can I eavesdrop, as far as I can tell, with no credentials from the remote machine? What am I exposing when I forward D-Bus to a TCP connection? Why are authorizations for
dbus-monitor
andnotify-send
different? - Why can I not eavesdrop from another account on the same machine, whether over the abstract socket or over the TCP connection?
- I noticed that the cookie file changes every few minutes (I haven't figured out if it's at regular intervals or not). Why?
(I know I can launch a D-Bus daemon that listens on TCP. That's not the purpose of my question, I want to understand why what I did did and did not work.)
- Why can I eavesdrop, as far as I can tell, with no credentials from the remote machine? What am I exposing when I forward D-Bus to a TCP connection? Why are authorizations for
-
Vasiliy Faronov almost 8 yearsThe reference implementation of D-Bus does not use
SCM_CREDENTIALS
specifically. On Linux, it uses theSO_PEERCRED
socket option instead. -
Jander almost 8 years@VasiliyFaronov You're right -- how interesting! Further, it looks like using
SCM_CREDENTIALS
would have prevented such a simple proxy, since it requires the sender to actively present its credentials, whereasSO_PEERCRED
merely checks who made the connection. I wonder why they made this choice. -
Vasiliy Faronov almost 8 yearsApparently because it “does not require the peer's cooperation,” so “this is much less fragile” (from comments in
dbus-sysdeps-unix.c
).