Skip to content

Commit

Permalink
Added some same-origin-domain checks.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Jeffrey committed Mar 14, 2017
1 parent 628cd7d commit 1f61a54
Show file tree
Hide file tree
Showing 45 changed files with 223 additions and 348 deletions.
10 changes: 5 additions & 5 deletions components/constellation/constellation.rs
Expand Up @@ -108,7 +108,7 @@ use servo_config::opts;
use servo_config::prefs::PREFS;
use servo_rand::{Rng, SeedableRng, ServoRng, random};
use servo_remutex::ReentrantMutex;
use servo_url::ServoUrl;
use servo_url::{Host, ServoUrl};
use std::borrow::ToOwned;
use std::collections::{HashMap, VecDeque};
use std::iter::once;
Expand Down Expand Up @@ -229,13 +229,13 @@ pub struct Constellation<Message, LTF, STF> {
/// event loop for each registered domain name (aka eTLD+1) in
/// each top-level frame. We store the event loops in a map
/// indexed by top-level frame id (as a `FrameId`) and registered
/// domain name (as a `String`) to event loops. This double
/// domain name (as a `Host`) to event loops. This double
/// indirection ensures that separate tabs do not share event
/// loops, even if the same domain is loaded in each.
/// It is important that scripts with the same eTLD+1
/// share an event loop, since they can use `document.domain`
/// to become same-origin, at which point they can share DOM objects.
event_loops: HashMap<FrameId, HashMap<String, Weak<EventLoop>>>,
event_loops: HashMap<FrameId, HashMap<Host, Weak<EventLoop>>>,

/// The set of all the pipelines in the browser.
/// (See the `pipeline` module for more details.)
Expand Down Expand Up @@ -606,10 +606,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => (None, None),
Some(host) => {
let event_loop = self.event_loops.get(&top_level_frame_id)
.and_then(|map| map.get(host))
.and_then(|map| map.get(&host))
.and_then(|weak| weak.upgrade());
match event_loop {
None => (None, Some(String::from(host))),
None => (None, Some(host)),
Some(event_loop) => (Some(event_loop.clone()), None),
}
},
Expand Down
11 changes: 8 additions & 3 deletions components/net_traits/pub_domains.rs
Expand Up @@ -15,7 +15,7 @@
//! those cases are not present.

use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl;
use servo_url::{Host, ImmutableOrigin, ServoUrl};
use std::collections::HashSet;
use std::iter::FromIterator;
use std::str::from_utf8;
Expand Down Expand Up @@ -146,6 +146,11 @@ pub fn is_reg_domain(domain: &str) -> bool {
/// Returns None if the URL has no host name.
/// Returns the registered suffix for the host name if it is a domain.
/// Leaves the host name alone if it is an IP address.
pub fn reg_host<'a>(url: &'a ServoUrl) -> Option<&'a str> {
url.domain().map(reg_suffix).or(url.host_str())
pub fn reg_host<'a>(url: &'a ServoUrl) -> Option<Host> {
match url.origin() {
ImmutableOrigin::Tuple(_, Host::Domain(domain), _) => Some(Host::Domain(String::from(reg_suffix(&*domain)))),
ImmutableOrigin::Tuple(_, Host::Ipv4(address), _) => Some(Host::Ipv4(address)),
ImmutableOrigin::Tuple(_, Host::Ipv6(address), _) => Some(Host::Ipv6(address)),
ImmutableOrigin::Opaque(_) => None,
}
}
3 changes: 1 addition & 2 deletions components/script/devtools.rs
Expand Up @@ -10,7 +10,6 @@ use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclar
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, jsstring_to_str};
use dom::bindings::inheritance::Castable;
Expand Down Expand Up @@ -261,6 +260,6 @@ pub fn handle_request_animation_frame(documents: &Documents,
pub fn handle_reload(documents: &Documents,
id: PipelineId) {
if let Some(win) = documents.find_window(id) {
win.Location().Reload();
win.Location().reload_without_origin_check();
}
}
5 changes: 4 additions & 1 deletion components/script/dom/document.rs
Expand Up @@ -3396,7 +3396,10 @@ impl DocumentMethods for Document {

let entry_responsible_document = GlobalScope::entry().as_window().Document();

if !self.origin.same_origin(&entry_responsible_document.origin) {
// This check should probably be same-origin-domain
// https://github.com/whatwg/html/issues/2282
// https://github.com/whatwg/html/pull/2288
if !self.origin.same_origin_domain(&entry_responsible_document.origin) {
// Step 4.
return Err(Error::Security);
}
Expand Down
3 changes: 1 addition & 2 deletions components/script/dom/history.rs
Expand Up @@ -4,7 +4,6 @@

use dom::bindings::codegen::Bindings::HistoryBinding;
use dom::bindings::codegen::Bindings::HistoryBinding::HistoryMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
Expand Down Expand Up @@ -65,7 +64,7 @@ impl HistoryMethods for History {
} else if delta < 0 {
TraversalDirection::Back(-delta as usize)
} else {
self.window.Location().Reload();
self.window.Location().reload_without_origin_check();
return;
};

Expand Down
40 changes: 22 additions & 18 deletions components/script/dom/htmliframeelement.rs
Expand Up @@ -327,20 +327,6 @@ impl HTMLIFrameElement {
false
}
}

pub fn get_content_window(&self) -> Option<Root<Window>> {
self.pipeline_id.get()
.and_then(|pipeline_id| ScriptThread::find_document(pipeline_id))
.and_then(|document| {
let current_global = GlobalScope::current();
let current_document = current_global.as_window().Document();
if document.origin().same_origin(current_document.origin()) {
Some(Root::from_ref(document.window()))
} else {
None
}
})
}
}

pub trait HTMLIFrameElementLayoutMethods {
Expand Down Expand Up @@ -512,15 +498,33 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {

// https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow
fn GetContentWindow(&self) -> Option<Root<BrowsingContext>> {
match self.get_content_window() {
Some(ref window) => Some(window.browsing_context()),
None => None
if self.pipeline_id.get().is_some() {
ScriptThread::find_browsing_context(self.frame_id)
} else {
None
}
}

// https://html.spec.whatwg.org/multipage/#dom-iframe-contentdocument
// https://html.spec.whatwg.org/multipage/#concept-bcc-content-document
fn GetContentDocument(&self) -> Option<Root<Document>> {
self.get_content_window().map(|window| window.Document())
// Step 1.
let pipeline_id = match self.pipeline_id.get() {
None => return None,
Some(pipeline_id) => pipeline_id,
};
// Step 2-3.
let document = match ScriptThread::find_document(pipeline_id) {
None => return None,
Some(document) => document,
};
// Step 4.
let current = GlobalScope::current().as_window().Document();
if !current.origin().same_origin_domain(document.origin()) {
return None;
}
// Step 5.
Some(document)
}

// Experimental mozbrowser implementation is based on the webidl
Expand Down
114 changes: 81 additions & 33 deletions components/script/dom/location.rs
Expand Up @@ -4,10 +4,12 @@

use dom::bindings::codegen::Bindings::LocationBinding;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
use dom::globalscope::GlobalScope;
use dom::urlhelper::UrlHelper;
use dom::window::Window;
use dom_struct::dom_struct;
Expand Down Expand Up @@ -43,11 +45,27 @@ impl Location {
setter(&mut url, value);
self.window.load_url(url, false, false, None);
}

fn check_same_origin_domain(&self) -> ErrorResult {
let entry_document = GlobalScope::entry().as_window().Document();
let this_document = self.window.Document();
if entry_document.origin().same_origin_domain(this_document.origin()) {
Ok(())
} else {
Err(Error::Security)
}
}

// https://html.spec.whatwg.org/multipage/#dom-location-reload
pub fn reload_without_origin_check(&self) {
self.window.load_url(self.get_url(), true, true, None);
}
}

impl LocationMethods for Location {
// https://html.spec.whatwg.org/multipage/#dom-location-assign
fn Assign(&self, url: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain()
// TODO: per spec, we should use the _API base URL_ specified by the
// _entry settings object_.
let base_url = self.window.get_url();
Expand All @@ -60,12 +78,15 @@ impl LocationMethods for Location {
}

// https://html.spec.whatwg.org/multipage/#dom-location-reload
fn Reload(&self) {
fn Reload(&self) -> ErrorResult {
try!(self.check_same_origin_domain());
self.window.load_url(self.get_url(), true, true, None);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-replace
fn Replace(&self, url: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain()
// TODO: per spec, we should use the _API base URL_ specified by the
// _entry settings object_.
let base_url = self.window.get_url();
Expand All @@ -78,97 +99,124 @@ impl LocationMethods for Location {
}

// https://html.spec.whatwg.org/multipage/#dom-location-hash
fn Hash(&self) -> USVString {
UrlHelper::Hash(&self.get_url())
fn GetHash(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Hash(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-hash
fn SetHash(&self, mut value: USVString) {
fn SetHash(&self, mut value: USVString) -> ErrorResult {
if value.0.is_empty() {
value = USVString("#".to_owned());
}
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHash);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-host
fn Host(&self) -> USVString {
UrlHelper::Host(&self.get_url())
fn GetHost(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Host(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-host
fn SetHost(&self, value: USVString) {
fn SetHost(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHost);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-origin
fn Origin(&self) -> USVString {
UrlHelper::Origin(&self.get_url())
fn GetOrigin(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Origin(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-hostname
fn Hostname(&self) -> USVString {
UrlHelper::Hostname(&self.get_url())
fn GetHostname(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Hostname(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-hostname
fn SetHostname(&self, value: USVString) {
fn SetHostname(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHostname);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-href
fn Href(&self) -> USVString {
UrlHelper::Href(&self.get_url())
fn GetHref(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Href(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-href
fn SetHref(&self, value: USVString) {
if let Ok(url) = self.window.get_url().join(&value.0) {
self.window.load_url(url, false, false, None);
}
fn SetHref(&self, value: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain()
let url = match self.window.get_url().join(&value.0) {
Ok(url) => url,
Err(e) => return Err(Error::Type(format!("Couldn't parse URL: {}", e))),
};
self.window.load_url(url, false, false, None);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-pathname
fn Pathname(&self) -> USVString {
UrlHelper::Pathname(&self.get_url())
fn GetPathname(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Pathname(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-pathname
fn SetPathname(&self, value: USVString) {
fn SetPathname(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetPathname);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-port
fn Port(&self) -> USVString {
UrlHelper::Port(&self.get_url())
fn GetPort(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Port(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-port
fn SetPort(&self, value: USVString) {
fn SetPort(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetPort);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-protocol
fn Protocol(&self) -> USVString {
UrlHelper::Protocol(&self.get_url())
fn GetProtocol(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Protocol(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-protocol
fn SetProtocol(&self, value: USVString) {
fn SetProtocol(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetProtocol);
Ok(())
}

// https://html.spec.whatwg.org/multipage/#dom-location-href
fn Stringifier(&self) -> DOMString {
DOMString::from(self.Href().0)
fn Stringifier(&self) -> Fallible<DOMString> {
Ok(DOMString::from(try!(self.GetHref()).0))
}

// https://html.spec.whatwg.org/multipage/#dom-location-search
fn Search(&self) -> USVString {
UrlHelper::Search(&self.get_url())
fn GetSearch(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Search(&self.get_url()))
}

// https://html.spec.whatwg.org/multipage/#dom-location-search
fn SetSearch(&self, value: USVString) {
fn SetSearch(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetSearch);
Ok(())
}
}

0 comments on commit 1f61a54

Please sign in to comment.