diff options
| -rw-r--r-- | hcid/dbus-adapter.c | 128 | ||||
| -rw-r--r-- | hcid/dbus-common.c | 16 | ||||
| -rw-r--r-- | hcid/dbus-manager.c | 58 | ||||
| -rw-r--r-- | hcid/dbus-security.c | 159 | ||||
| -rw-r--r-- | hcid/dbus.h | 8 | 
5 files changed, 255 insertions, 114 deletions
| diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 06eb40f6..e1627a6e 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -1310,68 +1310,59 @@ static DBusMessage *handle_dev_discover_service_req(DBusMessage *msg, void *data  }  static const struct service_data dev_services[] = { -	{ DEV_GET_ADDRESS,		handle_dev_get_address_req,		DEV_GET_ADDRESS_SIGNATURE		}, -	{ DEV_GET_VERSION,		handle_dev_get_version_req,		DEV_GET_VERSION_SIGNATURE		}, -	{ DEV_GET_REVISION,		handle_dev_get_revision_req,		DEV_GET_REVISION_SIGNATURE		}, -	{ DEV_GET_MANUFACTURER,		handle_dev_get_manufacturer_req,	DEV_GET_MANUFACTURER_SIGNATURE		}, -	{ DEV_GET_COMPANY,		handle_dev_get_company_req,		DEV_GET_COMPANY_SIGNATURE		}, -	{ DEV_GET_FEATURES,		handle_dev_get_features_req,		DEV_GET_FEATURES_SIGNATURE		}, -	{ DEV_GET_MODE,			handle_dev_get_mode_req,		DEV_GET_MODE_SIGNATURE			}, -	{ DEV_LIST_MINOR_CLASSES,	handle_dev_list_minor_classes_req,	DEV_LIST_MINOR_CLASSES_SIGNATURE	}, -	{ DEV_SET_MODE,			handle_dev_set_mode_req,		DEV_SET_MODE_SIGNATURE			}, -	{ DEV_GET_DISCOVERABLE_TO,	handle_dev_get_discoverable_to_req,	DEV_GET_DISCOVERABLE_TO_SIGNATURE	}, -	{ DEV_SET_DISCOVERABLE_TO,	handle_dev_set_discoverable_to_req,	DEV_SET_DISCOVERABLE_TO_SIGNATURE	}, -	{ DEV_IS_CONNECTABLE,		handle_dev_is_connectable_req,		DEV_IS_CONNECTABLE_SIGNATURE		}, -	{ DEV_IS_DISCOVERABLE,		handle_dev_is_discoverable_req,		DEV_IS_DISCOVERABLE_SIGNATURE		}, -	{ DEV_GET_MAJOR_CLASS,		handle_dev_get_major_class_req,		DEV_GET_MAJOR_CLASS_SIGNATURE		}, -	{ DEV_GET_MINOR_CLASS,		handle_dev_get_minor_class_req,		DEV_GET_MINOR_CLASS_SIGNATURE		}, -	{ DEV_SET_MINOR_CLASS,		handle_dev_set_minor_class_req,		DEV_SET_MINOR_CLASS_SIGNATURE		}, -	{ DEV_GET_SERVICE_CLASSES,	handle_dev_get_service_classes_req,	DEV_GET_SERVICE_CLASSES_SIGNATURE	}, -	{ DEV_GET_NAME,			handle_dev_get_name_req,		DEV_GET_NAME_SIGNATURE			}, -	{ DEV_SET_NAME,			handle_dev_set_name_req,		DEV_SET_NAME_SIGNATURE			}, +	{ DEV_GET_ADDRESS,		handle_dev_get_address_req,		}, +	{ DEV_GET_VERSION,		handle_dev_get_version_req,		}, +	{ DEV_GET_REVISION,		handle_dev_get_revision_req,		}, +	{ DEV_GET_MANUFACTURER,		handle_dev_get_manufacturer_req,	}, +	{ DEV_GET_COMPANY,		handle_dev_get_company_req,		}, +	{ DEV_GET_FEATURES,		handle_dev_get_features_req,		}, +	{ DEV_GET_MODE,			handle_dev_get_mode_req,		}, +	{ DEV_LIST_MINOR_CLASSES,	handle_dev_list_minor_classes_req,	}, +	{ DEV_SET_MODE,			handle_dev_set_mode_req,		}, +	{ DEV_GET_DISCOVERABLE_TO,	handle_dev_get_discoverable_to_req,	}, +	{ DEV_SET_DISCOVERABLE_TO,	handle_dev_set_discoverable_to_req,	}, +	{ DEV_IS_CONNECTABLE,		handle_dev_is_connectable_req,		}, +	{ DEV_IS_DISCOVERABLE,		handle_dev_is_discoverable_req,		}, +	{ DEV_GET_MAJOR_CLASS,		handle_dev_get_major_class_req,		}, +	{ DEV_GET_MINOR_CLASS,		handle_dev_get_minor_class_req,		}, +	{ DEV_SET_MINOR_CLASS,		handle_dev_set_minor_class_req,		}, +	{ DEV_GET_SERVICE_CLASSES,	handle_dev_get_service_classes_req,	}, +	{ DEV_GET_NAME,			handle_dev_get_name_req,		}, +	{ DEV_SET_NAME,			handle_dev_set_name_req,		}, -	{ DEV_GET_REMOTE_VERSION,	handle_dev_get_remote_version_req,	DEV_GET_REMOTE_VERSION_SIGNATURE	}, -	{ DEV_GET_REMOTE_REVISION,	handle_dev_get_remote_revision_req,	DEV_GET_REMOTE_REVISION_SIGNATURE	}, -	{ DEV_GET_REMOTE_MANUFACTURER,	handle_dev_get_remote_manufacturer_req,	DEV_GET_REMOTE_MANUFACTURER_SIGNATURE	}, -	{ DEV_GET_REMOTE_COMPANY,	handle_dev_get_remote_company_req,	DEV_GET_REMOTE_COMPANY_SIGNATURE	}, -	{ DEV_GET_REMOTE_NAME,		handle_dev_get_remote_name_req,		DEV_GET_REMOTE_NAME_SIGNATURE		}, -	{ DEV_GET_REMOTE_ALIAS,		handle_dev_get_remote_alias_req,	DEV_GET_REMOTE_ALIAS_SIGNATURE		}, -	{ DEV_SET_REMOTE_ALIAS,		handle_dev_set_remote_alias_req,	DEV_SET_REMOTE_ALIAS_SIGNATURE		}, - -	{ DEV_LAST_SEEN,		handle_dev_last_seen_req,		DEV_LAST_SEEN_SIGNATURE			}, -	{ DEV_LAST_USED,		handle_dev_last_used_req,		DEV_LAST_USED_SIGNATURE			}, - -	{ DEV_CREATE_BONDING,		handle_dev_create_bonding_req,		DEV_CREATE_BONDING_SIGNATURE		}, -	{ DEV_REMOVE_BONDING,		handle_dev_remove_bonding_req,		DEV_REMOVE_BONDING_SIGNATURE		}, -	{ DEV_HAS_BONDING_NAME,		handle_dev_has_bonding_req,		DEV_HAS_BONDING_SIGNATURE		}, -	{ DEV_LIST_BONDINGS,		handle_dev_list_bondings_req,		DEV_LIST_BONDINGS_SIGNATURE		}, -	{ DEV_GET_PIN_CODE_LENGTH,	handle_dev_get_pin_code_length_req,	DEV_GET_PIN_CODE_LENGTH_SIGNATURE	}, -	{ DEV_GET_ENCRYPTION_KEY_SIZE,	handle_dev_get_encryption_key_size_req,	DEV_GET_ENCRYPTION_KEY_SIZE_SIGNATURE	}, - -	{ DEV_DISCOVER_DEVICES,		handle_dev_discover_devices_req,	DEV_DISCOVER_DEVICES_SIGNATURE		}, -	{ DEV_CANCEL_DISCOVERY,		handle_dev_cancel_discovery_req,	DEV_CANCEL_DISCOVERY_SIGNATURE		}, -	{ DEV_DISCOVER_CACHE,		handle_dev_discover_cache_req,		DEV_DISCOVER_CACHE_SIGNATURE		}, -	{ DEV_DISCOVER_SERVICE,		handle_dev_discover_service_req,	DEV_DISCOVER_SERVICE_SIGNATURE		}, - -	{ NULL, NULL, NULL} +	{ DEV_GET_REMOTE_VERSION,	handle_dev_get_remote_version_req,	}, +	{ DEV_GET_REMOTE_REVISION,	handle_dev_get_remote_revision_req,	}, +	{ DEV_GET_REMOTE_MANUFACTURER,	handle_dev_get_remote_manufacturer_req,	}, +	{ DEV_GET_REMOTE_COMPANY,	handle_dev_get_remote_company_req,	}, +	{ DEV_GET_REMOTE_NAME,		handle_dev_get_remote_name_req,		}, +	{ DEV_GET_REMOTE_ALIAS,		handle_dev_get_remote_alias_req,	}, +	{ DEV_SET_REMOTE_ALIAS,		handle_dev_set_remote_alias_req,	}, + +	{ DEV_LAST_SEEN,		handle_dev_last_seen_req,		}, +	{ DEV_LAST_USED,		handle_dev_last_used_req,		}, + +	{ DEV_CREATE_BONDING,		handle_dev_create_bonding_req,		}, +	{ DEV_REMOVE_BONDING,		handle_dev_remove_bonding_req,		}, +	{ DEV_HAS_BONDING_NAME,		handle_dev_has_bonding_req,		}, +	{ DEV_LIST_BONDINGS,		handle_dev_list_bondings_req,		}, +	{ DEV_GET_PIN_CODE_LENGTH,	handle_dev_get_pin_code_length_req,	}, +	{ DEV_GET_ENCRYPTION_KEY_SIZE,	handle_dev_get_encryption_key_size_req,	}, + +	{ DEV_DISCOVER_DEVICES,		handle_dev_discover_devices_req,	}, +	{ DEV_CANCEL_DISCOVERY,		handle_dev_cancel_discovery_req,	}, +	{ DEV_DISCOVER_CACHE,		handle_dev_discover_cache_req,		}, +	{ DEV_DISCOVER_SERVICE,		handle_dev_discover_service_req,	}, + +	{ NULL, NULL }  };  DBusHandlerResult msg_func_device(DBusConnection *conn, DBusMessage *msg, void *data)  { -	const struct service_data *handlers = dev_services; -	DBusMessage *reply = NULL;  	struct hci_dbus_data *dbus_data = data; -	const char *method; -	const char *signature;  	const char *iface; -	uint32_t err = BLUEZ_EDBUS_UNKNOWN_METHOD; -	method = dbus_message_get_member(msg); -	signature = dbus_message_get_signature(msg);  	iface = dbus_message_get_interface(msg); -	info("Adapter path:%s iface:%s method:%s", dbus_message_get_path(msg), iface, method); -  	if (strcmp(ADAPTER_INTERFACE, iface))  		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1381,33 +1372,22 @@ DBusHandlerResult msg_func_device(DBusConnection *conn, DBusMessage *msg, void *  		goto failed;  	} -	/* It's a device path id */ -	for (; handlers->name != NULL; handlers++) { -		if (strcmp(handlers->name, method)) -			continue; +	handler = find_service_handler(dev_services, msg); +	if (!handler) +		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -		if (!strcmp(handlers->signature, signature)) { -			reply = handlers->handler_func(msg, data); -			err = 0; -			break; -		} else { -			/* Set the error, but continue looping incase there is -			 * another method with the same name but a different -			 * signature */ -			err = BLUEZ_EDBUS_WRONG_SIGNATURE; -			continue; -		} -	} +	return handler(conn, msg, data);  failed: -	if (err) -		reply = bluez_new_failure_msg(msg, err); +	if (err) { +		DBusMessage *reply = bluez_new_failure_msg(msg, err); -	if (reply) { -		if (!dbus_connection_send (conn, reply, NULL)) -			error("Can't send reply message"); +		if (reply) { +			if (!dbus_connection_send(conn, reply, NULL)) +				error("Can't send reply message"); -		dbus_message_unref(reply); +			dbus_message_unref(reply); +		}  	}  	return DBUS_HANDLER_RESULT_HANDLED; diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c index 45cc6246..41a9ce3e 100644 --- a/hcid/dbus-common.c +++ b/hcid/dbus-common.c @@ -281,3 +281,19 @@ int name_listener_remove(DBusConnection *connection, const char *name,  	return 0;  } + +service_hanbdler_func_t *find_service_handler(const service_data *handlers, DBusMessage *msg) +{ +	struct service_data *current; +	const char *name, *sig; + +	member = dbus_message_get_member(msg); + +	for (current = handlers; current->name != NULL; current++) { +		if (!strcmp(current->name, member)) +			return current->handler_func; +	} + +	return NULL; +} + diff --git a/hcid/dbus-manager.c b/hcid/dbus-manager.c index ad04f862..ffbdc943 100644 --- a/hcid/dbus-manager.c +++ b/hcid/dbus-manager.c @@ -127,53 +127,35 @@ static DBusMessage *handle_mgr_default_device_req(DBusMessage *msg, void *data)  }  static const struct service_data mgr_services[] = { -	{ MGR_LIST_ADAPTERS,	handle_mgr_list_devices_req,	MGR_LIST_ADAPTERS_SIGNATURE	}, -	{ MGR_DEFAULT_ADAPTER,	handle_mgr_default_device_req,	MGR_DEFAULT_ADAPTER_SIGNATURE	}, -	{ NULL, NULL, NULL } +	{ MGR_LIST_ADAPTERS,	handle_mgr_list_devices_req	}, +	{ MGR_DEFAULT_ADAPTER,	handle_mgr_default_device_req	}, +	{ NULL, NULL }  }; -DBusHandlerResult msg_func_manager(DBusConnection *conn, DBusMessage *msg, void *data) +static DBusHandlerResult handle_manager_method(DBusConnection *conn, +						DBusMessage *msg, void *data)  { -	const struct service_data *handlers; -	DBusMessage *reply = NULL; -	const char *iface; -	const char *method; -	const char *signature; -	uint32_t err = BLUEZ_EDBUS_UNKNOWN_METHOD; -	DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	iface = dbus_message_get_interface(msg); -	method = dbus_message_get_member(msg); -	signature = dbus_message_get_signature(msg); +	service_handler_func_t *handler; -	info("Manager path:%s method:%s", dbus_message_get_path(msg), method); +	handler = find_service_handler(mgr_services, msg); -	if (strcmp(iface, MANAGER_INTERFACE)) -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	if (handler) +		return handler(conn, msg, data); -	for (handlers = mgr_services; handlers->name != NULL; handlers++) { -		if (strcmp(handlers->name, method)) -			continue; - -		if (strcmp(handlers->signature, signature) != 0) -			err = BLUEZ_EDBUS_WRONG_SIGNATURE; -		else { -			reply = handlers->handler_func(msg, data); -			err = 0; -		} +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} -		ret = DBUS_HANDLER_RESULT_HANDLED; -	} +DBusHandlerResult msg_func_manager(DBusConnection *conn, DBusMessage *msg, void *data) +{ +	const char *iface; -	if (err) -		reply = bluez_new_failure_msg(msg, err); +	iface = dbus_message_get_interface(msg); -	if (reply) { -		if (!dbus_connection_send (conn, reply, NULL)) -			error("Can't send reply message"); +	if (!strcmp(iface, MANAGER_INTERFACE)) +		return handle_manager_method(conn, msg, data); -		dbus_message_unref(reply); -	} +	if (!strcmp(iface, SECURITY_INTERFACE)) +		return handle_security_method(conn, msg, data); -	return ret; +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;  } diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c index f3bf47c4..eec34272 100644 --- a/hcid/dbus-security.c +++ b/hcid/dbus-security.c @@ -27,3 +27,162 @@  #include <stdio.h>  #include <errno.h> + +#include <dbus/dbus.h> + +#include "dbus.h" +#include "dbus-error.h" +#include "dbus-common.h" + +static struct passkey_agent *default_agent = NULL; + +static const struct service_data sec_services[] = { +	{ "RegisterDefault",	register_default_agent		}, +	{ "UnregisterDefault",	unregister_default_agent	}, +	{ NULL, NULL } +}; + +static void default_agent_exited(const char *name, void *data) +{ +	debug("%s exited without unregistering the default passkey agent", name); + +	if (!default_agent || strcmp(name, default_agent->name)) { +		/* This should never happen (there's a bug in the code if it does */ +		debug("default_agent_exited: mismatch with actual default_agent"); +		return; +	} + +	free(default_agent->path); +	free(default_agent->name); +	free(default_agent); +	default_agent = NULL; +} + +static DBusHandlerResult register_default_agent(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	char *path; +	DBusMessage *reply; + +	if (default_agent) { +		reply = error_passkey_agent_already_exists(msg); +		if (!reply) +			return DBUS_HANDLER_RESULT_NEED_MEMORY; +		goto done; +	} + +	if (!dbus_message_get_args(msg, NULL, +				DBUS_TYPE_STRING, &path, +				DBUS_TYPE_INVALID)) { +		reply = error_invalid_arguments(msg); +		if (!reply) +			return DBUS_HANDLER_RESULT_NEED_MEMORY; +		goto done; +	} + +	default_agent = malloc(sizeof(struct passkey_agent)); +	if (!default_agent) +		goto need_memory; + +	memset(default_agent, 0, sizeof(struct passkey_agent)); + +	default_agent->name = strdup(dbus_message_get_sender(msg)); +	if (!default_agent->name) +		goto need_memory; + +	default_agent->path = strdup(path); +	if (!default_agent->path) +		goto need_memory; + +	reply = dbus_message_new_method_return(); +	if (!reply) +		goto need_memory; + +	name_listener_add(conn, default_agent->name, +			(name_cb_t)default_agent_exited, NULL); + +	info("Default passkey agent (%s, %s) registered", +			default_agent->name, default_agent->path); + +done: +	dbus_connection_send(conn, reply, NULL); +	dbus_message_unref(reply); + +	return DBUS_HANDLER_RESULT_HANDLED; + +need_memory: +	if (default_agent) { +		if (default_agent->name) +			free(default_agent->name); +		if (default_agent->path) +			free(default_agent->path); +		free(default_agent); +		default_agent = NULL; +	} + +	return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +static DBusHandlerResult unregister_default_agent(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	DBusMessage *reply; +	char *name, *path; + +	if (!default_agent) { +		reply = error_does_not_exist(msg); +		if (!reply) +			return DBUS_HANDLER_RESULT_NEED_MEMORY; +		goto done; +	} + +	if (!dbus_message_get_args(msg, NULL, +				DBUS_TYPE_STRING, &path, +				DBUS_TYPE_INVALID)) { +		reply = error_invalid_arguments(msg); +		if (!reply) +			return DBUS_HANDLER_RESULT_NEED_MEMORY; +		goto done; +	} + +	if (strcmp(name, default_agent->name) || strcmp(path, default_agent->path)) { +		reply = error_does_not_exist(msg); +		if (!reply) +			return DBUS_HANDLER_RESULT_NEED_MEMORY; +		goto done; +	} + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	name_listener_remove(conn, default_agent->name, +			(name_cb_t)default_agent_exited, NULL); + +	info("Default passkey agent (%s, %s) unregistered", +			default_agent->name, default_agent->path); + +	free(default_agent->path); +	free(default_agent->name); +	free(default_agent); +	default_agent = NULL; + +done: +	dbus_connection_send(conn, reply, NULL); +	dbus_message_unref(reply); + +	return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg, void *data) +{ +	service_handler_func_t *handler; + +	handler = find_service_handler(sec_services, msg); + +	if (handler) +		return handler(conn, msg, data); + +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + diff --git a/hcid/dbus.h b/hcid/dbus.h index f833a421..3ae122fb 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -56,12 +56,13 @@  #define MAX_PATH_LENGTH		64 -typedef DBusMessage* (service_handler_func_t) (DBusMessage *, void *); +typedef DBusMessage* (service_handler_func_t) (DBusConnection *conn, +						DBusMessage *msg, +						void *user_data);  struct service_data {  	const char		*name;  	service_handler_func_t	*handler_func; -	const char		*signature;  };  typedef int (timeout_handler_func_t) (void *data); @@ -121,6 +122,9 @@ int name_listener_add(DBusConnection *connection, const char *name,  int name_listener_remove(DBusConnection *connection, const char *name,  				name_cb_t func, void *user_data); +DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg, void *data); + +service_hanbdler_func_t *find_service_handler(service_data *services, DBusMessage *msg);  /*========================================================================       BlueZ D-Bus Manager service definitions "/org/bluez/Manager" | 
