📄 dbus-security.c
字号:
FALSE, 1); if (!req->call) goto fail; dbus_message_unref(message); dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL); return; } error("Passkey agent replied with an error: %s, %s", err.name, err.message); dbus_error_free(&err); goto fail; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID)) { error("Wrong passkey reply signature: %s", err.message); dbus_error_free(&err); goto fail; } len = strlen(pin); if (len > 16 || len < 1) { error("Invalid passkey length from handler"); goto fail; } set_pin_length(&req->sba, len); memset(&pr, 0, sizeof(pr)); bacpy(&pr.bdaddr, &req->bda); memcpy(pr.pin_code, pin, len); pr.pin_len = len; hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); goto done;fail: hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &req->bda);done: if (message) dbus_message_unref(message); agent->pending_requests = g_slist_remove(agent->pending_requests, req); dbus_pending_call_cancel(req->call); if (req->call) dbus_pending_call_unref(req->call); g_free(req->path); g_free(req); if (agent != default_agent) { agent->adapter->passkey_agents = g_slist_remove(agent->adapter->passkey_agents, agent); passkey_agent_free(agent); }}static int call_passkey_agent(DBusConnection *conn, struct passkey_agent *agent, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba){ struct pending_agent_request *req; if (!agent) { debug("call_passkey_agent(): no agent available"); goto send; } debug("Calling PasskeyAgent.Request: name=%s, path=%s", agent->name, agent->path); req = g_new0(struct pending_agent_request, 1); req->dev = dev; bacpy(&req->sba, sba); bacpy(&req->bda, dba); req->agent = agent; req->path = g_strdup(path); req->call = agent_request(path, dba, agent, FALSE, 0); if (!req->call) goto failed; dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL); agent->pending_requests = g_slist_append(agent->pending_requests, req); return 0;failed: g_free(req->path); g_free(req);send: hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); return -1;}int handle_passkey_request(DBusConnection *conn, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba){ struct passkey_agent *agent = default_agent; struct adapter *adapter = NULL; GSList *l; char addr[18]; void *data; dbus_connection_get_object_user_data(conn, path, &data); if (!data) goto done; adapter = data; if (!bacmp(&adapter->agents_disabled, dba)) goto done; ba2str(dba, addr); for (l = adapter->passkey_agents; l != NULL; l = l->next) { struct passkey_agent *a = l->data; if (a != default_agent && g_slist_length(a->pending_requests) >= 1) continue; if (!strcmp(a->addr, addr)) { agent = a; break; } }done: return call_passkey_agent(conn, agent, dev, path, sba, dba);}static DBusPendingCall *agent_confirm(const char *path, bdaddr_t *bda, struct passkey_agent *agent, const char *value){ DBusMessage *message; DBusPendingCall *call; char bda_str[18], *ptr = bda_str; message = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.PasskeyAgent", "Confirm"); if (message == NULL) { error("Couldn't allocate D-Bus message"); return NULL; } ba2str(bda, bda_str); dbus_message_append_args(message, DBUS_TYPE_STRING, &path, DBUS_TYPE_STRING, &ptr, DBUS_TYPE_STRING, &value, 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;}static void confirm_agent_reply(DBusPendingCall *call, void *user_data){ struct pending_agent_request *req = user_data; struct passkey_agent *agent = req->agent; pin_code_reply_cp pr; DBusMessage *message; DBusError err; int len; /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { error("Passkey agent replied with an error: %s, %s", err.name, err.message); dbus_error_free(&err); goto fail; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) { error("Wrong confirm reply signature: %s", err.message); dbus_error_free(&err); goto fail; } len = strlen(req->pin); set_pin_length(&req->sba, len); memset(&pr, 0, sizeof(pr)); bacpy(&pr.bdaddr, &req->bda); memcpy(pr.pin_code, req->pin, len); pr.pin_len = len; hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); goto done;fail: hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &req->bda);done: if (message) dbus_message_unref(message); agent->pending_requests = g_slist_remove(agent->pending_requests, req); dbus_pending_call_cancel(req->call); if (req->call) dbus_pending_call_unref(req->call); g_free(req->pin); g_free(req->path); g_free(req); if (agent != default_agent) { agent->adapter->passkey_agents = g_slist_remove(agent->adapter->passkey_agents, agent); passkey_agent_free(agent); }}static int call_confirm_agent(DBusConnection *conn, struct passkey_agent *agent, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba, const char *pin){ struct pending_agent_request *req; if (!agent) { debug("call_passkey_agent(): no agent available"); goto send; } debug("Calling PasskeyAgent.Confirm: name=%s, path=%s", agent->name, agent->path); req = g_new0(struct pending_agent_request, 1); req->dev = dev; bacpy(&req->sba, sba); bacpy(&req->bda, dba); req->agent = agent; req->path = g_strdup(path); req->pin = g_strdup(pin); req->call = agent_confirm(path, dba, agent, pin); if (!req->call) goto failed; dbus_pending_call_set_notify(req->call, confirm_agent_reply, req, NULL); agent->pending_requests = g_slist_append(agent->pending_requests, req); return 0;failed: g_free(req->pin); g_free(req->path); g_free(req);send: hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); return -1;}int handle_confirm_request(DBusConnection *conn, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba, const char *pin){ struct passkey_agent *agent = default_agent; struct adapter *adapter = NULL; GSList *l; char addr[18]; void *data; dbus_connection_get_object_user_data(conn, path, &data); if (!data) goto done; adapter = data; if (!bacmp(&adapter->agents_disabled, dba)) goto done; ba2str(dba, addr); for (l = adapter->passkey_agents; l != NULL; l = l->next) { struct passkey_agent *a = l->data; if (a != default_agent && g_slist_length(a->pending_requests) >= 1) continue; if (!strcmp(a->addr, addr)) { agent = a; break; } }done: return call_confirm_agent(conn, agent, dev, path, sba, dba, pin);}static void send_cancel_request(struct pending_agent_request *req){ DBusMessage *message; char address[18], *ptr = address; message = dbus_message_new_method_call(req->agent->name, req->agent->path, "org.bluez.PasskeyAgent", "Cancel"); if (message == NULL) { error("Couldn't allocate D-Bus message"); return; } ba2str(&req->bda, address); dbus_message_append_args(message, DBUS_TYPE_STRING, &req->path, DBUS_TYPE_STRING, &ptr, DBUS_TYPE_INVALID); dbus_message_set_no_reply(message, TRUE); send_message_and_unref(req->agent->conn, message); debug("PasskeyAgent.Request(%s, %s) was canceled", req->path, address); dbus_pending_call_cancel(req->call); dbus_pending_call_unref(req->call); g_free(req->pin); g_free(req->path); g_free(req);}static void release_agent(struct passkey_agent *agent){ DBusMessage *message; debug("Releasing agent %s, %s", agent->name, agent->path); message = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.PasskeyAgent", "Release"); if (message == NULL) { error("Couldn't allocate D-Bus message"); return; } dbus_message_set_no_reply(message, TRUE); send_message_and_unref(agent->conn, message); if (agent == default_agent) name_listener_remove(agent->conn, agent->name, (name_cb_t) default_agent_exited, NULL); else { struct passkey_agent ref; /* Only remove the name listener if there are no more agents for this name */ memset(&ref, 0, sizeof(ref)); ref.name = agent->name; if (!g_slist_find_custom(agent->adapter->passkey_agents, &ref, (GCompareFunc) agent_cmp)) name_listener_remove(agent->conn, ref.name, (name_cb_t) agent_exited, agent->adapter); }}void release_default_agent(void){ if (!default_agent) return; passkey_agent_free(default_agent); default_agent = NULL;}void release_default_auth_agent(void){ if (!default_auth_agent) return; auth_agent_cancel_requests(default_auth_agent); auth_agent_release(default_auth_agent); auth_agent_free(default_auth_agent); default_auth_agent = NULL;}void release_passkey_agents(struct adapter *adapter, bdaddr_t *bda){ GSList *l, *next; for (l = adapter->passkey_agents; l != NULL; l = next) { struct passkey_agent *agent = l->data; next = l->next; if (bda && agent->addr) { bdaddr_t tmp; str2ba(agent->addr, &tmp); if (bacmp(&tmp, bda)) continue; } adapter->passkey_agents = g_slist_remove(adapter->passkey_agents, agent); passkey_agent_free(agent); }}void cancel_passkey_agent_requests(GSList *agents, const char *path, bdaddr_t *addr){ GSList *l, *next; /* First check the default agent */ for (l = default_agent ? default_agent->pending_requests : NULL; l != NULL; l = next) { struct pending_agent_request *req = l->data; next = l->next; if (!strcmp(path, req->path) && (!addr || !bacmp(addr, &req->bda))) { send_cancel_request(req); default_agent->pending_requests = g_slist_remove(default_agent->pending_requests, req); } } /* and then the adapter specific agents */ for (; agents != NULL; agents = agents->next) { struct passkey_agent *agent = agents->data; for (l = agent->pending_requests; l != NULL; l = next) { struct pending_agent_request *req = l->data; next = l->next; if (!strcmp(path, req->path) && (!addr || !bacmp(addr, &req->bda))) { send_cancel_request(req); agent->pending_requests = g_slist_remove(agent->pending_requests, req); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -