Limit cookie header access to Network process
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Apr 2018 01:51:37 +0000 (01:51 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Apr 2018 01:51:37 +0000 (01:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184764
<rdar://problem/36785285>

Reviewed by Youenn Fablet.

Revise the handling of cookie request headers so that we don't interact with them in the
WebContent process. They are only needed for interaction with the server and the network
process, so we should limit their scope to just the Network process.

Instead, we should handle a token that represents the cookie headers in the WebContent
process, which can be converted to the relevant cookie data in the network process when
needed.

Source/WebCore:

* Modules/websockets/WebSocketChannel.cpp:
(WebCore::WebSocketChannel::didOpenSocketStream):
* Modules/websockets/WebSocketHandshake.cpp:
(WebCore::WebSocketHandshake::clientHandshakeMessage const):
(WebCore::WebSocketHandshake::clientHandshakeRequest const):
(WebCore::WebSocketHandshake::clientHandshakeCookieRequestHeaderFieldProxy const):
(WebCore::WebSocketHandshake::clientHandshakeMessage): Deleted.
(WebCore::WebSocketHandshake::clientHandshakeRequest): Deleted.
* Modules/websockets/WebSocketHandshake.h:
* WebCore.xcodeproj/project.pbxproj:
* loader/CookieJar.cpp:
(WebCore::cookieRequestHeaderFieldProxy):
* loader/CookieJar.h:
* platform/network/CookieRequestHeaderFieldProxy.h: Added.
(WebCore::CookieRequestHeaderFieldProxy::CookieRequestHeaderFieldProxy):
(WebCore::CookieRequestHeaderFieldProxy::isolatedCopy const):
(WebCore::CookieRequestHeaderFieldProxy::encode const):
(WebCore::CookieRequestHeaderFieldProxy::decode):
* platform/network/PlatformCookieJar.h:
* platform/network/SocketStreamHandle.cpp:
(WebCore::SocketStreamHandle::sendHandshake):
* platform/network/SocketStreamHandle.h:
* platform/network/SocketStreamHandleImpl.cpp:
(WebCore::SocketStreamHandleImpl::platformSendHandshake):
* platform/network/cf/SocketStreamHandleImpl.h:
* platform/network/curl/CookieJarCurl.cpp:
(WebCore::cookieRequestHeaderFieldValue):
* platform/network/curl/CookieJarCurl.h:
* platform/network/curl/SocketStreamHandleImpl.h:
* platform/network/mac/CookieJarMac.mm:
(WebCore::cookieRequestHeaderFieldValue):
* platform/network/soup/CookieJarSoup.cpp:
(WebCore::cookieRequestHeaderFieldValue):
* platform/network/soup/SocketStreamHandleImpl.h:

Source/WebKit:

* NetworkProcess/NetworkSocketStream.cpp:
(WebKit::NetworkSocketStream::sendHandshake):
* NetworkProcess/NetworkSocketStream.h:
* NetworkProcess/NetworkSocketStream.messages.in:
* WebProcess/Network/WebSocketStream.cpp:
(WebKit::WebSocketStream::networkProcessCrashed):
(WebKit::WebSocketStream::platformSendHandshake):
(WebKit::WebSocketStream::didSendHandshake):
* WebProcess/Network/WebSocketStream.h:
* WebProcess/Network/WebSocketStream.messages.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230875 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/websockets/WebSocketChannel.cpp
Source/WebCore/Modules/websockets/WebSocketHandshake.cpp
Source/WebCore/Modules/websockets/WebSocketHandshake.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/loader/CookieJar.cpp
Source/WebCore/loader/CookieJar.h
Source/WebCore/platform/network/CookieRequestHeaderFieldProxy.h [new file with mode: 0644]
Source/WebCore/platform/network/PlatformCookieJar.h
Source/WebCore/platform/network/SocketStreamHandle.cpp
Source/WebCore/platform/network/SocketStreamHandle.h
Source/WebCore/platform/network/SocketStreamHandleImpl.cpp
Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h
Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp
Source/WebCore/platform/network/curl/CookieJarCurl.cpp
Source/WebCore/platform/network/curl/CookieJarCurl.h
Source/WebCore/platform/network/curl/CookieJarCurlDatabase.cpp
Source/WebCore/platform/network/curl/CookieJarCurlDatabase.h
Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h
Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp
Source/WebCore/platform/network/mac/CookieJarMac.mm
Source/WebCore/platform/network/soup/CookieJarSoup.cpp
Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h
Source/WebCore/platform/network/soup/SocketStreamHandleImplSoup.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkSocketStream.cpp
Source/WebKit/NetworkProcess/NetworkSocketStream.h
Source/WebKit/NetworkProcess/NetworkSocketStream.messages.in
Source/WebKit/WebProcess/Network/WebSocketStream.cpp
Source/WebKit/WebProcess/Network/WebSocketStream.h
Source/WebKit/WebProcess/Network/WebSocketStream.messages.in

index b1562f0..35e84e3 100644 (file)
@@ -1,3 +1,54 @@
+2018-04-20  Brent Fulgham  <bfulgham@apple.com>
+
+        Limit cookie header access to Network process
+        https://bugs.webkit.org/show_bug.cgi?id=184764
+        <rdar://problem/36785285>
+
+        Reviewed by Youenn Fablet.
+
+        Revise the handling of cookie request headers so that we don't interact with them in the
+        WebContent process. They are only needed for interaction with the server and the network
+        process, so we should limit their scope to just the Network process.
+
+        Instead, we should handle a token that represents the cookie headers in the WebContent
+        process, which can be converted to the relevant cookie data in the network process when
+        needed.
+
+        * Modules/websockets/WebSocketChannel.cpp:
+        (WebCore::WebSocketChannel::didOpenSocketStream):
+        * Modules/websockets/WebSocketHandshake.cpp:
+        (WebCore::WebSocketHandshake::clientHandshakeMessage const):
+        (WebCore::WebSocketHandshake::clientHandshakeRequest const):
+        (WebCore::WebSocketHandshake::clientHandshakeCookieRequestHeaderFieldProxy const):
+        (WebCore::WebSocketHandshake::clientHandshakeMessage): Deleted.
+        (WebCore::WebSocketHandshake::clientHandshakeRequest): Deleted.
+        * Modules/websockets/WebSocketHandshake.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/CookieJar.cpp:
+        (WebCore::cookieRequestHeaderFieldProxy):
+        * loader/CookieJar.h:
+        * platform/network/CookieRequestHeaderFieldProxy.h: Added.
+        (WebCore::CookieRequestHeaderFieldProxy::CookieRequestHeaderFieldProxy):
+        (WebCore::CookieRequestHeaderFieldProxy::isolatedCopy const):
+        (WebCore::CookieRequestHeaderFieldProxy::encode const):
+        (WebCore::CookieRequestHeaderFieldProxy::decode):
+        * platform/network/PlatformCookieJar.h:
+        * platform/network/SocketStreamHandle.cpp:
+        (WebCore::SocketStreamHandle::sendHandshake):
+        * platform/network/SocketStreamHandle.h:
+        * platform/network/SocketStreamHandleImpl.cpp:
+        (WebCore::SocketStreamHandleImpl::platformSendHandshake):
+        * platform/network/cf/SocketStreamHandleImpl.h:
+        * platform/network/curl/CookieJarCurl.cpp:
+        (WebCore::cookieRequestHeaderFieldValue):
+        * platform/network/curl/CookieJarCurl.h:
+        * platform/network/curl/SocketStreamHandleImpl.h:
+        * platform/network/mac/CookieJarMac.mm:
+        (WebCore::cookieRequestHeaderFieldValue):
+        * platform/network/soup/CookieJarSoup.cpp:
+        (WebCore::cookieRequestHeaderFieldValue):
+        * platform/network/soup/SocketStreamHandleImpl.h:
+
 2018-04-20  Daniel Bates  <dabates@apple.com>
 
         Hide Strong Password label when text field is too narrow
index e9a4f6d..8147f0d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011, 2012 Google Inc.  All rights reserved.
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -270,12 +271,16 @@ void WebSocketChannel::didOpenSocketStream(SocketStreamHandle& handle)
     ASSERT(&handle == m_handle);
     if (!m_document)
         return;
-    if (m_identifier)
+    if (m_identifier && UNLIKELY(InspectorInstrumentation::hasFrontends()))
         InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest());
-    CString handshakeMessage = m_handshake->clientHandshakeMessage();
-    handle.sendData(handshakeMessage.data(), handshakeMessage.length(), [this, protectedThis = makeRef(*this)] (bool success) {
+    auto handshakeMessage = m_handshake->clientHandshakeMessage();
+    auto cookieRequestHeaderFieldProxy = m_handshake->clientHandshakeCookieRequestHeaderFieldProxy();
+    handle.sendHandshake(WTFMove(handshakeMessage), WTFMove(cookieRequestHeaderFieldProxy), [this, protectedThis = makeRef(*this)] (bool success, bool didAccessSecureCookies) {
         if (!success)
             fail("Failed to send WebSocket handshake.");
+
+        if (didAccessSecureCookies && m_document)
+            m_document->setSecureCookiesAccessed();
     });
 }
 
index 7ec2786..5455cd1 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011 Google Inc.  All rights reserved.
  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,6 +39,7 @@
 #include "HTTPHeaderMap.h"
 #include "HTTPHeaderNames.h"
 #include "HTTPParsers.h"
+#include "InspectorInstrumentation.h"
 #include "Logging.h"
 #include "ResourceRequest.h"
 #include "ScriptExecutionContext.h"
@@ -177,7 +179,7 @@ String WebSocketHandshake::clientLocation() const
     return builder.toString();
 }
 
-CString WebSocketHandshake::clientHandshakeMessage()
+CString WebSocketHandshake::clientHandshakeMessage() const
 {
     // Keep the following consistent with clientHandshakeRequest().
     StringBuilder builder;
@@ -194,12 +196,8 @@ CString WebSocketHandshake::clientHandshakeMessage()
     if (!m_clientProtocol.isEmpty())
         fields.append("Sec-WebSocket-Protocol: " + m_clientProtocol);
 
-    URL url = httpURLForAuthenticationAndCookies();
-    if (m_allowCookies && m_document) {
-        String cookie = cookieRequestHeaderFieldValue(*m_document, url);
-        if (!cookie.isEmpty())
-            fields.append("Cookie: " + cookie);
-    }
+    // Note: Cookies are not retrieved in the WebContent process. Instead, a proxy object is
+    // added in the handshake, and is exchanged for actual cookies in the Network process.
 
     // Add no-cache headers to avoid compatibility issue.
     // There are some proxies that rewrite "Connection: upgrade"
@@ -231,7 +229,7 @@ CString WebSocketHandshake::clientHandshakeMessage()
     return builder.toString().utf8();
 }
 
-ResourceRequest WebSocketHandshake::clientHandshakeRequest()
+ResourceRequest WebSocketHandshake::clientHandshakeRequest() const
 {
     // Keep the following consistent with clientHandshakeMessage().
     ResourceRequest request(m_url);
@@ -245,6 +243,7 @@ ResourceRequest WebSocketHandshake::clientHandshakeRequest()
 
     URL url = httpURLForAuthenticationAndCookies();
     if (m_allowCookies && m_document) {
+        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(InspectorInstrumentation::hasFrontends());
         String cookie = cookieRequestHeaderFieldValue(*m_document, url);
         if (!cookie.isEmpty())
             request.setHTTPHeaderField(HTTPHeaderName::Cookie, cookie);
@@ -265,6 +264,13 @@ ResourceRequest WebSocketHandshake::clientHandshakeRequest()
     return request;
 }
 
+std::optional<CookieRequestHeaderFieldProxy> WebSocketHandshake::clientHandshakeCookieRequestHeaderFieldProxy() const
+{
+    if (!m_document || !m_allowCookies)
+        return std::nullopt;
+    return cookieRequestHeaderFieldProxy(*m_document, httpURLForAuthenticationAndCookies());
+}
+
 void WebSocketHandshake::reset()
 {
     m_mode = Incomplete;
index b66c10f..cf2bd7a 100644 (file)
@@ -30,6 +30,7 @@
 
 #pragma once
 
+#include "CookieRequestHeaderFieldProxy.h"
 #include "URL.h"
 #include "ResourceResponse.h"
 #include "WebSocketExtensionDispatcher.h"
@@ -63,8 +64,9 @@ public:
     String clientOrigin() const;
     String clientLocation() const;
 
-    CString clientHandshakeMessage();
-    ResourceRequest clientHandshakeRequest();
+    CString clientHandshakeMessage() const;
+    ResourceRequest clientHandshakeRequest() const;
+    std::optional<CookieRequestHeaderFieldProxy> clientHandshakeCookieRequestHeaderFieldProxy() const;
 
     void reset();
     void clearDocument();
index 395aff7..54d9e94 100644 (file)
                7A54858014E02D51006AE05A /* InspectorHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A54857E14E02D51006AE05A /* InspectorHistory.h */; };
                7A54881714E432A1006AE05A /* DOMPatchSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A54881514E432A1006AE05A /* DOMPatchSupport.h */; };
                7A5515F5191830A3009687D2 /* YouTubePluginReplacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A5515F3191830A3009687D2 /* YouTubePluginReplacement.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7A5699702086C619000E0433 /* CookieRequestHeaderFieldProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A56996E2086C618000E0433 /* CookieRequestHeaderFieldProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7A674BDC0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A674BDA0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h */; };
                7A929CA71C598AA9004DF226 /* ResourceLoadStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7A93868518DCC14500B8263D /* VTTScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A93868218DCC14500B8263D /* VTTScanner.cpp */; };
                7A54881614E432A1006AE05A /* DOMPatchSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMPatchSupport.cpp; sourceTree = "<group>"; };
                7A5515F3191830A3009687D2 /* YouTubePluginReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YouTubePluginReplacement.h; sourceTree = "<group>"; };
                7A5515F4191830A3009687D2 /* YouTubePluginReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubePluginReplacement.cpp; sourceTree = "<group>"; };
+               7A56996E2086C618000E0433 /* CookieRequestHeaderFieldProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CookieRequestHeaderFieldProxy.h; sourceTree = "<group>"; };
                7A674BD90F9EBF4E006CF099 /* PageGroupLoadDeferrer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageGroupLoadDeferrer.cpp; sourceTree = "<group>"; };
                7A674BDA0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageGroupLoadDeferrer.h; sourceTree = "<group>"; };
                7A7256B915EB9F5B007323A7 /* InspectorOverlayPage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = InspectorOverlayPage.html; sourceTree = "<group>"; };
                                2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */,
                                E43AF8E41AC5B7DD00CA717E /* CacheValidation.cpp */,
                                E43AF8E51AC5B7DD00CA717E /* CacheValidation.h */,
+                               7A56996E2086C618000E0433 /* CookieRequestHeaderFieldProxy.h */,
                                E13F01EA1270E10D00DFBA71 /* CookieStorage.h */,
                                514C76590CE923A1007EF3CD /* Credential.h */,
                                514C76580CE923A1007EF3CD /* CredentialBase.cpp */,
                                FD31602912B0267600C1A359 /* ConvolverNode.h in Headers */,
                                D8B6152F1032495100C8554A /* Cookie.h in Headers */,
                                E1424C94164B52C800F32D40 /* CookieJar.h in Headers */,
+                               7A5699702086C619000E0433 /* CookieRequestHeaderFieldProxy.h in Headers */,
                                339B5B63131DAA3200F48D02 /* CookiesStrategy.h in Headers */,
                                33D0212D131DB37B004091A8 /* CookieStorage.h in Headers */,
                                5120BBAF1F1CECE700EFEBF1 /* CookieStorageObserver.h in Headers */,
index 172e8bb..374ff52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "CookieJar.h"
 
+#include "CookieRequestHeaderFieldProxy.h"
 #include "CookiesStrategy.h"
 #include "Document.h"
 #include "Frame.h"
@@ -55,11 +56,17 @@ inline NetworkStorageSession& storageSession(const Document& document)
     return context ? context->storageSession() : NetworkStorageSession::defaultStorageSession();
 }
 
+static IncludeSecureCookies shouldIncludeSecureCookies(const Document& document, const URL& url)
+{
+    return (url.protocolIs("https") && !document.foundMixedContent().contains(SecurityContext::MixedContentType::Active)) ? IncludeSecureCookies::Yes : IncludeSecureCookies::No;
+}
+
 String cookies(Document& document, const URL& url)
 {
     TraceScope scope(FetchCookiesStart, FetchCookiesEnd);
 
-    auto includeSecureCookies = (url.protocolIs("https") && !document.foundMixedContent().contains(SecurityContext::MixedContentType::Active)) ? IncludeSecureCookies::Yes : IncludeSecureCookies::No;
+    auto includeSecureCookies = shouldIncludeSecureCookies(document, url);
+
     std::pair<String, bool> result;
     auto frame = document.frame();
     if (frame)
@@ -73,6 +80,18 @@ String cookies(Document& document, const URL& url)
     return result.first;
 }
 
+CookieRequestHeaderFieldProxy cookieRequestHeaderFieldProxy(const Document& document, const URL& url)
+{
+    TraceScope scope(FetchCookiesStart, FetchCookiesEnd);
+
+    auto includeSecureCookies = shouldIncludeSecureCookies(document, url);
+
+    if (auto* frame = document.frame())
+        return { storageSession(document).sessionID(), document.firstPartyForCookies(), url, frame->loader().client().frameID(), frame->loader().client().pageID(), includeSecureCookies };
+
+    return { storageSession(document).sessionID(), document.firstPartyForCookies(), url, std::nullopt, std::nullopt, includeSecureCookies };
+}
+
 void setCookies(Document& document, const URL& url, const String& cookieString)
 {
     auto frame = document.frame();
@@ -89,7 +108,8 @@ bool cookiesEnabled(const Document& document)
 
 String cookieRequestHeaderFieldValue(Document& document, const URL& url)
 {
-    auto includeSecureCookies = (url.protocolIs("https") && !document.foundMixedContent().contains(SecurityContext::MixedContentType::Active)) ? IncludeSecureCookies::Yes : IncludeSecureCookies::No;
+    auto includeSecureCookies = shouldIncludeSecureCookies(document, url);
+
     std::pair<String, bool> result;
     auto frame = document.frame();
     if (frame)
index d79a09b..5fa705d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@ namespace WebCore {
 class Document;
 class URL;
 struct Cookie;
+struct CookieRequestHeaderFieldProxy;
 
 // Functions in this file take a Document pointer to determine which cookie storage to use. We should merge that into call sites, and use PlatformCookieJar directly.
 
@@ -42,6 +43,7 @@ WEBCORE_EXPORT void setCookies(Document&, const URL&, const String& cookieString
 
 WEBCORE_EXPORT bool cookiesEnabled(const Document&);
 WEBCORE_EXPORT String cookieRequestHeaderFieldValue(Document&, const URL&);
+WEBCORE_EXPORT CookieRequestHeaderFieldProxy cookieRequestHeaderFieldProxy(const Document&, const URL&);
 WEBCORE_EXPORT bool getRawCookies(const Document&, const URL&, Vector<Cookie>&);
 WEBCORE_EXPORT void deleteCookie(const Document&, const URL&, const String& cookieName);
 
diff --git a/Source/WebCore/platform/network/CookieRequestHeaderFieldProxy.h b/Source/WebCore/platform/network/CookieRequestHeaderFieldProxy.h
new file mode 100644 (file)
index 0000000..6b215dd
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CookiesStrategy.h"
+#include "URL.h"
+#include <pal/SessionID.h>
+
+namespace WebCore {
+
+struct CookieRequestHeaderFieldProxy {
+    PAL::SessionID m_sessionID;
+    URL m_firstParty;
+    URL m_url;
+    std::optional<uint64_t> m_frameID;
+    std::optional<uint64_t> m_pageID;
+    IncludeSecureCookies m_includeSecureCookies { IncludeSecureCookies::No };
+
+    CookieRequestHeaderFieldProxy() = default;
+    CookieRequestHeaderFieldProxy(PAL::SessionID&& sessionID, URL&& firstParty, URL&& url, std::optional<uint64_t>&& frameID, std::optional<uint64_t>&& pageID, IncludeSecureCookies includeSecureCookies)
+        : m_sessionID(WTFMove(sessionID))
+        , m_firstParty(WTFMove(firstParty))
+        , m_url(WTFMove(url))
+        , m_frameID(WTFMove(frameID))
+        , m_pageID(WTFMove(pageID))
+        , m_includeSecureCookies(includeSecureCookies)
+    {
+    }
+
+    CookieRequestHeaderFieldProxy(PAL::SessionID sessionID, const URL& firstParty, const URL& url, const std::optional<uint64_t>& frameID, const std::optional<uint64_t>& pageID, IncludeSecureCookies includeSecureCookies)
+        : m_sessionID(sessionID)
+        , m_firstParty(firstParty)
+        , m_url(url)
+        , m_frameID(frameID)
+        , m_pageID(pageID)
+        , m_includeSecureCookies(includeSecureCookies)
+    {
+    }
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<CookieRequestHeaderFieldProxy> decode(Decoder&);
+};
+
+template<class Encoder>
+void CookieRequestHeaderFieldProxy::encode(Encoder& encoder) const
+{
+    encoder << m_sessionID;
+    encoder << m_firstParty;
+    encoder << m_url;
+    encoder << m_frameID;
+    encoder << m_pageID;
+    encoder << m_includeSecureCookies;
+}
+
+template<class Decoder>
+std::optional<CookieRequestHeaderFieldProxy> CookieRequestHeaderFieldProxy::decode(Decoder& decoder)
+{
+    PAL::SessionID sessionID;
+    if (!decoder.decode(sessionID))
+        return std::nullopt;
+
+    URL firstParty;
+    if (!decoder.decode(firstParty))
+        return std::nullopt;
+
+    URL url;
+    if (!decoder.decode(url))
+        return std::nullopt;
+
+    std::optional<uint64_t> frameID;
+    if (!decoder.decode(frameID))
+        return std::nullopt;
+
+    std::optional<uint64_t> pageID;
+    if (!decoder.decode(pageID))
+        return std::nullopt;
+
+    IncludeSecureCookies includeSecureCookies;
+    if (!decoder.decode(includeSecureCookies))
+        return std::nullopt;
+
+    return {{ WTFMove(sessionID), WTFMove(firstParty), WTFMove(url), WTFMove(*frameID), WTFMove(*pageID), includeSecureCookies }};
+}
+
+}
index cb16967..9441c2b 100644 (file)
@@ -36,6 +36,7 @@ class URL;
 class NetworkStorageSession;
 
 struct Cookie;
+struct CookieRequestHeaderFieldProxy;
 
 enum class IncludeSecureCookies;
 
@@ -45,6 +46,7 @@ WEBCORE_EXPORT std::pair<String, bool> cookiesForDOM(const NetworkStorageSession
 WEBCORE_EXPORT void setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String&);
 WEBCORE_EXPORT bool cookiesEnabled(const NetworkStorageSession&);
 WEBCORE_EXPORT std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies);
+WEBCORE_EXPORT std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const CookieRequestHeaderFieldProxy&);
 WEBCORE_EXPORT bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&);
 WEBCORE_EXPORT void deleteCookie(const NetworkStorageSession&, const URL&, const String&);
 WEBCORE_EXPORT void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames);
index acd5819..270f613 100644 (file)
@@ -31,6 +31,7 @@
 #include "config.h"
 #include "SocketStreamHandle.h"
 
+#include "CookieRequestHeaderFieldProxy.h"
 #include "SocketStreamHandleClient.h"
 #include <wtf/Function.h>
 
@@ -52,7 +53,14 @@ void SocketStreamHandle::sendData(const char* data, size_t length, Function<void
 {
     if (m_state == Connecting || m_state == Closing)
         return completionHandler(false);
-    platformSend(data, length, WTFMove(completionHandler));
+    platformSend(reinterpret_cast<const uint8_t*>(data), length, WTFMove(completionHandler));
+}
+
+void SocketStreamHandle::sendHandshake(CString&& handshake, std::optional<CookieRequestHeaderFieldProxy>&& headerFieldProxy, Function<void(bool, bool)> completionHandler)
+{
+    if (m_state == Connecting || m_state == Closing)
+        return completionHandler(false, false);
+    platformSendHandshake(reinterpret_cast<const uint8_t*>(handshake.data()), handshake.length(), headerFieldProxy, WTFMove(completionHandler));
 }
 
 void SocketStreamHandle::close()
index c2979c4..b59bdba 100644 (file)
@@ -36,6 +36,7 @@
 
 namespace WebCore {
 
+struct CookieRequestHeaderFieldProxy;
 class SocketStreamHandleClient;
 
 typedef struct {
@@ -53,6 +54,7 @@ public:
     SocketStreamState state() const;
 
     void sendData(const char* data, size_t length, Function<void(bool)>);
+    void sendHandshake(CString&& handshake, std::optional<CookieRequestHeaderFieldProxy>&&, Function<void(bool, bool)>);
     void close(); // Disconnect after all data in buffer are sent.
     void disconnect();
     virtual size_t bufferedAmount() = 0;
@@ -60,7 +62,8 @@ public:
 protected:
     WEBCORE_EXPORT SocketStreamHandle(const URL&, SocketStreamHandleClient&);
 
-    virtual void platformSend(const char* data, size_t length, Function<void(bool)>&&) = 0;
+    virtual void platformSend(const uint8_t* data, size_t length, Function<void(bool)>&&) = 0;
+    virtual void platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>&, Function<void(bool, bool)>&&) = 0;
     virtual void platformClose() = 0;
 
     URL m_url;
index f11afc9..c6ac746 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "SocketStreamHandleImpl.h"
 
+#include "CookieRequestHeaderFieldProxy.h"
+#include "NetworkStorageSession.h"
+#include "PlatformCookieJar.h"
 #include "SocketStreamHandleClient.h"
 #include <wtf/Function.h>
 
 namespace WebCore {
 
-void SocketStreamHandleImpl::platformSend(const char* data, size_t length, Function<void(bool)>&& completionHandler)
+void SocketStreamHandleImpl::platformSend(const uint8_t* data, size_t length, Function<void(bool)>&& completionHandler)
 {
     if (!m_buffer.isEmpty()) {
         if (m_buffer.size() + length > maxBufferSize) {
@@ -60,6 +63,90 @@ void SocketStreamHandleImpl::platformSend(const char* data, size_t length, Funct
     return completionHandler(true);
 }
 
+static size_t removeTerminationCharacters(const uint8_t* data, size_t dataLength)
+{
+#ifndef NDEBUG
+    ASSERT(dataLength > 2);
+    ASSERT(data[dataLength - 2] == '\r');
+    ASSERT(data[dataLength - 1] == '\n');
+#else
+    UNUSED_PARAM(data);
+#endif
+
+    // Remove the terminating '\r\n'
+    return dataLength - 2;
+}
+
+static std::pair<Vector<uint8_t>, bool> cookieDataForHandshake(const CookieRequestHeaderFieldProxy& headerFieldProxy)
+{
+    auto networkStorageSession = NetworkStorageSession::storageSession(headerFieldProxy.m_sessionID);
+    RELEASE_ASSERT(networkStorageSession);
+
+    String cookieDataString;
+    bool secureCookiesAccessed = false;
+    std::tie(cookieDataString, secureCookiesAccessed) = WebCore::cookieRequestHeaderFieldValue(*networkStorageSession, headerFieldProxy);
+    if (cookieDataString.isEmpty())
+        return { { }, secureCookiesAccessed };
+
+    CString cookieData = cookieDataString.utf8();
+
+    Vector<uint8_t> data = { 'C', 'o', 'o', 'k', 'i', 'e', ':', ' ' };
+    data.append(cookieData.data(), cookieData.length());
+    data.appendVector(Vector<uint8_t>({ '\r', '\n', '\r', '\n' }));
+
+    return { data, secureCookiesAccessed };
+}
+
+void SocketStreamHandleImpl::platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>& headerFieldProxy, Function<void(bool, bool)>&& completionHandler)
+{
+    Vector<uint8_t> cookieData;
+    bool secureCookiesAccessed = false;
+
+    if (headerFieldProxy) {
+        std::tie(cookieData, secureCookiesAccessed) = cookieDataForHandshake(headerFieldProxy.value());
+        if (cookieData.size())
+            length = removeTerminationCharacters(data, length);
+    }
+
+    if (!m_buffer.isEmpty()) {
+        if (m_buffer.size() + length + cookieData.size() > maxBufferSize) {
+            // FIXME: report error to indicate that buffer has no more space.
+            return completionHandler(false, secureCookiesAccessed);
+        }
+        m_buffer.append(data, length);
+        m_buffer.append(cookieData.data(), cookieData.size());
+        m_client.didUpdateBufferedAmount(*this, bufferedAmount());
+        return completionHandler(true, secureCookiesAccessed);
+    }
+    size_t bytesWritten = 0;
+    if (m_state == Open) {
+        // Unfortunately, we need to send the data in one buffer or else the handshake fails.
+        Vector<uint8_t> sendData;
+        sendData.reserveCapacity(length + cookieData.size());
+        sendData.append(data, length);
+        sendData.append(cookieData.data(), cookieData.size());
+
+        if (auto result = platformSendInternal(sendData.data(), sendData.size()))
+            bytesWritten = result.value();
+        else
+            return completionHandler(false, secureCookiesAccessed);
+    }
+    if (m_buffer.size() + length + cookieData.size() - bytesWritten > maxBufferSize) {
+        // FIXME: report error to indicate that buffer has no more space.
+        return completionHandler(false, secureCookiesAccessed);
+    }
+    if (bytesWritten < length + cookieData.size()) {
+        size_t cookieBytesWritten = 0;
+        if (bytesWritten < length)
+            m_buffer.append(data + bytesWritten, length - bytesWritten);
+        else
+            cookieBytesWritten = bytesWritten - length;
+        m_buffer.append(cookieData.data() + cookieBytesWritten, cookieData.size() - cookieBytesWritten);
+        m_client.didUpdateBufferedAmount(static_cast<SocketStreamHandle&>(*this), bufferedAmount());
+    }
+    return completionHandler(true, secureCookiesAccessed);
+}
+
 bool SocketStreamHandleImpl::sendPendingData()
 {
     if (m_state != Open && m_state != Closing)
index 1bdce08..c5f9c76 100644 (file)
@@ -50,11 +50,12 @@ public:
 
     virtual ~SocketStreamHandleImpl();
 
-    WEBCORE_EXPORT void platformSend(const char* data, size_t length, Function<void(bool)>&&) final;
+    WEBCORE_EXPORT void platformSend(const uint8_t* data, size_t length, Function<void(bool)>&&) final;
+    WEBCORE_EXPORT void platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>&, Function<void(bool, bool)>&&) final;
     WEBCORE_EXPORT void platformClose() final;
 private:
     size_t bufferedAmount() final;
-    std::optional<size_t> platformSendInternal(const char*, size_t);
+    std::optional<size_t> platformSendInternal(const uint8_t*, size_t);
     bool sendPendingData();
 
     WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&);
@@ -103,7 +104,7 @@ private:
     String m_credentialPartition;
     SourceApplicationAuditToken m_auditData;
 
-    StreamBuffer<char, 1024 * 1024> m_buffer;
+    StreamBuffer<uint8_t, 1024 * 1024> m_buffer;
     static const unsigned maxBufferSize = 100 * 1024 * 1024;
 };
 
index 76ff83b..f186151 100644 (file)
@@ -696,7 +696,7 @@ SocketStreamHandleImpl::~SocketStreamHandleImpl()
     ASSERT(!m_pacRunLoopSource);
 }
 
-std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const char* data, size_t length)
+std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const uint8_t* data, size_t length)
 {
     if (!m_writeStream)
         return 0;
index 329f3a5..5fac123 100644 (file)
@@ -22,6 +22,7 @@
 
 #if USE(CURL)
 #include "Cookie.h"
+#include "CookieRequestHeaderFieldProxy.h"
 #include "NetworkStorageSession.h"
 #include "URL.h"
 
@@ -44,6 +45,11 @@ std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSessio
     return session.cookieStorage().cookieRequestHeaderFieldValue(session, firstParty, url, frameID, pageID, includeSecureCookies);
 }
 
+std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const CookieRequestHeaderFieldProxy& headerFieldProxy)
+{
+    return session.cookieStorage().cookieRequestHeaderFieldValue(session, headerFieldProxy.m_firstParty, headerFieldProxy.m_url, headerFieldProxy.m_frameID, headerFieldProxy.m_pageID, headerFieldProxy.m_includeSecureCookies);
+}
+
 bool cookiesEnabled(const NetworkStorageSession& session)
 {
     return session.cookieStorage().cookiesEnabled(session);
index b8c5469..7b5b079 100644 (file)
@@ -23,6 +23,7 @@
 namespace WebCore {
 
 struct Cookie;
+struct CookieRequestHeaderFieldProxy;
 class NetworkStorageSession;
 class URL;
 
@@ -33,6 +34,7 @@ public:
     virtual void setCookiesFromHTTPResponse(const NetworkStorageSession&, const URL&, const String&) const = 0;
     virtual bool cookiesEnabled(const NetworkStorageSession&) const = 0;
     virtual std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const = 0;
+    virtual std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const CookieRequestHeaderFieldProxy&) const = 0;
     virtual bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) const = 0;
     virtual void deleteCookie(const NetworkStorageSession&, const URL&, const String&) const = 0;
     virtual void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) const = 0;
index f8f497c..d699db9 100644 (file)
@@ -93,6 +93,11 @@ std::pair<String, bool> CookieJarCurlDatabase::cookieRequestHeaderFieldValue(con
     return { cookiesForSession(session, firstParty, url, true), false };
 }
 
+std::pair<String, bool> CookieJarCurlDatabase::cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const CookieRequestHeaderFieldProxy& headerFieldProxy) const
+{
+    return cookieRequestHeaderFieldValue(session, headerFieldProxy.m_firstParty, headerFieldProxy.m_url, headerFieldProxy.m_frameID, headerFieldProxy.m_pageID, headerFieldProxy.m_includeSecureCookies);    
+}
+
 bool CookieJarCurlDatabase::cookiesEnabled(const NetworkStorageSession& session) const
 {
     return session.cookieDatabase().isEnabled();
index d1d6651..a97f9b7 100644 (file)
@@ -34,6 +34,7 @@ class CookieJarCurlDatabase : public CookieJarCurl {
     void setCookiesFromHTTPResponse(const NetworkStorageSession&, const URL&, const String&) const override;
     bool cookiesEnabled(const NetworkStorageSession&) const override;
     std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const override;
+    std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const CookieRequestHeaderFieldProxy&) const override;
     bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) const override;
     void deleteCookie(const NetworkStorageSession&, const URL&, const String&) const override;
     void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) const override;
index ca7ed2d..0fb67ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,13 +57,14 @@ public:
 
     virtual ~SocketStreamHandleImpl();
 
-    WEBCORE_EXPORT void platformSend(const char* data, size_t length, Function<void(bool)>&&) final;
+    WEBCORE_EXPORT void platformSend(const uint8_t* data, size_t length, Function<void(bool)>&&) final;
+    WEBCORE_EXPORT void platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>&, Function<void(bool, bool)>&&) final;
     WEBCORE_EXPORT void platformClose() final;
 private:
     WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&);
 
     size_t bufferedAmount() final;
-    std::optional<size_t> platformSendInternal(const char*, size_t);
+    std::optional<size_t> platformSendInternal(const uint8_t*, size_t);
     bool sendPendingData();
 
     bool readData(CURL*);
@@ -102,7 +103,7 @@ private:
     Deque<SocketData> m_receiveData;
     bool m_closed { false };
 
-    StreamBuffer<char, 1024 * 1024> m_buffer;
+    StreamBuffer<uint8_t, 1024 * 1024> m_buffer;
     static const unsigned maxBufferSize = 100 * 1024 * 1024;
 };
 
index 441f32d..2eb4f7d 100644 (file)
@@ -66,7 +66,7 @@ SocketStreamHandleImpl::~SocketStreamHandleImpl()
     ASSERT(!m_workerThread);
 }
 
-std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const char* data, size_t length)
+std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const uint8_t* data, size_t length)
 {
     LOG(Network, "SocketStreamHandle %p platformSend", this);
 
@@ -74,7 +74,7 @@ std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const char* d
 
     startThread();
 
-    auto copy = createCopy(data, length);
+    auto copy = createCopy(reinterpret_cast<const char*>(data), length);
 
     std::lock_guard<Lock> lock(m_mutexSend);
     m_sendData.append(SocketData { WTFMove(copy), length });
index 4e8a7ea..c13e09a 100644 (file)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "PlatformCookieJar.h"
 
+#import "CookieRequestHeaderFieldProxy.h"
 #import "CookiesStrategy.h"
 #import "NetworkStorageSession.h"
 #import <pal/spi/cf/CFNetworkSPI.h>
@@ -251,6 +252,11 @@ std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSessio
     return cookiesForSession(session, firstParty, url, frameID, pageID, IncludeHTTPOnly, includeSecureCookies);
 }
 
+std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const CookieRequestHeaderFieldProxy& headerFieldProxy)
+{
+    return cookiesForSession(session, headerFieldProxy.m_firstParty, headerFieldProxy.m_url, headerFieldProxy.m_frameID, headerFieldProxy.m_pageID, IncludeHTTPOnly, headerFieldProxy.m_includeSecureCookies);
+}
+
 void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& cookieStr)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
index 96bec16..3a9c617 100644 (file)
@@ -23,6 +23,7 @@
 #if USE(SOUP)
 
 #include "Cookie.h"
+#include "CookieRequestHeaderFieldProxy.h"
 #include "CookiesStrategy.h"
 #include "GUniquePtrSoup.h"
 #include "NetworkStorageSession.h"
@@ -133,6 +134,11 @@ std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSessio
     return cookiesForSession(session, url, true, includeSecureCookies);
 }
 
+std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const CookieRequestHeaderFieldProxy& headerFieldProxy)
+{
+    return cookieRequestHeaderFieldValue(session, headerFieldProxy.m_firstParty, headerFieldProxy.m_url, headerFieldProxy.m_frameID, headerFieldProxy.m_pageID, headerFieldProxy.m_includeSecureCookies);
+}
+
 bool cookiesEnabled(const NetworkStorageSession& session)
 {
     auto policy = soup_cookie_jar_get_accept_policy(session.cookieStorage());
index 8a32eb1..3bdfd19 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc.  All rights reserved.
  * Copyright (C) 2012 Samsung Electronics Ltd. All Rights Reserved.
  *
@@ -51,13 +51,14 @@ public:
     static Ref<SocketStreamHandleImpl> create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&);
     virtual ~SocketStreamHandleImpl();
 
-    void platformSend(const char* data, size_t length, Function<void(bool)>&&) final;
+    void platformSend(const uint8_t* data, size_t length, Function<void(bool)>&&) final;
+    void platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>&, Function<void(bool, bool)>&&) final;
     void platformClose() final;
 private:
     SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&);
 
     size_t bufferedAmount() final;
-    std::optional<size_t> platformSendInternal(const char*, size_t);
+    std::optional<size_t> platformSendInternal(const uint8_t*, size_t);
     bool sendPendingData();
 
     void beginWaitingForSocketWritability();
@@ -79,7 +80,7 @@ private:
     GRefPtr<GCancellable> m_cancellable;
     UniqueArray<char> m_readBuffer;
 
-    StreamBuffer<char, 1024 * 1024> m_buffer;
+    StreamBuffer<uint8_t, 1024 * 1024> m_buffer;
     static const unsigned maxBufferSize = 100 * 1024 * 1024;
 };
 
index 1788066..2d5f497 100644 (file)
@@ -212,14 +212,14 @@ void SocketStreamHandleImpl::writeReady()
     sendPendingData();
 }
 
-std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const char* data, size_t length)
+std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const uint8_t* data, size_t length)
 {
     LOG(Network, "SocketStreamHandle %p platformSend", this);
     if (!m_outputStream || !data)
         return 0;
 
     GUniqueOutPtr<GError> error;
-    gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, m_cancellable.get(), &error.outPtr());
+    gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), reinterpret_cast<const char*>(data), length, m_cancellable.get(), &error.outPtr());
     if (error) {
         if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
             beginWaitingForSocketWritability();
index 505c631..b1b4995 100644 (file)
@@ -1,3 +1,30 @@
+2018-04-20  Brent Fulgham  <bfulgham@apple.com>
+
+        Limit cookie header access to Network process
+        https://bugs.webkit.org/show_bug.cgi?id=184764
+        <rdar://problem/36785285>
+
+        Reviewed by Youenn Fablet.
+
+        Revise the handling of cookie request headers so that we don't interact with them in the
+        WebContent process. They are only needed for interaction with the server and the network
+        process, so we should limit their scope to just the Network process.
+
+        Instead, we should handle a token that represents the cookie headers in the WebContent
+        process, which can be converted to the relevant cookie data in the network process when
+        needed.
+
+        * NetworkProcess/NetworkSocketStream.cpp:
+        (WebKit::NetworkSocketStream::sendHandshake):
+        * NetworkProcess/NetworkSocketStream.h:
+        * NetworkProcess/NetworkSocketStream.messages.in:
+        * WebProcess/Network/WebSocketStream.cpp:
+        (WebKit::WebSocketStream::networkProcessCrashed):
+        (WebKit::WebSocketStream::platformSendHandshake):
+        (WebKit::WebSocketStream::didSendHandshake):
+        * WebProcess/Network/WebSocketStream.h:
+        * WebProcess/Network/WebSocketStream.messages.in:
+
 2018-04-20  Jeremy Jones  <jeremyj@apple.com>
 
         Disable backward and forward navigation swipes while in fullscreen.
index c116083..8a77e46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #include "DataReference.h"
 #include "WebSocketStreamMessages.h"
+#include <WebCore/CookieRequestHeaderFieldProxy.h>
 #include <WebCore/SocketStreamError.h>
 #include <WebCore/SocketStreamHandleImpl.h>
 
@@ -49,11 +50,18 @@ NetworkSocketStream::NetworkSocketStream(URL&& url, PAL::SessionID sessionID, co
 
 void NetworkSocketStream::sendData(const IPC::DataReference& data, uint64_t identifier)
 {
-    m_impl->platformSend(reinterpret_cast<const char *>(data.data()), data.size(), [this, protectedThis = makeRef(*this), identifier] (bool success) {
+    m_impl->platformSend(data.data(), data.size(), [this, protectedThis = makeRef(*this), identifier] (bool success) {
         send(Messages::WebSocketStream::DidSendData(identifier, success));
     });
 }
 
+void NetworkSocketStream::sendHandshake(const IPC::DataReference& data, const std::optional<CookieRequestHeaderFieldProxy>& headerFieldProxy, uint64_t identifier)
+{
+    m_impl->platformSendHandshake(data.data(), data.size(), headerFieldProxy, [this, protectedThis = makeRef(*this), identifier] (bool success, bool didAccessSecureCookies) {
+        send(Messages::WebSocketStream::DidSendHandshake(identifier, success, didAccessSecureCookies));
+    });
+}
+
 void NetworkSocketStream::close()
 {
     m_impl->platformClose();
index 51f6286..906e58e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,6 +52,7 @@ public:
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
 
     void sendData(const IPC::DataReference&, uint64_t);
+    void sendHandshake(const IPC::DataReference&, const std::optional<WebCore::CookieRequestHeaderFieldProxy>&, uint64_t);
     void close();
     
     // SocketStreamHandleClient
index d7e823a..02e8518 100644 (file)
@@ -22,5 +22,6 @@
 
 messages -> NetworkSocketStream {
     SendData(IPC::DataReference data, uint64_t identifier)
+    SendHandshake(IPC::DataReference data, std::optional<WebCore::CookieRequestHeaderFieldProxy> headerFieldProxy, uint64_t identifier)
     Close()
 }
index 413dffb..37e3734 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,6 +32,7 @@
 #include "NetworkSocketStreamMessages.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebProcess.h"
+#include <WebCore/CookieRequestHeaderFieldProxy.h>
 #include <WebCore/SocketStreamError.h>
 #include <WebCore/SocketStreamHandleClient.h>
 #include <pal/SessionID.h>
@@ -57,6 +58,8 @@ void WebSocketStream::networkProcessCrashed()
     for (auto& stream : globalWebSocketStreamMap().values()) {
         for (auto& callback : stream->m_sendDataCallbacks.values())
             callback(false);
+        for (auto& callback : stream->m_sendHandshakeCallbacks.values())
+            callback(false, false);
         stream->m_client.didFailSocketStream(*stream, SocketStreamError(0, { }, "Network process crashed."));
     }
 
@@ -94,13 +97,22 @@ uint64_t WebSocketStream::messageSenderDestinationID()
     return identifier();
 }
 
-void WebSocketStream::platformSend(const char* data, size_t length, Function<void(bool)>&& completionHandler)
+void WebSocketStream::platformSend(const uint8_t* data, size_t length, Function<void(bool)>&& completionHandler)
 {
     static uint64_t nextDataIdentifier = 1;
     uint64_t dataIdentifier = nextDataIdentifier++;
-    send(Messages::NetworkSocketStream::SendData(IPC::DataReference(reinterpret_cast<const uint8_t *>(data), length), dataIdentifier));
+    send(Messages::NetworkSocketStream::SendData(IPC::DataReference(data, length), dataIdentifier));
     ASSERT(!m_sendDataCallbacks.contains(dataIdentifier));
-    m_sendDataCallbacks.set(dataIdentifier, WTFMove(completionHandler));
+    m_sendDataCallbacks.add(dataIdentifier, WTFMove(completionHandler));
+}
+
+void WebSocketStream::platformSendHandshake(const uint8_t* data, size_t length, const std::optional<CookieRequestHeaderFieldProxy>& headerFieldProxy, Function<void(bool, bool)>&& completionHandler)
+{
+    static uint64_t nextDataIdentifier = 1;
+    uint64_t dataIdentifier = nextDataIdentifier++;
+    send(Messages::NetworkSocketStream::SendHandshake(IPC::DataReference(data, length), headerFieldProxy, dataIdentifier));
+    ASSERT(!m_sendHandshakeCallbacks.contains(dataIdentifier));
+    m_sendHandshakeCallbacks.add(dataIdentifier, WTFMove(completionHandler));
 }
 
 void WebSocketStream::didSendData(uint64_t identifier, bool success)
@@ -108,7 +120,13 @@ void WebSocketStream::didSendData(uint64_t identifier, bool success)
     ASSERT(m_sendDataCallbacks.contains(identifier));
     m_sendDataCallbacks.take(identifier)(success);
 }
-    
+
+void WebSocketStream::didSendHandshake(uint64_t identifier, bool success, bool didAccessSecureCookies)
+{
+    ASSERT(m_sendHandshakeCallbacks.contains(identifier));
+    m_sendHandshakeCallbacks.take(identifier)(success, didAccessSecureCookies);
+}
+
 void WebSocketStream::platformClose()
 {
     send(Messages::NetworkSocketStream::Close());
index 9e9b834..3feb6a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,7 +52,8 @@ public:
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
     
     // SocketStreamHandle
-    void platformSend(const char*, size_t, Function<void(bool)>&&) final;
+    void platformSend(const uint8_t*, size_t, Function<void(bool)>&&) final;
+    void platformSendHandshake(const uint8_t*, size_t, const std::optional<WebCore::CookieRequestHeaderFieldProxy>&, Function<void(bool, bool)>&&);
     void platformClose() final;
     size_t bufferedAmount() final;
 
@@ -64,7 +65,8 @@ public:
     void didUpdateBufferedAmount(uint64_t);
     void didFailSocketStream(WebCore::SocketStreamError&&);
 
-    void didSendData(uint64_t, bool);
+    void didSendData(uint64_t, bool success);
+    void didSendHandshake(uint64_t, bool success, bool didAccessSecureCookies);
     
 private:
     // MessageSender
@@ -77,6 +79,7 @@ private:
     size_t m_bufferedAmount { 0 };
     WebCore::SocketStreamHandleClient& m_client;
     HashMap<uint64_t, Function<void(bool)>> m_sendDataCallbacks;
+    HashMap<uint64_t, Function<void(bool, bool)>> m_sendHandshakeCallbacks;
 };
 
 } // namespace WebKit
index 56e5908..e759177 100644 (file)
@@ -29,4 +29,5 @@ messages -> WebSocketStream {
     DidFailSocketStream(WebCore::SocketStreamError error)
 
     DidSendData(uint64_t identifier, bool success)
+    DidSendHandshake(uint64_t identifier, bool success, bool didAccessSecureCookies)
 }