การพิสูจน์ตัวตนและการอนุญาต 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 แรงบันดาลใจจากschedar 's เข้าถึง D-Bus ระยะไกลโดยใช้ 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

สเตรชพบว่ารุ่นนี้notify-sendไม่ได้พยายามอ่านไฟล์คุกกี้ดังนั้นฉันเข้าใจว่าทำไมมันไม่สามารถเชื่อมต่อได้

ฉันยังลอง SSHing ไปยังเครื่องอื่นและส่งต่อการเชื่อมต่อ TCP

ssh -R 8004:localhost:8004 remotehost

น่าแปลกที่dbus-monitorทำงานโดยไม่มีไฟล์คุกกี้! ฉันสามารถรับชม 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บ่นว่าไม่ได้หาคุกกี้ หลังจากคัดลอกไฟล์คุกกี้notify-sendทำงานจากเครื่องระยะไกล

เครื่องในพื้นที่ทำงาน Debian wheezy เครื่องระยะไกลรัน FreeBSD 10.1

ฉันไม่เข้าใจว่าการพิสูจน์ตัวตนและการอนุญาต D-Bus ทำงานอย่างไร

  1. ทำไมฉันถึงดักฟังเท่าที่ฉันสามารถบอกได้โดยไม่ต้องมีหนังสือรับรองจากเครื่องระยะไกล ฉันจะเปิดเผยอะไรเมื่อฉันส่งต่อ D-Bus ไปยังการเชื่อมต่อ TCP ทำไมจึงมีการอนุมัติสำหรับdbus-monitorและnotify-sendแตกต่างกันอย่างไร
  2. เหตุใดฉันจึงไม่สามารถดักฟังจากบัญชีอื่นในเครื่องเดียวกันไม่ว่าจะเป็นผ่านซ็อกเก็ตนามธรรมหรือผ่านการเชื่อมต่อ TCP
  3. ฉันสังเกตเห็นว่าไฟล์คุกกี้เปลี่ยนแปลงทุกสองสามนาที (ฉันไม่ได้คิดออกว่าเป็นช่วงปกติหรือไม่) ทำไม?

(ฉันรู้ว่าฉันสามารถเปิดตัว D-Bus daemon ที่ฟังบน TCP นั่นไม่ใช่จุดประสงค์ของคำถามของฉันฉันต้องการเข้าใจว่าทำไมสิ่งที่ฉันทำและไม่ได้ผล)

คำตอบ:


7

D-Bus ไม่ได้ใช้ไฟล์คุกกี้มายากลที่นี่ มันกำลังส่งข้อมูลรับรองผ่านซ็อกเก็ตโดเมน UNIX ( SCM_CREDENTIALS)

ไฟล์ magic cookie เป็นเพียงหนึ่งในกลไกการพิสูจน์ตัวตน D-Bus เท่านั้น D-Bus ใช้ส่วนต่อประสานSASL (ดูRFC4422 ) เพื่อสนับสนุนกลไกการตรวจสอบความถูกต้องที่หลากหลาย กลไกเหล่านี้อย่างใดอย่างหนึ่งเรียกว่า "ภายนอก" รับรองความถูกต้องและหมายความว่าควรใช้ช่องสัญญาณการขนส่งเพื่อรับประกันการรับรองความถูกต้อง อย่างน้อยในกรณีของ D-Bus บนซ็อกเก็ต UNIX นี่ดูเหมือนจะเป็นกลไกการพิสูจน์ตัวตนครั้งแรกที่ลองใช้

จากสเป็ค D-Bus:

ไบต์ nul ของหนังสือรับรองพิเศษ

ทันทีหลังจากเชื่อมต่อกับเซิร์ฟเวอร์ลูกค้าจะต้องส่ง nul ไบต์เดียว ไบต์นี้อาจมาพร้อมกับข้อมูลรับรองในระบบปฏิบัติการบางระบบที่ใช้ sendmsg () กับ SCM_CREDS หรือ SCM_CREDENTIALS เพื่อส่งข้อมูลรับรองผ่านซ็อกเก็ตโดเมน UNIX อย่างไรก็ตามไบต์ nul ต้องถูกส่งแม้บนซ็อกเก็ตชนิดอื่นและแม้แต่ในระบบปฏิบัติการที่ไม่ต้องการไบต์ที่จะส่งเพื่อส่งข้อมูลรับรอง โปรโตคอลข้อความที่อธิบายในเอกสารนี้เริ่มต้นหลังจากไบต์ nul เดียว หากไบต์แรกที่ได้รับจากไคลเอ็นต์ไม่ใช่ไบต์ nul เซิร์ฟเวอร์อาจยกเลิกการเชื่อมต่อไคลเอ็นต์นั้น

ไบต์ nul ในบริบทใด ๆ ที่ไม่ใช่ไบต์เริ่มต้นเป็นข้อผิดพลาด โปรโตคอลนั้นเป็นแบบ ASCII เท่านั้น

ข้อมูลประจำตัวที่ส่งพร้อมกับไบต์ nul อาจใช้กับกลไก SASL ภายนอก

หากคุณหยุดทำงานอินสแตนซ์ของ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 daemon กำลังใช้ ID ผู้ใช้ที่เคอร์เนลตรวจสอบเพื่อยืนยันตัวตนของคุณ เมื่อใช้socatการเชื่อมต่อพร็อกซีคุณจะอนุญาตให้ทุกคนเชื่อมต่อกับ D-Bus daemon โดยใช้ UID ของคุณ

  2. หากคุณพยายามเชื่อมต่อโดยตรงกับซ็อกเก็ตจาก UID อื่น daemon จะรับรู้ว่าการเชื่อมต่อ UID ไม่ใช่ UID ที่ควรได้รับอนุญาตให้เชื่อมต่อ ฉันเชื่อว่าค่าเริ่มต้นคืออนุญาตให้ใช้ UID ของ daemon เท่านั้น แต่ยังไม่ได้ยืนยันอย่างเป็นทางการ คุณสามารถอนุญาตให้ผู้ใช้อื่น ๆ แม้ว่า: เห็นไฟล์การกำหนดค่าในและยัง/etc/dbus-1/man dbus-daemon

  3. นี่คือเซิร์ฟเวอร์ D-Bus แทนที่คุกกี้เก่า / หมดอายุด้วยคุกกี้ใหม่ ตามส่วนDBUS_COOKIE_SHA1ของข้อมูลจำเพาะ D-Bus คุกกี้จะถูกเก็บไว้พร้อมกับเวลาในการสร้างและเซิร์ฟเวอร์ควรจะลบคุกกี้ที่ตัดสินใจว่าเก่าเกินไป เห็นได้ชัดว่าอายุการใช้งาน "สามารถค่อนข้างสั้น"


การใช้งานอ้างอิงของ D-Bus ไม่ได้ใช้เป็นการSCM_CREDENTIALSเฉพาะ บน Linux จะใช้SO_PEERCREDซ็อกเก็ตตัวเลือกแทน
Vasiliy Faronov

@VasiliyFaronov คุณพูดถูก - น่าสนใจมาก! นอกจากนี้ดูเหมือนว่าการใช้SCM_CREDENTIALSจะป้องกันพร็อกซีธรรมดา ๆ เช่นนี้เนื่องจากต้องการให้ผู้ส่งแสดงข้อมูลประจำตัวของตนอย่างแข็งขันในขณะที่SO_PEERCREDเพียงตรวจสอบว่าใครเป็นผู้ทำการเชื่อมต่อ ฉันสงสัยว่าทำไมพวกเขาถึงเลือกตัวเลือกนี้
Jander

เห็นได้ชัดเพราะมัน“ ไม่ต้องการความร่วมมือจากเพื่อน” ดังนั้น“ สิ่งนี้จึงบอบบางน้อยกว่า” (จากความคิดเห็นในdbus-sysdeps-unix.c)
Vasiliy Faronov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.