Implement cross origin resource policy check

I removed the window getter usage from those tests as servo does not
support that yet.
This commit is contained in:
Bastien Orivel 2020-05-07 21:27:56 +02:00
parent 6aec2c8594
commit 8249be38c9
14 changed files with 98 additions and 133 deletions

View file

@ -113,7 +113,7 @@ impl<'a> LayoutContext<'a> {
} }
match self.get_or_request_image_or_meta(node, url.clone(), use_placeholder) { match self.get_or_request_image_or_meta(node, url.clone(), use_placeholder) {
Some(ImageOrMetadataAvailable::ImageAvailable(image, _)) => { Some(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => {
let image_info = WebRenderImageInfo { let image_info = WebRenderImageInfo {
width: image.width, width: image.width,
height: image.height, height: image.height,

View file

@ -125,7 +125,7 @@ impl ReplacedContent {
image_url.clone(), image_url.clone(),
UsePlaceholder::No, UsePlaceholder::No,
) { ) {
Some(ImageOrMetadataAvailable::ImageAvailable(image, _)) => { Some(ImageOrMetadataAvailable::ImageAvailable { image, .. }) => {
(Some(image.clone()), image.width as f32, image.height as f32) (Some(image.clone()), image.width as f32, image.height as f32)
}, },
Some(ImageOrMetadataAvailable::MetadataAvailable(metadata)) => { Some(ImageOrMetadataAvailable::MetadataAvailable(metadata)) => {

View file

@ -33,6 +33,7 @@ use http::{HeaderMap, Request as HyperRequest};
use hyper::{Body, Client, Method, Response as HyperResponse, StatusCode}; use hyper::{Body, Client, Method, Response as HyperResponse, StatusCode};
use hyper_serde::Serde; use hyper_serde::Serde;
use msg::constellation_msg::{HistoryStateId, PipelineId}; use msg::constellation_msg::{HistoryStateId, PipelineId};
use net_traits::pub_domains::reg_suffix;
use net_traits::quality::{quality_to_value, Quality, QualityItem}; use net_traits::quality::{quality_to_value, Quality, QualityItem};
use net_traits::request::Origin::Origin as SpecificOrigin; use net_traits::request::Origin::Origin as SpecificOrigin;
use net_traits::request::{is_cors_safelisted_method, is_cors_safelisted_request_header}; use net_traits::request::{is_cors_safelisted_method, is_cors_safelisted_request_header};
@ -189,6 +190,28 @@ fn strict_origin_when_cross_origin(referrer_url: ServoUrl, url: ServoUrl) -> Opt
strip_url(referrer_url, cross_origin) strip_url(referrer_url, cross_origin)
} }
/// https://html.spec.whatwg.org/multipage/#schemelessly-same-site
fn is_schemelessy_same_site(site_a: &ImmutableOrigin, site_b: &ImmutableOrigin) -> bool {
// Step 1
if !site_a.is_tuple() && !site_b.is_tuple() && site_a == site_b {
true
} else if site_a.is_tuple() && site_b.is_tuple() {
// Step 2.1
let host_a = site_a.host().map(|h| h.to_string()).unwrap_or_default();
let host_b = site_b.host().map(|h| h.to_string()).unwrap_or_default();
let host_a_reg = reg_suffix(&host_a);
let host_b_reg = reg_suffix(&host_b);
// Step 2.2-2.3
(site_a.host() == site_b.host() && host_a_reg == "") ||
(host_a_reg == host_b_reg && host_a_reg != "")
} else {
// Step 3
false
}
}
/// <https://w3c.github.io/webappsec-referrer-policy/#strip-url> /// <https://w3c.github.io/webappsec-referrer-policy/#strip-url>
fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option<ServoUrl> { fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option<ServoUrl> {
const MAX_REFERRER_URL_LENGTH: usize = 4096; const MAX_REFERRER_URL_LENGTH: usize = 4096;
@ -1251,7 +1274,74 @@ fn http_network_or_cache_fetch(
// TODO: if necessary set response's range-requested flag // TODO: if necessary set response's range-requested flag
// Step 9 // Step 9
// TODO: handle CORS not set and cross-origin blocked // https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check
#[derive(PartialEq)]
enum CrossOriginResourcePolicy {
Allowed,
Blocked,
}
fn cross_origin_resource_policy_check(
request: &Request,
response: &Response,
) -> CrossOriginResourcePolicy {
// Step 1
if request.mode != RequestMode::NoCors {
return CrossOriginResourcePolicy::Allowed;
}
// Step 2
let current_url_origin = request.current_url().origin();
let same_origin = if let Origin::Origin(ref origin) = request.origin {
*origin == request.current_url().origin()
} else {
false
};
if same_origin {
return CrossOriginResourcePolicy::Allowed;
}
// Step 3
let policy = response
.headers
.get(HeaderName::from_static("cross-origin-resource-policy"))
.map(|h| h.to_str().unwrap_or(""))
.unwrap_or("");
// Step 4
if policy == "same-origin" {
return CrossOriginResourcePolicy::Blocked;
}
// Step 5
if let Origin::Origin(ref request_origin) = request.origin {
let schemeless_same_origin =
is_schemelessy_same_site(&request_origin, &current_url_origin);
if schemeless_same_origin &&
(request_origin.scheme() == Some("https") ||
response.https_state == HttpsState::None)
{
return CrossOriginResourcePolicy::Allowed;
}
};
// Step 6
if policy == "same-site" {
return CrossOriginResourcePolicy::Blocked;
}
CrossOriginResourcePolicy::Allowed
}
if http_request.response_tainting != ResponseTainting::CorsTainting &&
cross_origin_resource_policy_check(&http_request, &response) ==
CrossOriginResourcePolicy::Blocked
{
return Response::network_error(NetworkError::Internal(
"Cross-origin resource policy check failed".into(),
));
}
// Step 10 // Step 10
// FIXME: Figure out what to do with request window objects // FIXME: Figure out what to do with request window objects

View file

@ -61,7 +61,7 @@ pub enum CacheState {
} }
/// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state) /// [Https state](https://fetch.spec.whatwg.org/#concept-response-https-state)
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub enum HttpsState { pub enum HttpsState {
None, None,
Deprecated, Deprecated,

View file

@ -424333,7 +424333,7 @@
] ]
], ],
"image-loads.html": [ "image-loads.html": [
"8a0458f107abdf2b7d6664fb8194e6b4b0222989", "060b7551ea516837cf416c797e85474658857632",
[ [
null, null,
{} {}
@ -424379,7 +424379,7 @@
] ]
], ],
"script-loads.html": [ "script-loads.html": [
"5850e0109f18c23e40d73686bef5e4b6a6b40686", "a9690fc70be13885d7ca6448730c83f755810774",
[ [
null, null,
{} {}

View file

@ -5,15 +5,3 @@
[fetch-in-iframe] [fetch-in-iframe]
expected: FAIL expected: FAIL
[Cross-origin fetch in a data: iframe load fails if the server blocks cross-origin loads with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin fetch in a data: iframe load fails if the server blocks cross-origin loads with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin fetch in a cross origin iframe load fails if the server blocks cross-origin loads with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin fetch in a cross origin iframe load fails if the server blocks cross-origin loads with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL

View file

@ -7,53 +7,11 @@
[fetch] [fetch]
expected: FAIL expected: FAIL
[Valid cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a redirection.]
expected: FAIL
[Cross-origin no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' redirect response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-scheme (HTTP to HTTPS) no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[fetch.any.worker.html] [fetch.any.worker.html]
[fetch] [fetch]
expected: FAIL expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Valid cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a redirection.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' redirect response header.]
expected: FAIL
[Cross-scheme (HTTP to HTTPS) no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[fetch.any.sharedworker.html] [fetch.any.sharedworker.html]
expected: ERROR expected: ERROR

View file

@ -1,16 +1,4 @@
[fetch.https.any.html] [fetch.https.any.html]
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a redirection.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' redirect response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[fetch.https.any.serviceworker.html] [fetch.https.any.serviceworker.html]
expected: ERROR expected: ERROR
@ -25,18 +13,6 @@
[fetch.https.any.worker.html] [fetch.https.any.worker.html]
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a redirection.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' redirect response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[fetch] [fetch]
expected: FAIL expected: FAIL

View file

@ -1,8 +1,6 @@
[iframe-loads.html] [iframe-loads.html]
[Untitled] [Untitled]
expected: FAIL expected: FAIL
[Load an iframe that has Cross-Origin-Resource-Policy header]
expected: FAIL
[iframe-loads] [iframe-loads]
expected: FAIL expected: FAIL

View file

@ -1,19 +0,0 @@
[image-loads.html]
[Same-origin image load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Same-origin image load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin cors image load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin cors image load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin no-cors image load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors image load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL

View file

@ -1,9 +0,0 @@
[scheme-restriction.any.html]
[Cross-Origin-Resource-Policy: same-site blocks retrieving HTTPS from HTTP]
expected: FAIL
[scheme-restriction.any.worker.html]
[Cross-Origin-Resource-Policy: same-site blocks retrieving HTTPS from HTTP]
expected: FAIL

View file

@ -1,19 +0,0 @@
[script-loads.html]
[Same-origin script load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Same-origin script load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin cors script load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin cors script load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL
[Cross-origin no-cors script load with a 'Cross-Origin-Resource-Policy: same-origin' response header.]
expected: FAIL
[Cross-origin no-cors script load with a 'Cross-Origin-Resource-Policy: same-site' response header.]
expected: FAIL

View file

@ -16,6 +16,7 @@ const noCors = false;
function loadImage(url, shoudLoad, corsMode, title) function loadImage(url, shoudLoad, corsMode, title)
{ {
const testDiv = document.getElementById("testDiv");
promise_test(() => { promise_test(() => {
const img = new Image(); const img = new Image();
if (corsMode) if (corsMode)

View file

@ -16,6 +16,7 @@ const noCors = false;
function loadScript(url, shoudLoad, corsMode, title) function loadScript(url, shoudLoad, corsMode, title)
{ {
const testDiv = document.getElementById("testDiv");
promise_test(() => { promise_test(() => {
const script = document.createElement("script"); const script = document.createElement("script");
if (corsMode) if (corsMode)