diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2009-01-15 15:58:40 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-02-27 00:14:26 -0500 |
commit | 9f2c8a03fbb3048cf38b158f87aa0c3c09bca084 (patch) | |
tree | b8e81e5a8e3f0b8b8a15c06f1cf36e8aa02644e2 | |
parent | 2af6b9d518ddfbc4d6990d5f9c9b1a05341c1cef (diff) |
Bluetooth: Replace RFCOMM link mode with security level
Change the RFCOMM internals to use the new security levels and remove
the link mode details.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | include/net/bluetooth/rfcomm.h | 7 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 28 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 75 |
3 files changed, 79 insertions, 31 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 71b45f459687..bda68d833ddd 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
@@ -183,8 +183,8 @@ struct rfcomm_dlc { | |||
183 | u8 remote_v24_sig; | 183 | u8 remote_v24_sig; |
184 | u8 mscex; | 184 | u8 mscex; |
185 | u8 out; | 185 | u8 out; |
186 | 186 | u8 sec_level; | |
187 | u32 link_mode; | 187 | u8 role_switch; |
188 | u32 defer_setup; | 188 | u32 defer_setup; |
189 | 189 | ||
190 | uint mtu; | 190 | uint mtu; |
@@ -307,7 +307,8 @@ struct rfcomm_pinfo { | |||
307 | struct bt_sock bt; | 307 | struct bt_sock bt; |
308 | struct rfcomm_dlc *dlc; | 308 | struct rfcomm_dlc *dlc; |
309 | u8 channel; | 309 | u8 channel; |
310 | u32 link_mode; | 310 | u8 sec_level; |
311 | u8 role_switch; | ||
311 | }; | 312 | }; |
312 | 313 | ||
313 | int rfcomm_init_sockets(void); | 314 | int rfcomm_init_sockets(void); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 68f70c5270c6..db83f92d274c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -223,21 +223,11 @@ static int rfcomm_l2sock_create(struct socket **sock) | |||
223 | return err; | 223 | return err; |
224 | } | 224 | } |
225 | 225 | ||
226 | static inline int rfcomm_check_link_mode(struct rfcomm_dlc *d) | 226 | static inline int rfcomm_check_security(struct rfcomm_dlc *d) |
227 | { | 227 | { |
228 | struct sock *sk = d->session->sock->sk; | 228 | struct sock *sk = d->session->sock->sk; |
229 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | ||
230 | 229 | ||
231 | if (d->link_mode & RFCOMM_LM_SECURE) | 230 | return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level); |
232 | return hci_conn_security(conn->hcon, BT_SECURITY_HIGH); | ||
233 | |||
234 | if (d->link_mode & RFCOMM_LM_ENCRYPT) | ||
235 | return hci_conn_security(conn->hcon, BT_SECURITY_MEDIUM); | ||
236 | |||
237 | if (d->link_mode & RFCOMM_LM_AUTH) | ||
238 | return hci_conn_security(conn->hcon, BT_SECURITY_LOW); | ||
239 | |||
240 | return 1; | ||
241 | } | 231 | } |
242 | 232 | ||
243 | /* ---- RFCOMM DLCs ---- */ | 233 | /* ---- RFCOMM DLCs ---- */ |
@@ -390,7 +380,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, | |||
390 | d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc; | 380 | d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc; |
391 | 381 | ||
392 | if (s->state == BT_CONNECTED) { | 382 | if (s->state == BT_CONNECTED) { |
393 | if (rfcomm_check_link_mode(d)) | 383 | if (rfcomm_check_security(d)) |
394 | rfcomm_send_pn(s, 1, d); | 384 | rfcomm_send_pn(s, 1, d); |
395 | else | 385 | else |
396 | set_bit(RFCOMM_AUTH_PENDING, &d->flags); | 386 | set_bit(RFCOMM_AUTH_PENDING, &d->flags); |
@@ -1192,7 +1182,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) | |||
1192 | d->state_change(d, 0); | 1182 | d->state_change(d, 0); |
1193 | rfcomm_dlc_unlock(d); | 1183 | rfcomm_dlc_unlock(d); |
1194 | 1184 | ||
1195 | if (d->link_mode & RFCOMM_LM_MASTER) | 1185 | if (d->role_switch) |
1196 | hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00); | 1186 | hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00); |
1197 | 1187 | ||
1198 | rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); | 1188 | rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); |
@@ -1200,7 +1190,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) | |||
1200 | 1190 | ||
1201 | static void rfcomm_check_accept(struct rfcomm_dlc *d) | 1191 | static void rfcomm_check_accept(struct rfcomm_dlc *d) |
1202 | { | 1192 | { |
1203 | if (rfcomm_check_link_mode(d)) { | 1193 | if (rfcomm_check_security(d)) { |
1204 | if (d->defer_setup) { | 1194 | if (d->defer_setup) { |
1205 | set_bit(RFCOMM_DEFER_SETUP, &d->flags); | 1195 | set_bit(RFCOMM_DEFER_SETUP, &d->flags); |
1206 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); | 1196 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); |
@@ -1660,7 +1650,7 @@ static void rfcomm_process_connect(struct rfcomm_session *s) | |||
1660 | d = list_entry(p, struct rfcomm_dlc, list); | 1650 | d = list_entry(p, struct rfcomm_dlc, list); |
1661 | if (d->state == BT_CONFIG) { | 1651 | if (d->state == BT_CONFIG) { |
1662 | d->mtu = s->mtu; | 1652 | d->mtu = s->mtu; |
1663 | if (rfcomm_check_link_mode(d)) { | 1653 | if (rfcomm_check_security(d)) { |
1664 | rfcomm_send_pn(s, 1, d); | 1654 | rfcomm_send_pn(s, 1, d); |
1665 | } else { | 1655 | } else { |
1666 | set_bit(RFCOMM_AUTH_PENDING, &d->flags); | 1656 | set_bit(RFCOMM_AUTH_PENDING, &d->flags); |
@@ -1748,10 +1738,6 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) | |||
1748 | } else | 1738 | } else |
1749 | rfcomm_dlc_accept(d); | 1739 | rfcomm_dlc_accept(d); |
1750 | } | 1740 | } |
1751 | if (d->link_mode & RFCOMM_LM_SECURE) { | ||
1752 | struct sock *sk = s->sock->sk; | ||
1753 | hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon); | ||
1754 | } | ||
1755 | continue; | 1741 | continue; |
1756 | } else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) { | 1742 | } else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) { |
1757 | rfcomm_dlc_clear_timer(d); | 1743 | rfcomm_dlc_clear_timer(d); |
@@ -1994,7 +1980,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
1994 | d = list_entry(p, struct rfcomm_dlc, list); | 1980 | d = list_entry(p, struct rfcomm_dlc, list); |
1995 | 1981 | ||
1996 | if (!status && encrypt == 0x00 && | 1982 | if (!status && encrypt == 0x00 && |
1997 | (d->link_mode & RFCOMM_LM_ENCRYPT) && | 1983 | d->sec_level == BT_SECURITY_HIGH && |
1998 | (d->state == BT_CONNECTED || | 1984 | (d->state == BT_CONNECTED || |
1999 | d->state == BT_CONFIG)) { | 1985 | d->state == BT_CONFIG)) { |
2000 | __rfcomm_dlc_close(d, ECONNREFUSED); | 1986 | __rfcomm_dlc_close(d, ECONNREFUSED); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index d37a829a81e4..9986ef35c890 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -261,14 +261,19 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent) | |||
261 | 261 | ||
262 | if (parent) { | 262 | if (parent) { |
263 | sk->sk_type = parent->sk_type; | 263 | sk->sk_type = parent->sk_type; |
264 | pi->link_mode = rfcomm_pi(parent)->link_mode; | ||
265 | pi->dlc->defer_setup = bt_sk(parent)->defer_setup; | 264 | pi->dlc->defer_setup = bt_sk(parent)->defer_setup; |
265 | |||
266 | pi->sec_level = rfcomm_pi(parent)->sec_level; | ||
267 | pi->role_switch = rfcomm_pi(parent)->role_switch; | ||
266 | } else { | 268 | } else { |
267 | pi->link_mode = 0; | ||
268 | pi->dlc->defer_setup = 0; | 269 | pi->dlc->defer_setup = 0; |
270 | |||
271 | pi->sec_level = BT_SECURITY_LOW; | ||
272 | pi->role_switch = 0; | ||
269 | } | 273 | } |
270 | 274 | ||
271 | pi->dlc->link_mode = pi->link_mode; | 275 | pi->dlc->sec_level = pi->sec_level; |
276 | pi->dlc->role_switch = pi->role_switch; | ||
272 | } | 277 | } |
273 | 278 | ||
274 | static struct proto rfcomm_proto = { | 279 | static struct proto rfcomm_proto = { |
@@ -408,7 +413,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a | |||
408 | bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); | 413 | bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); |
409 | rfcomm_pi(sk)->channel = sa->rc_channel; | 414 | rfcomm_pi(sk)->channel = sa->rc_channel; |
410 | 415 | ||
411 | d->link_mode = rfcomm_pi(sk)->link_mode; | 416 | d->sec_level = rfcomm_pi(sk)->sec_level; |
417 | d->role_switch = rfcomm_pi(sk)->role_switch; | ||
412 | 418 | ||
413 | err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel); | 419 | err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel); |
414 | if (!err) | 420 | if (!err) |
@@ -741,7 +747,14 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u | |||
741 | break; | 747 | break; |
742 | } | 748 | } |
743 | 749 | ||
744 | rfcomm_pi(sk)->link_mode = opt; | 750 | if (opt & RFCOMM_LM_AUTH) |
751 | rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW; | ||
752 | if (opt & RFCOMM_LM_ENCRYPT) | ||
753 | rfcomm_pi(sk)->sec_level = BT_SECURITY_MEDIUM; | ||
754 | if (opt & RFCOMM_LM_SECURE) | ||
755 | rfcomm_pi(sk)->sec_level = BT_SECURITY_HIGH; | ||
756 | |||
757 | rfcomm_pi(sk)->role_switch = (opt & RFCOMM_LM_MASTER); | ||
745 | break; | 758 | break; |
746 | 759 | ||
747 | default: | 760 | default: |
@@ -756,7 +769,8 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u | |||
756 | static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) | 769 | static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) |
757 | { | 770 | { |
758 | struct sock *sk = sock->sk; | 771 | struct sock *sk = sock->sk; |
759 | int err = 0; | 772 | struct bt_security sec; |
773 | int len, err = 0; | ||
760 | u32 opt; | 774 | u32 opt; |
761 | 775 | ||
762 | BT_DBG("sk %p", sk); | 776 | BT_DBG("sk %p", sk); |
@@ -767,6 +781,23 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c | |||
767 | lock_sock(sk); | 781 | lock_sock(sk); |
768 | 782 | ||
769 | switch (optname) { | 783 | switch (optname) { |
784 | case BT_SECURITY: | ||
785 | sec.level = BT_SECURITY_LOW; | ||
786 | |||
787 | len = min_t(unsigned int, sizeof(sec), optlen); | ||
788 | if (copy_from_user((char *) &sec, optval, len)) { | ||
789 | err = -EFAULT; | ||
790 | break; | ||
791 | } | ||
792 | |||
793 | if (sec.level > BT_SECURITY_HIGH) { | ||
794 | err = -EINVAL; | ||
795 | break; | ||
796 | } | ||
797 | |||
798 | rfcomm_pi(sk)->sec_level = sec.level; | ||
799 | break; | ||
800 | |||
770 | case BT_DEFER_SETUP: | 801 | case BT_DEFER_SETUP: |
771 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { | 802 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { |
772 | err = -EINVAL; | 803 | err = -EINVAL; |
@@ -796,6 +827,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u | |||
796 | struct sock *l2cap_sk; | 827 | struct sock *l2cap_sk; |
797 | struct rfcomm_conninfo cinfo; | 828 | struct rfcomm_conninfo cinfo; |
798 | int len, err = 0; | 829 | int len, err = 0; |
830 | u32 opt; | ||
799 | 831 | ||
800 | BT_DBG("sk %p", sk); | 832 | BT_DBG("sk %p", sk); |
801 | 833 | ||
@@ -806,7 +838,26 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u | |||
806 | 838 | ||
807 | switch (optname) { | 839 | switch (optname) { |
808 | case RFCOMM_LM: | 840 | case RFCOMM_LM: |
809 | if (put_user(rfcomm_pi(sk)->link_mode, (u32 __user *) optval)) | 841 | switch (rfcomm_pi(sk)->sec_level) { |
842 | case BT_SECURITY_LOW: | ||
843 | opt = RFCOMM_LM_AUTH; | ||
844 | break; | ||
845 | case BT_SECURITY_MEDIUM: | ||
846 | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; | ||
847 | break; | ||
848 | case BT_SECURITY_HIGH: | ||
849 | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | | ||
850 | RFCOMM_LM_SECURE; | ||
851 | break; | ||
852 | default: | ||
853 | opt = 0; | ||
854 | break; | ||
855 | } | ||
856 | |||
857 | if (rfcomm_pi(sk)->role_switch) | ||
858 | opt |= RFCOMM_LM_MASTER; | ||
859 | |||
860 | if (put_user(opt, (u32 __user *) optval)) | ||
810 | err = -EFAULT; | 861 | err = -EFAULT; |
811 | break; | 862 | break; |
812 | 863 | ||
@@ -840,6 +891,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u | |||
840 | static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | 891 | static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) |
841 | { | 892 | { |
842 | struct sock *sk = sock->sk; | 893 | struct sock *sk = sock->sk; |
894 | struct bt_security sec; | ||
843 | int len, err = 0; | 895 | int len, err = 0; |
844 | 896 | ||
845 | BT_DBG("sk %p", sk); | 897 | BT_DBG("sk %p", sk); |
@@ -853,6 +905,15 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c | |||
853 | lock_sock(sk); | 905 | lock_sock(sk); |
854 | 906 | ||
855 | switch (optname) { | 907 | switch (optname) { |
908 | case BT_SECURITY: | ||
909 | sec.level = rfcomm_pi(sk)->sec_level; | ||
910 | |||
911 | len = min_t(unsigned int, len, sizeof(sec)); | ||
912 | if (copy_to_user(optval, (char *) &sec, len)) | ||
913 | err = -EFAULT; | ||
914 | |||
915 | break; | ||
916 | |||
856 | case BT_DEFER_SETUP: | 917 | case BT_DEFER_SETUP: |
857 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { | 918 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { |
858 | err = -EINVAL; | 919 | err = -EINVAL; |