diff options
-rw-r--r-- | hcid/dbus-database.c | 3 | ||||
-rw-r--r-- | hcid/dbus-service.c | 34 | ||||
-rw-r--r-- | hcid/dbus-service.h | 2 | ||||
-rw-r--r-- | hcid/hcid.h | 4 | ||||
-rw-r--r-- | hcid/storage.c | 129 |
5 files changed, 144 insertions, 28 deletions
diff --git a/hcid/dbus-database.c b/hcid/dbus-database.c index 86053915..755de673 100644 --- a/hcid/dbus-database.c +++ b/hcid/dbus-database.c @@ -339,8 +339,7 @@ static DBusHandlerResult request_authorization(DBusConnection *conn, if (!service) return error_not_authorized(conn, msg); - if (g_slist_find_custom(service->trusted_devices, address, - (GCompareFunc) strcasecmp)) { + if (read_trust(address, service->ident)) { DBusMessage *reply; reply = dbus_message_new_method_return(msg); diff --git a/hcid/dbus-service.c b/hcid/dbus-service.c index e99cb8e0..4a4da621 100644 --- a/hcid/dbus-service.c +++ b/hcid/dbus-service.c @@ -76,11 +76,6 @@ static void service_free(struct service *service) g_free(service->descr); g_free(service->ident); - if (service->trusted_devices) { - g_slist_foreach(service->trusted_devices, (GFunc) g_free, NULL); - g_slist_free(service->trusted_devices); - } - g_free(service); } @@ -481,7 +476,6 @@ static DBusHandlerResult set_trusted(DBusConnection *conn, DBusMessage *msg, void *data) { struct service *service = data; - GSList *l; DBusMessage *reply; const char *address; @@ -493,15 +487,11 @@ static DBusHandlerResult set_trusted(DBusConnection *conn, if (check_address(address) < 0) return error_invalid_arguments(conn, msg); - l = g_slist_find_custom(service->trusted_devices, address, (GCompareFunc) strcasecmp); - if (l) - return error_trusted_device_already_exists(conn, msg); - reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - service->trusted_devices = g_slist_append(service->trusted_devices, g_strdup(address)); + write_trust(address, service->ident, TRUE); return send_message_and_unref(conn, reply); } @@ -510,7 +500,6 @@ static DBusHandlerResult is_trusted(DBusConnection *conn, DBusMessage *msg, void *data) { struct service *service = data; - GSList *l; DBusMessage *reply; const char *address; dbus_bool_t trusted; @@ -520,14 +509,16 @@ static DBusHandlerResult is_trusted(DBusConnection *conn, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); - l = g_slist_find_custom(service->trusted_devices, address, (GCompareFunc) strcasecmp); - trusted = (l? TRUE : FALSE); + if (check_address(address) < 0) + return error_invalid_arguments(conn, msg); + + trusted = read_trust(address, service->ident); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(msg, + dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &trusted, DBUS_TYPE_INVALID); @@ -538,28 +529,23 @@ static DBusHandlerResult remove_trust(DBusConnection *conn, DBusMessage *msg, void *data) { struct service *service = data; - GSList *l; DBusMessage *reply; const char *address; - void *paddress; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); - l = g_slist_find_custom(service->trusted_devices, address, (GCompareFunc) strcasecmp); - if (!l) - return error_trusted_device_does_not_exists(conn, msg); + if (check_address(address) < 0) + return error_invalid_arguments(conn, msg); + + write_trust(address, service->ident, FALSE); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - paddress = l->data; - service->trusted_devices = g_slist_remove(service->trusted_devices, l->data); - g_free(paddress); - return send_message_and_unref(conn, reply); } diff --git a/hcid/dbus-service.h b/hcid/dbus-service.h index 948537c6..141d703f 100644 --- a/hcid/dbus-service.h +++ b/hcid/dbus-service.h @@ -47,8 +47,6 @@ struct service { /* Services without a *.service file */ gboolean external; - - GSList *trusted_devices; }; void release_services(DBusConnection *conn); diff --git a/hcid/hcid.h b/hcid/hcid.h index aeba6bb6..41a22983 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -26,6 +26,8 @@ #include <time.h> #include <sys/types.h> +#include <glib.h> + #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> @@ -189,3 +191,5 @@ int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key); int read_pin_length(bdaddr_t *local, bdaddr_t *peer); int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin); +gboolean read_trust(const char *addr, const char *service); +int write_trust(const char *addr, const char *service, gboolean trust); diff --git a/hcid/storage.c b/hcid/storage.c index d99defb4..145a0f82 100644 --- a/hcid/storage.c +++ b/hcid/storage.c @@ -37,6 +37,8 @@ #include <sys/param.h> #include <sys/socket.h> +#include <glib.h> + #include <bluetooth/bluetooth.h> #include "textfile.h" @@ -486,3 +488,130 @@ int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin) return len; } + +static GSList *service_string_to_list(char *services) +{ + GSList *l = NULL; + char *start = services; + int i, finished = 0; + + for (i = 0; ; i++) { + if (services[i] == '\0') + finished = 1; + + if (services[i] == ' ' || services[i] == '\0') { + services[i] = '\0'; + l = g_slist_append(l, start); + start = services + i + 1; + } + + if (finished) + break; + } + + return l; +} + +static char *service_list_to_string(GSList *services) +{ + char str[1024]; + int len = 0; + + if (!services) + return g_strdup(""); + + memset(str, 0, sizeof(str)); + + while (services) { + int ret; + char *ident = services->data; + + if (services->next) + ret = snprintf(str + len, sizeof(str) - len - 1, "%s ", + ident); + + else + ret = snprintf(str + len, sizeof(str) - len - 1, "%s", + ident); + + if (ret > 0) + len += ret; + + services = services->next; + } + + return g_strdup(str); +} + +int write_trust(const char *addr, const char *service, gboolean trust) +{ + char filename[PATH_MAX + 1], *str; + GSList *services = NULL, *match; + gboolean trusted; + int ret; + + create_filename(filename, PATH_MAX, BDADDR_ANY, "trusts"); + + create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + str = textfile_caseget(filename, addr); + if (str) + services = service_string_to_list(str); + + match = g_slist_find_custom(services, service, (GCompareFunc) strcmp); + trusted = match ? TRUE : FALSE; + + /* If the old setting is the same as the requested one, we're done */ + if (trusted == trust) { + g_slist_free(services); + if (str) + free(str); + return 0; + } + + if (trust) + services = g_slist_append(services, (void *) service); + else + services = g_slist_remove(services, match->data); + + /* Remove the entry if the last trusted service was removed */ + if (!trust && !services) + ret = textfile_casedel(filename, addr); + else { + char *new_str = service_list_to_string(services); + ret = textfile_caseput(filename, addr, new_str); + free(new_str); + } + + g_slist_free(services); + + if (str) + free(str); + + return ret; +} + +gboolean read_trust(const char *addr, const char *service) +{ + char filename[PATH_MAX + 1], *str; + GSList *services; + gboolean ret; + + create_filename(filename, PATH_MAX, BDADDR_ANY, "trusts"); + + str = textfile_caseget(filename, addr); + if (!str) + return FALSE; + + services = service_string_to_list(str); + + if (g_slist_find_custom(services, service, (GCompareFunc) strcmp)) + ret = TRUE; + else + ret = FALSE; + + g_slist_free(services); + free(str); + + return ret; +} |