From 23333ab922202ef3f5813511696f0f403157bc19 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Mon, 13 Oct 2008 19:02:41 -0300 Subject: [PATCH] obexd: Uses the BlueZ service plugin to ask for authorization for FTP --- obexd/src/bluetooth.c | 11 +++- obexd/src/dbus.h | 2 + obexd/src/manager.c | 146 ++++++++++++++++++++++++++++++++++++++++++ obexd/src/obex.c | 2 - 4 files changed, 158 insertions(+), 3 deletions(-) diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c index 15ef0ae72..d71de2439 100644 --- a/obexd/src/bluetooth.c +++ b/obexd/src/bluetooth.c @@ -182,8 +182,17 @@ static gboolean connect_event(GIOChannel *io, GIOCondition cond, gpointer user_d info("New connection from: %s, channel %u, fd %d", address, raddr.rc_channel, nsk); - if (obex_session_start(nsk, server) < 0) + if (server->service == OBEX_OPUSH) { + if (obex_session_start(nsk, server) < 0) + close(nsk); + + return TRUE; + } + + if (request_service_authorization(server, nsk) < 0) { close(nsk); + return TRUE; + } return TRUE; } diff --git a/obexd/src/dbus.h b/obexd/src/dbus.h index 627019fa2..5c9935433 100644 --- a/obexd/src/dbus.h +++ b/obexd/src/dbus.h @@ -41,6 +41,8 @@ void unregister_transfer(guint32 id); gint add_record(gchar *record); +gint request_service_authorization(struct server *server, gint nsk); + void register_session(guint32 id, struct obex_session *os); void unregister_session(guint32 id); diff --git a/obexd/src/manager.c b/obexd/src/manager.c index 4e832e33a..f06f9053d 100644 --- a/obexd/src/manager.c +++ b/obexd/src/manager.c @@ -25,6 +25,7 @@ #include #endif +#include #include #include #include @@ -55,6 +56,11 @@ struct agent { static struct agent *agent = NULL; +struct pending_request { + struct server *server; + gint nsk; +}; + static void agent_free(struct agent *agent) { g_free(agent->new_folder); @@ -630,6 +636,146 @@ gint add_record(gchar *record) return handle; } +static void service_reply(DBusPendingCall *call, gpointer user_data) +{ + struct pending_request *pending = user_data; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + DBusError derr; + + dbus_error_init(&derr); + if (dbus_set_error_from_message(&derr, reply)) { + error("Replied with an error: %s, %s", + derr.name, derr.message); + dbus_error_free(&derr); + dbus_message_unref(reply); + + close(pending->nsk); + g_free(pending); + return; + } + + if (obex_session_start(pending->nsk, pending->server) < 0) + close(pending->nsk); + + g_free(pending); + + dbus_message_unref(reply); +} + +static gboolean service_error(GIOChannel *io, GIOCondition cond, + gpointer user_data) +{ + gchar *adapter_path = user_data; + DBusMessage *msg; + + msg = dbus_message_new_method_call("org.bluez", + adapter_path, + "org.bluez.Service", + "CancelAuthorization"); + + dbus_connection_send_with_reply(system_conn, msg, NULL, -1); + + dbus_message_unref(msg); + + g_free(adapter_path); + + return FALSE; +} + +gint request_service_authorization(struct server *server, gint nsk) +{ + DBusMessage *msg, *reply; + DBusPendingCall *call; + GIOChannel *io; + struct sockaddr_rc src, dst; + socklen_t addrlen; + gchar address[18]; + const gchar *paddr = address; + gchar *adapter_path, *path; + guint watch; + struct pending_request *pending; + + if (system_conn == NULL) + return -1; + + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + addrlen = sizeof(src); + + if (getsockname(nsk, (struct sockaddr *) &src, &addrlen) < 0) + return -1; + + ba2str(&src.rc_bdaddr, address); + + msg = dbus_message_new_method_call("org.bluez", "/", + "org.bluez.Manager", "FindAdapter"); + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr, + DBUS_TYPE_INVALID); + + reply = dbus_connection_send_with_reply_and_block(system_conn, msg, + -1, NULL); + if (reply == NULL) { + dbus_message_unref(msg); + return -1; + } + + dbus_message_unref(msg); + + dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID); + + adapter_path = g_strdup(path); + + dbus_message_unref(reply); + + if (getpeername(nsk, (struct sockaddr *) &dst, &addrlen) < 0) { + g_free(adapter_path); + return -1; + } + + ba2str(&dst.rc_bdaddr, address); + + msg = dbus_message_new_method_call("org.bluez", adapter_path, + "org.bluez.Service", "RequestAuthorization"); + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr, + DBUS_TYPE_UINT32, &server->handle, + DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply(system_conn, + msg, &call, TIMEOUT)) { + g_free(adapter_path); + dbus_message_unref(msg); + return -EPERM; + } + + dbus_message_unref(msg); + + pending = g_new0(struct pending_request, 1); + pending->server = server; + pending->nsk = nsk; + + if (!dbus_pending_call_set_notify(call, service_reply, pending, NULL)) { + close(nsk); + g_free(adapter_path); + g_free(pending); + return -EPERM; + } + + dbus_pending_call_unref(call); + + /* Catches errors before authorization response comes */ + io = g_io_channel_unix_new(nsk); + watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, + G_IO_HUP | G_IO_ERR | G_IO_NVAL, + service_error, adapter_path, NULL); + g_io_channel_unref(io); + + return 0; +} + + void register_session(guint32 id, struct obex_session *os) { gchar *path = g_strdup_printf("/session%u", id); diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 0168f816a..2ccebd14d 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -223,8 +223,6 @@ static void cmd_connect(struct obex_session *os, return; } - /* FIXME: Request authorization */ - register_session(cid, os); emit_session_created(cid); -- 2.47.3