From da10b3ccf28d21e0bfa9ad458a350f64eb47b2be Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 28 Aug 2007 16:41:50 +0000 Subject: network: allow just one pending authorization at the same time --- network/server.c | 121 +++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 62 deletions(-) diff --git a/network/server.c b/network/server.c index 3fc6900e..7612bd2f 100644 --- a/network/server.c +++ b/network/server.c @@ -59,13 +59,11 @@ #include "manager.h" #include "server.h" -static GIOChannel *bnep_io = NULL; - /* Pending Authorization */ struct pending_auth { char *addr; /* Bluetooth Address */ GIOChannel *io; /* BNEP connection setup io channel */ - int attempts; /* BNEP setup conn requests counter */ + DBusConnection *conn; }; /* Main server structure */ @@ -80,10 +78,11 @@ struct network_server { uint32_t record_id; /* Service record id */ uint16_t id; /* Service class identifier */ DBusConnection *conn; /* D-Bus connection */ - struct pending_auth *pauth; /* Pending incomming connection/authorization */ }; static char netdev[16] = "bnep%d"; +static GIOChannel *bnep_io = NULL; +static struct pending_auth *pending_auth = NULL; static int store_property(bdaddr_t *src, uint16_t id, const char *key, const char *value) @@ -106,12 +105,14 @@ static void pending_auth_free(struct pending_auth *pauth) { if (!pauth) return; + if (pauth->addr) g_free(pauth->addr); if (pauth->io) { g_io_channel_close(pauth->io); g_io_channel_unref(pauth->io); } + dbus_connection_unref(pauth->conn); g_free(pauth); } @@ -257,17 +258,11 @@ static int send_bnep_ctrl_rsp(GIOChannel *chan, uint16_t response) return -gerr; } -static void cancel_authorization(struct network_server *ns) +static void cancel_authorization(DBusConnection *conn, const char *address) { DBusMessage *msg; - const char *paddress; const char *uuid = ""; - if (!ns->pauth) - return; - - paddress = ns->pauth->addr; - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", "org.bluez.Database", "CancelAuthorizationRequest"); @@ -277,11 +272,11 @@ static void cancel_authorization(struct network_server *ns) } dbus_message_append_args(msg, - DBUS_TYPE_STRING, &paddress, + DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); - send_message_and_unref(ns->conn, msg); + send_message_and_unref(conn, msg); } static void authorization_callback(DBusPendingCall *pcall, void *data) @@ -293,20 +288,20 @@ static void authorization_callback(DBusPendingCall *pcall, void *data) uint16_t response; int sk; - if (!ns->pauth) { + if (!pending_auth) { dbus_message_unref(reply); dbus_pending_call_unref(pcall); return; } - sk = g_io_channel_unix_get_fd(ns->pauth->io); + sk = g_io_channel_unix_get_fd(pending_auth->io); dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { error("Access denied: %s", derr.message); if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) { debug("Canceling authorization request"); - cancel_authorization(ns); + cancel_authorization(pending_auth->conn, pending_auth->addr); } response = BNEP_CONN_NOT_ALLOWED; dbus_error_free(&derr); @@ -339,10 +334,10 @@ static void authorization_callback(DBusPendingCall *pcall, void *data) /* FIXME: send the D-Bus message to notify the new bnep iface */ failed: - send_bnep_ctrl_rsp(ns->pauth->io, response); + send_bnep_ctrl_rsp(pending_auth->io, response); - pending_auth_free(ns->pauth); - ns->pauth = NULL; + pending_auth_free(pending_auth); + pending_auth = NULL; close(sk); @@ -350,7 +345,8 @@ failed: dbus_pending_call_unref(pcall); } -static int authorize_connection(struct network_server *ns) +static int authorize_connection(DBusConnection *conn, + const char *address, struct network_server *ns) { DBusMessage *msg; DBusPendingCall *pending; @@ -363,14 +359,14 @@ static int authorize_connection(struct network_server *ns) return -ENOMEM; } - debug("Requesting authorization for %s UUID:%s", ns->pauth->addr, uuid); + debug("Requesting authorization for %s UUID:%s", address, uuid); dbus_message_append_args(msg, - DBUS_TYPE_STRING, &ns->pauth->addr, + DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(ns->conn, msg, &pending, -1) == FALSE) { + if (dbus_connection_send_with_reply(conn, msg, &pending, -1) == FALSE) { error("Sending of authorization request failed"); dbus_message_unref(msg); return -EACCES; @@ -385,9 +381,10 @@ static int authorize_connection(struct network_server *ns) static gboolean connect_setup_event(GIOChannel *chan, GIOCondition cond, gpointer data) { - struct network_server *ns = data; + struct network_server *ns = NULL; struct bnep_setup_conn_req *req; unsigned char pkt[BNEP_MTU]; + char path[MAX_PATH_LENGTH]; gsize n; GIOError gerr; uint8_t *pservice; @@ -398,7 +395,7 @@ static gboolean connect_setup_event(GIOChannel *chan, if (cond & (G_IO_ERR | G_IO_HUP)) { error("Hangup or error on BNEP socket"); - cancel_authorization(ns); + cancel_authorization(pending_auth->conn, pending_auth->addr); return FALSE; } @@ -417,14 +414,6 @@ static gboolean connect_setup_event(GIOChannel *chan, return FALSE; } - if (++ns->pauth->attempts > 1) { - /* - * Ignore repeated BNEP setup connection request: there - * is a pending authorization request for this device. - */ - return TRUE; - } - /* * FIXME: According to BNEP SPEC the UUID size can be * 2-16 bytes. Currently only 2 bytes size is supported @@ -438,6 +427,14 @@ static gboolean connect_setup_event(GIOChannel *chan, /* Getting destination service: considering 2 bytes size */ role = ntohs(bt_get_unaligned((uint16_t *) pservice)); + snprintf(path, MAX_PATH_LENGTH, NETWORK_PATH"/%s", bnep_name(role)); + dbus_connection_get_object_user_data(pending_auth->conn, path, (void *) &ns); + + if (ns == NULL || ns->enable == FALSE) { + response = BNEP_CONN_NOT_ALLOWED; + goto reply; + } + pservice += req->uuid_size; /* Getting source service: considering 2 bytes size */ role = ntohs(bt_get_unaligned((uint16_t *) pservice)); @@ -448,10 +445,10 @@ static gboolean connect_setup_event(GIOChannel *chan, */ /* Wait authorization before reply success */ - if (authorize_connection(ns) < 0) { + if (authorize_connection(pending_auth->conn, + pending_auth->addr, ns) < 0) { response = BNEP_CONN_NOT_ALLOWED; goto reply; - } return TRUE; @@ -462,18 +459,16 @@ reply: static void connect_setup_destroy(gpointer data) { - struct network_server *ns = data; - - if (ns->pauth) { - pending_auth_free(ns->pauth); - ns->pauth = NULL; + if (pending_auth) { + pending_auth_free(pending_auth); + pending_auth = NULL; } } static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data) { - struct network_server *ns = data; + DBusConnection *conn = data; struct sockaddr_l2 addr; socklen_t addrlen; char peer[18]; @@ -501,11 +496,12 @@ static gboolean connect_event(GIOChannel *chan, bacpy(&dst, &addr.l2_bdaddr); psm = btohs(addr.l2_psm); + ba2str(&dst, peer); - /* FIXME: Maybe keep a list of connected devices */ + info("Connection from: %s on PSM %d", peer, psm); - ba2str(&dst, peer); - if (ns->pauth) { + /* Only one authorization at same time */ + if (pending_auth) { GIOChannel *io; error("Rejecting %s(pending authorization)", peer); io = g_io_channel_unix_new(nsk); @@ -515,24 +511,21 @@ static gboolean connect_event(GIOChannel *chan, return TRUE; } - info("Connection from:%s on PSM %d", peer, psm); - - /* Setting the pending incomming connection setup */ - ns->pauth = g_new0(struct pending_auth, 1); - ns->pauth->addr = g_strdup(peer); - ns->pauth->io = g_io_channel_unix_new(nsk); - - g_io_channel_set_close_on_unref(ns->pauth->io, FALSE); + pending_auth = g_new0(struct pending_auth, 1); + pending_auth->addr = g_strdup(peer); + pending_auth->io = g_io_channel_unix_new(nsk); + pending_auth->conn = dbus_connection_ref(conn); + g_io_channel_set_close_on_unref(pending_auth->io, FALSE); /* New watch for BNEP setup */ - g_io_add_watch_full(ns->pauth->io, G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_setup_event, ns, &connect_setup_destroy); + g_io_add_watch_full(pending_auth->io, G_PRIORITY_DEFAULT, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + connect_setup_event, pending_auth, &connect_setup_destroy); return TRUE; } -int server_init(struct network_server *ns) +static int server_init(DBusConnection *conn) { struct l2cap_options l2o; struct sockaddr_l2 l2a; @@ -577,8 +570,8 @@ int server_init(struct network_server *ns) goto fail; } - /* Set link mode */ - lm = (ns->secure ? L2CAP_LM_SECURE : 0); + /* FIXME: Set link mode - it is applied to all servers */ + lm = 0; if (lm && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0) { err = errno; error("Failed to set link mode. %s(%d)", @@ -594,10 +587,8 @@ int server_init(struct network_server *ns) bnep_io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(bnep_io, FALSE); - g_io_add_watch(bnep_io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_event, ns); - + connect_event, conn); return 0; fail: @@ -755,7 +746,13 @@ static int record_and_listen(struct network_server *ns) { int err; - if (bnep_io == NULL && (err = server_init(ns)) < 0) + /* + * There is one socket to handle the incomming connections. NAP, + * GN and PANU servers share the same PSM. The initial BNEP message + * (setup connection request) contains the destination service + * field that defines which service the source is connecting to. + */ + if (bnep_io == NULL && (err = server_init(ns->conn)) < 0) return -err; /* Add the service record */ -- cgit