diff mbox series

[Bluez,7/8] core: store ServiceAllowList into settings

Message ID 20210401182328.Bluez.7.Ie9fee4e1b2bf0a661af4a4834cd73bf8438ca755@changeid
State New
Headers show
Series Hi Linux-bluetooth, | expand

Commit Message

Howard Chung April 1, 2021, 10:24 a.m. UTC
This implements the logics of storing ServiceAllowList when the value
changed and restoring ServiceAllowList when adapter initialized.

The stored information would look like:
ServiceAllowList=$UUID128_STRING1;$UUID128_STRING2......

Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
---

 src/adapter.c      | 103 +++++++++++++++++++++++++++++++++++++++++++++
 src/adapter.h      |   1 +
 src/admin_policy.c |   1 +
 3 files changed, 105 insertions(+)
diff mbox series

Patch

diff --git a/src/adapter.c b/src/adapter.c
index 5531ed0e2246..f03eda2abc17 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -473,13 +473,19 @@  uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter)
 	return adapter->bdaddr_type;
 }
 
+static char **create_uuid_string_allowlist(GHashTable *allowed_uuid_set,
+							guint *num_of_uuid);
 static void store_adapter_info(struct btd_adapter *adapter)
 {
 	GKeyFile *key_file;
+	GHashTable *allowed_uuid_set;
 	char filename[PATH_MAX];
 	char *str;
 	gsize length = 0;
 	gboolean discoverable;
+	char **uuid_str_arr;
+	guint num_of_uuid = 0;
+	int i;
 
 	key_file = g_key_file_new();
 
@@ -508,15 +514,36 @@  static void store_adapter_info(struct btd_adapter *adapter)
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/settings",
 					btd_adapter_get_storage_dir(adapter));
 
+	if (adapter->admin_policy) {
+		allowed_uuid_set = btd_admin_policy_allowlist_get(
+							adapter->admin_policy);
+		uuid_str_arr = create_uuid_string_allowlist(allowed_uuid_set,
+								&num_of_uuid);
+		g_key_file_set_string_list(key_file, "Policy",
+				"ServiceAllowList",
+				(const char *const*)uuid_str_arr, num_of_uuid);
+	}
 	create_file(filename, 0600);
 
+
 	str = g_key_file_to_data(key_file, &length, NULL);
 	g_file_set_contents(filename, str, length, NULL);
 	g_free(str);
 
+	for (i = 0; i < num_of_uuid; i++)
+		g_free(uuid_str_arr[i]);
+
+	g_free(uuid_str_arr);
+
 	g_key_file_free(key_file);
 }
 
+void btd_adapter_store_adapter_info(struct btd_adapter *adapter)
+{
+	if (adapter)
+		store_adapter_info(adapter);
+}
+
 static void trigger_pairable_timeout(struct btd_adapter *adapter);
 static void adapter_start(struct btd_adapter *adapter);
 static void adapter_stop(struct btd_adapter *adapter);
@@ -3509,6 +3536,32 @@  void btd_adapter_refresh_is_blocked_by_policy(struct btd_adapter *adapter)
 									NULL);
 }
 
+static char **create_uuid_string_allowlist(GHashTable *allowed_uuid_set,
+							guint *num_of_uuid)
+{
+	int i;
+	gpointer *uuids;
+	char **uuid_str_allowlist;
+	bt_uuid_t *uuid;
+
+	uuids = g_hash_table_get_keys_as_array(allowed_uuid_set, num_of_uuid);
+	uuid_str_allowlist = g_try_malloc_n(*num_of_uuid, sizeof(char *));
+
+	if (!uuid_str_allowlist && !num_of_uuid) {
+		error("Failed to allocate memory for uuid_str_allowlist");
+		return NULL;
+	}
+
+	for (i = 0; i < *num_of_uuid; i++) {
+		uuid = uuids[i];
+		uuid_str_allowlist[i] = g_try_malloc(MAX_LEN_UUID_STR);
+		bt_uuid_to_string(uuid, uuid_str_allowlist[i],
+							MAX_LEN_UUID_STR);
+	}
+
+	return uuid_str_allowlist;
+}
+
 static const GDBusMethodTable adapter_methods[] = {
 	{ GDBUS_ASYNC_METHOD("StartDiscovery", NULL, NULL, start_discovery) },
 	{ GDBUS_METHOD("SetDiscoveryFilter",
@@ -6265,12 +6318,42 @@  static void fix_storage(struct btd_adapter *adapter)
 	textfile_del(filename, "converted");
 }
 
+static GHashTable *uuid_list_to_uuid_set(gchar **uuids, gsize num_of_uuid)
+{
+	int i;
+	bt_uuid_t *uuid;
+	GHashTable *uuid_set = g_hash_table_new_full(bt_uuid_hash,
+						bt_uuid_equal, g_free, NULL);
+
+	if (!uuid_set)
+		return NULL;
+
+	for (i = 0; i < num_of_uuid; i++) {
+		uuid = g_try_malloc(sizeof(*uuid));
+
+		if (!uuid || bt_string_to_uuid(uuid, *uuids))
+			goto failed;
+
+		g_hash_table_add(uuid_set, uuid);
+		uuids++;
+	}
+
+	return uuid_set;
+
+failed:
+	g_hash_table_destroy(uuid_set);
+	return NULL;
+}
+
 static void load_config(struct btd_adapter *adapter)
 {
 	GKeyFile *key_file;
 	char filename[PATH_MAX];
 	struct stat st;
+	GHashTable *uuid_set;
 	GError *gerr = NULL;
+	gchar **uuids = NULL;
+	gsize num_of_uuid;
 
 	key_file = g_key_file_new();
 
@@ -6320,6 +6403,23 @@  static void load_config(struct btd_adapter *adapter)
 		gerr = NULL;
 	}
 
+	if (adapter->admin_policy) {
+		uuids = g_key_file_get_string_list(key_file, "Policy",
+				"ServiceAllowList", &num_of_uuid, &gerr);
+
+		if (gerr) {
+			uuids = NULL;
+			num_of_uuid = 0;
+			g_error_free(gerr);
+			gerr = NULL;
+		}
+
+		uuid_set = uuid_list_to_uuid_set(uuids, num_of_uuid);
+		if (uuid_set)
+			btd_admin_policy_allowlist_set(adapter->admin_policy,
+								uuid_set);
+	}
+
 	g_key_file_free(key_file);
 }
 
@@ -8761,6 +8861,9 @@  load:
 	load_defaults(adapter);
 	load_devices(adapter);
 
+	/* Update IsBlockedByPolicy on devices */
+	g_slist_foreach(adapter->devices, update_device_is_blocked_by_policy,
+									NULL);
 	/* restore Service Changed CCC value for bonded devices */
 	btd_gatt_database_restore_svc_chng_ccc(adapter->database);
 
diff --git a/src/adapter.h b/src/adapter.h
index 8e8c61b7bdf1..038754b6d76c 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -90,6 +90,7 @@  const char *adapter_get_path(struct btd_adapter *adapter);
 const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter);
 uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter);
 const char *btd_adapter_get_storage_dir(struct btd_adapter *adapter);
+void btd_adapter_store_adapter_info(struct btd_adapter *adapter);
 int adapter_set_name(struct btd_adapter *adapter, const char *name);
 
 int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec);
diff --git a/src/admin_policy.c b/src/admin_policy.c
index 6498dcf05319..0b51b379ed74 100644
--- a/src/admin_policy.c
+++ b/src/admin_policy.c
@@ -154,6 +154,7 @@  static DBusMessage *set_service_allowlist(DBusConnection *conn,
 	g_hash_table_destroy(admin_policy->allowed_uuid_set);
 
 	btd_admin_policy_allowlist_set(admin_policy, uuid_set);
+	btd_adapter_store_adapter_info(adapter);
 
 	return dbus_message_new_method_return(msg);
 }