尝试将 运行 一个 linux 系统作为无头蓝牙服务器,向连接的 phone 或平板电脑询问 pin
Trying to run a linux system as a headless bluetooth server that asks the connecting phone or tablet for a pin
我正在使用一台 linux 计算机,在部署时将无法与之交互。
它必须启动的唯一(最终用户友好的)接入点是蓝牙接入点。
蓝牙通信已成功建立,phone无需在控制器上进行任何输入即可与控制器连接。
问题是在这种情况下不安全,现在任何东西都可以自由配对和连接。
我希望控制器从连接设备请求一个控制器唯一的 pin,这样只有有权访问该 pin 的人才能连接到控制器。
我正在使用 python 来管理处理配对过程的代理,我目前正在使用此代码:
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
BUS_NAME = 'org.bluez'
ADAPTER_IFACE = 'org.bluez.Adapter1'
ADAPTER_ROOT = '/org/bluez/hci'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
AGENT_PATH = '/my/app/agent'
AGNT_MNGR_PATH = '/org/bluez'
CAPABILITY = 'KeyboardDisplay'
DEVICE_IFACE = 'org.bluez.Device1'
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
def set_trusted(path):
props = dbus.Interface(bus.get_object(BUS_NAME, path), dbus.PROPERTIES_IFACE)
props.Set(DEVICE_IFACE, "Trusted", True)
class Agent(dbus.service.Object):
@dbus.service.method(AGENT_IFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
@dbus.service.method(AGENT_IFACE,
in_signature='o', out_signature='s')
def RequestPinCode(self, device):
print(f'RequestPinCode {device}')
return '0000'
@dbus.service.method(AGENT_IFACE,
in_signature="ou", out_signature="")
def RequestConfirmation(self, device, passkey):
print("RequestConfirmation (%s, %06d)" % (device, passkey))
set_trusted(device)
return
@dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="")
def RequestAuthorization(self, device):
print("RequestAuthorization (%s)" % (device))
auth = input("Authorize? (yes/no): ")
if (auth == "yes"):
return
raise Rejected("Pairing rejected")
@dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="u")
def RequestPasskey(self, device):
print("RequestPasskey (%s)" % (device))
set_trusted(device)
passkey = input("Enter passkey: ")
return dbus.UInt32(passkey)
@dbus.service.method(AGENT_IFACE,
in_signature="ouq", out_signature="")
def DisplayPasskey(self, device, passkey, entered):
print("DisplayPasskey (%s, %06u entered %u)" %
(device, passkey, entered))
@dbus.service.method(AGENT_IFACE,
in_signature="os", out_signature="")
def DisplayPinCode(self, device, pincode):
print("DisplayPinCode (%s, %s)" % (device, pincode))
class Adapter:
def __init__(self, idx=0):
bus = dbus.SystemBus()
self.path = f'{ADAPTER_ROOT}{idx}'
self.adapter_object = bus.get_object(BUS_NAME, self.path)
self.adapter_props = dbus.Interface(self.adapter_object,
dbus.PROPERTIES_IFACE)
self.adapter_props.Set(ADAPTER_IFACE,
'DiscoverableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Discoverable', True)
self.adapter_props.Set(ADAPTER_IFACE,
'PairableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Pairable', True)
if __name__ == '__main__':
agent = Agent(bus, AGENT_PATH)
agnt_mngr = dbus.Interface(bus.get_object(BUS_NAME, AGNT_MNGR_PATH),
AGNT_MNGR_IFACE)
agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
agnt_mngr.RequestDefaultAgent(AGENT_PATH)
adapter = Adapter()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
agnt_mngr.UnregisterAgent(AGENT_PATH)
mainloop.quit()
我从这里得到这段代码,但老实说,我看不懂。
它定义了一堆 dbus.service.method,我认为它以某种方式选择了一个或其他东西。
作为一个习惯了不太抽象的语言的人,我只是不知道它把所有这些东西放在哪里或者它拉到哪里。
我相信在这种情况下它只是使用 RequestConfirmation() 方法。所以其他的都是垃圾。
但我想知道 if/how 当我尝试与控制器配对时,我可以修改它以使其在我的 phone 上要求输入密码或密码。
尝试解释代码的作用...
Linux 系统上有蓝牙守护程序 (bluetoothd
) 运行。 bluetoothd
处理系统上的蓝牙功能。下面是与 bluetoothd
进行配对的交互序列图。
RegisterAgent()
用于告诉bluetoothd
D-Bus org.bluez.Agent1
接口创建的位置以及使用此注册代理的功能。
当配对请求进入 bluetoothd
时,它会在注册位置调用 RequestConfirmation()
。如果返回值为空,则确认确认。如果抛出 org.bluez.Error.Rejected
或 org.bluez.Error.Canceled
则配对被拒绝。
org.bluez.Agent1
方法中的哪一个被 bluetoothd
调用将取决于收到的配对请求的确切类型。
功能设置可能最好总结为 table:
如果调用的是 RequestConfirmation()
方法,则设备 D-Bus 路径和 uint32 密码是传入的参数。由代理中的方法决定, 根据该信息,是否应接受请求。
org.bluez.Agent1
接口记录在:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt
简单代理的官方 BlueZ 示例位于:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/simple-agent
我正在使用一台 linux 计算机,在部署时将无法与之交互。
它必须启动的唯一(最终用户友好的)接入点是蓝牙接入点。
蓝牙通信已成功建立,phone无需在控制器上进行任何输入即可与控制器连接。
问题是在这种情况下不安全,现在任何东西都可以自由配对和连接。
我希望控制器从连接设备请求一个控制器唯一的 pin,这样只有有权访问该 pin 的人才能连接到控制器。
我正在使用 python 来管理处理配对过程的代理,我目前正在使用此代码:
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
BUS_NAME = 'org.bluez'
ADAPTER_IFACE = 'org.bluez.Adapter1'
ADAPTER_ROOT = '/org/bluez/hci'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
AGENT_PATH = '/my/app/agent'
AGNT_MNGR_PATH = '/org/bluez'
CAPABILITY = 'KeyboardDisplay'
DEVICE_IFACE = 'org.bluez.Device1'
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
def set_trusted(path):
props = dbus.Interface(bus.get_object(BUS_NAME, path), dbus.PROPERTIES_IFACE)
props.Set(DEVICE_IFACE, "Trusted", True)
class Agent(dbus.service.Object):
@dbus.service.method(AGENT_IFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
@dbus.service.method(AGENT_IFACE,
in_signature='o', out_signature='s')
def RequestPinCode(self, device):
print(f'RequestPinCode {device}')
return '0000'
@dbus.service.method(AGENT_IFACE,
in_signature="ou", out_signature="")
def RequestConfirmation(self, device, passkey):
print("RequestConfirmation (%s, %06d)" % (device, passkey))
set_trusted(device)
return
@dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="")
def RequestAuthorization(self, device):
print("RequestAuthorization (%s)" % (device))
auth = input("Authorize? (yes/no): ")
if (auth == "yes"):
return
raise Rejected("Pairing rejected")
@dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="u")
def RequestPasskey(self, device):
print("RequestPasskey (%s)" % (device))
set_trusted(device)
passkey = input("Enter passkey: ")
return dbus.UInt32(passkey)
@dbus.service.method(AGENT_IFACE,
in_signature="ouq", out_signature="")
def DisplayPasskey(self, device, passkey, entered):
print("DisplayPasskey (%s, %06u entered %u)" %
(device, passkey, entered))
@dbus.service.method(AGENT_IFACE,
in_signature="os", out_signature="")
def DisplayPinCode(self, device, pincode):
print("DisplayPinCode (%s, %s)" % (device, pincode))
class Adapter:
def __init__(self, idx=0):
bus = dbus.SystemBus()
self.path = f'{ADAPTER_ROOT}{idx}'
self.adapter_object = bus.get_object(BUS_NAME, self.path)
self.adapter_props = dbus.Interface(self.adapter_object,
dbus.PROPERTIES_IFACE)
self.adapter_props.Set(ADAPTER_IFACE,
'DiscoverableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Discoverable', True)
self.adapter_props.Set(ADAPTER_IFACE,
'PairableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Pairable', True)
if __name__ == '__main__':
agent = Agent(bus, AGENT_PATH)
agnt_mngr = dbus.Interface(bus.get_object(BUS_NAME, AGNT_MNGR_PATH),
AGNT_MNGR_IFACE)
agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
agnt_mngr.RequestDefaultAgent(AGENT_PATH)
adapter = Adapter()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
agnt_mngr.UnregisterAgent(AGENT_PATH)
mainloop.quit()
我从这里得到这段代码,但老实说,我看不懂。
它定义了一堆 dbus.service.method,我认为它以某种方式选择了一个或其他东西。
作为一个习惯了不太抽象的语言的人,我只是不知道它把所有这些东西放在哪里或者它拉到哪里。
我相信在这种情况下它只是使用 RequestConfirmation() 方法。所以其他的都是垃圾。
但我想知道 if/how 当我尝试与控制器配对时,我可以修改它以使其在我的 phone 上要求输入密码或密码。
尝试解释代码的作用...
Linux 系统上有蓝牙守护程序 (bluetoothd
) 运行。 bluetoothd
处理系统上的蓝牙功能。下面是与 bluetoothd
进行配对的交互序列图。
RegisterAgent()
用于告诉bluetoothd
D-Bus org.bluez.Agent1
接口创建的位置以及使用此注册代理的功能。
当配对请求进入 bluetoothd
时,它会在注册位置调用 RequestConfirmation()
。如果返回值为空,则确认确认。如果抛出 org.bluez.Error.Rejected
或 org.bluez.Error.Canceled
则配对被拒绝。
org.bluez.Agent1
方法中的哪一个被 bluetoothd
调用将取决于收到的配对请求的确切类型。
功能设置可能最好总结为 table:
如果调用的是 RequestConfirmation()
方法,则设备 D-Bus 路径和 uint32 密码是传入的参数。由代理中的方法决定, 根据该信息,是否应接受请求。
org.bluez.Agent1
接口记录在:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt
简单代理的官方 BlueZ 示例位于:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/simple-agent