diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp | 122 |
1 files changed, 40 insertions, 82 deletions
diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp index b0ed328eb15..84d97869282 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp @@ -34,18 +34,17 @@ #include "modules/websockets/WebSocketHandshake.h" #include "core/dom/Document.h" -#include "core/dom/ExecutionContext.h" #include "core/inspector/ScriptCallStack.h" #include "core/loader/CookieJar.h" #include "modules/websockets/WebSocket.h" #include "platform/Cookie.h" +#include "platform/Crypto.h" #include "platform/Logging.h" #include "platform/network/HTTPHeaderMap.h" #include "platform/network/HTTPParsers.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" #include "wtf/CryptographicallyRandomNumber.h" -#include "wtf/SHA1.h" #include "wtf/StdLibExtras.h" #include "wtf/StringExtras.h" #include "wtf/Vector.h" @@ -56,23 +55,11 @@ namespace WebCore { -namespace { - -// FIXME: The spec says that the Sec-WebSocket-Protocol header in a handshake -// response can't be null if the header in a request is not null. -// Some servers are not accustomed to the shutdown, -// so we provide an adhoc white-list for it tentatively. -const char* const missingProtocolWhiteList[] = { - "ica.citrix.com", -}; - String formatHandshakeFailureReason(const String& detail) { return "Error during WebSocket handshake: " + detail; } -} // namespace - static String resourceName(const KURL& url) { StringBuilder name; @@ -104,10 +91,9 @@ static String hostName(const KURL& url, bool secure) static const size_t maxInputSampleSize = 128; static String trimInputSample(const char* p, size_t len) { - String s = String(p, std::min<size_t>(len, maxInputSampleSize)); if (len > maxInputSampleSize) - s.append(horizontalEllipsis); - return s; + return String(p, maxInputSampleSize) + horizontalEllipsis; + return String(p, len); } static String generateSecWebSocketKey() @@ -121,21 +107,24 @@ static String generateSecWebSocketKey() String WebSocketHandshake::getExpectedWebSocketAccept(const String& secWebSocketKey) { static const char webSocketKeyGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - static const size_t sha1HashSize = 20; // FIXME: This should be defined in SHA1.h. - SHA1 sha1; CString keyData = secWebSocketKey.ascii(); - sha1.addBytes(reinterpret_cast<const uint8_t*>(keyData.data()), keyData.length()); - sha1.addBytes(reinterpret_cast<const uint8_t*>(webSocketKeyGUID), strlen(webSocketKeyGUID)); - Vector<uint8_t, sha1HashSize> hash; - sha1.computeHash(hash); - return base64Encode(reinterpret_cast<const char*>(hash.data()), sha1HashSize); + + StringBuilder digestable; + digestable.append(secWebSocketKey); + digestable.append(webSocketKeyGUID, strlen(webSocketKeyGUID)); + CString digestableCString = digestable.toString().utf8(); + DigestValue digest; + bool digestSuccess = computeDigest(HashAlgorithmSha1, digestableCString.data(), digestableCString.length(), digest); + RELEASE_ASSERT(digestSuccess); + + return base64Encode(reinterpret_cast<const char*>(digest.data()), sha1HashSize); } -WebSocketHandshake::WebSocketHandshake(const KURL& url, const String& protocol, ExecutionContext* context) +WebSocketHandshake::WebSocketHandshake(const KURL& url, const String& protocol, Document* document) : m_url(url) , m_clientProtocol(protocol) , m_secure(m_url.protocolIs("wss")) - , m_context(context) + , m_document(document) , m_mode(Incomplete) { m_secWebSocketKey = generateSecWebSocketKey(); @@ -179,7 +168,7 @@ bool WebSocketHandshake::secure() const String WebSocketHandshake::clientOrigin() const { - return m_context->securityOrigin()->toString(); + return m_document->securityOrigin()->toString(); } String WebSocketHandshake::clientLocation() const @@ -194,6 +183,8 @@ String WebSocketHandshake::clientLocation() const CString WebSocketHandshake::clientHandshakeMessage() const { + ASSERT(m_document); + // Keep the following consistent with clientHandshakeRequest(). StringBuilder builder; @@ -209,15 +200,6 @@ CString WebSocketHandshake::clientHandshakeMessage() const if (!m_clientProtocol.isEmpty()) fields.append("Sec-WebSocket-Protocol: " + m_clientProtocol); - KURL url = httpURLForAuthenticationAndCookies(); - if (m_context->isDocument()) { - Document* document = toDocument(m_context); - String cookie = cookieRequestHeaderFieldValue(document, url); - if (!cookie.isEmpty()) - fields.append("Cookie: " + cookie); - // Set "Cookie2: <cookie>" if cookies 2 exists for url? - } - // Add no-cache headers to avoid compatibility issue. // There are some proxies that rewrite "Connection: upgrade" // to "Connection: close" in the response if a request doesn't contain @@ -231,8 +213,7 @@ CString WebSocketHandshake::clientHandshakeMessage() const if (extensionValue.length()) fields.append("Sec-WebSocket-Extensions: " + extensionValue); - // Add a User-Agent header. - fields.append("User-Agent: " + m_context->userAgent(m_context->url())); + fields.append("User-Agent: " + m_document->userAgent(m_document->url())); // Fields in the handshake are sent by the client in a random order; the // order is not meaningful. Thus, it's ok to send the order we constructed @@ -250,37 +231,36 @@ CString WebSocketHandshake::clientHandshakeMessage() const PassRefPtr<WebSocketHandshakeRequest> WebSocketHandshake::clientHandshakeRequest() const { + ASSERT(m_document); + // Keep the following consistent with clientHandshakeMessage(). // FIXME: do we need to store m_secWebSocketKey1, m_secWebSocketKey2 and // m_key3 in WebSocketHandshakeRequest? - RefPtr<WebSocketHandshakeRequest> request = WebSocketHandshakeRequest::create("GET", m_url); + RefPtr<WebSocketHandshakeRequest> request = WebSocketHandshakeRequest::create(m_url); request->addHeaderField("Upgrade", "websocket"); request->addHeaderField("Connection", "Upgrade"); - request->addHeaderField("Host", hostName(m_url, m_secure)); - request->addHeaderField("Origin", clientOrigin()); + request->addHeaderField("Host", AtomicString(hostName(m_url, m_secure))); + request->addHeaderField("Origin", AtomicString(clientOrigin())); if (!m_clientProtocol.isEmpty()) - request->addHeaderField("Sec-WebSocket-Protocol", m_clientProtocol); + request->addHeaderField("Sec-WebSocket-Protocol", AtomicString(m_clientProtocol)); KURL url = httpURLForAuthenticationAndCookies(); - if (m_context->isDocument()) { - Document* document = toDocument(m_context); - String cookie = cookieRequestHeaderFieldValue(document, url); - if (!cookie.isEmpty()) - request->addHeaderField("Cookie", cookie); - // Set "Cookie2: <cookie>" if cookies 2 exists for url? - } + + String cookie = cookieRequestHeaderFieldValue(m_document, url); + if (!cookie.isEmpty()) + request->addHeaderField("Cookie", AtomicString(cookie)); + // Set "Cookie2: <cookie>" if cookies 2 exists for url? request->addHeaderField("Pragma", "no-cache"); request->addHeaderField("Cache-Control", "no-cache"); - request->addHeaderField("Sec-WebSocket-Key", m_secWebSocketKey); + request->addHeaderField("Sec-WebSocket-Key", AtomicString(m_secWebSocketKey)); request->addHeaderField("Sec-WebSocket-Version", "13"); const String extensionValue = m_extensionDispatcher.createHeaderValue(); if (extensionValue.length()) - request->addHeaderField("Sec-WebSocket-Extensions", extensionValue); + request->addHeaderField("Sec-WebSocket-Extensions", AtomicString(extensionValue)); - // Add a User-Agent header. - request->addHeaderField("User-Agent", m_context->userAgent(m_context->url())); + request->addHeaderField("User-Agent", AtomicString(m_document->userAgent(m_document->url()))); return request.release(); } @@ -291,9 +271,9 @@ void WebSocketHandshake::reset() m_extensionDispatcher.reset(); } -void WebSocketHandshake::clearExecutionContext() +void WebSocketHandshake::clearDocument() { - m_context = 0; + m_document = 0; } int WebSocketHandshake::readServerHandshake(const char* header, size_t len) @@ -353,16 +333,6 @@ const AtomicString& WebSocketHandshake::serverWebSocketProtocol() const return m_response.headerFields().get("sec-websocket-protocol"); } -const AtomicString& WebSocketHandshake::serverSetCookie() const -{ - return m_response.headerFields().get("set-cookie"); -} - -const AtomicString& WebSocketHandshake::serverSetCookie2() const -{ - return m_response.headerFields().get("set-cookie2"); -} - const AtomicString& WebSocketHandshake::serverUpgrade() const { return m_response.headerFields().get("upgrade"); @@ -482,7 +452,7 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e bool sawSecWebSocketAcceptHeaderField = false; bool sawSecWebSocketProtocolHeaderField = false; const char* p = start; - for (; p < end; p++) { + while (p < end) { size_t consumedLength = parseHTTPHeader(p, end - p, m_failureReason, name, value); if (!consumedLength) return 0; @@ -520,7 +490,7 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e String extensions = m_extensionDispatcher.acceptedExtensions(); if (!extensions.isEmpty()) - m_response.addHeaderField("Sec-WebSocket-Extensions", extensions); + m_response.addHeaderField("Sec-WebSocket-Extensions", AtomicString(extensions)); return p; } @@ -563,26 +533,14 @@ bool WebSocketHandshake::checkResponseHeaders() return false; } Vector<String> result; - m_clientProtocol.split(String(WebSocket::subProtocolSeperator()), result); + m_clientProtocol.split(String(WebSocket::subprotocolSeperator()), result); if (!result.contains(serverWebSocketProtocol)) { m_failureReason = formatHandshakeFailureReason("'Sec-WebSocket-Protocol' header value '" + serverWebSocketProtocol + "' in response does not match any of sent values"); return false; } } else if (!m_clientProtocol.isEmpty()) { - // FIXME: Some servers are not accustomed to this failure, so we provide an adhoc white-list for it tentatively. - Vector<String> protocols; - m_clientProtocol.split(String(WebSocket::subProtocolSeperator()), protocols); - bool match = false; - for (size_t i = 0; i < protocols.size() && !match; ++i) { - for (size_t j = 0; j < WTF_ARRAY_LENGTH(missingProtocolWhiteList) && !match; ++j) { - if (protocols[i] == missingProtocolWhiteList[j]) - match = true; - } - } - if (!match) { - m_failureReason = formatHandshakeFailureReason("Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received"); - return false; - } + m_failureReason = formatHandshakeFailureReason("Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received"); + return false; } return true; } |