Autenticación y autorización de D-Bus

13

Estoy tratando de configurar el acceso remoto a D-Bus, y no entiendo cómo funcionan (no) la autenticación y la autorización.

Tengo un servidor D-Bus escuchando en un socket abstracto.

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

Corro dbus-monitora ver lo que está pasando. Mi caso de prueba es notify-send hello, que funciona cuando se ejecuta desde la máquina local.

Desde otra cuenta en la misma máquina, no puedo conectarme a ese 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

Después de examinar la especificación de D-Bus , copié ~/.dbus-keyrings/org_freedesktop_generala la otra cuenta, pero no ayuda.

He intentado enviar el zócalo de D-Bus a través de TCP, inspirado por Schedar 's Acceso D-Bus de forma remota utilizando socat .

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

Puedo conectarme al socket TCP desde mi cuenta.

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

Pero no de la otra cuenta, ni con dbus-monitorni con notify-send. Mismo mensaje de error para el dbus-monitoranterior con el socket abstracto; notify-sendahora emite un rastro:

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 versión de notify-sendno intenta leer el archivo de cookies, por lo que entiendo por qué no podría conectarse.

También probé SSHing en otra máquina y reenvié la conexión TCP.

ssh -R 8004:localhost:8004 remotehost

Sorprendentemente, dbus-monitorfunciona sin un archivo de cookies. Puedo ver el tráfico de D-Bus desde el host remoto. Veo un aviso sobre espionaje en mi dbus-monitorinstancia 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"

Si ejecuto notify-senden la máquina local, dbus-monitoren el host remoto ve la notificación. Definitivamente ha alcanzado un nivel de acceso que debería requerir autenticación.

notify-sendse quejó de no encontrar una cookie. Después de copiar el archivo cookie, notify-sendfunciona desde la máquina remota.

La máquina local ejecuta Debian wheezy. La máquina remota ejecuta FreeBSD 10.1.

No entiendo cómo funcionan la autenticación y autorización de D-Bus.

  1. ¿Por qué puedo espiar, hasta donde puedo decir, sin credenciales de la máquina remota? ¿Qué expongo cuando reenvío D-Bus a una conexión TCP? ¿Por qué las autorizaciones para dbus-monitory notify-senddiferentes?
  2. ¿Por qué no puedo espiar desde otra cuenta en la misma máquina, ya sea a través del socket abstracto o por la conexión TCP?
  3. Noté que el archivo de cookies cambia cada pocos minutos (no he descubierto si es a intervalos regulares o no). ¿Por qué?

(Sé que puedo lanzar un demonio D-Bus que escucha en TCP. Ese no es el propósito de mi pregunta, quiero entender por qué lo que hice y no funcionó).

Gilles 'SO- deja de ser malvado'
fuente

Respuestas:

7

D-Bus no está usando el archivo de cookies mágico aquí; está pasando credenciales sobre el socket de dominio UNIX ( SCM_CREDENTIALS).

El archivo de cookies mágico es solo uno de varios mecanismos de autenticación de D-Bus. D-Bus implementa una interfaz compatible con SASL (consulte RFC4422 ) para admitir una amplia gama de mecanismos de autenticación. Uno de estos mecanismos se denomina autenticación "EXTERNA", y significa que el canal de transporte en sí debe usarse para garantizar la autenticación. Al menos en el caso de D-Bus sobre sockets UNIX, este parece ser el primer mecanismo de autenticación que se prueba.

De la especificación D-Bus:

Credenciales especiales que pasan byte nul

Inmediatamente después de conectarse al servidor, el cliente debe enviar un solo byte nulo. Este byte puede ir acompañado de información de credenciales en algunos sistemas operativos que usan sendmsg () con SCM_CREDS o SCM_CREDENTIALS para pasar credenciales a través de sockets de dominio UNIX. Sin embargo, el byte nulo debe enviarse incluso en otros tipos de socket e incluso en sistemas operativos que no requieren que se envíe un byte para transmitir credenciales. El protocolo de texto descrito en este documento comienza después del byte nulo único. Si el primer byte recibido del cliente no es un byte nulo, el servidor puede desconectar ese cliente.

Un byte nulo en cualquier contexto que no sea el byte inicial es un error; el protocolo es solo ASCII.

Las credenciales enviadas junto con el byte nulo pueden usarse con el mecanismo SASL EXTERNO.

Si selecciona una instancia de dbus-daemon, puede ver que cuando se conecta a ella, verifica las credenciales del usuario que se conecta:

$ 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

Entonces para responder a sus preguntas:

  1. El demonio D-Bus está utilizando su ID de usuario verificado por el núcleo para verificar su identidad. Al usar socatconexiones proxy, está permitiendo que cualquiera se conecte al demonio D-Bus usando su UID.

  2. Si intenta conectarse directamente al socket desde otro UID, el demonio reconoce que el UID de conexión no es un UID que se supone que debe conectarse. Creo que el valor predeterminado es que solo se permite el UID del propio demonio, pero no lo hemos verificado formalmente. Sin embargo, puede permitir a otros usuarios: ver los archivos de configuración en /etc/dbus-1/, y también man dbus-daemon.

  3. Este es el servidor D-Bus que reemplaza las cookies antiguas / caducadas por otras nuevas. De acuerdo con la sección DBUS_COOKIE_SHA1 de la especificación D-Bus, una cookie se almacena junto con su tiempo de creación, y se supone que el servidor elimina las cookies que considera que son demasiado antiguas. Al parecer, la vida útil "puede ser bastante corta".

Jander
fuente
La implementación de referencia de D-Bus no se usa SCM_CREDENTIALSespecíficamente. En Linux, utiliza la SO_PEERCREDopción de socket en su lugar.
Vasiliy Faronov
@VasiliyFaronov Tienes razón, ¡qué interesante! Además, parece que el uso SCM_CREDENTIALShabría evitado un proxy tan simple, ya que requiere que el remitente presente activamente sus credenciales, mientras que SO_PEERCREDsimplemente verifica quién realizó la conexión. Me pregunto por qué hicieron esta elección.
Jander
Aparentemente porque "no requiere la cooperación de los pares", entonces "esto es mucho menos frágil" (de los comentarios en dbus-sysdeps-unix.c).
Vasiliy Faronov