kevincar / bless

Cross-platform Bluetooth Low Energy Server Python Library
MIT License
78 stars 26 forks source link

Permissions appear to be ignored #115

Open legraphista opened 9 months ago

legraphista commented 9 months ago

The problem I tested a quick example where I have a GATT service with 1 characteristic, where it has READ/WRITE properties, but does not have read permissions (just to test)

I was able to read/write without any issues to that characteristic.

This test stemmed from trying out {read,write}_encryption_required permissions but being able to manipulate the field without pairing the devices.

Reproduction


import logging
import asyncio
from datetime import datetime

from typing import Any, Dict

from bless import (  # type: ignore
        BlessServer,
        BlessGATTCharacteristic,
        GATTCharacteristicProperties,
        GATTAttributePermissions
)

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(name=__name__)

def write_request(
        characteristic: BlessGATTCharacteristic,
        value: Any,
        **kwargs
        ):

    logger.debug(f"Writing {value} to {characteristic}")
    characteristic.value = value
    logger.debug(f"Char value set to {characteristic.value}")

def read_request(
        characteristic: BlessGATTCharacteristic,
        **kwargs
        ) -> bytearray:
    logger.debug(f"Reading {characteristic.value}")
    return characteristic.value

async def run(loop):
    # Instantiate the server
    gatt: Dict = {
        "0000ffe0-0000-1000-8000-00805f9b34fb": {
            "61FF12BB-3ED8-46E5-B4F9-D64E2FEC021B": {
                "Properties": (GATTCharacteristicProperties.read |
                                GATTCharacteristicProperties.write),
                "Permissions": (
                                # GATTAttributePermissions.read_encryption_required |
                                GATTAttributePermissions.write_encryption_required),
                "Value": None
            },
        }
    }

    server_name = "MY_NOTIFY_SERVER"

    server = BlessServer(name=server_name, loop=loop, name_overwrite=True, )
    server.write_request_func = write_request  # not required if we don't have a write characteristic
    server.read_request_func = read_request

    await server.add_gatt(gatt)
    await server.start()

    while True:
        await asyncio.sleep(0.5)

    logger.debug("Stopping")
    await server.stop()

loop = asyncio.get_event_loop()
loop.run_until_complete(run(loop))

Screenshot_20231013-155114~2

Expected behavior I should not be able to write unless the devices are paired and should not be able to read at all

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Additional context

jcapona commented 8 months ago

hey @legraphista

I'm also dealing with the same issue; apparently, the permissions (GATTAttributePermissions) are not used at all on the bluezdbus backend, used by 'linux'; they're only used on macOS and windows. If you run the sample code you provided on a non-linux machine, it should work as expected. I think the characteristic permissions on the bluezdbus backend are determined by the properties (GATTCharacteristicProperties) (maintainers, correct me if I'm wrong).

What worked for me was changing the property GATTCharacteristicProperties.write to GATTCharacteristicProperties.authenticated_signed_writes. In this case, you'll need to bond with the device first to be able to write to the characteristic. Not sure about 'protected reads'...

kosma commented 6 months ago

@jcapona You have saved me endless agony. ❤️