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-Bus по TCP, вдохновленный доступом D-Bus от Schedar , с помощью 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, поэтому я понимаю, почему он не сможет подключиться.

Я также попытался использовать SSHing на другой машине и переслать 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-monitorи notify-sendразные?
  2. Почему я не могу прослушать другую учетную запись на том же компьютере, будь то через абстрактный сокет или через соединение TCP?
  3. Я заметил, что файл cookie меняется каждые несколько минут (я не понял, регулярно ли он или нет). Почему?

(Я знаю, что могу запустить демон D-Bus, который слушает TCP. Это не цель моего вопроса, я хочу понять, почему то, что я сделал, и не сработало.)

Жиль "ТАК - прекрати быть злым"
источник

Ответы:

7

D-Bus здесь не использует волшебный файл cookie; он передает учетные данные через сокет домена UNIX ( SCM_CREDENTIALS).

Волшебный cookie-файл является лишь одним из нескольких механизмов аутентификации D-Bus. D-Bus реализует интерфейс, совместимый с SASL (см. RFC4422 ), для поддержки широкого спектра механизмов аутентификации. Один из этих механизмов называется «EXTERNAL» auth, и это означает, что сам транспортный канал должен использоваться для гарантии аутентификации. По крайней мере, в случае D-Bus через сокеты UNIX, это, кажется, первый проверенный механизм аутентификации.

Из спецификации D-Bus:

Специальные учетные данные, передаваемые nul byte

Сразу после подключения к серверу клиент должен отправить один нуль-байт. Этот байт может сопровождаться информацией об учетных данных в некоторых операционных системах, которые используют sendmsg () с SCM_CREDS или SCM_CREDENTIALS для передачи учетных данных через сокеты домена UNIX. Однако нулевой байт должен быть отправлен даже в другие виды сокетов и даже в операционных системах, которые не требуют отправки байта для передачи учетных данных. Текстовый протокол, описанный в этом документе, начинается после единственного нулевого байта. Если первый байт, полученный от клиента, не равен нулю, сервер может отключить этого клиента.

Нулевой байт в любом контексте, кроме начального байта, является ошибкой; протокол только для 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 использует проверенный ядром идентификатор пользователя для подтверждения вашей личности. Используя socatпрокси-соединения, вы позволяете кому-либо подключаться к демону D-Bus, используя ваш UID.

  2. Если вы попытаетесь подключиться напрямую к сокету с другого UID, демон распознает, что UID подключения не является UID, которому, как предполагается, разрешено подключаться. Я считаю, что по умолчанию разрешено использовать только собственный UID демона, но формально это не проверено. Вы можете разрешить другим пользователям: увидеть файлы конфигурации в /etc/dbus-1/, а также man dbus-daemon.

  3. Это сервер D-Bus, заменяющий старые / просроченные файлы cookie новыми. Согласно разделу DBUS_COOKIE_SHA1 спецификации D-Bus, cookie сохраняется вместе со временем его создания, и сервер должен удалять cookie, которые, по его мнению, являются слишком старыми. Видимо, срок службы "может быть довольно коротким".

Jander
источник
Эталонная реализация D-Bus не использует SCM_CREDENTIALSспециально. В Linux SO_PEERCREDвместо этого используется опция сокета.
Василий Фаронов
@VasiliyFaronov Вы правы - как интересно! Кроме того, похоже, что использование SCM_CREDENTIALSпомешало бы такому простому прокси-серверу, поскольку оно требует от отправителя активно представлять свои учетные данные, а SO_PEERCREDпросто проверяет, кто установил соединение. Интересно, почему они сделали этот выбор?
Джандер
Очевидно, потому что это «не требует сотрудничества со стороны сверстников», поэтому «это гораздо менее хрупко» (из комментариев в dbus-sysdeps-unix.c).
Василий Фаронов