aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:50 -0400
committerMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:50 -0400
commit40be492fe4fab829951681860c2bb26fa1d5fe4a (patch)
tree41b576692c2206c9a51e689f54170076ec95bc3a
parentf8558555f31e177e2644f3c8116801c3e5c29974 (diff)
[Bluetooth] Export details about authentication requirements
With the Simple Pairing support, the authentication requirements are an explicit setting during the bonding process. Track and enforce the requirements and allow higher layers like L2CAP and RFCOMM to increase them if needed. This patch introduces a new IOCTL that allows to query the current authentication requirements. It is also possible to detect Simple Pairing support in the kernel this way. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-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))