@@ -327,7 +327,6 @@ static struct btd_profile batt_profile = {
.device_remove = batt_remove,
.accept = batt_accept,
.disconnect = batt_disconnect,
- .external = true,
};
static int batt_init(void)
@@ -138,7 +138,6 @@ static int deviceinfo_disconnect(struct btd_service *service)
static struct btd_profile deviceinfo_profile = {
.name = "deviceinfo",
.remote_uuid = DEVICE_INFORMATION_UUID,
- .external = true,
.device_probe = deviceinfo_probe,
.device_remove = deviceinfo_remove,
.accept = deviceinfo_accept,
@@ -42,6 +42,12 @@ enum sc_mode_t {
SC_ONLY,
};
+enum bt_gatt_export_t {
+ BT_GATT_EXPORT_OFF,
+ BT_GATT_EXPORT_READ_ONLY,
+ BT_GATT_EXPORT_READ_WRITE,
+};
+
struct btd_br_defaults {
uint16_t page_scan_type;
uint16_t page_scan_interval;
@@ -147,6 +153,7 @@ struct btd_opts {
uint16_t gatt_mtu;
uint8_t gatt_channels;
bool gatt_client;
+ enum bt_gatt_export_t gatt_export;
enum mps_mode_t mps;
struct btd_avdtp_opts avdtp;
@@ -66,6 +66,7 @@ struct btd_gatt_client {
struct service {
struct btd_gatt_client *client;
bool primary;
+ bool claimed;
uint16_t start_handle;
uint16_t end_handle;
bt_uuid_t uuid;
@@ -616,6 +617,14 @@ static DBusMessage *descriptor_write_value(DBusConnection *conn,
if (parse_options(&iter, &offset, NULL))
return btd_error_invalid_args(msg);
+ /*
+ * Check if service was previously claimed by a plugin and if we shall
+ * consider it read-only, in that case return not authorized.
+ */
+ if (desc->chrc->service->claimed &&
+ btd_opts.gatt_export == BT_GATT_EXPORT_READ_ONLY)
+ return btd_error_not_authorized(msg);
+
/*
* Don't allow writing to Client Characteristic Configuration
* descriptors. We achieve this through the StartNotify and StopNotify
@@ -1046,6 +1055,14 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
if (parse_options(&iter, &offset, &type))
return btd_error_invalid_args(msg);
+ /*
+ * Check if service was previously claimed by a plugin and if we shall
+ * consider it read-only, in that case return not authorized.
+ */
+ if (chrc->service->claimed &&
+ btd_opts.gatt_export == BT_GATT_EXPORT_READ_ONLY)
+ return btd_error_not_authorized(msg);
+
/*
* Decide which write to use based on characteristic properties. For now
* we don't perform signed writes since gatt-client doesn't support them
@@ -1295,6 +1312,14 @@ static DBusMessage *characteristic_acquire_write(DBusConnection *conn,
if (!gatt)
return btd_error_failed(msg, "Not connected");
+ /*
+ * Check if service was previously claimed by a plugin and if we shall
+ * consider it read-only, in that case return not authorized.
+ */
+ if (chrc->service->claimed &&
+ btd_opts.gatt_export == BT_GATT_EXPORT_READ_ONLY)
+ return btd_error_not_authorized(msg);
+
if (chrc->write_io)
return btd_error_not_permitted(msg, "Write acquired");
@@ -1954,6 +1979,7 @@ static struct service *service_create(struct gatt_db_attribute *attr,
service->chrcs = queue_new();
service->incl_services = queue_new();
service->client = client;
+ service->claimed = gatt_db_service_get_claimed(attr);
gatt_db_attribute_get_service_data(attr, &service->start_handle,
&service->end_handle,
@@ -2097,8 +2123,15 @@ static void export_service(struct gatt_db_attribute *attr, void *user_data)
struct btd_gatt_client *client = user_data;
struct service *service;
- if (gatt_db_service_get_claimed(attr))
- return;
+ if (gatt_db_service_get_claimed(attr)) {
+ switch (btd_opts.gatt_export) {
+ case BT_GATT_EXPORT_OFF:
+ return;
+ case BT_GATT_EXPORT_READ_ONLY:
+ case BT_GATT_EXPORT_READ_WRITE:
+ break;
+ }
+ }
service = service_create(attr, client);
if (!service)
@@ -148,6 +148,7 @@ static const char *gatt_options[] = {
"ExchangeMTU",
"Channels",
"Client",
+ "ExportClaimedServices",
NULL
};
@@ -1066,6 +1067,33 @@ static void parse_gatt_cache(GKeyFile *config)
g_free(str);
}
+static enum bt_gatt_export_t parse_gatt_export_str(const char *str)
+{
+ if (!strcmp(str, "no") || !strcmp(str, "false") ||
+ !strcmp(str, "off")) {
+ return BT_GATT_EXPORT_OFF;
+ } else if (!strcmp(str, "read-only")) {
+ return BT_GATT_EXPORT_READ_ONLY;
+ } else if (!strcmp(str, "read-write")) {
+ return BT_GATT_EXPORT_READ_WRITE;
+ }
+
+ DBG("Invalid value for ExportClaimedServices=%s", str);
+ return BT_GATT_EXPORT_READ_ONLY;
+}
+
+static void parse_gatt_export(GKeyFile *config)
+{
+ char *str = NULL;
+
+ parse_config_string(config, "GATT", "ExportClaimedServices", &str);
+ if (!str)
+ return;
+
+ btd_opts.gatt_export = parse_gatt_export_str(str);
+ g_free(str);
+}
+
static void parse_gatt(GKeyFile *config)
{
parse_gatt_cache(config);
@@ -1075,6 +1103,7 @@ static void parse_gatt(GKeyFile *config)
parse_config_u8(config, "GATT", "Channels", &btd_opts.gatt_channels,
1, 5);
parse_config_bool(config, "GATT", "Client", &btd_opts.gatt_client);
+ parse_gatt_export(config);
}
static void parse_csis_sirk(GKeyFile *config)
@@ -1219,6 +1248,7 @@ static void init_defaults(void)
btd_opts.gatt_mtu = BT_ATT_MAX_LE_MTU;
btd_opts.gatt_channels = 1;
btd_opts.gatt_client = true;
+ btd_opts.gatt_export = BT_GATT_EXPORT_READ_ONLY;
btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
@@ -262,6 +262,11 @@
# Default to 1
#Channels = 1
+# Export claimed services by plugins
+# Possible values: no, read-only, read-write
+# Default: read-only
+#ExportClaimedServices = read-only
+
[CSIS]
# SIRK - Set Identification Resolution Key which is common for all the
# sets. They SIRK key is used to identify its sets. This can be any
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This adds GATT.ExportClaimedService which can be used to allow access to service under control of bluetoothd(1) since often times it should be safe to allow read-only access as it shouldn't interfere with each other, but this one step further and allow the systems to be configured with read-write as well just in case some sort of workaround is needed, or for debugging purposes. Since this is now a proper system policy this removes the expections from battery and deviceinfo introduced by 713f6f09f017 ("profile: Add exception to battery profile for external access") and 0cef5a7996db ("deviceinfo: Enable external flag"). --- profiles/battery/battery.c | 1 - profiles/deviceinfo/deviceinfo.c | 1 - src/btd.h | 7 ++++++ src/gatt-client.c | 37 ++++++++++++++++++++++++++++++-- src/main.c | 30 ++++++++++++++++++++++++++ src/main.conf | 5 +++++ 6 files changed, 77 insertions(+), 4 deletions(-)