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 (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-monitorpara ver o que está acontecendo. Meu caso de teste é o notify-send helloque funciona quando executado a partir da 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 D-Bus , copiei ~/.dbus-keyrings/org_freedesktop_generalpara a outra conta, mas isso não ajuda.

Tentei encaminhar tomada de D-Bus através de TCP, inspirado por Schedar de Acesso D-Bus remotamente usando 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-monitornem com notify-send. A mesma mensagem de erro dbus-monitorcomo acima com o soquete abstrato; notify-sendagora emite um rastreio:

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

** (notify-send:2952): WARNING **: The connection is closed

O Stracing revela que esta versão do notify-sendnão tenta ler o arquivo de cookies, então eu entendo por que ele não conseguiu se conectar.

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

ssh -R 8004:localhost:8004 remotehost

Surpreendentemente, dbus-monitorfunciona sem um arquivo de cookie! Eu posso assistir o tráfego do D-Bus no host remoto. Eu vejo um aviso sobre a escuta na minha dbus-monitorinstância local .

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-sendna máquina local, dbus-monitoro host remoto verá a notificação. Definitivamente, alcançou um nível de acesso que deve exigir autenticação.

notify-sendreclamou por não encontrar um cookie. Depois de copiar o arquivo de cookie, notify-sendfunciona a partir da máquina remota.

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

Não entendo como a autenticação e autorização do D-Bus funcionam.

  1. Por que posso escutar, até onde sei, 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 dbus-monitore são notify-senddiferentes?
  2. Por que não posso escutar de outra conta na mesma máquina, seja pelo soquete abstrato ou pela conexão TCP?
  3. Percebi que o arquivo do cookie muda a cada poucos minutos (não descobri se é em intervalos regulares ou não). Por quê?

(Eu sei que posso iniciar um daemon D-Bus que escute no TCP. Esse não é o objetivo da minha pergunta. Quero entender por que o que fiz e o que não fiz).

Gilles 'SO- parar de ser mau'
fonte

Respostas:

7

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

O arquivo de cookie mágico é apenas um dos vários mecanismos de autenticação D-Bus. O D-Bus implementa uma interface compatível com SASL (consulte RFC4422 ) para suportar uma ampla variedade de mecanismos de autenticação. Um desses mecanismos é chamado de autenticação "EXTERNA" 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 soquetes UNIX, esse parece ser o primeiro mecanismo de autenticação tentado.

A partir da especificação D-Bus:

Bytes de nul de passagem de credenciais especiais

Imediatamente após a conexão com o servidor, o cliente deve enviar um único byte nulo. Esse byte pode ser acompanhado por informações sobre credenciais em alguns sistemas operacionais que usam sendmsg () com SCM_CREDS ou SCM_CREDENTIALS para passar credenciais em soquetes de domínio UNIX. No entanto, o nul byte deve ser enviado mesmo em outros tipos de soquete e até mesmo em sistemas operacionais que não exigem o envio de um byte para transmitir credenciais. O protocolo de texto descrito neste documento começa após o único byte nul. Se o primeiro byte recebido do cliente não for um nulo, o servidor poderá desconectar esse cliente.

Um byte nulo em qualquer contexto que não seja o byte inicial é um erro; o protocolo é somente ASCII.

As credenciais enviadas junto com o byte nul podem ser usadas com o mecanismo SASL EXTERNAL.

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

$ 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

Então, para responder às suas perguntas:

  1. O daemon D-Bus está usando seu ID de usuário verificado pelo kernel para verificar sua identidade. Ao usar socatconexões proxy, você permite que alguém se conecte ao daemon D-Bus usando seu UID.

  2. Se você tentar se conectar diretamente ao soquete a partir 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 apenas o UID do daemon é permitido, mas não o verificamos 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 os cookies antigos / expirados pelos novos. De acordo com a seção DBUS_COOKIE_SHA1 da especificação do D-Bus, um cookie é armazenado junto com o tempo de criação, e o servidor deve excluir os cookies que julgar muito antigos. Aparentemente, a vida "pode ​​ser bastante curta".

Jander
fonte
A implementação de referência do D-Bus não usa SCM_CREDENTIALSespecificamente. No Linux, ele usa a SO_PEERCREDopção de soquete.
Vasiliy Faronov 07/07
@VasiliyFaronov Você está certo - que interessante! Além disso, parece que o uso SCM_CREDENTIALSteria impedido um proxy tão simples, pois exige que o remetente apresente ativamente suas credenciais, enquanto SO_PEERCREDapenas verifica quem fez a conexão. Eu me pergunto por que eles fizeram essa escolha.
Jander
Aparentemente, porque “não requer a cooperação de pares”, então “isso é muito menos frágil” (dos comentários em dbus-sysdeps-unix.c).
Vasiliy Faronov