1

If I pair a bluetooth device to my PC but I don't trust it, any time I power on the bluetooth device I will get a prompt like this in bluetoothctl:

Authorize service
[agent] Authorize service 0000111f-0000-1000-8000-00805f9b34fb (yes/no):

If I type yes, the device is allowed to connect.

I would like to write a small Python script that watches for new services and prompts me to authorize them using inotify-send, and pybluez seems like the tool for the job. However, after reading the documentation, I can't figure out if this is even possible. (Probably in large part because I'm not familiar with technical Bluetooth terminology.)

Is it possible to watch for- and authorize services using pybluez, and if so, how?

Hubro
  • 56,214
  • 69
  • 228
  • 381
  • 1
    BlueZ is being the authorize agent. The BlueZ API to write a custom agent is documented at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt. The BlueZ source tree also has an example simple agent: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/simple-agent – ukBaz Oct 16 '21 at 06:10

1 Answers1

1

Here you go, no pybluez needed.

#!/usr/bin/python3

import dbus
import dbus.mainloop.glib
import dbus.service
from gi.repository import GLib

AGENT_PATH = "/org/bluez/AuthorizeServiceAgent"
AGENT_INTERFACE = 'org.bluez.Agent1'
CAPABILITY = "DisplayYesNo"

class Agent(dbus.service.Object):
    @dbus.service.method(AGENT_INTERFACE, in_signature="os", out_signature="")
    def AuthorizeService(self, device, uuid):
        print("AuthorizeService %s %s" % (device, uuid))
        if uuid == "0000111f-0000-1000-8000-00805f9b34fb":
            print("Whitelisted")
            return
        print("Rejected")
        raise dbus.DBusException("AuthorizeService rejected")

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()
    agent = Agent(bus, AGENT_PATH)
    obj = bus.get_object("org.bluez", "/org/bluez")

    manager = dbus.Interface(obj, "org.bluez.AgentManager1")
    manager.RegisterAgent(AGENT_PATH, CAPABILITY)
    manager.RequestDefaultAgent(AGENT_PATH)

    GLib.MainLoop().run()

I wrote this to work around a related problem, namely bluez 5.53 kept unpairing my PS4 controller whenever I plugged it in. What bluez is actually doing is sending an authorize service request every time the controller is plugged in, or in your case anytime you power your bluetooth device, which is automatically denied if there's no bluetooth agent to respond. If you're running bluetoothctl then it acts as a bluetooth agent and asks whether to authorize the service.

The controller issue looks fixed in the latest bluez but not in Ubuntu LTS 22.04 or earlier. Not sure if your case is affected by this fix.

The code is based on the example/test code that bluez provides.

Mihai
  • 1,261
  • 2
  • 12
  • 19