⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbus-security.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  Nokia Corporation *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org> *  Copyright (C) 2005-2007  Johan Hedberg <johan.hedberg@nokia.com> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sdp.h>#include <glib.h>#include <dbus/dbus.h>#include "adapter.h"#include "dbus.h"#include "dbus-helper.h"#include "hcid.h"#include "dbus-common.h"#include "dbus-service.h"#include "dbus-error.h"#include "error.h"#include "dbus-security.h"#include "dbus-hci.h"#define REQUEST_TIMEOUT (60 * 1000)		/* 60 seconds */#define AGENT_TIMEOUT (10 * 60 * 1000)		/* 10 minutes */struct passkey_agent {	struct adapter *adapter;	DBusConnection *conn;	char *addr;	char *name;	char *path;	GSList *pending_requests;	int exited;	guint timeout;};struct pending_agent_request {	struct passkey_agent *agent;	int dev;	bdaddr_t sba;	bdaddr_t bda;	char *path;	DBusPendingCall *call;	int old_if;	char *pin;};struct authorization_agent {	DBusConnection *conn;	char *name;	char *path;	GSList *pending_requests;};struct auth_agent_req {	DBusMessage *msg;	struct authorization_agent *agent;	char *adapter_path;	char *address;	char *service_path;	char *uuid;	DBusPendingCall *call;};static struct passkey_agent *default_agent = NULL;static struct authorization_agent *default_auth_agent = NULL;static void release_agent(struct passkey_agent *agent);static void send_cancel_request(struct pending_agent_request *req);static void passkey_agent_free(struct passkey_agent *agent){	GSList *l;	if (!agent)		return;	for (l = agent->pending_requests; l != NULL; l = l->next) {		struct pending_agent_request *req = l->data;		hci_send_cmd(req->dev, OGF_LINK_CTL,				OCF_PIN_CODE_NEG_REPLY, 6, &req->bda);		send_cancel_request(req);	}	if (agent->timeout)		g_source_remove(agent->timeout);	if (!agent->exited)		release_agent(agent);	g_free(agent->name);	g_free(agent->path);	g_free(agent->addr);	if (agent->conn)		dbus_connection_unref(agent->conn);	g_slist_free(agent->pending_requests);	g_free(agent);}static void agent_exited(const char *name, struct adapter *adapter){	GSList *cur, *next;	debug("Passkey agent %s exited without calling Unregister", name);	for (cur = adapter->passkey_agents; cur != NULL; cur = next) {		struct passkey_agent *agent = cur->data;		next = cur->next;		if (strcmp(agent->name, name))			continue;		agent->exited = 1;		adapter->passkey_agents = g_slist_remove(adapter->passkey_agents, agent);		passkey_agent_free(agent);	}}static gboolean agent_timeout(struct passkey_agent *agent){	struct adapter *adapter = agent->adapter;	debug("Passkey Agent at %s, %s timed out", agent->name, agent->path);	if (adapter)		adapter->passkey_agents = g_slist_remove(adapter->passkey_agents, agent);	agent->timeout = 0;	passkey_agent_free(agent);	return FALSE;}static void default_agent_exited(const char *name, void *data){	debug("%s exited without unregistering the default passkey agent", name);	if (!default_agent || strcmp(name, default_agent->name)) {		/* This should never happen (there's a bug in the code if it does) */		debug("default_agent_exited: mismatch with actual default_agent");		return;	}	default_agent->exited = 1;	passkey_agent_free(default_agent);	default_agent = NULL;}static struct passkey_agent *passkey_agent_new(struct adapter *adapter, DBusConnection *conn,						const char *name, const char *path,						const char *addr){	struct passkey_agent *agent;	agent = g_new0(struct passkey_agent, 1);	agent->adapter = adapter;	agent->name = g_strdup(name);	agent->path = g_strdup(path);	if (addr)		agent->addr = g_strdup(addr);	agent->conn = dbus_connection_ref(conn);	return agent;}static int agent_cmp(const struct passkey_agent *a, const struct passkey_agent *b){	int ret;	if (b->name) {		if (!a->name)			return -1;		ret = strcmp(a->name, b->name);		if (ret)			return ret;	}	if (b->path) {		if (!a->path)			return -1;		ret = strcmp(a->path, b->path);		if (ret)			return ret;	}	if (b->addr) {		if (!a->addr)			return -1;		ret = strcmp(a->addr, b->addr);		if (ret)			return ret;	}	return 0;}static DBusHandlerResult register_passkey_agent(DBusConnection *conn,					DBusMessage *msg, void *data){	struct passkey_agent *agent, ref;	struct adapter *adapter;	DBusMessage *reply;	const char *path, *addr;	if (!data) {		error("register_passkey_agent called without any adapter info!");		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	}	adapter = data;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_STRING, &addr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if ((check_address(addr) < 0) || (path[0] != '/'))		return error_invalid_arguments(conn, msg, NULL);	memset(&ref, 0, sizeof(ref));	ref.name = (char *) dbus_message_get_sender(msg);	ref.addr = (char *) addr;	ref.path = (char *) path;	if (g_slist_find_custom(adapter->passkey_agents, &ref, (GCompareFunc) agent_cmp))		return error_passkey_agent_already_exists(conn, msg);	agent = passkey_agent_new(adapter, conn, ref.name, path, addr);	if (!agent)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	reply = dbus_message_new_method_return(msg);	if (!reply) {		agent->exited = 1;		passkey_agent_free(agent);		return DBUS_HANDLER_RESULT_NEED_MEMORY;	}	/* Only add a name listener if there isn't one already for this name */	ref.addr = NULL;	ref.path = NULL;	if (!g_slist_find_custom(adapter->passkey_agents, &ref, (GCompareFunc) agent_cmp))		name_listener_add(conn, ref.name, (name_cb_t) agent_exited, adapter);	agent->timeout = g_timeout_add(AGENT_TIMEOUT, (GSourceFunc)agent_timeout, agent);	adapter->passkey_agents = g_slist_append(adapter->passkey_agents, agent);	return send_message_and_unref(conn, reply);}static DBusHandlerResult unregister_passkey_agent(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter;	GSList *match;	struct passkey_agent ref, *agent;	DBusMessage *reply;	const char *path, *addr;	if (!data) {		error("unregister_passkey_agent called without any adapter info!");		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	}	adapter = data;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_STRING, &addr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	memset(&ref, 0, sizeof(ref));	ref.name = (char *) dbus_message_get_sender(msg);	ref.path = (char *) path;	ref.addr = (char *) addr;	match = g_slist_find_custom(adapter->passkey_agents, &ref, (GCompareFunc) agent_cmp);	if (!match)		return error_passkey_agent_does_not_exist(conn, msg);	agent = match->data;	name_listener_remove(agent->conn, agent->name,			(name_cb_t) agent_exited, adapter);	adapter->passkey_agents = g_slist_remove(adapter->passkey_agents, agent);	agent->exited = 1;	passkey_agent_free(agent);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	return send_message_and_unref(conn, reply);}static DBusHandlerResult register_default_passkey_agent(DBusConnection *conn,							DBusMessage *msg, void *data){	DBusMessage *reply;	const char *path;	if (default_agent)		return error_passkey_agent_already_exists(conn, msg);	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	default_agent = passkey_agent_new(NULL, conn, dbus_message_get_sender(msg),						path, NULL);	if (!default_agent)		goto need_memory;	reply = dbus_message_new_method_return(msg);	if (!reply)		goto need_memory;	name_listener_add(conn, default_agent->name,			(name_cb_t) default_agent_exited, NULL);	info("Default passkey agent (%s, %s) registered",			default_agent->name, default_agent->path);	return send_message_and_unref(conn, reply);need_memory:	if (default_agent) {		default_agent->exited = 1;		passkey_agent_free(default_agent);		default_agent = NULL;	}	return DBUS_HANDLER_RESULT_NEED_MEMORY;}static DBusHandlerResult unregister_default_passkey_agent(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	const char *path, *name;	if (!default_agent)		return error_passkey_agent_does_not_exist(conn, msg);	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	name = dbus_message_get_sender(msg);	if (strcmp(name, default_agent->name) || strcmp(path, default_agent->path))		return error_passkey_agent_does_not_exist(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	name_listener_remove(conn, default_agent->name,			(name_cb_t) default_agent_exited, NULL);	info("Default passkey agent (%s, %s) unregistered",			default_agent->name, default_agent->path);	default_agent->exited = 1;	passkey_agent_free(default_agent);	default_agent = NULL;	return send_message_and_unref(conn, reply);}static struct auth_agent_req *auth_agent_req_new(DBusMessage *msg,						struct authorization_agent *agent,						const char *adapter_path,						const char *address,						const char *service_path,						const char *uuid){	struct auth_agent_req *req;	req = g_new0(struct auth_agent_req, 1);	req->agent = agent;	req->msg = dbus_message_ref(msg);	req->adapter_path = g_strdup(adapter_path);	req->address = g_strdup(address);	req->service_path = g_strdup(service_path);	req->uuid = g_strdup(uuid);	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);	g_free(req->uuid);	if (req->call)		dbus_pending_call_unref(req->call);	g_free(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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -