diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-06-17 19:37:36 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-06-17 19:37:36 +0000 | 
| commit | e8ca2351ee3ba3f8b2b99731972234f42ae9b64b (patch) | |
| tree | 8a639f9f831dd79ec2b3b8d5d952d649885a59ba | |
| parent | bbec31284f7e4e960c07bddd9fd1d7ee5c990118 (diff) | |
Fix authorization mechanism for 3.x.
| -rw-r--r-- | audio/avdtp.c | 34 | ||||
| -rw-r--r-- | audio/control.c | 91 | ||||
| -rw-r--r-- | audio/main.c | 26 | ||||
| -rw-r--r-- | audio/manager.c | 12 | ||||
| -rw-r--r-- | audio/manager.h | 7 | ||||
| -rw-r--r-- | hcid/dbus-security.c | 172 | ||||
| -rw-r--r-- | hcid/dbus-security.h | 16 | ||||
| -rw-r--r-- | hcid/dbus-service.c | 10 | ||||
| -rw-r--r-- | hcid/dbus-service.h | 2 | ||||
| -rw-r--r-- | input/server.c | 2 | ||||
| -rw-r--r-- | network/server.c | 2 | 
11 files changed, 243 insertions, 131 deletions
| diff --git a/audio/avdtp.c b/audio/avdtp.c index b0cd98ba..bda21ac5 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -1496,13 +1496,6 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,  	return TRUE;  failed: -	if (session->pending_auth) { -		manager_cancel_authorize(&session->dst, ADVANCED_AUDIO_UUID, -						session->pending_auth); -		dbus_pending_call_unref(session->pending_auth); -		session->pending_auth = NULL; -	} -  	connection_lost(session, -EIO);  	return FALSE; @@ -2691,10 +2684,7 @@ static void auth_cb(DBusError *derr, void *user_data)  		error("Access denied: %s", derr->message);  		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) {  			debug("Canceling authorization request"); -			if (service_cancel_auth(&session->dst) < 0) -				manager_cancel_authorize(&session->dst, -							ADVANCED_AUDIO_UUID, -							NULL); +			service_cancel_auth(&session->src, &session->dst);  		}  		connection_lost(session, -EACCES); @@ -2721,23 +2711,6 @@ static void auth_cb(DBusError *derr, void *user_data)  	g_io_channel_unref(io);  } -static void auth_cb_old(DBusPendingCall *call, void *data) -{ -	struct avdtp *session = data; -	DBusMessage *reply = dbus_pending_call_steal_reply(call); -	DBusError err; - -	dbus_pending_call_unref(session->pending_auth); -	session->pending_auth = NULL; - -	dbus_error_init(&err); -	dbus_set_error_from_message(&err, reply); -	auth_cb(&err, data); -	dbus_error_free(&err); - -	dbus_message_unref(reply); -} -  static void avdtp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,  		const bdaddr_t *dst, gpointer data)  { @@ -2785,10 +2758,7 @@ static void avdtp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,  	g_io_channel_unref(chan);  	if (service_req_auth(src, dst, ADVANCED_AUDIO_UUID, auth_cb, -			session) == 0) -		return; -	else if (!manager_authorize(dst, ADVANCED_AUDIO_UUID, auth_cb_old, -			session, &session->pending_auth)) { +			session) < 0) {  		avdtp_unref(session);  		goto drop;  	} diff --git a/audio/control.c b/audio/control.c index 6778b268..9139213b 100644 --- a/audio/control.c +++ b/audio/control.c @@ -165,8 +165,6 @@ struct avctp {  	guint io;  	uint16_t mtu; - -	DBusPendingCall *pending_auth;  };  struct control { @@ -323,12 +321,8 @@ static struct avctp *avctp_get(const bdaddr_t *src, const bdaddr_t *dst)  	assert(dst != NULL);  	session = find_session(src, dst); -	if (session) { -		if (session->pending_auth) -			return NULL; -		else -			return session; -	} +	if (session) +		return session;  	session = g_new0(struct avctp, 1); @@ -420,13 +414,6 @@ static void avctp_unref(struct avctp *session)  {  	sessions = g_slist_remove(sessions, session); -	if (session->pending_auth) { -		manager_cancel_authorize(&session->dst, AVRCP_TARGET_UUID, -						NULL); -		dbus_pending_call_cancel(session->pending_auth); -		dbus_pending_call_unref(session->pending_auth); -	} -  	if (session->state == AVCTP_STATE_CONNECTED)  		g_dbus_emit_signal(session->dev->conn,  						session->dev->path, @@ -609,56 +596,47 @@ static void init_uinput(struct avctp *session)  		debug("AVRCP: uinput initialized for %s", name);  } -static void auth_cb(DBusError *derr, void *user_data) +static void avctp_connect_session(struct avctp *session)  { -	struct avctp *session = user_data;  	GIOChannel *io; -	if (derr && dbus_error_is_set(derr)) { -		error("Access denied: %s", derr->message); -		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) { -			debug("Canceling authorization request"); -			if (service_cancel_auth(&session->dst) < 0) -				manager_cancel_authorize(&session->dst, -							AVRCP_TARGET_UUID, -							NULL); -		} - -		avctp_unref(session); -		return; -	} -  	session->state = AVCTP_STATE_CONNECTED; -  	session->dev = manager_device_connected(&session->dst,  						AVRCP_TARGET_UUID);  	session->dev->control->session = session; +  	init_uinput(session);  	g_dbus_emit_signal(session->dev->conn, session->dev->path,  					AUDIO_CONTROL_INTERFACE, "Connected",  					DBUS_TYPE_INVALID); -	g_source_remove(session->io); +	if (session->io) +		g_source_remove(session->io);  	io = g_io_channel_unix_new(session->sock);  	session->io = g_io_add_watch(io, -				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, -				(GIOFunc) session_cb, session); +			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, +			(GIOFunc) session_cb, session);  	g_io_channel_unref(io);  } -static void auth_cb_old(DBusPendingCall *call, void *data) +static void auth_cb(DBusError *derr, void *user_data)  { -	DBusMessage *reply = dbus_pending_call_steal_reply(call); -	DBusError err; +	struct avctp *session = user_data; -	dbus_error_init(&err); -	dbus_set_error_from_message(&err, reply); -	auth_cb(&err, data); -	dbus_error_free(&err); +	if (derr && dbus_error_is_set(derr)) { +		error("Access denied: %s", derr->message); +		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) { +			debug("Canceling authorization request"); +			service_cancel_auth(&session->src, &session->dst); +		} -	dbus_message_unref(reply); +		avctp_unref(session); +		return; +	} + +	avctp_connect_session(session);  }  static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src, @@ -701,6 +679,7 @@ static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,  	}  	session->mtu = l2o.imtu; +  	session->io = g_io_add_watch(chan, flags, (GIOFunc) session_cb,  				session);  	g_io_channel_unref(chan); @@ -708,34 +687,18 @@ static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,  	if (avdtp_is_connected(src, dst))  		goto proceed; -	if (service_req_auth(src, dst, AVRCP_TARGET_UUID, auth_cb, session) == 0) -		goto proceed; -	else if (!manager_authorize(dst, AVRCP_TARGET_UUID, auth_cb_old, session, -				&session->pending_auth)) { -		avctp_unref(session); +	if (service_req_auth(src, dst, AVRCP_TARGET_UUID, auth_cb, session) < 0)  		goto drop; -	} + +	return;  proceed: -	if (!session->pending_auth) { -		session->state = AVCTP_STATE_CONNECTED; -		session->dev = manager_device_connected(dst, -							AVRCP_TARGET_UUID); -		session->dev->control->session = session; -		init_uinput(session); -		flags |= G_IO_IN; -		g_dbus_emit_signal(session->dev->conn, -						session->dev->path, -						AUDIO_CONTROL_INTERFACE, -						"Connected", -						DBUS_TYPE_INVALID); -	} +	avctp_connect_session(session);  	return;  drop: -	g_io_channel_close(chan); -	g_io_channel_unref(chan); +	close(session->sock);  }  static GIOChannel *avctp_server_socket(gboolean master) diff --git a/audio/main.c b/audio/main.c index 86efce27..bbe06e05 100644 --- a/audio/main.c +++ b/audio/main.c @@ -80,6 +80,28 @@ static struct btd_device_driver a2dp_driver = {  	.remove	= a2dp_remove,  }; +static int audio_probe(struct btd_device *device) +{ +	DBG("path %s", device->path); + +	return 0; +} + +static void audio_remove(struct btd_device *device) +{ +	DBG("path %s", device->path); +} + +static struct btd_device_driver audio_driver = { +	.name	= "audio", +	.uuids	= BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID, +			ADVANCED_AUDIO_UUID, A2DP_SOURCE_UUID, A2DP_SINK_UUID, +			AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID), +	.probe	= audio_probe, +	.remove	= audio_remove, +}; + +  static GKeyFile *load_config_file(const char *file)  {  	GError *err = NULL; @@ -124,11 +146,15 @@ static int audio_init(void)  	btd_register_device_driver(&a2dp_driver); +	btd_register_device_driver(&audio_driver); +  	return 0;  }  static void audio_exit(void)  { +	btd_unregister_device_driver(&audio_driver); +  	btd_unregister_device_driver(&a2dp_driver);  	btd_unregister_device_driver(&headset_driver); diff --git a/audio/manager.c b/audio/manager.c index 242f16bb..18ef9eb4 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -1164,9 +1164,7 @@ static void auth_cb(DBusError *derr, void *user_data)  		error("Access denied: %s", derr->message);  		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) {  			debug("Canceling authorization request"); -			if (service_cancel_auth(&device->dst) < 0) -				manager_cancel_authorize(&device->dst, uuid, -							NULL); +			service_cancel_auth(&device->src, &device->dst);  		}  		headset_set_state(device, HEADSET_STATE_DISCONNECTED); @@ -1219,9 +1217,13 @@ static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,  		goto drop;  	} -	if (!service_req_auth(&device->src, &device->dst, uuid, auth_cb, -				device) == 0) +	err = service_req_auth(&device->src, &device->dst, uuid, auth_cb, +				device); +	if (err < 0) { +		debug("Authorization denied: %s", strerror(-err));  		headset_close_rfcomm(device); +		return; +	}  	headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS); diff --git a/audio/manager.h b/audio/manager.h index 6b2b90d8..8f7f6be3 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -48,10 +48,3 @@ struct audio_device *manager_device_connected(const bdaddr_t *bda, const char *u  gboolean manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,  				void *user_data); - -gboolean manager_authorize(const bdaddr_t *dba, const char *uuid, -				DBusPendingCallNotifyFunction cb, -				void *user_data, -				DBusPendingCall **pending); -void manager_cancel_authorize(bdaddr_t *dba, const char *uuid, -				DBusPendingCall *pending); diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c index 8f587001..f77ec180 100644 --- a/hcid/dbus-security.c +++ b/hcid/dbus-security.c @@ -87,12 +87,13 @@ struct authorization_agent {  };  struct auth_agent_req { -	DBusMessage *msg;  	struct authorization_agent *agent;  	char *adapter_path;  	char *address;  	char *service_path;  	char *uuid; +	service_auth_cb cb; +	void *user_data;  	DBusPendingCall *call;  }; @@ -410,9 +411,31 @@ static DBusMessage *unregister_default_passkey_agent(DBusConnection *conn,  	return dbus_message_new_method_return(msg);  } +static struct auth_agent_req *auth_agent_req_new(struct authorization_agent *agent, +						const char *adapter_path, +						const char *address, +						const char *service_path, +						const char *uuid, +						service_auth_cb cb, +						void *user_data) +{ +	struct auth_agent_req *req; + +	req = g_new0(struct auth_agent_req, 1); + +	req->agent = agent; +	req->adapter_path = g_strdup(adapter_path); +	req->address = g_strdup(address); +	req->service_path = g_strdup(service_path); +	req->uuid = g_strdup(uuid); +	req->cb = cb; +	req->user_data = user_data; + +	return req; +} +  static void auth_agent_req_free(struct auth_agent_req *req)  { -	dbus_message_unref(req->msg);  	g_free(req->adapter_path);  	g_free(req->address);  	g_free(req->service_path); @@ -425,8 +448,6 @@ static void auth_agent_req_free(struct auth_agent_req *req)  static void auth_agent_req_cancel(struct auth_agent_req *req)  {  	dbus_pending_call_cancel(req->call); -	error_canceled(req->agent->conn, req->msg, -			"Authorization process was canceled");  }  static void auth_agent_cancel_requests(struct authorization_agent *agent) @@ -440,6 +461,32 @@ static void auth_agent_cancel_requests(struct authorization_agent *agent)  	}  } +static void auth_agent_call_cancel(struct auth_agent_req *req) +{ +	struct authorization_agent *agent = req->agent; +	DBusMessage *message; + +	message = dbus_message_new_method_call(agent->name, agent->path, +				"org.bluez.AuthorizationAgent", "Cancel"); +	if (!message) { +		error("Couldn't allocate D-Bus message"); +		return; +	} + +	dbus_message_append_args(message, +				DBUS_TYPE_STRING, &req->adapter_path, +				DBUS_TYPE_STRING, &req->address, +				DBUS_TYPE_STRING, &req->service_path, +				DBUS_TYPE_STRING, &req->uuid, +				DBUS_TYPE_INVALID); + +	dbus_message_set_no_reply(message, TRUE); + +	dbus_connection_send(agent->conn, message, NULL); + +	dbus_message_unref(message); +} +  static void auth_agent_free(struct authorization_agent *agent)  {  	g_free(agent->name); @@ -576,6 +623,123 @@ static DBusMessage *unregister_default_auth_agent(DBusConnection *conn,  	return dbus_message_new_method_return(msg);  } +static void auth_agent_req_reply(DBusPendingCall *call, void *data) +{ +	struct auth_agent_req *req = data; +	DBusMessage *reply = dbus_pending_call_steal_reply(call); +	DBusError err; + +	debug("authorize reply"); + +	dbus_error_init(&err); +	dbus_set_error_from_message(&err, reply); +	req->cb(&err, req->user_data); + +	default_auth_agent->pending_requests = +		g_slist_remove(default_auth_agent->pending_requests, req); +	auth_agent_req_free(req); + +	debug("auth_agent_reply: returning"); +} + +static DBusPendingCall *auth_agent_call_authorize(struct authorization_agent *agent, +						const char *adapter_path, +						const char *service_path, +						const char *address, +						const char *uuid) +{ +	DBusMessage *message; +	DBusPendingCall *call; + +	message = dbus_message_new_method_call(agent->name, agent->path, +				"org.bluez.AuthorizationAgent", "Authorize"); +	if (!message) { +		error("Couldn't allocate D-Bus message"); +		return NULL; +	} + +	dbus_message_append_args(message, +				DBUS_TYPE_STRING, &adapter_path, +				DBUS_TYPE_STRING, &address, +				DBUS_TYPE_STRING, &service_path, +				DBUS_TYPE_STRING, &uuid, +				DBUS_TYPE_INVALID); + +	if (dbus_connection_send_with_reply(agent->conn, message, +					&call, REQUEST_TIMEOUT) == FALSE) { +		error("D-Bus send failed"); +		dbus_message_unref(message); +		return NULL; +	} + +	dbus_message_unref(message); +	return call; +} + +int handle_authorize_request_old(struct service *service, const char *path, +				const char *address, const char *uuid, +				service_auth_cb cb, void *user_data) +{ +	struct auth_agent_req *req; + +	if (!default_auth_agent) { +		debug("no default agent"); +		return -EPERM; +	} + +	req = auth_agent_req_new(default_auth_agent, path, +				address, service->object_path, +				uuid, cb, user_data); + +	req->call = auth_agent_call_authorize(default_auth_agent, path, +					service->object_path, address, uuid); +	if (!req->call) { +		auth_agent_req_free(req); +		return -ENOMEM; +	} + +	dbus_pending_call_set_notify(req->call, auth_agent_req_reply, req, +					NULL); +	default_auth_agent->pending_requests = +		g_slist_append(default_auth_agent->pending_requests, req); + +	debug("authorize request was forwarded"); + +	return 0; +} + +static int auth_agent_send_cancel(struct authorization_agent *agent, +				const char *adapter_path, +				const char *address) +{ +	struct auth_agent_req *req = NULL; +	GSList *l; + +	for (l = agent->pending_requests; l != NULL; l = l->next) { +		req = l->data; +		if (!strcmp(adapter_path, req->adapter_path) && +				!strcmp(address, req->address)) +			break; +	} + +	if (!req) +		return -EIO; + +	auth_agent_call_cancel(req); +	auth_agent_req_cancel(req); +	agent->pending_requests = g_slist_remove(agent->pending_requests, req); +	auth_agent_req_free(req); + +	return 0; +} + +int cancel_authorize_request_old(const char *path, const char *address) +{ +	if (!default_auth_agent) +		return -EIO; + +	return auth_agent_send_cancel(default_auth_agent, path, address); +}  static GDBusMethodTable security_methods[] = {  	{ "RegisterDefaultPasskeyAgent",	"s",	"", diff --git a/hcid/dbus-security.h b/hcid/dbus-security.h index cf54a5a8..8c23417a 100644 --- a/hcid/dbus-security.h +++ b/hcid/dbus-security.h @@ -44,15 +44,7 @@ void release_passkey_agents(struct adapter *adapter, bdaddr_t *bda);  void cancel_passkey_agent_requests(GSList *agents, const char *path, bdaddr_t *dba); -DBusHandlerResult handle_authorize_request_old(DBusConnection *conn, -					DBusMessage *msg, -					struct service *service, -					const char *path, -					const char *address, -					const char *uuid); - -DBusHandlerResult cancel_authorize_request_old(DBusConnection *conn, -						DBusMessage *msg, -						struct service *service, -						const char *address, -						const char *path); +int handle_authorize_request_old(struct service *service, const char *path, +				const char *address, const char *uuid, +				service_auth_cb cb, void *user_data); +int cancel_authorize_request_old(const char *path, const char *address); diff --git a/hcid/dbus-service.c b/hcid/dbus-service.c index 67c5a7cd..18c9b68e 100644 --- a/hcid/dbus-service.c +++ b/hcid/dbus-service.c @@ -55,6 +55,7 @@  #include "device.h"  #include "dbus-service.h"  #include "dbus-hci.h" +#include "dbus-security.h"  #define SERVICE_INTERFACE "org.bluez.Service" @@ -703,7 +704,8 @@ int service_req_auth(const bdaddr_t *src, const bdaddr_t *dst,  	agent = (device->agent ? : adapter->agent);  	if (!agent) -		return -EPERM; +		return handle_authorize_request_old(service, adapter->path, +					address, uuid, cb, user_data);  	auth = g_try_new0(struct service_auth, 1);  	if (!auth) @@ -715,7 +717,7 @@ int service_req_auth(const bdaddr_t *src, const bdaddr_t *dst,  	return agent_authorize(agent, device->path, uuid, agent_auth_cb, auth);  } -int service_cancel_auth(const bdaddr_t *src) +int service_cancel_auth(const bdaddr_t *src, const bdaddr_t *dst)  {  	struct adapter *adapter = manager_find_adapter(src);  	struct device *device; @@ -725,7 +727,7 @@ int service_cancel_auth(const bdaddr_t *src)  	if (!adapter)  		return -EPERM; -	ba2str(src, address); +	ba2str(dst, address);  	device = adapter_find_device(adapter, address);  	if (!device)  		return -EPERM; @@ -737,7 +739,7 @@ int service_cancel_auth(const bdaddr_t *src)  	agent = (device->agent ? : adapter->agent);  	if (!agent) -		return -EPERM; +		return cancel_authorize_request_old(adapter->path, address);  	return agent_cancel(agent);  } diff --git a/hcid/dbus-service.h b/hcid/dbus-service.h index 99da10c0..d41a170a 100644 --- a/hcid/dbus-service.h +++ b/hcid/dbus-service.h @@ -44,4 +44,4 @@ void unregister_service(const char *ident);  typedef void (*service_auth_cb) (DBusError *derr, void *user_data);  int service_req_auth(const bdaddr_t *src, const bdaddr_t *dst,  		const char *uuid, service_auth_cb cb, void *user_data); -int service_cancel_auth(const bdaddr_t *src); +int service_cancel_auth(const bdaddr_t *src, const bdaddr_t *dst); diff --git a/input/server.c b/input/server.c index 003ce53b..9267e4aa 100644 --- a/input/server.c +++ b/input/server.c @@ -64,7 +64,7 @@ static void auth_callback(DBusError *derr, void *user_data)  	if (derr) {  		error("Access denied: %s", derr->message);  		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) -			service_cancel_auth(&auth->dst); +			service_cancel_auth(&auth->src, &auth->dst);  		input_device_close_channels(&auth->src, &auth->dst);  	} else diff --git a/network/server.c b/network/server.c index 7d951765..e94964ae 100644 --- a/network/server.c +++ b/network/server.c @@ -363,7 +363,7 @@ static void req_auth_cb(DBusError *derr, void *user_data)  		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) {  			bdaddr_t dst;  			str2ba(setup->address, &dst); -			service_cancel_auth(&dst); +			service_cancel_auth(&ns->src, &dst);  		}  		val = BNEP_CONN_NOT_ALLOWED;  		goto done; | 
