aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/compat_ioctl.c1
-rw-r--r--include/net/bluetooth/hci.h18
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--net/bluetooth/hci_conn.c38
-rw-r--r--net/bluetooth/hci_sock.c18
-rw-r--r--net/bluetooth/l2cap.c14
-rw-r--r--net/bluetooth/rfcomm/core.c3
7 files changed, 68 insertions, 26 deletions
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 97dba0d92348..d63d430d3b26 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -2399,6 +2399,7 @@ COMPATIBLE_IOCTL(HCIGETDEVLIST)
2399COMPATIBLE_IOCTL(HCIGETDEVINFO) 2399COMPATIBLE_IOCTL(HCIGETDEVINFO)
2400COMPATIBLE_IOCTL(HCIGETCONNLIST) 2400COMPATIBLE_IOCTL(HCIGETCONNLIST)
2401COMPATIBLE_IOCTL(HCIGETCONNINFO) 2401COMPATIBLE_IOCTL(HCIGETCONNINFO)
2402COMPATIBLE_IOCTL(HCIGETAUTHINFO)
2402COMPATIBLE_IOCTL(HCISETRAW) 2403COMPATIBLE_IOCTL(HCISETRAW)
2403COMPATIBLE_IOCTL(HCISETSCAN) 2404COMPATIBLE_IOCTL(HCISETSCAN)
2404COMPATIBLE_IOCTL(HCISETAUTH) 2405COMPATIBLE_IOCTL(HCISETAUTH)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 55576e848827..3cc294919312 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -72,8 +72,6 @@ enum {
72 HCI_INQUIRY, 72 HCI_INQUIRY,
73 73
74 HCI_RAW, 74 HCI_RAW,
75
76 HCI_SECMGR
77}; 75};
78 76
79/* HCI ioctl defines */ 77/* HCI ioctl defines */
@@ -86,6 +84,7 @@ enum {
86#define HCIGETDEVINFO _IOR('H', 211, int) 84#define HCIGETDEVINFO _IOR('H', 211, int)
87#define HCIGETCONNLIST _IOR('H', 212, int) 85#define HCIGETCONNLIST _IOR('H', 212, int)
88#define HCIGETCONNINFO _IOR('H', 213, int) 86#define HCIGETCONNINFO _IOR('H', 213, int)
87#define HCIGETAUTHINFO _IOR('H', 215, int)
89 88
90#define HCISETRAW _IOW('H', 220, int) 89#define HCISETRAW _IOW('H', 220, int)
91#define HCISETSCAN _IOW('H', 221, int) 90#define HCISETSCAN _IOW('H', 221, int)
@@ -97,8 +96,6 @@ enum {
97#define HCISETACLMTU _IOW('H', 227, int) 96#define HCISETACLMTU _IOW('H', 227, int)
98#define HCISETSCOMTU _IOW('H', 228, int) 97#define HCISETSCOMTU _IOW('H', 228, int)
99 98
100#define HCISETSECMGR _IOW('H', 230, int)
101
102#define HCIINQUIRY _IOR('H', 240, int) 99#define HCIINQUIRY _IOR('H', 240, int)
103 100
104/* HCI timeouts */ 101/* HCI timeouts */
@@ -203,6 +200,14 @@ enum {
203#define HCI_LM_RELIABLE 0x0010 200#define HCI_LM_RELIABLE 0x0010
204#define HCI_LM_SECURE 0x0020 201#define HCI_LM_SECURE 0x0020
205 202
203/* Authentication types */
204#define HCI_AT_NO_BONDING 0x00
205#define HCI_AT_NO_BONDING_MITM 0x01
206#define HCI_AT_DEDICATED_BONDING 0x02
207#define HCI_AT_DEDICATED_BONDING_MITM 0x03
208#define HCI_AT_GENERAL_BONDING 0x04
209#define HCI_AT_GENERAL_BONDING_MITM 0x05
210
206/* ----- HCI Commands ---- */ 211/* ----- HCI Commands ---- */
207#define HCI_OP_INQUIRY 0x0401 212#define HCI_OP_INQUIRY 0x0401
208struct hci_cp_inquiry { 213struct hci_cp_inquiry {
@@ -1001,6 +1006,11 @@ struct hci_conn_info_req {
1001 struct hci_conn_info conn_info[0]; 1006 struct hci_conn_info conn_info[0];
1002}; 1007};
1003 1008
1009struct hci_auth_info_req {
1010 bdaddr_t bdaddr;
1011 __u8 type;
1012};
1013
1004struct hci_inquiry_req { 1014struct hci_inquiry_req {
1005 __u16 dev_id; 1015 __u16 dev_id;
1006 __u16 flags; 1016 __u16 flags;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 28fbd0caa534..cbf751094688 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -168,6 +168,7 @@ struct hci_conn {
168 __u16 pkt_type; 168 __u16 pkt_type;
169 __u16 link_policy; 169 __u16 link_policy;
170 __u32 link_mode; 170 __u32 link_mode;
171 __u8 auth_type;
171 __u8 power_save; 172 __u8 power_save;
172 unsigned long pend; 173 unsigned long pend;
173 174
@@ -422,6 +423,7 @@ int hci_get_dev_list(void __user *arg);
422int hci_get_dev_info(void __user *arg); 423int hci_get_dev_info(void __user *arg);
423int hci_get_conn_list(void __user *arg); 424int hci_get_conn_list(void __user *arg);
424int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); 425int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
426int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
425int hci_inquiry(void __user *arg); 427int hci_inquiry(void __user *arg);
426 428
427void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 429void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6f22533e7656..0d4b8aeb8e09 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -379,13 +379,21 @@ int hci_conn_auth(struct hci_conn *conn)
379{ 379{
380 BT_DBG("conn %p", conn); 380 BT_DBG("conn %p", conn);
381 381
382 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
383 if (!(conn->auth_type & 0x01)) {
384 conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
385 conn->link_mode &= ~HCI_LM_AUTH;
386 }
387 }
388
382 if (conn->link_mode & HCI_LM_AUTH) 389 if (conn->link_mode & HCI_LM_AUTH)
383 return 1; 390 return 1;
384 391
385 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 392 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
386 struct hci_cp_auth_requested cp; 393 struct hci_cp_auth_requested cp;
387 cp.handle = cpu_to_le16(conn->handle); 394 cp.handle = cpu_to_le16(conn->handle);
388 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 395 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
396 sizeof(cp), &cp);
389 } 397 }
390 return 0; 398 return 0;
391} 399}
@@ -397,7 +405,7 @@ int hci_conn_encrypt(struct hci_conn *conn)
397 BT_DBG("conn %p", conn); 405 BT_DBG("conn %p", conn);
398 406
399 if (conn->link_mode & HCI_LM_ENCRYPT) 407 if (conn->link_mode & HCI_LM_ENCRYPT)
400 return 1; 408 return hci_conn_auth(conn);
401 409
402 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 410 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
403 return 0; 411 return 0;
@@ -406,7 +414,8 @@ int hci_conn_encrypt(struct hci_conn *conn)
406 struct hci_cp_set_conn_encrypt cp; 414 struct hci_cp_set_conn_encrypt cp;
407 cp.handle = cpu_to_le16(conn->handle); 415 cp.handle = cpu_to_le16(conn->handle);
408 cp.encrypt = 1; 416 cp.encrypt = 1;
409 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp); 417 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
418 sizeof(cp), &cp);
410 } 419 }
411 return 0; 420 return 0;
412} 421}
@@ -420,7 +429,8 @@ int hci_conn_change_link_key(struct hci_conn *conn)
420 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 429 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
421 struct hci_cp_change_conn_link_key cp; 430 struct hci_cp_change_conn_link_key cp;
422 cp.handle = cpu_to_le16(conn->handle); 431 cp.handle = cpu_to_le16(conn->handle);
423 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp); 432 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
433 sizeof(cp), &cp);
424 } 434 }
425 return 0; 435 return 0;
426} 436}
@@ -624,3 +634,23 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
624 634
625 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0; 635 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
626} 636}
637
638int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
639{
640 struct hci_auth_info_req req;
641 struct hci_conn *conn;
642
643 if (copy_from_user(&req, arg, sizeof(req)))
644 return -EFAULT;
645
646 hci_dev_lock_bh(hdev);
647 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
648 if (conn)
649 req.type = conn->auth_type;
650 hci_dev_unlock_bh(hdev);
651
652 if (!conn)
653 return -ENOENT;
654
655 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
656}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 747fabd735d2..d62579b67959 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -193,19 +193,11 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
193 193
194 return 0; 194 return 0;
195 195
196 case HCISETSECMGR:
197 if (!capable(CAP_NET_ADMIN))
198 return -EACCES;
199
200 if (arg)
201 set_bit(HCI_SECMGR, &hdev->flags);
202 else
203 clear_bit(HCI_SECMGR, &hdev->flags);
204
205 return 0;
206
207 case HCIGETCONNINFO: 196 case HCIGETCONNINFO:
208 return hci_get_conn_info(hdev, (void __user *)arg); 197 return hci_get_conn_info(hdev, (void __user *) arg);
198
199 case HCIGETAUTHINFO:
200 return hci_get_auth_info(hdev, (void __user *) arg);
209 201
210 default: 202 default:
211 if (hdev->ioctl) 203 if (hdev->ioctl)
@@ -217,7 +209,7 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
217static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 209static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
218{ 210{
219 struct sock *sk = sock->sk; 211 struct sock *sk = sock->sk;
220 void __user *argp = (void __user *)arg; 212 void __user *argp = (void __user *) arg;
221 int err; 213 int err;
222 214
223 BT_DBG("cmd %x arg %lx", cmd, arg); 215 BT_DBG("cmd %x arg %lx", cmd, arg);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 252264062f59..30ad59b717d5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2150,7 +2150,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
2150static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) 2150static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
2151{ 2151{
2152 struct l2cap_chan_list *l; 2152 struct l2cap_chan_list *l;
2153 struct l2cap_conn *conn = conn = hcon->l2cap_data; 2153 struct l2cap_conn *conn = hcon->l2cap_data;
2154 struct l2cap_conn_rsp rsp; 2154 struct l2cap_conn_rsp rsp;
2155 struct sock *sk; 2155 struct sock *sk;
2156 int result; 2156 int result;
@@ -2165,11 +2165,17 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
2165 read_lock(&l->lock); 2165 read_lock(&l->lock);
2166 2166
2167 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { 2167 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2168 struct l2cap_pinfo *pi = l2cap_pi(sk);
2169
2168 bh_lock_sock(sk); 2170 bh_lock_sock(sk);
2169 2171
2170 if (sk->sk_state != BT_CONNECT2 || 2172 if (sk->sk_state != BT_CONNECT2) {
2171 (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) || 2173 bh_unlock_sock(sk);
2172 (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) { 2174 continue;
2175 }
2176
2177 if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
2178 !(hcon->link_mode & HCI_LM_ENCRYPT)) {
2173 bh_unlock_sock(sk); 2179 bh_unlock_sock(sk);
2174 continue; 2180 continue;
2175 } 2181 }
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index e7a6a03cea37..e56bcfc35a49 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1969,7 +1969,8 @@ static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
1969 list_for_each_safe(p, n, &s->dlcs) { 1969 list_for_each_safe(p, n, &s->dlcs) {
1970 d = list_entry(p, struct rfcomm_dlc, list); 1970 d = list_entry(p, struct rfcomm_dlc, list);
1971 1971
1972 if (d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) 1972 if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
1973 !(conn->link_mode & HCI_LM_ENCRYPT) && !status)
1973 continue; 1974 continue;
1974 1975
1975 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) 1976 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))