Skip to content

Commit

Permalink
[Bluetooth] Disconnect when encryption gets disabled
Browse files Browse the repository at this point in the history
The Bluetooth specification allows to enable or disable the encryption
of an ACL link at any time by either the peer or the remote device. If
a L2CAP or RFCOMM connection requested an encrypted link, they will now
disconnect that link if the encryption gets disabled. Higher protocols
that don't care about encryption (like SDP) are not affected.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Marcel Holtmann committed Jul 14, 2008
1 parent 77db198 commit 9719f8a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 6 deletions.
10 changes: 5 additions & 5 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ struct hci_proto {
int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
int (*auth_cfm) (struct hci_conn *conn, __u8 status);
int (*encrypt_cfm) (struct hci_conn *conn, __u8 status);
int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
};

static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
Expand Down Expand Up @@ -532,17 +532,17 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
hp->auth_cfm(conn, status);
}

static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
register struct hci_proto *hp;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status);
hp->encrypt_cfm(conn, status, encrypt);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status);
hp->encrypt_cfm(conn, status, encrypt);
}

int hci_register_proto(struct hci_proto *hproto);
Expand Down Expand Up @@ -579,7 +579,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
{
struct list_head *p;

hci_proto_encrypt_cfm(conn, status);
hci_proto_encrypt_cfm(conn, status, encrypt);

read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
Expand Down
13 changes: 12 additions & 1 deletion net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
return 0;
}

static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{
struct l2cap_chan_list *l;
struct l2cap_conn *conn = hcon->l2cap_data;
Expand All @@ -2215,8 +2215,19 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
read_lock(&l->lock);

for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
struct l2cap_pinfo *pi = l2cap_pi(sk);

bh_lock_sock(sk);

if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
(sk->sk_state == BT_CONNECTED ||
sk->sk_state == BT_CONFIG) &&
!status && encrypt == 0x00) {
__l2cap_sock_close(sk, ECONNREFUSED);
bh_unlock_sock(sk);
continue;
}

if (sk->sk_state != BT_CONNECT2) {
bh_unlock_sock(sk);
continue;
Expand Down
8 changes: 8 additions & 0 deletions net/bluetooth/rfcomm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,14 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
list_for_each_safe(p, n, &s->dlcs) {
d = list_entry(p, struct rfcomm_dlc, list);

if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
(d->state == BT_CONNECTED ||
d->state == BT_CONFIG) &&
!status && encrypt == 0x00) {
__rfcomm_dlc_close(d, ECONNREFUSED);
continue;
}

if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
continue;

Expand Down

0 comments on commit 9719f8a

Please sign in to comment.