diff options
-rw-r--r-- | net/bluetooth/l2cap_core.c | 61 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 16 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 40 |
3 files changed, 75 insertions, 42 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 865716504396..584a4237eb3f 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -890,6 +890,23 @@ clean: | |||
890 | bh_unlock_sock(parent); | 890 | bh_unlock_sock(parent); |
891 | } | 891 | } |
892 | 892 | ||
893 | static void l2cap_chan_ready(struct sock *sk) | ||
894 | { | ||
895 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
896 | struct sock *parent = bt_sk(sk)->parent; | ||
897 | |||
898 | BT_DBG("sk %p, parent %p", sk, parent); | ||
899 | |||
900 | chan->conf_state = 0; | ||
901 | __clear_chan_timer(chan); | ||
902 | |||
903 | sk->sk_state = BT_CONNECTED; | ||
904 | sk->sk_state_change(sk); | ||
905 | |||
906 | if (parent) | ||
907 | parent->sk_data_ready(parent, 0); | ||
908 | } | ||
909 | |||
893 | static void l2cap_conn_ready(struct l2cap_conn *conn) | 910 | static void l2cap_conn_ready(struct l2cap_conn *conn) |
894 | { | 911 | { |
895 | struct l2cap_chan *chan; | 912 | struct l2cap_chan *chan; |
@@ -906,13 +923,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
906 | 923 | ||
907 | bh_lock_sock(sk); | 924 | bh_lock_sock(sk); |
908 | 925 | ||
909 | if (conn->hcon->type == LE_LINK) { | 926 | if (conn->hcon->type == LE_LINK) |
910 | __clear_chan_timer(chan); | ||
911 | l2cap_state_change(chan, BT_CONNECTED); | ||
912 | sk->sk_state_change(sk); | ||
913 | if (smp_conn_security(conn, chan->sec_level)) | 927 | if (smp_conn_security(conn, chan->sec_level)) |
914 | BT_DBG("Insufficient security"); | 928 | l2cap_chan_ready(sk); |
915 | } | ||
916 | 929 | ||
917 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 930 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
918 | __clear_chan_timer(chan); | 931 | __clear_chan_timer(chan); |
@@ -1675,30 +1688,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) | |||
1675 | return err; | 1688 | return err; |
1676 | } | 1689 | } |
1677 | 1690 | ||
1678 | static void l2cap_chan_ready(struct sock *sk) | ||
1679 | { | ||
1680 | struct sock *parent = bt_sk(sk)->parent; | ||
1681 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
1682 | |||
1683 | BT_DBG("sk %p, parent %p", sk, parent); | ||
1684 | |||
1685 | chan->conf_state = 0; | ||
1686 | __clear_chan_timer(chan); | ||
1687 | |||
1688 | if (!parent) { | ||
1689 | /* Outgoing channel. | ||
1690 | * Wake up socket sleeping on connect. | ||
1691 | */ | ||
1692 | l2cap_state_change(chan, BT_CONNECTED); | ||
1693 | sk->sk_state_change(sk); | ||
1694 | } else { | ||
1695 | /* Incoming channel. | ||
1696 | * Wake up socket sleeping on accept. | ||
1697 | */ | ||
1698 | parent->sk_data_ready(parent, 0); | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | /* Copy frame to all raw sockets on that connection */ | 1691 | /* Copy frame to all raw sockets on that connection */ |
1703 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | 1692 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) |
1704 | { | 1693 | { |
@@ -4188,6 +4177,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4188 | 4177 | ||
4189 | bh_lock_sock(sk); | 4178 | bh_lock_sock(sk); |
4190 | 4179 | ||
4180 | BT_DBG("chan->scid %d", chan->scid); | ||
4181 | |||
4182 | if (chan->scid == L2CAP_CID_LE_DATA) { | ||
4183 | if (!status && encrypt) { | ||
4184 | chan->sec_level = hcon->sec_level; | ||
4185 | l2cap_chan_ready(sk); | ||
4186 | } | ||
4187 | |||
4188 | bh_unlock_sock(sk); | ||
4189 | continue; | ||
4190 | } | ||
4191 | |||
4191 | if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { | 4192 | if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { |
4192 | bh_unlock_sock(sk); | 4193 | bh_unlock_sock(sk); |
4193 | continue; | 4194 | continue; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1d9c36509d7b..5c819e002fb1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
30 | #include <net/bluetooth/hci_core.h> | 30 | #include <net/bluetooth/hci_core.h> |
31 | #include <net/bluetooth/l2cap.h> | 31 | #include <net/bluetooth/l2cap.h> |
32 | #include <net/bluetooth/smp.h> | ||
32 | 33 | ||
33 | static const struct proto_ops l2cap_sock_ops; | 34 | static const struct proto_ops l2cap_sock_ops; |
34 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); | 35 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
@@ -562,6 +563,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
562 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 563 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
563 | struct bt_security sec; | 564 | struct bt_security sec; |
564 | struct bt_power pwr; | 565 | struct bt_power pwr; |
566 | struct l2cap_conn *conn; | ||
565 | int len, err = 0; | 567 | int len, err = 0; |
566 | u32 opt; | 568 | u32 opt; |
567 | 569 | ||
@@ -598,6 +600,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
598 | } | 600 | } |
599 | 601 | ||
600 | chan->sec_level = sec.level; | 602 | chan->sec_level = sec.level; |
603 | |||
604 | conn = chan->conn; | ||
605 | if (conn && chan->scid == L2CAP_CID_LE_DATA) { | ||
606 | if (!conn->hcon->out) { | ||
607 | err = -EINVAL; | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | if (smp_conn_security(conn, sec.level)) | ||
612 | break; | ||
613 | |||
614 | err = 0; | ||
615 | sk->sk_state = BT_CONFIG; | ||
616 | } | ||
601 | break; | 617 | break; |
602 | 618 | ||
603 | case BT_DEFER_SETUP: | 619 | case BT_DEFER_SETUP: |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 69839797b7dc..da46d76fc13d 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -336,9 +336,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
336 | { | 336 | { |
337 | struct smp_cmd_security_req *rp = (void *) skb->data; | 337 | struct smp_cmd_security_req *rp = (void *) skb->data; |
338 | struct smp_cmd_pairing cp; | 338 | struct smp_cmd_pairing cp; |
339 | struct hci_conn *hcon = conn->hcon; | ||
339 | 340 | ||
340 | BT_DBG("conn %p", conn); | 341 | BT_DBG("conn %p", conn); |
341 | 342 | ||
343 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
344 | return; | ||
345 | |||
342 | skb_pull(skb, sizeof(*rp)); | 346 | skb_pull(skb, sizeof(*rp)); |
343 | memset(&cp, 0, sizeof(cp)); | 347 | memset(&cp, 0, sizeof(cp)); |
344 | 348 | ||
@@ -353,6 +357,20 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
353 | memcpy(&conn->preq[1], &cp, sizeof(cp)); | 357 | memcpy(&conn->preq[1], &cp, sizeof(cp)); |
354 | 358 | ||
355 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 359 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
360 | |||
361 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
362 | } | ||
363 | |||
364 | static __u8 seclevel_to_authreq(__u8 level) | ||
365 | { | ||
366 | switch (level) { | ||
367 | case BT_SECURITY_HIGH: | ||
368 | /* For now we don't support bonding */ | ||
369 | return SMP_AUTH_MITM; | ||
370 | |||
371 | default: | ||
372 | return SMP_AUTH_NONE; | ||
373 | } | ||
356 | } | 374 | } |
357 | 375 | ||
358 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | 376 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) |
@@ -365,21 +383,16 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
365 | if (IS_ERR(hcon->hdev->tfm)) | 383 | if (IS_ERR(hcon->hdev->tfm)) |
366 | return 1; | 384 | return 1; |
367 | 385 | ||
368 | switch (sec_level) { | 386 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) |
369 | case BT_SECURITY_MEDIUM: | 387 | return 0; |
370 | /* Encrypted, no MITM protection */ | ||
371 | authreq = HCI_AT_NO_BONDING_MITM; | ||
372 | break; | ||
373 | 388 | ||
374 | case BT_SECURITY_HIGH: | 389 | if (sec_level == BT_SECURITY_LOW) |
375 | /* Bonding, MITM protection */ | 390 | return 1; |
376 | authreq = HCI_AT_GENERAL_BONDING_MITM; | ||
377 | break; | ||
378 | 391 | ||
379 | case BT_SECURITY_LOW: | 392 | if (hcon->sec_level >= sec_level) |
380 | default: | ||
381 | return 1; | 393 | return 1; |
382 | } | 394 | |
395 | authreq = seclevel_to_authreq(sec_level); | ||
383 | 396 | ||
384 | if (hcon->link_mode & HCI_LM_MASTER) { | 397 | if (hcon->link_mode & HCI_LM_MASTER) { |
385 | struct smp_cmd_pairing cp; | 398 | struct smp_cmd_pairing cp; |
@@ -400,6 +413,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
400 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); | 413 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); |
401 | } | 414 | } |
402 | 415 | ||
416 | hcon->pending_sec_level = sec_level; | ||
417 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
418 | |||
403 | return 0; | 419 | return 0; |
404 | } | 420 | } |
405 | 421 | ||