diff options
author | fokinv <fokinv@inf.u-szeged.hu> | 2016-05-20 13:19:58 +0200 |
---|---|---|
committer | Attila Dusnoki <dati91@gmail.com> | 2016-05-31 17:05:45 +0200 |
commit | a920e6d54e4e75e06ac8ac5029f9aa69fdf31ae8 (patch) | |
tree | 473b5d5892ace996d2afccdcbc7fbfe61f7ef13a /components | |
parent | b11648903bb07a31ec93f3030058ed41b3472b17 (diff) | |
download | servo-a920e6d54e4e75e06ac8ac5029f9aa69fdf31ae8.tar.gz servo-a920e6d54e4e75e06ac8ac5029f9aa69fdf31ae8.zip |
Add WebBluetooth Blacklist support
Diffstat (limited to 'components')
-rw-r--r-- | components/script/bluetooth_blacklist.rs | 124 | ||||
-rw-r--r-- | components/script/dom/bluetooth.rs | 15 | ||||
-rw-r--r-- | components/script/dom/bluetoothremotegattcharacteristic.rs | 19 | ||||
-rw-r--r-- | components/script/dom/bluetoothremotegattdescriptor.rs | 9 | ||||
-rw-r--r-- | components/script/dom/bluetoothremotegattserver.rs | 13 | ||||
-rw-r--r-- | components/script/dom/bluetoothremotegattservice.rs | 13 | ||||
-rw-r--r-- | components/script/lib.rs | 1 |
7 files changed, 184 insertions, 10 deletions
diff --git a/components/script/bluetooth_blacklist.rs b/components/script/bluetooth_blacklist.rs new file mode 100644 index 00000000000..f9d1c564692 --- /dev/null +++ b/components/script/bluetooth_blacklist.rs @@ -0,0 +1,124 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use regex::Regex; +use std::cell::RefCell; +use std::collections::HashMap; +use std::io::BufRead; +use std::string::String; +use util::resource_files::read_resource_file; + +const BLACKLIST_FILE: &'static str = "gatt_blacklist.txt"; +const BLACKLIST_FILE_NOT_FOUND: &'static str = "Could not find gatt_blacklist.txt file"; +const EXCLUDE_READS: &'static str = "exclude-reads"; +const EXCLUDE_WRITES: &'static str = "exclude-writes"; +const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + +thread_local!(pub static BLUETOOTH_BLACKLIST: RefCell<BluetoothBlacklist> = + RefCell::new(BluetoothBlacklist(parse_blacklist()))); + +pub fn uuid_is_blacklisted(uuid: &str, exclude_type: Blacklist) -> bool { + BLUETOOTH_BLACKLIST.with(|blist| { + match exclude_type { + Blacklist::All => { + blist.borrow().is_blacklisted(uuid) + }, + Blacklist::Reads => { + blist.borrow().is_blacklisted_for_reads(uuid) + } + Blacklist::Writes => { + blist.borrow().is_blacklisted_for_writes(uuid) + } + } + }) +} + +pub struct BluetoothBlacklist(Option<HashMap<String, Blacklist>>); + +#[derive(Eq, PartialEq)] +pub enum Blacklist { + All, // Read and Write + Reads, + Writes, +} + +impl BluetoothBlacklist { + // https://webbluetoothcg.github.io/web-bluetooth/#blacklisted + pub fn is_blacklisted(&self, uuid: &str) -> bool { + match self.0 { + Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All)), + None => false, + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#blacklisted-for-reads + pub fn is_blacklisted_for_reads(&self, uuid: &str) -> bool { + match self.0 { + Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All) || + et.eq(&Blacklist::Reads)), + None => false, + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#blacklisted-for-writes + pub fn is_blacklisted_for_writes(&self, uuid: &str) -> bool { + match self.0 { + Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All) || + et.eq(&Blacklist::Writes)), + None => false, + } + } +} + +// https://webbluetoothcg.github.io/web-bluetooth/#parsing-the-blacklist +fn parse_blacklist() -> Option<HashMap<String, Blacklist>> { + // Step 1 missing, currently we parse ./resources/gatt_blacklist.txt. + let valid_uuid_regex = Regex::new(VALID_UUID_REGEX).unwrap(); + let content = read_resource_file(BLACKLIST_FILE).expect(BLACKLIST_FILE_NOT_FOUND); + // Step 3 + let mut result = HashMap::new(); + // Step 2 and 4 + for line in content.lines() { + let line = match line { + Ok(l) => l, + Err(_) => return None, + }; + // Step 4.1 + if line.is_empty() || line.starts_with('#') { + continue; + } + let mut exclude_type = Blacklist::All; + let mut words = line.split_whitespace(); + let uuid = match words.next() { + Some(uuid) => uuid, + None => continue, + }; + if !valid_uuid_regex.is_match(uuid) { + return None; + } + match words.next() { + // Step 4.2 We already have an initialized exclude_type variable with Blacklist::All. + None => {}, + // Step 4.3 + Some(EXCLUDE_READS) => { + exclude_type = Blacklist::Reads; + }, + Some(EXCLUDE_WRITES) => { + exclude_type = Blacklist::Writes; + }, + // Step 4.4 + _ => { + return None; + }, + } + // Step 4.5 + if result.contains_key(uuid) { + return None; + } + // Step 4.6 + result.insert(uuid.to_string(), exclude_type); + } + // Step 5 + return Some(result); +} diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 9617dad4485..e00fb33cf59 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -2,11 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use core::clone::Clone; use dom::bindings::codegen::Bindings::BluetoothBinding; use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions; use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothScanFilter, BluetoothMethods}; -use dom::bindings::error::Error::Type; +use dom::bindings::error::Error::{Security, Type}; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; @@ -71,7 +72,11 @@ fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Falli return Err(Type(SERVICE_ERROR.to_owned())); } for service in services { - services_vec.push(try!(BluetoothUUID::GetService(global, service.clone())).to_string()); + let uuid = try!(BluetoothUUID::GetService(global, service.clone())).to_string(); + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + services_vec.push(uuid); } } @@ -119,7 +124,11 @@ fn convert_request_device_options(options: &RequestDeviceOptions, let mut optional_services = vec!(); if let Some(ref opt_services) = options.optionalServices { for opt_service in opt_services { - optional_services.push(try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string()); + let uuid = try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string(); + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + optional_services.push(uuid); } } diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index cb1585b559f..2b3443f8a40 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding; @@ -9,7 +10,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding:: BluetoothRemoteGATTCharacteristicMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; -use dom::bindings::error::Error::{Network, Type}; +use dom::bindings::error::Error::{Network, Security, Type}; use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -93,6 +94,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Fallible<Root<BluetoothRemoteGATTDescriptor>> { let uuid = try!(BluetoothUUID::GetDescriptor(self.global().r(), descriptor)).to_string(); + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap(); @@ -116,7 +120,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris -> Fallible<Vec<Root<BluetoothRemoteGATTDescriptor>>> { let mut uuid: Option<String> = None; if let Some(d) = descriptor { - uuid = Some(try!(BluetoothUUID::GetDescriptor(self.global().r(), d)).to_string()) + uuid = Some(try!(BluetoothUUID::GetDescriptor(self.global().r(), d)).to_string()); + if let Some(ref uuid) = uuid { + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + } }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( @@ -144,6 +153,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue fn ReadValue(&self) -> Fallible<ByteString> { + if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); if !self.Service().Device().Gatt().Connected() { return Err(Network) @@ -165,6 +177,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue fn WriteValue(&self, value: Vec<u8>) -> ErrorResult { + if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index 03de0a52dd6..d2c1de65cb3 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding:: @@ -10,7 +11,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; -use dom::bindings::error::Error::{Type, Network}; +use dom::bindings::error::Error::{Network, Security, Type}; use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -85,6 +86,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue fn ReadValue(&self) -> Fallible<ByteString> { + if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); if !self.Characteristic().Service().Device().Gatt().Connected() { return Err(Network) @@ -106,6 +110,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue fn WriteValue(&self, value: Vec<u8>) -> ErrorResult { + if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 4813aa77183..56aad1b8bf6 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -2,10 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; -use dom::bindings::error::Error::Type; +use dom::bindings::error::Error::{Security, Type}; use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -96,6 +97,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Fallible<Root<BluetoothRemoteGATTService>> { let uuid = try!(BluetoothUUID::GetService(self.global().r(), service)).to_string(); + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap(); @@ -120,7 +124,12 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> { let mut uuid: Option<String> = None; if let Some(s) = service { - uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string()) + uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string()); + if let Some(ref uuid) = uuid { + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + } }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index 78427f7f6de..48cf9be6361 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -2,9 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use bluetooth_blacklist::{Blacklist, uuid_is_blacklisted}; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; -use dom::bindings::error::Error::Type; +use dom::bindings::error::Error::{Security, Type}; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -88,6 +89,9 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { characteristic: BluetoothCharacteristicUUID) -> Fallible<Root<BluetoothRemoteGATTCharacteristic>> { let uuid = try!(BluetoothUUID::GetCharacteristic(self.global().r(), characteristic)).to_string(); + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); @@ -122,7 +126,12 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { -> Fallible<Vec<Root<BluetoothRemoteGATTCharacteristic>>> { let mut uuid: Option<String> = None; if let Some(c) = characteristic { - uuid = Some(try!(BluetoothUUID::GetCharacteristic(self.global().r(), c)).to_string()) + uuid = Some(try!(BluetoothUUID::GetCharacteristic(self.global().r(), c)).to_string()); + if let Some(ref uuid) = uuid { + if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) { + return Err(Security) + } + } }; let mut characteristics = vec!(); let (sender, receiver) = ipc::channel().unwrap(); diff --git a/components/script/lib.rs b/components/script/lib.rs index af6d3b2a9c0..6e978eb01c1 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -87,6 +87,7 @@ extern crate webrender_traits; extern crate websocket; extern crate xml5ever; +pub mod bluetooth_blacklist; pub mod clipboard_provider; pub mod cors; mod devtools; |