Changeset 239132 in webkit


Ignore:
Timestamp:
Dec 12, 2018 3:57:10 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

HTTPS Upgrade: Figure out if/how to tell clients that the HTTPS upgrade happened
https://bugs.webkit.org/show_bug.cgi?id=192375
<rdar://problem/45851159>

Patch by Vivek Seth <v_seth@apple.com> on 2018-12-12
Reviewed by Chris Dumez.

Use simulated redirect to tell clients that HTTPS Upgrade happened.

Source/WebCore:

  • platform/network/ResourceResponseBase.cpp:

(WebCore::ResourceResponseBase::syntheticRedirectResponse):

  • platform/network/ResourceResponseBase.h:
  • platform/network/mac/WebCoreURLResponse.mm:

(WebCore::synthesizeRedirectResponseIfNecessary):

Source/WebKit:

  • NetworkProcess/NetworkLoadChecker.cpp:

(WebKit::NetworkLoadChecker::NetworkLoadChecker):
(WebKit::NetworkLoadChecker::checkRedirection):
(WebKit::NetworkLoadChecker::accessControlErrorForValidationHandler):
(WebKit::NetworkLoadChecker::applyHTTPSUpgradeIfNeeded const):
(WebKit::NetworkLoadChecker::checkRequest):
(WebKit::NetworkLoadChecker::continueCheckingRequestOrDoSyntheticRedirect):
(WebKit::NetworkLoadChecker::checkCORSRequestWithPreflight):
(WebKit::NetworkLoadChecker::applyHTTPSUpgradeIfNeeded): Deleted.

  • NetworkProcess/NetworkLoadChecker.h:
  • NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::start):

  • NetworkProcess/PingLoad.cpp:
Location:
trunk/Source
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r239130 r239132  
     12018-12-12  Vivek Seth  <v_seth@apple.com>
     2
     3        HTTPS Upgrade: Figure out if/how to tell clients that the HTTPS upgrade happened
     4        https://bugs.webkit.org/show_bug.cgi?id=192375
     5        <rdar://problem/45851159>
     6
     7        Reviewed by Chris Dumez.
     8
     9        Use simulated redirect to tell clients that HTTPS Upgrade happened.
     10
     11        * platform/network/ResourceResponseBase.cpp:
     12        (WebCore::ResourceResponseBase::syntheticRedirectResponse):
     13        * platform/network/ResourceResponseBase.h:
     14        * platform/network/mac/WebCoreURLResponse.mm:
     15        (WebCore::synthesizeRedirectResponseIfNecessary):
     16
    1172018-12-12  Chris Dumez  <cdumez@apple.com>
    218
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp

    r238953 r239132  
    119119
    120120    return response;
     121}
     122
     123ResourceResponse ResourceResponseBase::syntheticRedirectResponse(const URL& fromURL, const URL& toURL)
     124{
     125    ResourceResponse redirectResponse;
     126    redirectResponse.setURL(fromURL);
     127    redirectResponse.setHTTPStatusCode(302);
     128    redirectResponse.setHTTPVersion("HTTP/1.1"_s);
     129    redirectResponse.setHTTPHeaderField(HTTPHeaderName::Location, toURL.string());
     130    redirectResponse.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-store"_s);
     131
     132    return redirectResponse;
    121133}
    122134
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.h

    r238771 r239132  
    174174    static ResourceResponse filter(const ResourceResponse&);
    175175
     176    WEBCORE_EXPORT static ResourceResponse syntheticRedirectResponse(const URL& fromURL, const URL& toURL);
     177
    176178    static bool compare(const ResourceResponse&, const ResourceResponse&);
    177179
  • trunk/Source/WebCore/platform/network/mac/WebCoreURLResponse.mm

    r239037 r239132  
    348348        return nil;
    349349
    350     // If the new request is a different protocol than the current request, synthesize a redirect response.
    351     // This is critical for HSTS (<rdar://problem/14241270>).
    352     NSDictionary *synthesizedResponseHeaderFields = @{ @"Location": [[newRequest URL] absoluteString], @"Cache-Control": @"no-store" };
    353     return [[[NSHTTPURLResponse alloc] initWithURL:[currentRequest URL] statusCode:302 HTTPVersion:(NSString *)kCFHTTPVersion1_1 headerFields:synthesizedResponseHeaderFields] autorelease];
    354 }
    355 
    356 }
     350    return [[ResourceResponse::syntheticRedirectResponse(URL([currentRequest URL]), URL([newRequest URL])).nsURLResponse() retain] autorelease];
     351}
     352
     353}
  • trunk/Source/WebKit/ChangeLog

    r239131 r239132  
     12018-12-12  Vivek Seth  <v_seth@apple.com>
     2
     3        HTTPS Upgrade: Figure out if/how to tell clients that the HTTPS upgrade happened
     4        https://bugs.webkit.org/show_bug.cgi?id=192375
     5        <rdar://problem/45851159>
     6
     7        Reviewed by Chris Dumez.
     8
     9        Use simulated redirect to tell clients that HTTPS Upgrade happened.
     10
     11        * NetworkProcess/NetworkLoadChecker.cpp:
     12        (WebKit::NetworkLoadChecker::NetworkLoadChecker):
     13        (WebKit::NetworkLoadChecker::checkRedirection):
     14        (WebKit::NetworkLoadChecker::accessControlErrorForValidationHandler):
     15        (WebKit::NetworkLoadChecker::applyHTTPSUpgradeIfNeeded const):
     16        (WebKit::NetworkLoadChecker::checkRequest):
     17        (WebKit::NetworkLoadChecker::continueCheckingRequestOrDoSyntheticRedirect):
     18        (WebKit::NetworkLoadChecker::checkCORSRequestWithPreflight):
     19        (WebKit::NetworkLoadChecker::applyHTTPSUpgradeIfNeeded): Deleted.
     20        * NetworkProcess/NetworkLoadChecker.h:
     21        * NetworkProcess/NetworkResourceLoader.cpp:
     22        (WebKit::NetworkResourceLoader::start):
     23        * NetworkProcess/PingLoad.cpp:
     24
    1252018-12-12  Ross Kirsling  <ross.kirsling@sony.com>
    226
  • trunk/Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp

    r239007 r239132  
    4646}
    4747
    48 NetworkLoadChecker::NetworkLoadChecker(FetchOptions&& options, PAL::SessionID sessionID, uint64_t pageID, uint64_t frameID, HTTPHeaderMap&& originalRequestHeaders, URL&& url, RefPtr<SecurityOrigin>&& sourceOrigin, PreflightPolicy preflightPolicy, String&& referrer, bool shouldCaptureExtraNetworkLoadMetrics)
     48NetworkLoadChecker::NetworkLoadChecker(FetchOptions&& options, PAL::SessionID sessionID, uint64_t pageID, uint64_t frameID, HTTPHeaderMap&& originalRequestHeaders, URL&& url, RefPtr<SecurityOrigin>&& sourceOrigin, PreflightPolicy preflightPolicy, String&& referrer, bool shouldCaptureExtraNetworkLoadMetrics, LoadType requestLoadType)
    4949    : m_options(WTFMove(options))
    5050    , m_sessionID(sessionID)
     
    5757    , m_referrer(WTFMove(referrer))
    5858    , m_shouldCaptureExtraNetworkLoadMetrics(shouldCaptureExtraNetworkLoadMetrics)
     59    , m_requestLoadType(requestLoadType)
    5960{
    6061    m_isSameOriginRequest = isSameOrigin(m_url, m_origin.get());
     
    133134
    134135    checkRequest(WTFMove(redirectRequest), client, [handler = WTFMove(handler), request = WTFMove(request), redirectResponse = WTFMove(redirectResponse)](auto&& result) mutable {
    135         if (!result.has_value()) {
    136             handler(makeUnexpected(WTFMove(result.error())));
    137             return;
    138         }
    139         handler(RedirectionTriplet { WTFMove(request), WTFMove(result.value()), WTFMove(redirectResponse) });
     136        WTF::switchOn(result,
     137            [&handler] (ResourceError& error) mutable {
     138                handler(makeUnexpected(WTFMove(error)));
     139            },
     140            [&handler, &request, &redirectResponse] (RedirectionTriplet& triplet) mutable {
     141                // FIXME: if checkRequest returns a RedirectionTriplet, it means the requested URL has changed and we should update the redirectResponse to match.
     142                handler(RedirectionTriplet { WTFMove(request), WTFMove(triplet.redirectRequest), WTFMove(redirectResponse) });
     143            },
     144            [&handler, &request, &redirectResponse] (ResourceRequest& redirectRequest) mutable {
     145                handler(RedirectionTriplet { WTFMove(request), WTFMove(redirectRequest), WTFMove(redirectResponse) });
     146            }
     147        );
    140148    });
    141149}
     
    178186}
    179187
    180 auto NetworkLoadChecker::accessControlErrorForValidationHandler(String&& message) -> RequestOrError
    181 {
    182     return makeUnexpected(ResourceError { String { }, 0, m_url, WTFMove(message), ResourceError::Type::AccessControl });
     188auto NetworkLoadChecker::accessControlErrorForValidationHandler(String&& message) -> RequestOrRedirectionTripletOrError
     189{
     190    return ResourceError { String { }, 0, m_url, WTFMove(message), ResourceError::Type::AccessControl };
    183191}
    184192
    185193#if ENABLE(HTTPS_UPGRADE)
    186 bool NetworkLoadChecker::applyHTTPSUpgradeIfNeeded(ResourceRequest& request)
    187 {
     194void NetworkLoadChecker::applyHTTPSUpgradeIfNeeded(ResourceRequest& request) const
     195{
     196    if (m_requestLoadType != LoadType::MainFrame)
     197        return;
     198
    188199    // Use dummy list for now.
    189200    static NeverDestroyed<HashSet<String>> upgradableHosts = std::initializer_list<String> {
     
    197208    // Only upgrade http urls.
    198209    if (!url.protocolIs("http"))
    199         return false;
     210        return;
    200211
    201212    if (!upgradableHosts.get().contains(url.host().toString()))
    202         return false;
     213        return;
    203214
    204215    auto newURL = url;
    205216    newURL.setProtocol("https"_s);
    206217    request.setURL(newURL);
    207     return true;
    208 
    209     return false;
     218
     219    RELEASE_LOG_IF_ALLOWED("applyHTTPSUpgradeIfNeeded - Upgrade URL from HTTP to HTTPS");
    210220}
    211221#endif // ENABLE(HTTPS_UPGRADE)
     
    213223void NetworkLoadChecker::checkRequest(ResourceRequest&& request, ContentSecurityPolicyClient* client, ValidationHandler&& handler)
    214224{
     225    ResourceRequest originalRequest = request;
    215226
    216227#if ENABLE(HTTPS_UPGRADE)
    217     if (request.requester() == ResourceRequest::Requester::Main) {
    218         if (applyHTTPSUpgradeIfNeeded(request))
    219             ASSERT(request.url().protocolIs("https"));
    220     }
    221 
     228    applyHTTPSUpgradeIfNeeded(request);
    222229#endif // ENABLE(HTTPS_UPGRADE)
    223230
     
    234241
    235242#if ENABLE(CONTENT_EXTENSIONS)
    236     processContentExtensionRulesForLoad(WTFMove(request), [this, handler = WTFMove(handler)](auto result) mutable {
     243    processContentExtensionRulesForLoad(WTFMove(request), [this, handler = WTFMove(handler), originalRequest = WTFMove(originalRequest)](auto result) mutable {
    237244        if (!result.has_value()) {
    238245            ASSERT(result.error().isCancellation());
    239             handler(makeUnexpected(WTFMove(result.error())));
     246            handler(WTFMove(result.error()));
    240247            return;
    241248        }
     
    244251            return;
    245252        }
    246         this->continueCheckingRequest(WTFMove(result.value().request), WTFMove(handler));
     253
     254        continueCheckingRequestOrDoSyntheticRedirect(WTFMove(originalRequest), WTFMove(result.value().request), WTFMove(handler));
    247255    });
    248256#else
    249     continueCheckingRequest(WTFMove(request), WTFMove(handler));
     257    continueCheckingRequestOrDoSyntheticRedirect(WTFMove(originalRequest), WTFMove(request), WTFMove(handler));
    250258#endif
     259}
     260
     261void NetworkLoadChecker::continueCheckingRequestOrDoSyntheticRedirect(ResourceRequest&& originalRequest, ResourceRequest&& currentRequest, ValidationHandler&& handler)
     262{
     263    // If main frame load and request has been modified, trigger a synthetic redirect.
     264    if (m_requestLoadType == LoadType::MainFrame && currentRequest.url() != originalRequest.url()) {
     265        ResourceResponse redirectResponse = ResourceResponse::syntheticRedirectResponse(originalRequest.url(), currentRequest.url());
     266        handler(RedirectionTriplet { WTFMove(originalRequest), WTFMove(currentRequest), WTFMove(redirectResponse) });
     267        return;
     268    }
     269    this->continueCheckingRequest(WTFMove(currentRequest), WTFMove(handler));
    251270}
    252271
     
    395414
    396415        if (!error.isNull()) {
    397             handler(makeUnexpected(WTFMove(error)));
     416            handler(WTFMove(error));
    398417            return;
    399418        }
  • trunk/Source/WebKit/NetworkProcess/NetworkLoadChecker.h

    r239007 r239132  
    3131#include <wtf/CompletionHandler.h>
    3232#include <wtf/Expected.h>
     33#include <wtf/Variant.h>
    3334
    3435namespace WebCore {
     
    4344class NetworkLoadChecker : public CanMakeWeakPtr<NetworkLoadChecker> {
    4445public:
    45     NetworkLoadChecker(WebCore::FetchOptions&&, PAL::SessionID, uint64_t pageID, uint64_t frameID, WebCore::HTTPHeaderMap&&, URL&&, RefPtr<WebCore::SecurityOrigin>&&, WebCore::PreflightPolicy, String&& referrer, bool shouldCaptureExtraNetworkLoadMetrics = false);
     46    enum class LoadType : bool { MainFrame, Other };
     47
     48    NetworkLoadChecker(WebCore::FetchOptions&&, PAL::SessionID, uint64_t pageID, uint64_t frameID, WebCore::HTTPHeaderMap&&, URL&&, RefPtr<WebCore::SecurityOrigin>&&, WebCore::PreflightPolicy, String&& referrer, bool shouldCaptureExtraNetworkLoadMetrics = false, LoadType requestLoadType = LoadType::Other);
    4649    ~NetworkLoadChecker();
    47 
    48     using RequestOrError = Expected<WebCore::ResourceRequest, WebCore::ResourceError>;
    49     using ValidationHandler = CompletionHandler<void(RequestOrError&&)>;
    50     void check(WebCore::ResourceRequest&&, WebCore::ContentSecurityPolicyClient*, ValidationHandler&&);
    5150
    5251    struct RedirectionTriplet {
     
    5554        WebCore::ResourceResponse redirectResponse;
    5655    };
     56
     57    using RequestOrRedirectionTripletOrError = Variant<WebCore::ResourceRequest, RedirectionTriplet, WebCore::ResourceError>;
     58    using ValidationHandler = CompletionHandler<void(RequestOrRedirectionTripletOrError&&)>;
     59    void check(WebCore::ResourceRequest&&, WebCore::ContentSecurityPolicyClient*, ValidationHandler&&);
     60
    5761    using RedirectionRequestOrError = Expected<RedirectionTriplet, WebCore::ResourceError>;
    5862    using RedirectionValidationHandler = CompletionHandler<void(RedirectionRequestOrError&&)>;
     
    9094
    9195    void continueCheckingRequest(WebCore::ResourceRequest&&, ValidationHandler&&);
     96    void continueCheckingRequestOrDoSyntheticRedirect(WebCore::ResourceRequest&& originalRequest, WebCore::ResourceRequest&& currentRequest, ValidationHandler&&);
    9297
    9398    bool doesNotNeedCORSCheck(const URL&) const;
     
    96101    void checkCORSRequestWithPreflight(WebCore::ResourceRequest&&, ValidationHandler&&);
    97102
    98     RequestOrError accessControlErrorForValidationHandler(String&&);
     103    RequestOrRedirectionTripletOrError accessControlErrorForValidationHandler(String&&);
    99104
    100105#if ENABLE(CONTENT_EXTENSIONS)
     
    107112    void processContentExtensionRulesForLoad(WebCore::ResourceRequest&&, ContentExtensionCallback&&);
    108113#endif
     114
     115#if ENABLE(HTTPS_UPGRADE)
     116    void applyHTTPSUpgradeIfNeeded(WebCore::ResourceRequest&) const;
     117#endif // ENABLE(HTTPS_UPGRADE)
     118
    109119    WebCore::FetchOptions m_options;
    110120    WebCore::StoredCredentialsPolicy m_storedCredentialsPolicy;
     
    135145    WebCore::NetworkLoadInformation m_loadInformation;
    136146
    137 #if ENABLE(HTTPS_UPGRADE)
    138     static bool applyHTTPSUpgradeIfNeeded(WebCore::ResourceRequest&);
    139 #endif // ENABLE(HTTPS_UPGRADE)
    140 
     147    LoadType m_requestLoadType;
    141148};
    142149
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r239007 r239132  
    112112
    113113    if (synchronousReply || parameters.shouldRestrictHTTPResponseAccess) {
    114         m_networkLoadChecker = std::make_unique<NetworkLoadChecker>(FetchOptions { m_parameters.options }, m_parameters.sessionID, m_parameters.webPageID, m_parameters.webFrameID, HTTPHeaderMap { m_parameters.originalRequestHeaders }, URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, originalRequest().httpReferrer(), shouldCaptureExtraNetworkLoadMetrics());
     114        NetworkLoadChecker::LoadType requestLoadType = isMainFrameLoad() ? NetworkLoadChecker::LoadType::MainFrame : NetworkLoadChecker::LoadType::Other;
     115        m_networkLoadChecker = std::make_unique<NetworkLoadChecker>(FetchOptions { m_parameters.options }, m_parameters.sessionID, m_parameters.webPageID, m_parameters.webFrameID, HTTPHeaderMap { m_parameters.originalRequestHeaders }, URL { m_parameters.request.url() }, m_parameters.sourceOrigin.copyRef(), m_parameters.preflightPolicy, originalRequest().httpReferrer(), shouldCaptureExtraNetworkLoadMetrics(), requestLoadType);
    115116        if (m_parameters.cspResponseHeaders)
    116117            m_networkLoadChecker->setCSPResponseHeaders(ContentSecurityPolicyResponseHeaders { m_parameters.cspResponseHeaders.value() });
     
    180181    if (m_networkLoadChecker) {
    181182        m_networkLoadChecker->check(ResourceRequest { originalRequest() }, this, [this] (auto&& result) {
    182             if (!result.has_value()) {
    183                 if (!result.error().isCancellation())
    184                     this->didFailLoading(result.error());
    185                 return;
    186             }
    187 
    188             auto currentRequest = result.value();
    189             if (this->canUseCache(currentRequest)) {
    190                 RELEASE_LOG_IF_ALLOWED("start: Checking cache for resource (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, this->isMainResource(), this->isSynchronous());
    191                 this->retrieveCacheEntry(currentRequest);
    192                 return;
    193             }
    194 
    195             this->startNetworkLoad(WTFMove(result.value()), FirstLoad::Yes);
     183            WTF::switchOn(result,
     184                [this] (ResourceError& error) {
     185                    if (!error.isCancellation())
     186                        this->didFailLoading(error);
     187                },
     188                [this] (NetworkLoadChecker::RedirectionTriplet& triplet) {
     189                    this->m_isWaitingContinueWillSendRequestForCachedRedirect = true;
     190                    this->willSendRedirectedRequest(WTFMove(triplet.request), WTFMove(triplet.redirectRequest), WTFMove(triplet.redirectResponse));
     191                    RELEASE_LOG_IF_ALLOWED("NetworkResourceLoader: synthetic redirect sent because request URL was modified.");
     192                },
     193                [this] (ResourceRequest& request) {
     194                    if (this->canUseCache(request)) {
     195                        RELEASE_LOG_IF_ALLOWED("start: Checking cache for resource (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, this->isMainResource(), this->isSynchronous());
     196                        this->retrieveCacheEntry(request);
     197                        return;
     198                    }
     199
     200                    this->startNetworkLoad(WTFMove(request), FirstLoad::Yes);
     201                }
     202            );
    196203        });
    197204        return;
  • trunk/Source/WebKit/NetworkProcess/PingLoad.cpp

    r239007 r239132  
    5858
    5959    m_networkLoadChecker->check(ResourceRequest { m_parameters.request }, nullptr, [this] (auto&& result) {
    60         if (!result.has_value()) {
    61             this->didFinish(result.error());
    62             return;
    63         }
    64         this->loadRequest(WTFMove(result.value()));
     60        WTF::switchOn(result,
     61            [this] (ResourceError& error) {
     62                this->didFinish(error);
     63            },
     64            [] (NetworkLoadChecker::RedirectionTriplet& triplet) {
     65                // We should never send a synthetic redirect for PingLoads.
     66                ASSERT_NOT_REACHED();
     67            },
     68            [this] (ResourceRequest& request) {
     69                this->loadRequest(WTFMove(request));
     70            }
     71        );
    6572    });
    6673}
Note: See TracChangeset for help on using the changeset viewer.