diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-31 20:00:23 -0500 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-31 20:00:23 -0500 |
commit | 6b1088234bca2643a993dd8b9b809e8a763c03bb (patch) | |
tree | e86c558ccc82a923a77f8eccf23794e2e69b130c /components/script | |
parent | d53507f747f7122dc520f5e4a374ee1ad955aa5d (diff) | |
parent | a920e6d54e4e75e06ac8ac5029f9aa69fdf31ae8 (diff) | |
download | servo-6b1088234bca2643a993dd8b9b809e8a763c03bb.tar.gz servo-6b1088234bca2643a993dd8b9b809e8a763c03bb.zip |
Auto merge of #11335 - szeged:blacklist, r=jdm
Add WebBluetooth GATTBlacklist support
Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data:
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy --faster` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
Either:
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because there are no webbluetooth tests yet.
Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11335)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-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; |