D-Bus身份验证和授权


13

我正在尝试设置对D-Bus的远程访问,但我不了解身份验证和授权的工作方式(不)。

我有一台D-Bus服务器在抽象套接字上侦听。

$ echo $DBUS_SESSION_BUS_ADDRESS 
unix:abstract=/tmp/dbus-g5sxxvDlmz,guid=49bd93b893fe40d83604952155190c31

我跑去dbus-monitor看发生了什么。我的测试用例是notify-send hello,当从本地计算机执行时可以工作。

从同一台计算机上的另一个帐户,我无法连接到该总线。

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

浏览D-Bus规范后,我已复制~/.dbus-keyrings/org_freedesktop_general到另一个帐户,但这无济于事。

我试图转发d总线插槽通过TCP,灵感来自schedar访问d-Bus的远程使用socat

socat TCP-LISTEN:8004,reuseaddr,fork,range=127.0.0.1/32 ABSTRACT-CONNECT:/tmp/dbus-g5sxxvDlmz

我可以从我的帐户连接到TCP套接字。

DBUS_SESSION_BUS_ADDRESS=tcp:host=127.0.0.1,port=8004 notify-send hello

但不能从另一个帐户获得,也不能与dbus-monitor或一起使用notify-send。与dbus-monitor上述抽象套接字相同的错误消息;notify-send现在发出跟踪:

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揭示此版本的notify-send不会尝试读取cookie文件,因此我了解为什么它无法连接。

我还尝试了SSH进入另一台计算机并转发TCP连接。

ssh -R 8004:localhost:8004 remotehost

令人惊讶的是,dbus-monitor没有cookie文件就可以工作!我可以查看来自远程主机的D-Bus通信。我看到有关在本地dbus-monitor实例中进行监听的通知。

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"

如果我notify-send在本地计算机dbus-monitor上运行,则在远程主机上会看到通知。绝对达到了需要身份验证的访问级别。

notify-send抱怨找不到饼干。复制cookie文件后,notify-send可以在远程计算机上工作。

本地计算机运行Debian wheezy。远程机器运行FreeBSD 10.1。

我不了解D-Bus身份验证和授权的工作方式。

  1. 据我所知,为什么我可以在没有远程计算机凭据的情况下进行监听?将D-Bus转发到TCP连接时我要暴露什么?为什么是授权dbus-monitornotify-send不同?
  2. 为什么无论是通过抽象套接字还是通过TCP连接,都无法从同一计算机上的另一个帐户进行窃听?
  3. 我注意到cookie文件每隔几分钟就会更改一次(我不确定是否有规律的间隔)。为什么?

(我知道我可以启动一个侦听TCP的D-Bus守护程序。这不是我提出问题的目的,我想了解为什么我做到了却没起作用。)

Answers:


7

D-Bus在这里不使用魔术cookie文件;它通过UNIX域套接字(SCM_CREDENTIALS)传递凭据。

魔术cookie文件只是几种D-Bus身份验证机制之一。D-Bus实现了SASL兼容接口(请参阅RFC4422),以支持各种身份验证机制。这些机制之一称为“ EXTERNAL”身份验证,这意味着应该使用传输通道本身来保证身份验证。至少在通过UNIX套接字进行D-Bus的情况下,这似乎是尝试使用的第一种身份验证机制。

根据D-Bus规范:

特殊凭证传递的nul字节

连接到服务器后,客户端必须立即发送单个nul字节。在某些使用sendmsg()和SCM_CREDS或SCM_CREDENTIALS来通过UNIX域套接字传递凭据的操作系统上,此字节可能伴随有凭据信息。但是,即使在其他类型的套接字上,甚至在不需要发送字节即可传输凭据的操作系统上,也必须发送nul字节。本文档中描述的文本协议在单个nul字节之后开始。如果从客户端收到的第一个字节不是空字节,则服务器可能会断开该客户端的连接。

除初始字节外的任何上下文中的nul字节都是错误;该协议仅是ASCII。

与空字节一起发送的凭证可以与SASL机制EXTERNAL一起使用。

如果跟踪的实例dbus-daemon,则可以看到在连接到该实例时,它将检查连接用户的凭据:

$ 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

因此,回答您的问题:

  1. D-Bus守护程序正在使用您的内核验证的用户ID来验证您的身份。通过使用socat代理连接,您可以让任何人使用您的UID连接到D-Bus守护程序。

  2. 如果尝试从另一个UID直接连接到套接字,则守护程序会识别出正在连接的UID不是应该允许连接的UID。我相信默认值是仅允许守护程序自己的UID,但尚未正式验证。不过,您可以允许其他用户使用:在/etc/dbus-1/和中查看配置文件man dbus-daemon

  3. 这是D-Bus服务器,用新的替换旧的/过期的cookie。根据D-Bus规范的DBUS_COOKIE_SHA1部分,将存储cookie及其创建时间,并且服务器应删除它认为过旧的cookie。显然,生命周期“可能很短”。


D-Bus的参考实现未SCM_CREDENTIALS专门使用。在Linux上,它改用SO_PEERCREDsocket选项。
Vasiliy Faronov '16

@VasiliyFaronov你是对的-多么有趣!此外,由于使用SCM_CREDENTIALS它需要发件人主动提供其凭据,而SO_PEERCRED仅检查谁进行了连接,因此似乎使用会阻止这种简单的代理。我不知道他们为什么做出这个选择。
詹德(Jander)2016年

显然是因为它“不需要同行的合作”,所以“这不那么脆弱”(来自中的评论dbus-sysdeps-unix.c)。
Vasiliy Faronov '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.