Otentikasi dan otorisasi D-Bus

13

Saya mencoba mengatur akses jarak jauh ke D-Bus, dan saya tidak mengerti bagaimana otentikasi dan otorisasi (tidak) berfungsi.

Saya memiliki server D-Bus yang mendengarkan pada soket abstrak.

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

Saya berlari dbus-monitoruntuk menonton apa yang terjadi. Kasing uji saya adalah notify-send hello, yang berfungsi saat dijalankan dari mesin lokal.

Dari akun lain di mesin yang sama, saya tidak dapat terhubung ke bus itu.

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

Setelah menelusuri spesifikasi D-Bus , saya menyalin ~/.dbus-keyrings/org_freedesktop_generalke akun lain, tetapi itu tidak membantu.

Saya mencoba meneruskan soket D-Bus melalui TCP, terinspirasi oleh schedar 's Access D-Bus dari jarak jauh menggunakan socat .

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

Saya dapat terhubung ke soket TCP dari akun saya.

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

Tapi bukan dari akun lain, baik dengan dbus-monitormaupun dengan notify-send. Pesan kesalahan yang sama dbus-monitorseperti di atas dengan soket abstrak; notify-sendsekarang memancarkan jejak:

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 mengungkapkan bahwa versi notify-sendini tidak mencoba membaca file cookie, jadi saya mengerti mengapa itu tidak dapat terhubung.

Saya juga mencoba SSHing ke komputer lain dan meneruskan koneksi TCP.

ssh -R 8004:localhost:8004 remotehost

Anehnya, dbus-monitorbekerja tanpa file cookie! Saya dapat menonton lalu lintas D-Bus dari host jarak jauh. Saya melihat pemberitahuan tentang menguping dalam dbus-monitorcontoh lokal saya .

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"

Jika saya menjalankan notify-senddi mesin lokal, dbus-monitorpada host jarak jauh melihat pemberitahuan. Sudah pasti mencapai tingkat akses yang harus memerlukan otentikasi.

notify-sendmengeluh karena tidak menemukan cookie. Setelah menyalin file cookie, notify-sendbekerja dari mesin jarak jauh.

Mesin lokal menjalankan Debian wheezy. Mesin jarak jauh menjalankan FreeBSD 10.1.

Saya tidak mengerti bagaimana otentikasi dan otorisasi D-Bus bekerja.

  1. Mengapa saya bisa menguping, sejauh yang saya tahu, tanpa kredensial dari mesin jarak jauh? Apa yang saya paparkan ketika saya meneruskan D-Bus ke koneksi TCP? Mengapa otorisasi berbeda dbus-monitordan notify-send?
  2. Mengapa saya tidak dapat menguping dari akun lain di mesin yang sama, baik melalui soket abstrak atau melalui koneksi TCP?
  3. Saya perhatikan bahwa file cookie berubah setiap beberapa menit (saya belum tahu apakah itu secara berkala atau tidak). Mengapa?

(Saya tahu saya bisa meluncurkan D-Bus daemon yang mendengarkan TCP. Itu bukan tujuan pertanyaan saya, saya ingin mengerti mengapa apa yang saya lakukan dan tidak berhasil.)

Gilles 'SANGAT berhenti menjadi jahat'
sumber

Jawaban:

7

D-Bus tidak menggunakan file cookie ajaib di sini; itu melewati kredensial melalui soket domain UNIX ( SCM_CREDENTIALS).

File cookie ajaib hanya salah satu dari beberapa mekanisme otentikasi D-Bus. D-Bus mengimplementasikan antarmuka yang kompatibel dengan SASL (lihat RFC4422 ) untuk mendukung berbagai mekanisme otentikasi. Salah satu mekanisme ini disebut "EKSTERNAL" auth, dan itu berarti bahwa saluran transportasi itu sendiri harus digunakan untuk menjamin otentikasi. Setidaknya dalam kasus D-Bus melalui soket UNIX, ini tampaknya menjadi mekanisme otentikasi pertama yang dicoba.

Dari spesifikasi D-Bus:

Byte khusus melewati kredensial

Segera setelah terhubung ke server, klien harus mengirim satu byte byte. Byte ini dapat disertai dengan informasi kredensial pada beberapa sistem operasi yang menggunakan sendmsg () dengan SCM_CREDS atau SCM_CREDENTIALS untuk meneruskan kredensial melalui soket domain UNIX. Namun, byte byte harus dikirim bahkan pada soket jenis lain, dan bahkan pada sistem operasi yang tidak memerlukan byte untuk dikirim untuk mengirimkan kredensial. Protokol teks yang dijelaskan dalam dokumen ini dimulai setelah byte tunggal. Jika byte pertama yang diterima dari klien bukan byte byte, server dapat memutuskan koneksi klien itu.

Byte byte dalam konteks apa pun selain byte awal adalah kesalahan; protokolnya adalah ASCII saja.

Kredensial yang dikirim bersama dengan byte nul dapat digunakan dengan mekanisme SASL EKSTERNAL.

Jika Anda mengambil contoh dbus-daemon, Anda bisa melihat bahwa ketika Anda terhubung, itu memeriksa kredensial pengguna yang terhubung:

$ 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

Jadi untuk menjawab pertanyaan Anda:

  1. Daemon D-Bus menggunakan ID pengguna Anda yang diverifikasi kernel untuk memverifikasi identitas Anda. Dengan menggunakan socatkoneksi proxy, Anda membiarkan siapa saja terhubung ke daemon D-Bus menggunakan UID Anda.

  2. Jika Anda mencoba menghubungkan langsung ke soket dari UID lain, daemon mengakui bahwa UID penghubung bukan UID yang seharusnya diizinkan untuk terhubung. Saya percaya defaultnya adalah hanya UID daemon sendiri yang diizinkan, tetapi belum diverifikasi secara formal. Anda dapat mengizinkan pengguna lain: melihat file konfigurasi di /etc/dbus-1/, dan juga man dbus-daemon.

  3. Ini adalah server D-Bus yang mengganti cookie lama / kadaluarsa dengan yang baru. Menurut bagian DBUS_COOKIE_SHA1 dari spesifikasi D-Bus, cookie disimpan bersama dengan waktu pembuatannya, dan server seharusnya menghapus cookie yang diputuskan terlalu lama. Rupanya seumur hidup "bisa sangat singkat".

Jander
sumber
Referensi implementasi D-Bus tidak digunakan SCM_CREDENTIALSsecara khusus. Di Linux, ia menggunakan SO_PEERCREDopsi soket sebagai gantinya.
Vasiliy Faronov
@VasiliyFaronov Anda benar - betapa menarik! Lebih lanjut, sepertinya menggunakan SCM_CREDENTIALSakan mencegah proxy yang sederhana, karena mengharuskan pengirim untuk secara aktif menunjukkan kredensial, sedangkan SO_PEERCREDhanya memeriksa siapa yang membuat koneksi. Saya heran mengapa mereka membuat pilihan ini.
Jander
Rupanya karena itu "tidak memerlukan kerjasama rekan," jadi "ini jauh lebih rapuh" (dari komentar di dbus-sysdeps-unix.c).
Vasiliy Faronov