diff options
| author | plunky <plunky@NetBSD.org> | 2007-04-21 06:15:22 +0000 |
|---|---|---|
| committer | plunky <plunky@NetBSD.org> | 2007-04-21 06:15:22 +0000 |
| commit | f5db72e7b75e66bff8fd02536e16c714f586d6a3 (patch) | |
| tree | da2c5f808b067b36ddaac23b9d44090f993f0673 /sys/dev | |
| parent | c4ec0fc4f86bef89641b9da211a0db43ed55abbf (diff) | |
Add 'service level' security for L2CAP and RFCOMM connections, following
the Linux (BlueZ) API.
- L2CAP or RFCOMM connections can require the baseband radio link
mode be any of:
authenticated (devices are paired)
encrypted (implies authentication)
secured (encryption, plus generate new link key)
- for sockets, the mode is set using setsockopt(2) and the socket
connection will be aborted if the mode change fails.
- mode settings will be applied during connection establishment, and
for safety, we enter a wait state and will only proceed when the mode
settings are successfuly set.
- It is possible to change the mode on already open connections, but
not possible to guarantee that data already queued (from either end)
will not be delivered. (this is a feature, not a bug)
- bthidev(4) and rfcomm_sppd(1) support "auth", "encrypt" and
"secure" options
- btdevctl(8) by default enables "auth" for HIDs, and "encrypt" for
keyboards (which are required to support it)
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/bluetooth/btdev.h | 6 | ||||
| -rw-r--r-- | sys/dev/bluetooth/bthidev.c | 62 | ||||
| -rw-r--r-- | sys/dev/bluetooth/btsco.c | 14 |
3 files changed, 77 insertions, 5 deletions
diff --git a/sys/dev/bluetooth/btdev.h b/sys/dev/bluetooth/btdev.h index c0b6bdac4f4..bd9e0551db2 100644 --- a/sys/dev/bluetooth/btdev.h +++ b/sys/dev/bluetooth/btdev.h @@ -1,4 +1,4 @@ -/* $NetBSD: btdev.h,v 1.5 2006/10/04 19:23:59 plunky Exp $ */ +/* $NetBSD: btdev.h,v 1.6 2007/04/21 06:15:22 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -43,6 +43,10 @@ #define BTDEVladdr "local-bdaddr" #define BTDEVraddr "remote-bdaddr" #define BTDEVservice "service-name" +#define BTDEVmode "link-mode" +#define BTDEVauth "auth" +#define BTDEVencrypt "encrypt" +#define BTDEVsecure "secure" #ifdef _KERNEL struct btdev { diff --git a/sys/dev/bluetooth/bthidev.c b/sys/dev/bluetooth/bthidev.c index 2d1f6358026..85fdef68e68 100644 --- a/sys/dev/bluetooth/bthidev.c +++ b/sys/dev/bluetooth/bthidev.c @@ -1,4 +1,4 @@ -/* $NetBSD: bthidev.c,v 1.7 2006/11/16 01:32:48 christos Exp $ */ +/* $NetBSD: bthidev.c,v 1.8 2007/04/21 06:15:22 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.7 2006/11/16 01:32:48 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.8 2007/04/21 06:15:22 plunky Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -72,6 +72,7 @@ struct bthidev_softc { bdaddr_t sc_laddr; /* local address */ bdaddr_t sc_raddr; /* remote address */ + int sc_mode; /* link mode */ uint16_t sc_ctlpsm; /* control PSM */ struct l2cap_channel *sc_ctl; /* control channel */ @@ -125,6 +126,7 @@ static void bthidev_int_disconnected(void *, int); static void *bthidev_ctl_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void *bthidev_int_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void bthidev_complete(void *, int); +static void bthidev_linkmode(void *, int); static void bthidev_input(void *, struct mbuf *); static const struct btproto bthidev_ctl_proto = { @@ -133,6 +135,7 @@ static const struct btproto bthidev_ctl_proto = { bthidev_ctl_disconnected, bthidev_ctl_newconn, bthidev_complete, + bthidev_linkmode, bthidev_input, }; @@ -142,6 +145,7 @@ static const struct btproto bthidev_int_proto = { bthidev_int_disconnected, bthidev_int_newconn, bthidev_complete, + bthidev_linkmode, bthidev_input, }; @@ -198,6 +202,23 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) obj = prop_dictionary_get(dict, BTDEVraddr); bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); + obj = prop_dictionary_get(dict, BTDEVmode); + if (prop_object_type(obj) == PROP_TYPE_STRING) { + if (prop_string_equals_cstring(obj, BTDEVauth)) + sc->sc_mode = L2CAP_LM_AUTH; + else if (prop_string_equals_cstring(obj, BTDEVencrypt)) + sc->sc_mode = L2CAP_LM_ENCRYPT; + else if (prop_string_equals_cstring(obj, BTDEVsecure)) + sc->sc_mode = L2CAP_LM_SECURE; + else { + aprint_error(" unknown %s\n", BTDEVmode); + return; + } + + aprint_verbose(" %s %s", BTDEVmode, + prop_string_cstring_nocopy(obj)); + } + obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm); if (prop_object_type(obj) == PROP_TYPE_NUMBER) { sc->sc_ctlpsm = prop_number_integer_value(obj); @@ -435,6 +456,10 @@ bthidev_listen(struct bthidev_softc *sc) if (err) return err; + err = l2cap_setopt(sc->sc_ctl_l, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + sa.bt_psm = sc->sc_ctlpsm; err = l2cap_bind(sc->sc_ctl_l, &sa); if (err) @@ -451,6 +476,10 @@ bthidev_listen(struct bthidev_softc *sc) if (err) return err; + err = l2cap_setopt(sc->sc_int_l, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + sa.bt_psm = sc->sc_intpsm; err = l2cap_bind(sc->sc_int_l, &sa); if (err) @@ -488,6 +517,10 @@ bthidev_connect(struct bthidev_softc *sc) return err; } + err = l2cap_setopt(sc->sc_ctl, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); err = l2cap_bind(sc->sc_ctl, &sa); if (err) { @@ -543,6 +576,10 @@ bthidev_ctl_connected(void *arg) if (err) goto fail; + err = l2cap_setopt(sc->sc_int, SO_L2CAP_LM, &sc->sc_mode); + if (err) + goto fail; + memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; @@ -707,6 +744,27 @@ bthidev_complete(void *arg, int count) /* dont care */ } +static void +bthidev_linkmode(void *arg, int new) +{ + struct bthidev_softc *sc = arg; + + if ((sc->sc_mode & L2CAP_LM_AUTH) && !(new & L2CAP_LM_AUTH)) + printf("%s: auth failed\n", device_xname((struct device *)sc)); + else if ((sc->sc_mode & L2CAP_LM_ENCRYPT) && !(new & L2CAP_LM_ENCRYPT)) + printf("%s: encrypt off\n", device_xname((struct device *)sc)); + else if ((sc->sc_mode & L2CAP_LM_SECURE) && !(new & L2CAP_LM_SECURE)) + printf("%s: insecure\n", device_xname((struct device *)sc)); + else + return; + + if (sc->sc_int != NULL) + l2cap_disconnect(sc->sc_int, 0); + + if (sc->sc_ctl != NULL) + l2cap_disconnect(sc->sc_ctl, 0); +} + /* * Receive reports from the protocol stack. */ diff --git a/sys/dev/bluetooth/btsco.c b/sys/dev/bluetooth/btsco.c index d82173197c2..95d63cfee0f 100644 --- a/sys/dev/bluetooth/btsco.c +++ b/sys/dev/bluetooth/btsco.c @@ -1,4 +1,4 @@ -/* $NetBSD: btsco.c,v 1.13 2007/03/13 19:26:06 plunky Exp $ */ +/* $NetBSD: btsco.c,v 1.14 2007/04/21 06:15:22 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.13 2007/03/13 19:26:06 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.14 2007/04/21 06:15:22 plunky Exp $"); #include <sys/param.h> #include <sys/audioio.h> @@ -215,6 +215,7 @@ static void btsco_sco_connected(void *); static void btsco_sco_disconnected(void *, int); static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void btsco_sco_complete(void *, int); +static void btsco_sco_linkmode(void *, int); static void btsco_sco_input(void *, struct mbuf *); static const struct btproto btsco_sco_proto = { @@ -223,6 +224,7 @@ static const struct btproto btsco_sco_proto = { btsco_sco_disconnected, btsco_sco_newconn, btsco_sco_complete, + btsco_sco_linkmode, btsco_sco_input, }; @@ -502,6 +504,14 @@ btsco_sco_complete(void *arg, int count) } static void +btsco_sco_linkmode(void *arg, int new) +{ +/* struct btsco_softc *sc = arg; */ + + /* dont care */ +} + +static void btsco_sco_input(void *arg, struct mbuf *m) { struct btsco_softc *sc = arg; |
