From ce16adc5c13b56b0f8a6487c71fb030a9bccafce Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Mon, 7 Mar 2016 15:54:02 +0100 Subject: [PATCH] Define the WebSocket client handshake in terms of Fetch Fixes #235. --- Overview.html | 172 ++++++++++++++++++++++++++++++++++++++++++---- Overview.src.html | 160 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 305 insertions(+), 27 deletions(-) diff --git a/Overview.html b/Overview.html index 0fd37582d..72030a1ad 100644 --- a/Overview.html +++ b/Overview.html @@ -7,7 +7,7 @@

Fetch

-

Living Standard — Last Updated 8 March 2016

+

Living Standard — Last Updated 9 March 2016

Participate: @@ -93,6 +93,10 @@

Table of Contents

  • 6.5 Structured cloning of Headers, Request, and Response objects
  • 6.6 Fetch method
  • 6.7 Garbage collection
  • +
  • 7 WebSocket protocol alterations +
      +
    1. 7.1 Connections
    2. +
    3. 7.2 Opening handshake
  • Background reading
    1. HTTP header layer division
    2. @@ -732,7 +736,7 @@

      3.1.5 Requests

      connect-src navigator.sendBeacon(), EventSource, HTML's ping="", fetch(), - XMLHttpRequest, Cache API? + XMLHttpRequest, WebSocket, Cache API? "object" object-src @@ -873,14 +877,15 @@

      3.1.5 Requests

      synchronous flag. Unless stated otherwise it is unset.

      A request has an associated -mode, which is "navigate", -"same-origin", "no-cors", or "cors". -Unless stated otherwise, it is "no-cors". +mode, which is "same-origin", +"cors", "no-cors", "navigate", or +"websocket". Unless stated otherwise, it is "no-cors".

      Even though the default request mode is "no-cors", standards are highly -discouraged from using it for new features. It is rather unsafe. "navigate" is a -special value for HTML. [HTML] +discouraged from using it for new features. It is rather unsafe. "navigate" and +"websocket" are special values for the HTML Standard. +[HTML]

      A request has an associated use-CORS-preflight flag. Unless stated otherwise, it is unset. @@ -1909,7 +1914,7 @@

      5.1 Main fetch

      scheme is "about"
      request's mode is - "navigate" + "navigate" or "websocket"

      The result of performing a basic fetch using request. @@ -2817,10 +2822,21 @@

      5.6 HTTP-network fetch

      Let credentials be true if credentials flag is set, and false otherwise. -

    3. Let connection be the result of - obtaining a connection, given request's - current url's - origin and credentials. +

    4. +

      Switch on request's mode: + +

      +
      "websocket" +

      Let connection be the result of + obtaining a WebSocket connection, given + request's current url. + +

      Otherwise +

      Let connection be the result of + obtaining a connection, given request's + current url's + origin and credentials. +

    5. If connection is failure, return a network error. @@ -3914,7 +3930,8 @@

      6.3 Request class

      "serviceworker" is omitted from RequestDestination as it cannot be observed from JavaScript. Implementations will still need to support it as a -destination. +destination. "websocket" is +omitted from RequestMode as it cannot be used nor observed from JavaScript.

      A Request object has an associated request (a request). @@ -4606,7 +4623,7 @@

      6.7 Garbage collectionThe server being able to observe garbage collection has precedent, e.g., -with WebSocket and XMLHttpRequest. +with WebSocket and XMLHttpRequest objects.

      The user agent can terminate the fetch because the termination cannot be observed. @@ -4637,6 +4654,127 @@

      6.7 Garbage collection7 WebSocket protocol alterations

      + +
      +

      This section replaces part of the WebSocket protocol opening handshake client requirement to + integrate it with algorithms defined in Fetch. This way CSP, cookies, HSTS, and other Fetch-related + protocols are handled in a single location. Ideally the RFC would be updated with this language, + but it is never that easy. The WebSocket API, defined in the HTML Standard, has been updated to use + this language. [WSP] [HTML] + +

      The way this works is by replacing The WebSocket Protocol's "establish a WebSocket connection" + algorithm with a new one that integrates with Fetch. "Establish a WebSocket connection" consists of + three algorithms: setting up a connection, creating and transmiting a handshake request, and + validating the handshake response. That layering is different from Fetch, which first creates a + handshake, then sets up a connection and transmits the handshake, and finally validates the + response. Keep that in mind while reading these alterations. +

      + + +

      7.1 Connections

      + +

      To obtain a WebSocket connection, given a +url, run these steps: + +

        +
      1. Let host be url's + host. + +

      2. Let port be url's + port. + +

      3. Let secure be false, if url's + scheme is "http", and true otherwise. + +

      4. Follow the requirements stated in step 2 to 5, inclusive, of the first set of steps in + section 4.1 of The WebSocket Protocol + to establish a WebSocket connection. + [WSP] + +

      5. If that established a connection, return it, and return failure otherwise. +

      + +

      Although structured a little differently, carrying different properties, and +therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" +connection. + + +

      7.2 Opening handshake

      + +

      To establish a WebSocket connection, given a +url, protocols, and client, run these steps:

      + +
        +
      1. Let requestURL be a copy of url, with its + scheme set to "http", + if url's scheme is + "ws", and to "https" otherwise. + +

      2. Let request be a new request, whose + url is url, + client is client, + skip-service-worker flag is set, + synchronous flag is set, + mode is "websocket", + credentials mode is + "include", and + redirect mode is "error". + +

      3. Append + `Upgrade`/`websocket` to + request's header list. + +

      4. Append + `Connection`/`Upgrade` to + request's header list. + +

      5. +

        Let keyValue be nonce consisting of a randomly selected 16-byte value that has been + base64-encoded (see section 4 of + [RFC4648]).

        + +

        If the randomly selected value was the byte sequence 0x01 0x02 0x03 0x04 0x05 + 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, keyValue would be + `AQIDBAUGBwgJCgsMDQ4PEC==`. + +

      6. Append + `Sec-WebSocket-Key`/keyValue to + request's header list. + +

      7. Append + `Sec-WebSocket-Version`/`13` to + request's header list. + +

      8. For each protocol in protocols, + combine + `Sec-WebSocket-Protocol`/protocol. + +

      9. Let response be the result of fetching + request.

      10. + +
      11. If response is a network error or its + status is not 101, + fail the WebSocket connection. + +

      12. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in + section 4.1 of The WebSocket Protocol + to validate response. This either results in fail the WebSocket connection + or the WebSocket connection is established. +

      + +

      Fail the WebSocket connection and the WebSocket connection is established +are defined by The WebSocket Protocol. [WSP] + +

      The reason redirects are not followed, HTTP authentication will not function, and +this handshake is generally restricted is because that could introduce serious security problems in +a web browser context. For example, consider a host with a WebSocket server at one path and an open +HTTP redirector at another. Suddenly, any script that can be given a particular WebSocket URL can be +tricked into communicating to (and potentially sharing secrets with) any host on the internet, even +if the script checks that the URL has the right hostname. + + +

      Background reading

      This section and its subsections are informative only. @@ -4771,6 +4909,9 @@

      References

      [RFC2388]
      Returning Values from Forms: multipart/form-data, L. Masinter. IETF. +
      [RFC4648] +
      The Base16, Base32, and Base64 Data Encodings, S. Josefsson. IETF. +
      [SRI]
      Subresource Integrity, Devdatta Akhawe, Francois Marier, Frederik Braun et al.. W3C. @@ -4792,6 +4933,9 @@

      References

      [WEBIDL]
      Web IDL, Cameron McCormack. W3C. +
      [WSP] +
      The WebSocket Protocol, I. Fette and A. Melnikov. IETF. +
      [XHR]
      (Non-normative) XMLHttpRequest, Anne van Kesteren. WHATWG. diff --git a/Overview.src.html b/Overview.src.html index 8f660e3e9..2201ee9c1 100644 --- a/Overview.src.html +++ b/Overview.src.html @@ -670,7 +670,7 @@

      Requests

      connect-src navigator.sendBeacon(), EventSource, HTML's ping="", fetch(), - XMLHttpRequest, Cache API? + XMLHttpRequest, WebSocket, Cache API? "object" object-src @@ -811,14 +811,15 @@

      Requests

      synchronous flag. Unless stated otherwise it is unset.

      A request has an associated -mode, which is "navigate", -"same-origin", "no-cors", or "cors". -Unless stated otherwise, it is "no-cors". +mode, which is "same-origin", +"cors", "no-cors", "navigate", or +"websocket". Unless stated otherwise, it is "no-cors".

      Even though the default request mode is "no-cors", standards are highly -discouraged from using it for new features. It is rather unsafe. "navigate" is a -special value for HTML. HTML +discouraged from using it for new features. It is rather unsafe. "navigate" and +"websocket" are special values for the HTML Standard. +HTML

      A request has an associated use-CORS-preflight flag. Unless stated otherwise, it is unset. @@ -1847,7 +1848,7 @@

      Main fetch

      scheme is "about"
      request's mode is - "navigate" + "navigate" or "websocket"

      The result of performing a basic fetch using request. @@ -2755,10 +2756,21 @@

      HTTP-network fetch

    6. Let credentials be true if credentials flag is set, and false otherwise. -

    7. Let connection be the result of - obtaining a connection, given request's - current url's - origin and credentials. +

    8. +

      Switch on request's mode: + +

      +
      "websocket" +

      Let connection be the result of + obtaining a WebSocket connection, given + request's current url. + +

      Otherwise +

      Let connection be the result of + obtaining a connection, given request's + current url's + origin and credentials. +

    9. If connection is failure, return a network error. @@ -3852,7 +3864,8 @@

      Request class

      "serviceworker" is omitted from RequestDestination as it cannot be observed from JavaScript. Implementations will still need to support it as a -destination. +destination. "websocket" is +omitted from RequestMode as it cannot be used nor observed from JavaScript.

      A Request object has an associated request (a request). @@ -4544,7 +4557,7 @@

      Garbage collection

      communicating with the server through a side-channel are not included.

      The server being able to observe garbage collection has precedent, e.g., -with WebSocket and XMLHttpRequest. +with WebSocket and XMLHttpRequest objects.

      The user agent can terminate the fetch because the termination cannot be observed. @@ -4575,6 +4588,127 @@

      Garbage collection

      +

      WebSocket protocol alterations

      + +
      +

      This section replaces part of the WebSocket protocol opening handshake client requirement to + integrate it with algorithms defined in Fetch. This way CSP, cookies, HSTS, and other Fetch-related + protocols are handled in a single location. Ideally the RFC would be updated with this language, + but it is never that easy. The WebSocket API, defined in the HTML Standard, has been updated to use + this language. WSP HTML + +

      The way this works is by replacing The WebSocket Protocol's "establish a WebSocket connection" + algorithm with a new one that integrates with Fetch. "Establish a WebSocket connection" consists of + three algorithms: setting up a connection, creating and transmiting a handshake request, and + validating the handshake response. That layering is different from Fetch, which first creates a + handshake, then sets up a connection and transmits the handshake, and finally validates the + response. Keep that in mind while reading these alterations. +

      + + +

      Connections

      + +

      To obtain a WebSocket connection, given a +url, run these steps: + +

        +
      1. Let host be url's + host. + +

      2. Let port be url's + port. + +

      3. Let secure be false, if url's + scheme is "http", and true otherwise. + +

      4. Follow the requirements stated in step 2 to 5, inclusive, of the first set of steps in + section 4.1 of The WebSocket Protocol + to establish a WebSocket connection. + WSP + +

      5. If that established a connection, return it, and return failure otherwise. +

      + +

      Although structured a little differently, carrying different properties, and +therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" +connection. + + +

      Opening handshake

      + +

      To establish a WebSocket connection, given a +url, protocols, and client, run these steps:

      + +
        +
      1. Let requestURL be a copy of url, with its + scheme set to "http", + if url's scheme is + "ws", and to "https" otherwise. + +

      2. Let request be a new request, whose + url is url, + client is client, + skip-service-worker flag is set, + synchronous flag is set, + mode is "websocket", + credentials mode is + "include", and + redirect mode is "error". + +

      3. Append + `Upgrade`/`websocket` to + request's header list. + +

      4. Append + `Connection`/`Upgrade` to + request's header list. + +

      5. +

        Let keyValue be nonce consisting of a randomly selected 16-byte value that has been + base64-encoded (see section 4 of + RFC4648).

        + +

        If the randomly selected value was the byte sequence 0x01 0x02 0x03 0x04 0x05 + 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, keyValue would be + `AQIDBAUGBwgJCgsMDQ4PEC==`. + +

      6. Append + `Sec-WebSocket-Key`/keyValue to + request's header list. + +

      7. Append + `Sec-WebSocket-Version`/`13` to + request's header list. + +

      8. For each protocol in protocols, + combine + `Sec-WebSocket-Protocol`/protocol. + +

      9. Let response be the result of fetching + request.

      10. + +
      11. If response is a network error or its + status is not 101, + fail the WebSocket connection. + +

      12. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in + section 4.1 of The WebSocket Protocol + to validate response. This either results in fail the WebSocket connection + or the WebSocket connection is established. +

      + +

      Fail the WebSocket connection and the WebSocket connection is established +are defined by The WebSocket Protocol. WSP + +

      The reason redirects are not followed, HTTP authentication will not function, and +this handshake is generally restricted is because that could introduce serious security problems in +a web browser context. For example, consider a host with a WebSocket server at one path and an open +HTTP redirector at another. Suddenly, any script that can be given a particular WebSocket URL can be +tricked into communicating to (and potentially sharing secrets with) any host on the internet, even +if the script checks that the URL has the right hostname. + + +

      Background reading

      This section and its subsections are informative only.