[Bluetooth] Reject L2CAP connections on an insecure ACL link
The Security Mode 4 of the Bluetooth 2.1 specification has strict authentication and encryption requirements. It is the initiators job to create a secure ACL link. However in case of malicious devices, the acceptor has to make sure that the ACL is encrypted before allowing any kind of L2CAP connection. The only exception here is the PSM 1 for the service discovery protocol, because that is allowed to run on an insecure ACL link. Previously it was enough to reject a L2CAP connection during the connection setup phase, but with Bluetooth 2.1 it is forbidden to do any L2CAP protocol exchange on an insecure link (except SDP). The new hci_conn_check_link_mode() function can be used to check the integrity of an ACL link. This functions also takes care of the cases where Security Mode 4 is disabled or one of the devices is based on an older specification. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Родитель
09ab6f4c23
Коммит
e7c29cb16c
|
@ -326,6 +326,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev);
|
|||
void hci_conn_check_pending(struct hci_dev *hdev);
|
||||
|
||||
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
int hci_conn_auth(struct hci_conn *conn);
|
||||
int hci_conn_encrypt(struct hci_conn *conn);
|
||||
int hci_conn_change_link_key(struct hci_conn *conn);
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.12"
|
||||
#define VERSION "2.13"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
|
|
|
@ -376,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
|
|||
}
|
||||
EXPORT_SYMBOL(hci_connect);
|
||||
|
||||
/* Check link security requirement */
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
|
||||
!(conn->link_mode & HCI_LM_ENCRYPT))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_conn_check_link_mode);
|
||||
|
||||
/* Authenticate remote device */
|
||||
int hci_conn_auth(struct hci_conn *conn)
|
||||
{
|
||||
|
|
|
@ -1568,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
||||
struct l2cap_conn_rsp rsp;
|
||||
struct sock *sk, *parent;
|
||||
int result, status = 0;
|
||||
int result, status = L2CAP_CS_NO_INFO;
|
||||
|
||||
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
||||
__le16 psm = req->psm;
|
||||
__le16 psm = req->psm;
|
||||
|
||||
BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
|
||||
|
||||
|
@ -1582,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||
goto sendresp;
|
||||
}
|
||||
|
||||
/* Check if the ACL is secure enough (if not SDP) */
|
||||
if (psm != cpu_to_le16(0x0001) &&
|
||||
!hci_conn_check_link_mode(conn->hcon)) {
|
||||
result = L2CAP_CR_SEC_BLOCK;
|
||||
goto response;
|
||||
}
|
||||
|
||||
result = L2CAP_CR_NO_MEM;
|
||||
|
||||
/* Check for backlog size */
|
||||
|
@ -2239,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
@ -2311,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
||||
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
|
||||
rsp.result = cpu_to_le16(result);
|
||||
rsp.status = cpu_to_le16(0);
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче