Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bluez - NoInputNoOutput agent configuration does not work #291

Open
OrangeDog opened this issue Feb 25, 2022 · 47 comments
Open

bluez - NoInputNoOutput agent configuration does not work #291

OrangeDog opened this issue Feb 25, 2022 · 47 comments

Comments

@OrangeDog
Copy link

OrangeDog commented Feb 25, 2022

With the upgrade to Bullseye and bluez-5.55-3.1+rpt1, registering an agent with the NoInputNoOutput capability no longer works.

This affects the bt-agent program in the bluez-tools package, but also any other agent using the D-Bus interface.

More details: https://forums.raspberrypi.com/viewtopic.php?t=324225

@XECDesign
Copy link
Member

@pelwell Any idea about this one?

@pelwell
Copy link
Member

pelwell commented Mar 1, 2022

This is the first I'm hearing of the issue.

@OrangeDog The forum thread implies that upgrading to a newer version of BlueZ will resolve the problem - do you have any evidence of that?

Using a Bullseye image, running bt-agent -c NoInputNoOutput in a shell seems to work - with it I can connect in from my phone with no prompting (on the Pi side), and without it there is a pop-up asking for confirmation.

Have you tested it in this way? Is there something specific about your systemd service (or that the fact that it is a systemd service)? Posting your service here would be helpful.

@OrangeDog
Copy link
Author

implies that upgrading to a newer version of BlueZ will resolve the problem

Does it? The other person on that thread tried but couldn't get the newer version building.

Have you tested it in this way?

That's the first thing I did, before I tried writing my own that also didn't work.

bluetooth.service.d/override.conf:

[Service]
ExecStart=
ExecStart=/usr/libexec/bluetooth/bluetoothd -C --noplugin=sap
Restart=on-failure
WatchdogSec=5

ExecStartPost=/bin/hciconfig hci0 up
ExecStartPost=/usr/bin/sdptool add SP
ExecStartPost=/bin/hciconfig hci0 piscan

bluetooth_agent.service:

[Unit]
Description=Bluetooth Simple Agent
After=network.target bluetooth.service
StartLimitIntervalSec=0

[Service]
Type=simple
KillSignal=SIGINT
ExecStart=/bin/sh -c 'yes | /usr/bin/bt-agent -c NoInputNoOutput'
Restart=always
RestartSec=1

User=pi
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

Found another apparent copy of this issue: khvzak/bluez-tools#31

@phamhien2102
Copy link

Anyone has solutions? I am facing this issue

@pelwell
Copy link
Member

pelwell commented Mar 1, 2022

That's the first thing I did, before I tried writing my own that also didn't work.

And you found that it worked when run from the command line, but not from a systemd service? If so, don't you think your issue report could have made that clear?

@OrangeDog
Copy link
Author

OrangeDog commented Mar 1, 2022 via email

@pelwell
Copy link
Member

pelwell commented Mar 1, 2022

I was not prompted at all.

I'm confused - isn't that the goal?

Please state clearly:

  1. What you did.
  2. What you expected to happen.
  3. What actually happened.

@OrangeDog
Copy link
Author

OrangeDog commented Mar 1, 2022

  1. Ran bt-agent -c NoInputNoOutput. Attempted to connect from another device.
  2. The agent prompts yes/no. You enter "yes" and the device connects. (this is what happened in the buster images)
  3. Nothing

@pelwell
Copy link
Member

pelwell commented Mar 2, 2022

As I understand it, the agent names describe the capabilities of the device running the agent:

  • NoInputNoOutput is for unattended appliances that automatically except pairing attempts.
  • DisplayYesNo prompts for a yes/no confirmation from the user.
  • KeyboardDisplay
  • KeyboardOnly

Try running bt-agent -c DisplayYesNo.

@phamhien2102
Copy link

phamhien2102 commented Mar 2, 2022

For me:

  1. I install Bluez to version 5.55
  2. Look for a line starts with “ExecStart” and add compatibility flag ‘--experimental’ at the end of the line.
    ExecStart=/usr/lib/bluetooth/bluetoothd --experimental
  3. Finally, run example-advertisement or run demo of this project.

All things worked well. You can follow me.

=======
For more information of OS Debian Bulleye

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

@pelwell Your understanding is not correct. The capabilities only describe the physical user-facing input and output methods of the device, not the I/O of the agent program.

NoInputNoOutput means no interaction with the connecting user, but the attempt still needs to be authorised via some method. When using the bt-agent that method is answering the yes/no prompt on the console.

DisplayYesNo prompts the connecting user to confirm on their device that the code they are shown matches the code displayed on the agent's device. While that is functional as a workaround, you now have to train your users to ignore the security prompt for their "upgraded" devices.

Windows 10 BT connect prompt

@phamhien2102
Copy link

phamhien2102 commented Mar 2, 2022

@pelwell Your understanding is not correct. The capabilities only describe the physical user-facing input and output methods of the device, not the I/O of the agent program.

NoInputNoOutput means no interaction with the connecting user, but the attempt still needs to be authorised via some method. When using the bt-agent that method is answering the yes/no prompt on the console.

DisplayYesNo prompts the connecting user to confirm on their device that the code they are shown matches the code displayed on the agent's device. While that is functional as a workaround, you now have to train your users to ignore the security prompt for their "upgraded" devices.

I think you try to reinstall another version of bluez. For me, I install 5.63 but it didn't work, then I reinstalled bluez to 5.55

@OrangeDog
Copy link
Author

reinstalled bluez to 5.50

The point of this issue is that 5.50 works, but 5.55 (which is what the bullseye image comes with) doesn't.

@phamhien2102
Copy link

reinstalled bluez to 5.50

The point of this issue is that 5.50 works, but 5.55 (which is what the bullseye image comes with) doesn't.

I am sorry, I mistyped. My current bluez verion is 5.55. It worked well in the 5.55 version.

=====
I edited comments above

@pelwell
Copy link
Member

pelwell commented Mar 2, 2022

BlueZ D-Bus Agent API description
**********************************


Agent Manager hierarchy
=======================

Service		org.bluez
Interface	org.bluez.AgentManager1
Object path	/org/bluez

		void RegisterAgent(object agent, string capability)

			This registers an agent handler.

			The object path defines the path of the agent
			that will be called when user input is needed.

			Every application can register its own agent and
			for all actions triggered by that application its
			agent is used.

			It is not required by an application to register
			an agent. If an application does chooses to not
			register an agent, the default agent is used. This
			is on most cases a good idea. Only application
			like a pairing wizard should register their own
			agent.

			An application can only register one agent. Multiple
			agents per application is not supported.

			The capability parameter can have the values
			"DisplayOnly", "DisplayYesNo", "KeyboardOnly",
			"NoInputNoOutput" and "KeyboardDisplay" which
			reflects the input and output capabilities of the
			agent.

			If an empty string is used it will fallback to
			"KeyboardDisplay".

			Possible errors: org.bluez.Error.InvalidArguments
					 org.bluez.Error.AlreadyExists

@OrangeDog
Copy link
Author

@pelwell I assume you're quoting that because of "reflects the input and output capabilities of the agent"?

It should more correctly be "of the hardware to which the agent's application has access". That's why it's specifically "keyboard", "display" and "yes/no". I can go through every capability and give you screenshots of what it does with the bt-agent program for both old and new versions of bluez if you don't believe me and cannot check yourself.

@pelwell
Copy link
Member

pelwell commented Mar 2, 2022

The capabilities only describe the physical user-facing input and output methods of the device, not the I/O of the agent program.

This does not make sense - how can a BlueTooth device be expected to know about the capabilities of all the things that might want to connect to it? In this scenario the Pi is the device.

I can go through every capability and give you screenshots of what it does with the bt-agent program for both old and new versions of bluez if you don't believe me and cannot check yourself.

Please do - it might help to uncross our purposes.

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

How can a BlueTooth device be expected to know about the capabilities of all the things that might want to connect to it? In this scenario the Pi is the device.

You have it the wrong way around. It's not the capabilities of all the things that might want to connect to it, it's the capabilities of the device that it itself is.

The agent on a smart speaker should use NoInputNoOutput (though I guess you could make one read out the code and use that as Display). The agent on a TV should use DisplayOnly. The agent on a mobile phone should use KeyboardDisplay, etc.

The bt-agent program is a simple utility that implements the agent interface just on the console. Any production device needs to provide its own agent to appropriately display the codes and prompts on its hardware and make the auth decisions. Though in a specific case of NoInputNoOutput and "all devices can connect" you used to be able to just pipe yes into bt-agent.

Please do

I'll get on it...

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

Pi is running Pi OS Bullseye (bluez 5.55-3.1+rpt1).
Connecting device is Windows 10.
Console is connected via SSH over WiFi.

NoInputNoOutput
DisplayOnly
DisplayYesNo
KeyboardOnly

(bt-agent does not support KeyboardDisplay)

With Pi OS Buster (bluez 5.50-1.2~deb10u2+rpt1) they are all the same except for NoInputNoOutput:

NoInputNoOutput

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

add compatibility flag --experimental at the end of the line

Just tested this, and it made no difference.
@phamhien2102 did you reinstall the provided 5.55 package, or get one from somewhere else?
Possibly you left something else non-default while changing things.

@pelwell
Copy link
Member

pelwell commented Mar 2, 2022

Thanks - your screenshots show that the Pi and bt-agent are behaving in the way that I expect, except that when the NoInputNoOutput agent is selected your PC is unable to connect to the Pi.

Repeating the same test here with a laptop running Windows 10 it is able to connect to the Pi running BlueZ 5.55, regardless of the agent selected (and with the expected level of interaction on the Pi).

Have you tried connecting to the Pi running NoInputNoOutput from another host - a phone, say?

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

Because your expectations are wrong about the intended behaviour of bt-agent, as I have been trying to explain.
Note that DisplayOnly also has a yes/no prompt that you have to reply to in order to connect.
The fact that there is a console prompt is unrelated to whether the device has Keyboard capability,

Have you tried connecting to the Pi running NoInputNoOutput from another host - a phone, say?

Collegeues have tried with multiple Android phones, and they get the same thing (i.e. nothing but a connection error).

it is able to connect to the Pi

I assume your configuration must differ in some way to mine (and others reporting the same issue).

Does the hardware matter? This is a PiZero W v1.1
Are you using the same --noplugin=sap, and hciconfig/sdptool commands?
I also have the discover and pairing timeouts disabled.
I am advertising the service via python with the UUID 00001101-0000-1000-8000-00805F9B34FB (SSP)

@pelwell
Copy link
Member

pelwell commented Mar 2, 2022

Are you using the same --noplugin=sap, and hciconfig/sdptool commands?
I also have the discover and pairing timeouts disabled.
I am advertising the service via python with the UUID 00001101-0000-1000-8000-00805F9B34FB (SSP)

Of course not - I'm using the standard Pi desktop "Make discoverable", which presents a headset/headphone device.

From the other commentors there is clearly some pairing issue with the NoInputNoOutput agent in BlueZ 5.55, even though it works.

@XECDesign Will Debian bump to a newer version, or are we stuck with 5.55 until the next major OS release?

@Callenberg
Copy link

Just want to confirm a use case when the agent NoInputNoOutput does not work...
I use a Raspberry Pi4 and Bullseye (lite version, Bluez version 5.55 and headless). The application is that I want to connect to the Raspberry from smart phone without any passkeys. For some years the NoInputNoOutput agent worked as intended - not anymore...

Using bluetoothctl I now have to confirm with yes two times:

[bluetooth]# agent NoInputNoOutput
Agent is already registered
[NEW] Device 8C:DE:E6:25:C5:8C Galaxy S21 Ultra 5G
Request confirmation
[agent] Confirm passkey 372154 (yes/no): yes <-- first confirmation
[CHG] Device 8C:DE:E6:25:C5:8C Modalias: bluetooth:v0075p0100d0201
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001105-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110a-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001112-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001115-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000111f-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000112f-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001132-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001800-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C ServicesResolved: yes
[CHG] Device 8C:DE:E6:25:C5:8C Paired: yes
Authorize service
[agent] Authorize service 0000110d-0000-1000-8000-00805f9b34fb (yes/no): yes <-- second confirmation
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001105-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110a-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110d-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001112-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001115-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000111f-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 0000112f-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001132-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001800-0000-1000-8000-00805f9b34fb
[CHG] Device 8C:DE:E6:25:C5:8C UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[Galaxy S21 Ultra 5G]#

I was the one that started the thread mentioned in the top post at the Raspberry Pi forum back in November:
https://forums.raspberrypi.com/viewtopic.php?t=324225

@OrangeDog
Copy link
Author

OrangeDog commented Mar 2, 2022

Sorted out another Pi Zero W running buster. Added screenshot above.
I have confirmed at the D-Bus level what is going on via dbus-monitor --system

When the connection is started with the buster image, a RequestAuthorization method call is sent to the agent:

signal time=1636996110.593709 sender=:1.5 -> destination=(null destination) serial=61 path=/org/bluez/hci0/dev_00_1A_7D_DA_71_15; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.bluez.Device1"
   array [
      dict entry(
         string "Connected"
         variant             boolean true
      )
   ]
   array [
   ]
signal time=1636996110.780436 sender=:1.3 -> destination=(null destination) serial=1027 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
   string "sys-devices-platform-soc-20201000.serial-tty-ttyAMA0-hci0-hci0:12.device"
   object path "/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a12_2edevice"
signal time=1636996110.782439 sender=:1.3 -> destination=(null destination) serial=1028 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
   string "sys-subsystem-bluetooth-devices-hci0:12.device"
   object path "/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a12_2edevice"
method call time=1636996110.823709 sender=:1.5 -> destination=:1.22 serial=62 path=/org/blueztools; interface=org.bluez.Agent1; member=RequestAuthorization
   object path "/org/bluez/hci0/dev_00_1A_7D_DA_71_15"
method call time=1636996110.826851 sender=:1.22 -> destination=org.freedesktop.DBus serial=25 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.bluez',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/bluez/hci0/dev_00_1A_7D_DA_71_15',arg0='org.bluez.Device1'"
method return time=1636996110.828362 sender=org.freedesktop.DBus -> destination=:1.22 serial=20 reply_serial=25
method call time=1636996110.832014 sender=:1.22 -> destination=org.freedesktop.DBus serial=26 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.bluez',interface='org.bluez.Device1',path='/org/bluez/hci0/dev_00_1A_7D_DA_71_15'"
method return time=1636996110.833422 sender=org.freedesktop.DBus -> destination=:1.22 serial=21 reply_serial=26
[... a bunch of other calls getting/setting properties, etc. ...]
method return time=1636996110.935401 sender=:1.22 -> destination=:1.5 serial=39 reply_serial=62

However, with the bullseye image, there are only the connection signals and no method calls are made:

signal time=1646232193.846139 sender=:1.84 -> destination=(null destination) serial=224 path=/org/bluez/hci0/dev_00_1A_7D_DA_71_15; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.bluez.Device1"
   array [
      dict entry(
         string "Connected"
         variant             boolean true
      )
   ]
   array [
   ]
signal time=1646232193.929596 sender=:1.3 -> destination=(null destination) serial=8552 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
   string "sys-devices-platform-soc-20201000.serial-tty-ttyAMA0-hci0-hci0:12.device"
   object path "/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a12_2edevice"
signal time=1646232193.931952 sender=:1.3 -> destination=(null destination) serial=8553 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
   string "sys-subsystem-bluetooth-devices-hci0:12.device"
   object path "/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a12_2edevice"

This demonstrates that the problem is not simply with the bt-agent utility, but the bluez system as a whole.

In a desktop environment I guess D-Bus is set up differently, which may account for why it works for @pelwell?

@XECDesign
Copy link
Member

@XECDesign Will Debian bump to a newer version, or are we stuck with 5.55 until the next major OS release?

Debian is unlikely to bump the version unless there's a set of security issues that make it unreasonable to backport the fix.

If you believe it's the right thing to do and won't cause issues, we can bump it to 5.55 on our end.

@pelwell
Copy link
Member

pelwell commented Mar 4, 2022

I can't hand-on-heart say it is the right thing to do without taking time to test it, but that's probably the way to go. 5.63 is the latest version - I'll give it a spin when I get a chance.

@XECDesign
Copy link
Member

XECDesign commented Mar 7, 2022

Alright, then maybe I should update the package in the internal repo anyway. Then if you test it we can be sure I didn't miss anything on the packaging side and it doesn't need to be tested twice.

@OrangeDog
Copy link
Author

OrangeDog commented Mar 7, 2022

For me, I install 5.63 but it didn't work,

bump it to 5.55 on our end.

I'm a bit confused by what's going on here. 5.55 is the current version and doesn't work. Apparently upgrading to 5.63 doesn't fix it either. The buster images worked, but that may actually be unrelated to the bluez version (5.50), and instead be some dbus-related change.

@Sammy93
Copy link

Sammy93 commented May 26, 2022

My solution was to do run an expect script at boot with bluetoothctl like this one:

#!/usr/bin/expect -f
sleep 15
set timeout 600
set prompt "#"



spawn /usr/bin/bluetoothctl
expect  "Agent registered"

send -- "list\r"
send -- "power on\r"
send -- "discoverable on\r"
send -- "pairable on\r"
sleep 5
expect  "agent"
sleep 5
expect  "passkey"
send -- "yes\r"
sleep 3
expect  "Authorize service"
send -- "yes\r"
sleep 3
expect  "Authorize service"
send -- "yes\r"

expect

expect eof

@frmunozForcast
Copy link

in case it helps, I was also trying to set my rpi to receive automatic bluetooth connections and faced this problem with NoInputNoOutput agent.

The simplest solution I could find was to modify the simple-agent from the examples on bluez/bluez-tools: https://github.com/bluez/bluez/blob/master/test/simple-agent

here the simplest fix is to set capability = "NoInputNoOutput" on line 138 so the connections will not show any pin and change the ask function to always return "yes" on line line 25 so automatic connections can be made (NOT SAFE AT ALL). The agent is completely customizable, so more safer changes could be made too.

then just run the script on a systemctl service and it will work.

@pirateradiohack
Copy link

@frmunozForcast I think this is a valid workaround, but I can't get it to work. I still get the same issue.

The moment I update the simple-agent with capability = "NoInputNoOutput" I get the issue again.

@OrangeDog
Copy link
Author

@frmunozForcast the point of this issue is that setting capability = "NoInputNoOutput" does not work. That example script is the same. All the options work as expected (see earlier screenshots) except for NoInputNoOutput, where RequestAuthorization is never called.

@pirateradiohack
Copy link

@OrangeDog have you had any luck so far? with a fix or a workaround? That is quite an annoying bug.

@frmunozForcast
Copy link

@frmunozForcast the point of this issue is that setting capability = "NoInputNoOutput" does not work. That example script is the same. All the options work as expected (see earlier screenshots) except for NoInputNoOutput, where RequestAuthorization is never called.

yes, after some testing I had this issue and could not fix it. At the end, I changed to capability = "KeyboardDisplay" and set a custom, default pin on RequestPinCode method like.

...
@dbus.service.method(settings.AGENT_INTERFACE,
                         in_signature='o', out_signature='s')
    def RequestPinCode(self, device):
        print(f'RequestPinCode {device}')
        return '0000'
...

With this i can still have automatic connection and everything seems to work properly (so far), device can disconnect and re-connect freely, multiple devices can connect, etc.

@OrangeDog
Copy link
Author

OrangeDog commented Jul 4, 2022

@frmunozForcast the only issue with that is some devices are going to ask you to type "0000" into the Pi, or to check the Pi's display, which may confuse the users.

@OrangeDog
Copy link
Author

OrangeDog commented Jun 27, 2024

Just a quick update. I have re-tested with Bookworm (raspios_lite_armhf-2024-03-15, using bluez-5.66-1+rpt1+deb12u1) and behaviour is almost the same.
When the agent is registered as NoInputNoOutput it receives no messages at any point.

When the agent is registered with any capability it now also never receives a RequestPinCode nor RequestPasskey. A random code is used instead. i.e. this mitigation is now broken too.

I tested with the autopair plugin both enabled and disabled in bluetoothd.

@pelwell
Copy link
Member

pelwell commented Jun 27, 2024

Does dtparam=krnbt=off change the behaviour?

@OrangeDog
Copy link
Author

Does dtparam=krnbt=off change the behaviour?

No.

However, I have discovered that NoInputNoOutput does appear to work once now, at least for a single device (I don't have any others to hand right now). After rebooting it will then work again, once. However, I'm using overlayfs so it may be due to some file state.

I'll try to do some more investigation on that another day.

@kinnairdclan
Copy link

Have a workaround solution but it depends on what OP desires. I was encountering the same issue searching for converting an old sound system into a bluetooth speaker using a Pi3. I wanted seamless re-connection using NoInputNoOutput, but it was not re-connecting after the first pair using Debian Bookworm Bluez. The following actions got me to this functionality.

This is for Raspbian Debian Bookworm:

  • First download build-dependencies to compile bluez from source:
    sudo apt-get build-dep bluez

  • Then download Bluez 5.76 either by zip or by Git: https://github.com/bluez/bluez

  • Build bluez following their instructions

  • After bluez is installed, edit /etc/bluetooth/main.conf:

  • Set Class = 0x41c (you might be looking to implement a different device but this one is for portable speaker).

  • Set DiscoverableTimeout = 0

  • Set AlwaysPairable = 0

  • Set JustWorksRepairing = always. This seems to be a new setting people are mentioning elsewhere. No idea what it does.

  • Execute bluetoothd, mine was in /usr/local/libexec/bluetooth/bluetoothd. Daemonize via systemd or other manners as you see fit. For now we can just keep it running manually and attach to the daemon with another shell.

  • Execute bluetoothctl to connect to the daemon.

  • Set pairable on, discoverable on.

  • Pair your smartphone etc with the bluetoothctl open. Say yes to all permission requests.

  • Trust the device after it has paired. Find its MAC with info in bluetoothctl and then trust xx:xx:xx:xx:xx:xx.

  • The device can then be connected and disconnected without prompts. Note that questioning of the initial pair is there, but that seems secure or else you'd have everyone able to connect to the BT device without impediment. But again, not sure if that answers what OP needs.

Looks like trixie may have a more up-to-date version of bluez if one wants to apt-pin or what not. Cheers.

@OrangeDog
Copy link
Author

OrangeDog commented Jul 5, 2024

@kinnairdclan did you try building the "current" version 5.66 to see if it's maybe a config issue? Are you using the desktop or lite image? Did you actually set NoInputNoOutput at some point? And what exactly do you mean by "disconnected" and "prompts". Are you getting a prompt on the paired device, or only from the agent (the bluetoothctl console)?

everyone able to connect to the BT device without impediment

This is necessary, as the device will have no inputs or outputs (including no console in which to type "yes"). I don't know how you expect a bluetooth speaker to work any differently.

And to reiterate the issue again: when using NoInputNoOutput, the RequestConfirmation was never sent, so there would have been no console prompt to you. However, I still need to sit down and re-debug with dbus-monitor to see what (if anything) has changed for the first-time pairing.

@kinnairdclan
Copy link

kinnairdclan commented Jul 5, 2024

@OrangeDog

I did not try building 5.66, but I did try the 5.66 Bookworm apt package using agent NoInputNoOutput. I did not use NoInputNoOutput with the subsequent solution. 5.66 should have the JustWorksRepairing option, I simply decided to use the latest release. It looks like Bookworm and Bullseye should ship with this option, Buster at 5.50 will not.

And what exactly do you mean by "disconnected" and "prompts".

Disconnected -- in your paired device's bluetooth menu, there is usually an option to "disconnect" from a device or "forget" a device. I meant that when you disconnect your paired device in this sense, and then connect again any given time later, it is totally seamless with no further confirmation requests from the bluetooth speaker device. It behaves like you would expect a bluetooth speaker to behave with e.g. a cellphone that has already been paired to it at least once before--seamless.

Prompts -- By this I meant any modal prompts on the pairing device before pairing succeeds. For example, the initial "Pair" prompt, when connecting to a device for the first time my Android phone, presents six digits that must match the digits the RPi is presenting via bluetoothctl when you are accepting the incoming pair request.

I don't know how you expect a bluetooth speaker to work any differently.

Many bluetooth speakers have a button that turns on discoverablilty as a barrier to unauthorized device pairing. Something like a Pi has no such button, therefore I equated this bluetoothctl-based confirmation to the hitting of that button. Not 1:1 exactly the same thing that's going on, but it works in the same way to keep unauthorized devices from connecting to your speakers.

I'll take the above down as off-topic if it's not useful, just let me know. I just wanted to present a solution that could work for many bluetooth-speaker related projects.

@OrangeDog
Copy link
Author

OrangeDog commented Jul 5, 2024

@kinnairdclan

I did not use NoInputNoOutput

Then it is not a solution to NoInputNoOutput not working.

an option to "disconnect" from a device or "forget" a device

Disconnect (what you did) has no issues. It's "forget" that is the problem, because that requires re-pairing, and the request to authorise pairing does not happen correctly.

presents six digits that must match the digits the RPi is presenting

The point of NoInputNoOutput is to not do that, because the Pi has no way to present anything if there is no output attached. Standard bluetooth audio devices also do not do that (though theoretically they could TTS the code, I've never seen one for sale that does).

I equated this bluetoothctl-based confirmation to the hitting of that button

That would be incorrect. Pushing the button does the equivalent of discoverable on.

@OrangeDog
Copy link
Author

However, thank you @kinnairdclan for pointing out the new config options that I had not looked at.

If your aim is to have unconditional pairing then a viable workaround appears to be AlwaysPairable=true, JustWorksRepairing=always and then do not register any agent. However, if you need an agent to make a decision you're still stuck.

I'll try to do some more investigation on that another day.

I can confirm that the "it works once" observation applies to each device separately.
The registered agent still receives no requests at any time. Something else confirms that first pairing request.
This is true even with an explicit AlwaysPairable=false.

Deleting the keys from the Pi side (e.g. bluetoothctl remove) does allow a re-pair.
Setting JustWorksRepairing=always allows re-pairing from the other device's side, but still nothing is sent to the agent.

Overall, it looks like it treats registering NoInputNoOutput as there being no agent, which is incorrect behaviour.
It also looks like AlwaysPairable is always treated as true, which then comes into effect when it mistakenly believes there is no agent.

Logs confirming that the agent is completely ignored in NoInputNoOutput mode:
https://gist.github.com/OrangeDog/189dd6eb228be2903844ead9a63a9974

@guillaumecardon
Copy link

guillaumecardon commented Aug 11, 2024

I think i have the same issue.

I want to connect my smartphone (Android 14) on my Raspberry 3B+ to send audio from my phone to the raspberry.

Commands (using bluetoothctl 5.66) :

[bluetooth]# discoverable yes
Changing discoverable on succeeded
[bluetooth]# pairable yes
Changing pairable on succeeded
[bluetooth]# agent NoInputNoOutput
Agent is already registered
[CHG] Device 74:XX:XX:XX:C1:39 Connected: yes
Request confirmation
[agent] Confirm passkey 345638 (yes/no):

Indeed, my smartphone want a passkey confirmation...but i specified "agentNoInputNoOutput" so i don't understand why i need to confirm on the smartphone and on my raspberry prompt.

I have a bluetooth speaker (a classic JBL Charge)... and when i trigger an apparing sequence pushing a button on my speaker, my phone is connected without a passkey.
I thought the command "agent NoInputNoOutput" played that role..

@AmbroiseS
Copy link

I can confirm and reproduce exactly OrangeDog scenario:

  • set up agent with NoInputNoOutput ( i created auto yes service to do so)

  • connect phone , it works, perfect

  • delete connection from phone (not disconnect but remove)

  • try tro reconnect gives authentication failed

  • remove phone from computer with bluetoothctl remove XX

  • can connect with phone

It should match MAC address and not auto generated pin in the case of NoInputNoOutput.

So 2 issues :
bt-agent -c NoInputNoOutput -d doesnt work
when agent is NoInputNoOutput it should be able to recreate connection for mac adress even if older pin doesnt match

@ghollingworth
Copy link

Does it work for you if you kill the panel?

$ pkill lwrespawn
$ pkill wf-panel-pi

Then try again?

The panel is an agent, so I'm guessing it's controlling it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests