mirror of
https://github.com/servo/servo.git
synced 2025-07-23 23:33:43 +01:00
Implement PolicyContainer and update the default ReferrerPolicy (#33977)
* Implement PolicyContainer Signed-off-by: Shane Handley <shanehandley@fastmail.com> * implement small parts of fetch that interact with policy container Signed-off-by: Shane Handley <shanehandley@fastmail.com> * fix: allow policy container's csp list to be unset Signed-off-by: Shane Handley <shanehandley@fastmail.com> * fix: use the correct default policy when parsing from a token Signed-off-by: Shane Handley <shanehandley@fastmail.com> --------- Signed-off-by: Shane Handley <shanehandley@fastmail.com>
This commit is contained in:
parent
4f6283d7fe
commit
6451767428
201 changed files with 210 additions and 5178 deletions
|
@ -20,6 +20,7 @@ use log::warn;
|
|||
use mime::{self, Mime};
|
||||
use net_traits::filemanager_thread::{FileTokenCheck, RelativePos};
|
||||
use net_traits::http_status::HttpStatus;
|
||||
use net_traits::policy_container::{PolicyContainer, RequestPolicyContainer};
|
||||
use net_traits::request::{
|
||||
is_cors_safelisted_method, is_cors_safelisted_request_header, BodyChunkRequest,
|
||||
BodyChunkResponse, CredentialsMode, Destination, Origin, RedirectMode, Referrer, Request,
|
||||
|
@ -27,8 +28,8 @@ use net_traits::request::{
|
|||
};
|
||||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||
use net_traits::{
|
||||
FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceAttribute, ResourceFetchTiming,
|
||||
ResourceTimeValue, ResourceTimingType,
|
||||
FetchTaskTarget, NetworkError, ResourceAttribute, ResourceFetchTiming, ResourceTimeValue,
|
||||
ResourceTimingType,
|
||||
};
|
||||
use rustls::Certificate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -114,52 +115,83 @@ pub async fn fetch(request: &mut Request, target: Target<'_>, context: &FetchCon
|
|||
fetch_with_cors_cache(request, &mut CorsCache::default(), target, context).await;
|
||||
}
|
||||
|
||||
/// Continuation of fetch from step 9.
|
||||
///
|
||||
/// <https://fetch.spec.whatwg.org#concept-fetch>
|
||||
pub async fn fetch_with_cors_cache(
|
||||
request: &mut Request,
|
||||
cache: &mut CorsCache,
|
||||
target: Target<'_>,
|
||||
context: &FetchContext,
|
||||
) {
|
||||
// Step 1.
|
||||
// Step 9: If request’s window is "client", then set request’s window to request’s client, if
|
||||
// request’s client’s global object is a Window object; otherwise "no-window".
|
||||
if request.window == Window::Client {
|
||||
// TODO: Set window to request's client object if client is a Window object
|
||||
} else {
|
||||
request.window = Window::NoWindow;
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
// Step 10: If request’s origin is "client", then set request’s origin to request’s client’s
|
||||
// origin.
|
||||
if request.origin == Origin::Client {
|
||||
// TODO: set request's origin to request's client's origin
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
set_default_accept(request);
|
||||
// Step 11: If all of the following conditions are true:
|
||||
// - request’s URL’s scheme is an HTTP(S) scheme
|
||||
// - request’s mode is "same-origin", "cors", or "no-cors"
|
||||
// - request’s window is an environment settings object
|
||||
// - request’s method is `GET`
|
||||
// - request’s unsafe-request flag is not set or request’s header list is empty
|
||||
// TODO: evaluate these conditions when we have an an environment settings object
|
||||
|
||||
// Step 4.
|
||||
set_default_accept_language(&mut request.headers);
|
||||
// Step 12: If request’s policy container is "client", then:
|
||||
if let RequestPolicyContainer::Client = request.policy_container {
|
||||
// Step 12.1: If request’s client is non-null, then set request’s policy container to a clone
|
||||
// of request’s client’s policy container.
|
||||
// TODO: Requires request's client to support PolicyContainer
|
||||
|
||||
// Step 5.
|
||||
// TODO: figure out what a Priority object is.
|
||||
|
||||
// Step 6.
|
||||
// TODO: handle client hints headers.
|
||||
|
||||
// Step 7.
|
||||
if request.is_subresource_request() {
|
||||
// TODO: handle client hints headers.
|
||||
// Step 12.2: Otherwise, set request’s policy container to a new policy container.
|
||||
request.policy_container =
|
||||
RequestPolicyContainer::PolicyContainer(PolicyContainer::default());
|
||||
}
|
||||
|
||||
// Step 8.
|
||||
// Step 13: If request’s header list does not contain `Accept`:
|
||||
set_default_accept(request);
|
||||
|
||||
// Step 14: If request’s header list does not contain `Accept-Language`, then user agents should
|
||||
// append (`Accept-Language, an appropriate header value) to request’s header list.
|
||||
set_default_accept_language(&mut request.headers);
|
||||
|
||||
// Step 15. If request’s internal priority is null, then use request’s priority, initiator,
|
||||
// destination, and render-blocking in an implementation-defined manner to set request’s
|
||||
// internal priority to an implementation-defined object.
|
||||
// TODO: figure out what a Priority object is.
|
||||
|
||||
// Step 16: If request is a subresource request, then:
|
||||
if request.is_subresource_request() {
|
||||
// TODO: requires keepalive.
|
||||
}
|
||||
|
||||
// Step 17: Run main fetch given fetchParams.
|
||||
main_fetch(request, cache, false, false, target, &mut None, context).await;
|
||||
|
||||
// Step 18: Return fetchParams’s controller.
|
||||
// TODO: We don't implement fetchParams as defined in the spec
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/CSP/#should-block-request>
|
||||
pub fn should_request_be_blocked_by_csp(request: &Request) -> csp::CheckResult {
|
||||
pub fn should_request_be_blocked_by_csp(
|
||||
request: &Request,
|
||||
policy_container: &PolicyContainer,
|
||||
) -> csp::CheckResult {
|
||||
let origin = match &request.origin {
|
||||
Origin::Client => return csp::CheckResult::Allowed,
|
||||
Origin::Origin(origin) => origin,
|
||||
};
|
||||
|
||||
let csp_request = csp::Request {
|
||||
url: request.url().into_url(),
|
||||
origin: origin.clone().into_url_origin(),
|
||||
|
@ -170,8 +202,9 @@ pub fn should_request_be_blocked_by_csp(request: &Request) -> csp::CheckResult {
|
|||
integrity_metadata: request.integrity_metadata.clone(),
|
||||
parser_metadata: csp::ParserMetadata::None,
|
||||
};
|
||||
|
||||
// TODO: Instead of ignoring violations, report them.
|
||||
request
|
||||
policy_container
|
||||
.csp_list
|
||||
.as_ref()
|
||||
.map(|c| c.should_request_be_blocked(&csp_request).0)
|
||||
|
@ -213,8 +246,15 @@ pub async fn main_fetch(
|
|||
// Step 2.2.
|
||||
// TODO: Report violations.
|
||||
|
||||
// The request should have a valid policy_container associated with it.
|
||||
// TODO: This should not be `Client` here
|
||||
let policy_container = match &request.policy_container {
|
||||
RequestPolicyContainer::Client => PolicyContainer::default(),
|
||||
RequestPolicyContainer::PolicyContainer(container) => container.to_owned(),
|
||||
};
|
||||
|
||||
// Step 2.4.
|
||||
if should_request_be_blocked_by_csp(request) == csp::CheckResult::Blocked {
|
||||
if should_request_be_blocked_by_csp(request, &policy_container) == csp::CheckResult::Blocked {
|
||||
warn!("Request blocked by CSP");
|
||||
response = Some(Response::network_error(NetworkError::Internal(
|
||||
"Blocked by Content-Security-Policy".into(),
|
||||
|
@ -236,16 +276,14 @@ pub async fn main_fetch(
|
|||
// TODO: handle blocking as mixed content.
|
||||
// TODO: handle blocking by content security policy.
|
||||
|
||||
// Step 6
|
||||
// TODO: handle request's client's referrer policy.
|
||||
|
||||
// Step 7.
|
||||
// Step 8: If request’s referrer policy is the empty string, then set request’s referrer policy
|
||||
// to request’s policy container’s referrer policy.
|
||||
request.referrer_policy = request
|
||||
.referrer_policy
|
||||
.or(Some(ReferrerPolicy::NoReferrerWhenDowngrade));
|
||||
.or(Some(policy_container.referrer_policy));
|
||||
|
||||
// Step 8.
|
||||
assert!(request.referrer_policy.is_some());
|
||||
|
||||
let referrer_url = match mem::replace(&mut request.referrer, Referrer::NoReferrer) {
|
||||
Referrer::NoReferrer => None,
|
||||
Referrer::ReferrerUrl(referrer_source) | Referrer::Client(referrer_source) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue