Ejemplo n.º 1
0
void DocumentThreadableLoader::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
    ASSERT(m_client);
    ASSERT_UNUSED(resource, resource == m_resource);

    Ref<DocumentThreadableLoader> protectedThis(*this);
    if (!isAllowedByContentSecurityPolicy(request.url(), !redirectResponse.isNull())) {
        m_client->didFailRedirectCheck();
        request = ResourceRequest();
        return;
    }

    // Allow same origin requests to continue after allowing clients to audit the redirect.
    if (isAllowedRedirect(request.url()))
        return;

    // When using access control, only simple cross origin requests are allowed to redirect. The new request URL must have a supported
    // scheme and not contain the userinfo production. In addition, the redirect response must pass the access control check if the
    // original request was not same-origin.
    if (m_options.crossOriginRequestPolicy == UseAccessControl) {
        bool allowRedirect = false;
        if (m_simpleRequest) {
            String accessControlErrorDescription;
            allowRedirect = isValidCrossOriginRedirectionURL(request.url())
                            && (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, m_options.allowCredentials(), securityOrigin(), accessControlErrorDescription));
        }

        if (allowRedirect) {
            if (m_resource)
                clearResource();

            RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::createFromString(redirectResponse.url());
            RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::createFromString(request.url());
            // If the original request wasn't same-origin, then if the request URL origin is not same origin with the original URL origin,
            // set the source origin to a globally unique identifier. (If the original request was same-origin, the origin of the new request
            // should be the original URL origin.)
            if (!m_sameOriginRequest && !originalOrigin->isSameSchemeHostPort(requestOrigin.get()))
                m_options.securityOrigin = SecurityOrigin::createUnique();
            // Force any subsequent request to use these checks.
            m_sameOriginRequest = false;

            // Since the request is no longer same-origin, if the user didn't request credentials in
            // the first place, update our state so we neither request them nor expect they must be allowed.
            if (m_options.credentialRequest() == ClientDidNotRequestCredentials)
                m_options.setAllowCredentials(DoNotAllowStoredCredentials);

            cleanRedirectedRequestForAccessControl(request);

            makeCrossOriginAccessRequest(request);
            return;
        }
    }

    m_client->didFailRedirectCheck();
    request = ResourceRequest();
}
Ejemplo n.º 2
0
bool SubresourceLoader::checkRedirectionCrossOriginAccessControl(const ResourceRequest& previousRequest, const ResourceResponse& redirectResponse, ResourceRequest& newRequest, String& errorMessage)
{
    bool crossOriginFlag = m_resource->isCrossOrigin();
    bool isNextRequestCrossOrigin = m_origin && !m_origin->canRequest(newRequest.url());

    if (isNextRequestCrossOrigin)
        m_resource->setCrossOrigin();

    ASSERT(options().mode != FetchOptions::Mode::SameOrigin || !m_resource->isCrossOrigin());

    if (options().mode != FetchOptions::Mode::Cors)
        return true;

    // Implementing https://fetch.spec.whatwg.org/#concept-http-redirect-fetch step 8 & 9.
    if (m_resource->isCrossOrigin() && !isValidCrossOriginRedirectionURL(newRequest.url())) {
        errorMessage = ASCIILiteral("URL is either a non-HTTP URL or contains credentials.");
        return false;
    }

    ASSERT(m_origin);
    if (crossOriginFlag && !passesAccessControlCheck(redirectResponse, options().allowCredentials, *m_origin, errorMessage))
        return false;

    bool redirectingToNewOrigin = false;
    if (m_resource->isCrossOrigin()) {
        if (!crossOriginFlag && isNextRequestCrossOrigin)
            redirectingToNewOrigin = true;
        else
            redirectingToNewOrigin = !SecurityOrigin::create(previousRequest.url())->canRequest(newRequest.url());
    }

    // Implementing https://fetch.spec.whatwg.org/#concept-http-redirect-fetch step 10.
    if (crossOriginFlag && redirectingToNewOrigin)
        m_origin = SecurityOrigin::createUnique();

    if (redirectingToNewOrigin) {
        cleanRedirectedRequestForAccessControl(newRequest);
        updateRequestForAccessControl(newRequest, *m_origin, options().allowCredentials);
    }

    return true;
}
Ejemplo n.º 3
0
bool SubresourceLoader::checkCrossOriginAccessControl(const ResourceRequest& previousRequest, const ResourceResponse& redirectResponse, ResourceRequest& newRequest)
{
    if (m_origin->canRequest(newRequest.url()))
        return true;

    String errorDescription;
    bool responsePassesCORS = m_origin->canRequest(previousRequest.url())
        || passesAccessControlCheck(redirectResponse, options().allowCredentials(), m_origin.get(), errorDescription);
    if (!responsePassesCORS || !isValidCrossOriginRedirectionURL(newRequest.url())) {
        if (m_frame && m_frame->document()) {
            String errorMessage = "Cross-origin redirection denied by Cross-Origin Resource Sharing policy: " +
                (!responsePassesCORS ? errorDescription : "Redirected to either a non-HTTP URL or a URL that contains credentials.");
            m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, errorMessage);
        }
        return false;
    }

    // If the request URL origin is not the same as the original origin, the request origin should be set to a globally unique identifier.
    m_origin = SecurityOrigin::createUnique();
    cleanRedirectedRequestForAccessControl(newRequest);
    updateRequestForAccessControl(newRequest, m_origin.get(), options().allowCredentials());

    return true;
}