Autenticação e autorização D-Bus

13

Estou tentando configurar o acesso remoto ao D-Bus e não entendo como a autenticação e a autorização estão (e não) funcionando.

Eu tenho um servidor D-Bus escutando em um soquete abstrato.

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

Eu corro dbus-monitor para ver o que está acontecendo. Meu caso de teste é notify-send hello , que funciona quando executado na máquina local.

De outra conta na mesma máquina, não consigo me conectar a esse barramento.

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

Depois de navegar na especificação do D-Bus , copiei ~/.dbus-keyrings/org_freedesktop_general para a outra conta , mas isso não ajuda.

Eu tentei encaminhar o soquete D-Bus via TCP, inspirado pelo programa 's Acesse o D-Bus remotamente usando o socat .

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

Eu posso conectar ao soquete TCP da minha conta.

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

Mas não da outra conta, nem com dbus-monitor nem com notify-send . Mesma mensagem de erro para dbus-monitor como acima com o soquete abstrato; notify-send agora emite um traço:

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 revela que esta versão de notify-send não tenta ler o arquivo de cookie, então eu entendo por que ele não seria capaz de se conectar.

Eu também tentei o SSHing em outra máquina e encaminhei a conexão TCP.

ssh -R 8004:localhost:8004 remotehost

Surpreendentemente, dbus-monitor funciona sem um arquivo de cookie! Eu posso assistir ao tráfego D-Bus do host remoto. Eu vejo um aviso sobre espionagem na minha instância local 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"

Se eu executar notify-send na máquina local, dbus-monitor no host remoto verá a notificação. Definitivamente atingiu um nível de acesso que deve exigir autenticação.

notify-send reclamou sobre não encontrar um cookie. Depois de copiar o arquivo de cookie, notify-send funciona da máquina remota.

A máquina local roda Debian wheezy. A máquina remota executa o FreeBSD 10.1.

Eu não entendo como funciona a autenticação e a autorização do D-Bus.

  1. Por que eu posso espionar, até onde posso dizer, sem credenciais da máquina remota? O que estou expondo quando encaminhar o D-Bus para uma conexão TCP? Por que as autorizações para dbus-monitor e notify-send são diferentes?
  2. Por que não posso espionar de outra conta na mesma máquina, seja pelo soquete abstrato ou pela conexão TCP?
  3. Percebi que o arquivo de cookie muda a cada poucos minutos (não entendi se está em intervalos regulares ou não). Por quê?

(Eu sei que posso iniciar um daemon D-Bus que ouve no TCP. Esse não é o propósito da minha pergunta, eu quero entender por que o que eu fiz e não funcionou.)

    
por Gilles 04.04.2015 / 02:51

1 resposta

6

O D-Bus não está usando o arquivo magic cookie aqui; está passando as credenciais pelo soquete do domínio UNIX ( SCM_CREDENTIALS ).

O arquivo magic cookie é apenas um dos vários mecanismos de autenticação do D-Bus. O D-Bus implementa uma interface compatível com o SASL (veja RFC4422 ) para suportar uma ampla gama de mecanismos de autenticação. Um desses mecanismos é chamado de autenticação "EXTERNAL" e significa que o próprio canal de transporte deve ser usado para garantir a autenticação. Pelo menos no caso do D-Bus sobre sockets UNIX, este parece ser o primeiro mecanismo de autenticação que é tentado.

Da especificação do D-Bus:

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.

Se você rastrear uma instância de dbus-daemon , poderá ver que, ao se conectar a ela, ela verifica as credenciais do usuário conectado:

$ 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)=[{"
$ 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)=[{"%pre%", 1}], msg_controllen=0, msg_flags=0}, 0) = 1
getsockopt(8, SOL_SOCKET, SO_PEERCRED, {pid=6694, uid=1000, gid=1000}, [12]) = 0
", 1}], msg_controllen=0, msg_flags=0}, 0) = 1 getsockopt(8, SOL_SOCKET, SO_PEERCRED, {pid=6694, uid=1000, gid=1000}, [12]) = 0

Então, responda suas perguntas:

  1. O daemon D-Bus está usando seu ID de usuário verificado pelo kernel para verificar sua identidade. Usando socat para conexões proxy, você está permitindo que qualquer um se conecte ao daemon D-Bus usando seu UID.

  2. Se você tentar se conectar diretamente ao soquete de outro UID, o daemon reconhecerá que o UID de conexão não é um UID que deve ter permissão para se conectar. Acredito que o padrão é que somente o próprio UID do daemon é permitido, mas não o verificaram formalmente. Você pode permitir outros usuários: veja os arquivos de configuração em /etc/dbus-1/ e também man dbus-daemon .

  3. Este é o servidor D-Bus que substitui cookies antigos / expirados por novos. De acordo com a seção DBUS_COOKIE_SHA1 da especificação D-Bus, um cookie é armazenado juntamente com o tempo de criação, e o servidor deve excluir os cookies que considera antigos demais. Aparentemente, o tempo de vida "pode ser bastante curto".

por 03.05.2015 / 13:02