summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-06-17 19:37:36 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-06-17 19:37:36 +0000
commite8ca2351ee3ba3f8b2b99731972234f42ae9b64b (patch)
tree8a639f9f831dd79ec2b3b8d5d952d649885a59ba
parentbbec31284f7e4e960c07bddd9fd1d7ee5c990118 (diff)
Fix authorization mechanism for 3.x.
-rw-r--r--audio/avdtp.c34
-rw-r--r--audio/control.c91
-rw-r--r--audio/main.c26
-rw-r--r--audio/manager.c12
-rw-r--r--audio/manager.h7
-rw-r--r--hcid/dbus-security.c172
-rw-r--r--hcid/dbus-security.h16
-rw-r--r--hcid/dbus-service.c10
-rw-r--r--hcid/dbus-service.h2
-rw-r--r--input/server.c2
-rw-r--r--network/server.c2
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;