Example #1
0
void control_message(uint16_t opcode, const void *data, uint16_t size)
{
	if (!decode_control)
		return;

	switch (opcode) {
	case MGMT_EV_INDEX_ADDED:
		mgmt_index_added(size, data);
		break;
	case MGMT_EV_INDEX_REMOVED:
		mgmt_index_removed(size, data);
		break;
	case MGMT_EV_CONTROLLER_ERROR:
		mgmt_controller_error(size, data);
		break;
	case MGMT_EV_NEW_SETTINGS:
		mgmt_new_settings(size, data);
		break;
	case MGMT_EV_CLASS_OF_DEV_CHANGED:
		mgmt_class_of_dev_changed(size, data);
		break;
	case MGMT_EV_LOCAL_NAME_CHANGED:
		mgmt_local_name_changed(size, data);
		break;
	case MGMT_EV_NEW_LINK_KEY:
		mgmt_new_link_key(size, data);
		break;
	case MGMT_EV_NEW_LONG_TERM_KEY:
		mgmt_new_long_term_key(size, data);
		break;
	case MGMT_EV_DEVICE_CONNECTED:
		mgmt_device_connected(size, data);
		break;
	case MGMT_EV_DEVICE_DISCONNECTED:
		mgmt_device_disconnected(size, data);
		break;
	case MGMT_EV_CONNECT_FAILED:
		mgmt_connect_failed(size, data);
		break;
	case MGMT_EV_PIN_CODE_REQUEST:
		mgmt_pin_code_request(size, data);
		break;
	case MGMT_EV_USER_CONFIRM_REQUEST:
		mgmt_user_confirm_request(size, data);
		break;
	case MGMT_EV_USER_PASSKEY_REQUEST:
		mgmt_user_passkey_request(size, data);
		break;
	case MGMT_EV_AUTH_FAILED:
		mgmt_auth_failed(size, data);
		break;
	case MGMT_EV_DEVICE_FOUND:
		mgmt_device_found(size, data);
		break;
	case MGMT_EV_DISCOVERING:
		mgmt_discovering(size, data);
		break;
	case MGMT_EV_DEVICE_BLOCKED:
		mgmt_device_blocked(size, data);
		break;
	case MGMT_EV_DEVICE_UNBLOCKED:
		mgmt_device_unblocked(size, data);
		break;
	case MGMT_EV_DEVICE_UNPAIRED:
		mgmt_device_unpaired(size, data);
		break;
	case MGMT_EV_PASSKEY_NOTIFY:
		mgmt_passkey_notify(size, data);
		break;
	case MGMT_EV_NEW_IRK:
		mgmt_new_irk(size, data);
		break;
	case MGMT_EV_NEW_CSRK:
		mgmt_new_csrk(size, data);
		break;
	case MGMT_EV_DEVICE_ADDED:
		mgmt_device_added(size, data);
		break;
	case MGMT_EV_DEVICE_REMOVED:
		mgmt_device_removed(size, data);
		break;
	case MGMT_EV_NEW_CONN_PARAM:
		mgmt_new_conn_param(size, data);
		break;
	case MGMT_EV_UNCONF_INDEX_ADDED:
		mgmt_unconf_index_added(size, data);
		break;
	case MGMT_EV_UNCONF_INDEX_REMOVED:
		mgmt_unconf_index_removed(size, data);
		break;
	case MGMT_EV_NEW_CONFIG_OPTIONS:
		mgmt_new_config_options(size, data);
		break;
	case MGMT_EV_EXT_INDEX_ADDED:
		mgmt_ext_index_added(size, data);
		break;
	case MGMT_EV_EXT_INDEX_REMOVED:
		mgmt_ext_index_removed(size, data);
		break;
	case MGMT_EV_ADVERTISING_ADDED:
		mgmt_advertising_added(size, data);
		break;
	case MGMT_EV_ADVERTISING_REMOVED:
		mgmt_advertising_removed(size, data);
		break;
	default:
		printf("* Unknown control (code %d len %d)\n", opcode, size);
		packet_hexdump(data, size);
		break;
	}
}
Example #2
0
static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
						u8 local_io, u8 remote_io)
{
	struct hci_conn *hcon = conn->hcon;
	struct smp_chan *smp = conn->smp_chan;
	u8 method;
	u32 passkey = 0;
	int ret = 0;

	/* Initialize key for JUST WORKS */
	memset(smp->tk, 0, sizeof(smp->tk));
	clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);

	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);

	/* If neither side wants MITM, use JUST WORKS */
	/* If either side has unknown io_caps, use JUST WORKS */
	/* Otherwise, look up method from the table */
	if (!(auth & SMP_AUTH_MITM) ||
			local_io > SMP_IO_KEYBOARD_DISPLAY ||
			remote_io > SMP_IO_KEYBOARD_DISPLAY)
		method = JUST_WORKS;
	else
		method = gen_method[remote_io][local_io];

	/* If not bonding, don't ask user to confirm a Zero TK */
	if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
		method = JUST_WORKS;

	/* If Just Works, Continue with Zero TK */
	if (method == JUST_WORKS) {
		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
		return 0;
	}

	/* Not Just Works/Confirm results in MITM Authentication */
	if (method != JUST_CFM)
		set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);

	/* If both devices have Keyoard-Display I/O, the master
	 * Confirms and the slave Enters the passkey.
	 */
	if (method == OVERLAP) {
		if (hcon->link_mode & HCI_LM_MASTER)
			method = CFM_PASSKEY;
		else
			method = REQ_PASSKEY;
	}

	/* Generate random passkey. Not valid until confirmed. */
	if (method == CFM_PASSKEY) {
		u8 key[16];

		memset(key, 0, sizeof(key));
		get_random_bytes(&passkey, sizeof(passkey));
		passkey %= 1000000;
		put_unaligned_le32(passkey, key);
		swap128(key, smp->tk);
		BT_DBG("PassKey: %d", passkey);
	}

	hci_dev_lock(hcon->hdev);

	if (method == REQ_PASSKEY)
		ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
						hcon->type, hcon->dst_type);
	else
		ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
						hcon->type, hcon->dst_type,
						cpu_to_le32(passkey), 0);

	hci_dev_unlock(hcon->hdev);

	return ret;
}
Example #3
0
static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
						u8 local_io, u8 remote_io)
{
	struct hci_conn *hcon = conn->hcon;
	u8 method;
	u32 passkey = 0;
	int ret = 0;

	/* Initialize key to JUST WORKS */
	memset(hcon->tk, 0, sizeof(hcon->tk));
	hcon->tk_valid = FALSE;
	hcon->auth = auth;

	/* By definition, OOB data will be used if both sides have it available
	 */
	if (remote_oob && hcon->oob) {
		method = SMP_REQ_OOB;
		goto agent_request;
	}

	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);

	/* If neither side wants MITM, use JUST WORKS */
	/* If either side has unknown io_caps, use JUST_WORKS */
	if (!(auth & SMP_AUTH_MITM) ||
			local_io > SMP_IO_KEYBOARD_DISPLAY ||
			remote_io > SMP_IO_KEYBOARD_DISPLAY) {
		hcon->auth &= ~SMP_AUTH_MITM;
		hcon->tk_valid = TRUE;
		return 0;
	}

	/* MITM is now officially requested, but not required */
	/* Determine what we need (if anything) from the agent */
	method = gen_method[local_io][remote_io];

	BT_DBG("tk_method: %d", method);

	if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
		hcon->auth &= ~SMP_AUTH_MITM;

	/* Don't bother confirming unbonded JUST_WORKS */
	if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
		hcon->tk_valid = TRUE;
		return 0;
	} else if (method == SMP_JUST_WORKS) {
		hcon->tk_valid = TRUE;
		return 0;
	} else if (method == SMP_OVERLAP) {
		if (hcon->link_mode & HCI_LM_MASTER)
			method = SMP_CFM_PASSKEY;
		else
			method = SMP_REQ_PASSKEY;
	}

	BT_DBG("tk_method-2: %d", method);

	if (method == SMP_CFM_PASSKEY) {
		u8 key[16];
		/* Generate a passkey for display. It is not valid until
		 * confirmed.
		 */
		memset(key, 0, sizeof(key));
		get_random_bytes(&passkey, sizeof(passkey));
		passkey %= 1000000;
		put_unaligned_le32(passkey, key);
		swap128(key, hcon->tk);
		BT_DBG("PassKey: %d", passkey);
	}

agent_request:
	hci_dev_lock(hcon->hdev);

	switch (method) {
	case SMP_REQ_PASSKEY:
		ret = mgmt_user_confirm_request(hcon->hdev->id,
				HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
		break;
	case SMP_CFM_PASSKEY:
	default:
		ret = mgmt_user_confirm_request(hcon->hdev->id,
			HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
		break;
	}

	hci_dev_unlock(hcon->hdev);

	return ret;
}
Example #4
0
static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
						u8 local_io, u8 remote_io)
{
	struct hci_conn *hcon = conn->hcon;
	u8 method;
	u32 passkey = 0;
	int ret = 0;

	
	memset(hcon->tk, 0, sizeof(hcon->tk));
	hcon->tk_valid = FALSE;
	hcon->auth = auth;

	if (remote_oob && hcon->oob) {
		method = SMP_REQ_OOB;
		goto agent_request;
	}

	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);

	
	
	if (!(auth & SMP_AUTH_MITM) ||
			local_io > SMP_IO_KEYBOARD_DISPLAY ||
			remote_io > SMP_IO_KEYBOARD_DISPLAY) {
		hcon->auth &= ~SMP_AUTH_MITM;
		hcon->tk_valid = TRUE;
		return 0;
	}

	
	
	method = gen_method[local_io][remote_io];

	BT_DBG("tk_method: %d", method);

	if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
		hcon->auth &= ~SMP_AUTH_MITM;

	
	if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
		hcon->tk_valid = TRUE;
		return 0;
	} else if (method == SMP_JUST_WORKS) {
		hcon->tk_valid = TRUE;
		return 0;
	} else if (method == SMP_OVERLAP) {
		if (hcon->link_mode & HCI_LM_MASTER)
			method = SMP_CFM_PASSKEY;
		else
			method = SMP_REQ_PASSKEY;
	}

	BT_DBG("tk_method-2: %d", method);

	if (method == SMP_CFM_PASSKEY) {
		u8 key[16];
		memset(key, 0, sizeof(key));
		get_random_bytes(&passkey, sizeof(passkey));
		passkey %= 1000000;
		put_unaligned_le32(passkey, key);
		swap128(key, hcon->tk);
		BT_DBG("PassKey: %d", passkey);
	}

agent_request:
	hci_dev_lock(hcon->hdev);

	switch (method) {
	case SMP_REQ_PASSKEY:
		ret = mgmt_user_confirm_request(hcon->hdev->id,
				HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
		break;
	case SMP_CFM_PASSKEY:
	default:
		ret = mgmt_user_confirm_request(hcon->hdev->id,
			HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
		break;
	}

	hci_dev_unlock(hcon->hdev);

	return ret;
}
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data)
{
	char buf[MGMT_BUF_SIZE];
	struct mgmt_hdr *hdr = (void *) buf;
	int sk;
	ssize_t ret;
	uint16_t len, opcode, index;

	DBG("cond %d", cond);

	if (cond & G_IO_NVAL)
		return FALSE;

	sk = g_io_channel_unix_get_fd(io);

	if (cond & (G_IO_ERR | G_IO_HUP)) {
		error("Error on management socket");
		return FALSE;
	}

	ret = read(sk, buf, sizeof(buf));
	if (ret < 0) {
		error("Unable to read from management socket: %s (%d)",
						strerror(errno), errno);
		return TRUE;
	}

	DBG("Received %zd bytes from management socket", ret);

	if (ret < MGMT_HDR_SIZE) {
		error("Too small Management packet");
		return TRUE;
	}

	opcode = btohs(bt_get_unaligned(&hdr->opcode));
	len = btohs(bt_get_unaligned(&hdr->len));
	index = btohs(bt_get_unaligned(&hdr->index));

	if (ret != MGMT_HDR_SIZE + len) {
		error("Packet length mismatch. ret %zd len %u", ret, len);
		return TRUE;
	}

	switch (opcode) {
	case MGMT_EV_CMD_COMPLETE:
		mgmt_cmd_complete(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_CMD_STATUS:
		mgmt_cmd_status(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_CONTROLLER_ERROR:
		mgmt_controller_error(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_INDEX_ADDED:
		mgmt_index_added(sk, index);
		break;
	case MGMT_EV_INDEX_REMOVED:
		mgmt_index_removed(sk, index);
		break;
	case MGMT_EV_POWERED:
		mgmt_powered(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_DISCOVERABLE:
		mgmt_discoverable(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_CONNECTABLE:
		mgmt_connectable(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_PAIRABLE:
		mgmt_pairable(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_NEW_KEY:
		mgmt_new_key(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_DEVICE_CONNECTED:
		mgmt_device_connected(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_DEVICE_DISCONNECTED:
		mgmt_device_disconnected(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_CONNECT_FAILED:
		mgmt_connect_failed(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_PIN_CODE_REQUEST:
		mgmt_pin_code_request(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_USER_CONFIRM_REQUEST:
		mgmt_user_confirm_request(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_AUTH_FAILED:
		mgmt_auth_failed(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_LOCAL_NAME_CHANGED:
		mgmt_local_name_changed(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_DEVICE_FOUND:
		mgmt_device_found(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_REMOTE_NAME:
		mgmt_remote_name(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	case MGMT_EV_DISCOVERING:
		mgmt_discovering(sk, index, buf + MGMT_HDR_SIZE, len);
		break;
	default:
		error("Unknown Management opcode %u (index %u)", opcode, index);
		break;
	}

	return TRUE;
}