diff options
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-database.c | 16 | ||||
-rw-r--r-- | hcid/dbus-security.c | 8 | ||||
-rw-r--r-- | hcid/dbus-service.c | 117 | ||||
-rw-r--r-- | hcid/dbus-service.h | 5 | ||||
-rw-r--r-- | hcid/plugin.c | 12 |
5 files changed, 137 insertions, 21 deletions
diff --git a/hcid/dbus-database.c b/hcid/dbus-database.c index a32bc810..d37b4d97 100644 --- a/hcid/dbus-database.c +++ b/hcid/dbus-database.c @@ -422,7 +422,10 @@ static DBusHandlerResult request_authorization_old(DBusConnection *conn, sender = dbus_message_get_sender(msg); - service = search_service(sender); + service = search_service_by_uuid(uuid); + if (!service) + service = search_service(sender); + if (!service) { debug("Got RequestAuthorization from non-service owner %s", sender); @@ -458,20 +461,23 @@ static DBusHandlerResult request_authorization_old(DBusConnection *conn, static DBusHandlerResult cancel_authorization_request(DBusConnection *conn, DBusMessage *msg, void *data) { - const char *sender, *address, *path; + const char *sender, *address, *uuid; struct service *service; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) == FALSE) + DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID) == FALSE) return error_invalid_arguments(conn, msg, NULL); sender = dbus_message_get_sender(msg); - service = search_service(sender); + service = search_service_by_uuid(uuid); + if (!service) + service = search_service(sender); + if (!service) return error_not_authorized(conn, msg); - return cancel_authorize_request_old(conn, msg, service, address, path); + return cancel_authorize_request_old(conn, msg, service, address, uuid); } static DBusMethodVTable database_methods[] = { diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c index 16ca7585..6b680c70 100644 --- a/hcid/dbus-security.c +++ b/hcid/dbus-security.c @@ -766,7 +766,7 @@ static DBusHandlerResult auth_agent_send_cancel(DBusMessage *msg, const char *adapter_path, struct service *service, const char *address, - const char *path) + const char *uuid) { struct auth_agent_req *req = NULL; DBusMessage *message; @@ -777,7 +777,7 @@ static DBusHandlerResult auth_agent_send_cancel(DBusMessage *msg, if (!strcmp(adapter_path, req->adapter_path) && !strcmp(address, req->address) && !strcmp(service->object_path, req->service_path) && - !strcmp(path, req->uuid)) + !strcmp(uuid, req->uuid)) break; } @@ -801,7 +801,7 @@ DBusHandlerResult cancel_authorize_request_old(DBusConnection *conn, DBusMessage *msg, struct service *service, const char *address, - const char *path) + const char *uuid) { char adapter_path[PATH_MAX]; int adapter_id; @@ -820,7 +820,7 @@ DBusHandlerResult cancel_authorize_request_old(DBusConnection *conn, adapter_id); return auth_agent_send_cancel(msg, default_auth_agent, adapter_path, - service, address, path); + service, address, uuid); } static DBusMethodVTable security_methods[] = { diff --git a/hcid/dbus-service.c b/hcid/dbus-service.c index 1d201a04..be41b22e 100644 --- a/hcid/dbus-service.c +++ b/hcid/dbus-service.c @@ -65,7 +65,13 @@ #define NAME_MATCH "interface=" DBUS_INTERFACE_DBUS ",member=NameOwnerChanged" +struct service_uuids { + char *name; + char **uuids; +}; + static GSList *services = NULL; +static GSList *services_uuids = NULL; static GSList *removed = NULL; static void service_free(struct service *service) @@ -829,6 +835,12 @@ void release_services(DBusConnection *conn) struct service *search_service(const char *pattern) { GSList *l; + const char *bus_id; + + /* Workaround for plugins: share the same bus id */ + bus_id = dbus_bus_get_unique_name(get_dbus_connection()); + if (!strcmp(bus_id, pattern)) + return NULL; for (l = services; l != NULL; l = l->next) { struct service *service = l->data; @@ -1060,22 +1072,25 @@ int service_register(DBusConnection *conn, const char *bus_name, const char *ide const char *name, const char *description) { struct service *service; - - if (!conn) - return -1; + const char *sender; service = create_external_service(ident, name, description); if (!service) return -1; - service->bus_name = g_strdup(bus_name); + if (!bus_name) { + sender = dbus_bus_get_unique_name(get_dbus_connection()); + service->bus_name = g_strdup(sender); + } else + service->bus_name = g_strdup(bus_name); if (register_service(service) < 0) { service_free(service); return -1; } - name_listener_add(conn, bus_name, (name_cb_t) external_service_exit, + if (conn && bus_name) + name_listener_add(conn, bus_name, (name_cb_t) external_service_exit, service); dbus_connection_emit_signal(get_dbus_connection(), service->object_path, @@ -1089,3 +1104,95 @@ int service_unregister(DBusConnection *conn, struct service *service) { return unregister_service_for_connection(conn, service); } + +static gint name_cmp(struct service_uuids *su, const char *name) +{ + return strcmp(su->name, name); +} + +static gint uuid_cmp(struct service_uuids *su, const char *uuid) +{ + int i; + + for (i = 0; su->uuids[i]; i++) { + if (!strcasecmp(su->uuids[i], uuid)) + return 0; + } + + return -1; +} + +struct service *search_service_by_uuid(const char *uuid) +{ + struct service_uuids *su; + struct service *service; + GSList *l; + + if (!services_uuids) + return NULL; + + l = g_slist_find_custom(services_uuids, uuid, (GCompareFunc) uuid_cmp); + if (!l) + return NULL; + + su = l->data; + service = search_service(su->name); + if (!service) + return NULL; + + return service; +} + +void register_uuids(const char *name, const char **uuids) +{ + struct service_uuids *su; + int i; + + if (!name) + return; + + su = g_new0(struct service_uuids, 1); + su->name = g_strdup(name); + + for (i = 0; uuids[i]; i++); + + su->uuids = g_new0(char *, i + 1); + + for (i = 0; uuids[i]; i++) + su->uuids[i] = g_strdup(uuids[i]); + + services_uuids = g_slist_append(services_uuids, su); +} + +static void service_uuids_free(struct service_uuids *su) +{ + int i; + + if (!su) + return; + + g_free(su->name); + + for (i = 0; su->uuids[i]; i++) + g_free(su->uuids[i]); + + g_free(su); +} + +void unregister_uuids(const char *name) +{ + struct service_uuids *su; + GSList *l; + + if (!services_uuids) + return; + + l = g_slist_find_custom(services_uuids, name, (GCompareFunc) name_cmp); + if (!l) + return; + + su = l->data; + services_uuids = g_slist_remove(services_uuids, su); + + service_uuids_free(su); +} diff --git a/hcid/dbus-service.h b/hcid/dbus-service.h index 2e7d78ce..d7661789 100644 --- a/hcid/dbus-service.h +++ b/hcid/dbus-service.h @@ -53,6 +53,8 @@ void append_available_services(DBusMessageIter *iter); struct service *search_service(const char *pattern); +struct service *search_service_by_uuid(const char *uuid); + int service_start(struct service *service, DBusConnection *conn); int init_services(const char *path); @@ -61,3 +63,6 @@ int service_register(DBusConnection *conn, const char *bus_name, const char *ide const char *name, const char *description); int service_unregister(DBusConnection *conn, struct service *service); + +void register_uuids(const char *name, const char **uuids); +void unregister_uuids(const char *name); diff --git a/hcid/plugin.c b/hcid/plugin.c index 7d275786..6cc54de1 100644 --- a/hcid/plugin.c +++ b/hcid/plugin.c @@ -38,6 +38,7 @@ #include <dbus/dbus.h> #include "dbus-helper.h" +#include "dbus-service.h" #include "adapter.h" #include "dbus-hci.h" #include "agent.h" @@ -210,18 +211,15 @@ int plugin_req_auth(bdaddr_t *src, bdaddr_t *dst, dst, active_conn_find_by_bdaddr)) return -ENOTCONN; - /* FIXME: Is there a plugin that exports this service? */ - ba2str(dst, address); device = adapter_find_device(adapter, address); if (!device) return -EPERM; - /* - * FIXME: Trusted device? Currently, service are based on a friendly - * name, it is necessary convert UUID128 to friendly name or store the - * UUID128 in the trusted file. - */ + if (!search_service_by_uuid(uuid)) + return -EPERM; + + /* FIXME: Missing check trusted file entries */ agent = (device->agent ? : adapter->agent); if (!agent) |