|
@@ -8272,9 +8272,11 @@ struct WebSocketUpgradeResponse {
|
|
|
std::string selected_subprotocol;
|
|
std::string selected_subprotocol;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-inline bool read_websocket_upgrade_response(Stream &strm,
|
|
|
|
|
- const std::string &expected_accept,
|
|
|
|
|
- WebSocketUpgradeResponse &upgrade) {
|
|
|
|
|
|
|
+inline bool
|
|
|
|
|
+read_websocket_upgrade_response(Stream &strm,
|
|
|
|
|
+ const std::string &expected_accept,
|
|
|
|
|
+ const std::string &offered_subprotocols,
|
|
|
|
|
+ WebSocketUpgradeResponse &upgrade) {
|
|
|
// Read status line
|
|
// Read status line
|
|
|
const auto bufsiz = 2048;
|
|
const auto bufsiz = 2048;
|
|
|
char buf[bufsiz];
|
|
char buf[bufsiz];
|
|
@@ -8331,6 +8333,22 @@ inline bool read_websocket_upgrade_response(Stream &strm,
|
|
|
upgrade.selected_subprotocol = proto_it->second;
|
|
upgrade.selected_subprotocol = proto_it->second;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Verify the subprotocol is one the client offered (RFC 6455 4.1)
|
|
|
|
|
+ if (!upgrade.selected_subprotocol.empty()) {
|
|
|
|
|
+ auto was_offered = false;
|
|
|
|
|
+ split(offered_subprotocols.data(),
|
|
|
|
|
+ offered_subprotocols.data() + offered_subprotocols.size(), ',',
|
|
|
|
|
+ [&](const char *b, const char *e) {
|
|
|
|
|
+ if (std::string(b, e) == upgrade.selected_subprotocol) {
|
|
|
|
|
+ was_offered = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ if (!was_offered) {
|
|
|
|
|
+ upgrade.error = Error::WebSocketHandshake;
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -10328,7 +10346,10 @@ inline bool perform_websocket_handshake(Stream &strm, Request &req,
|
|
|
|
|
|
|
|
// Verify 101 response and Sec-WebSocket-Accept header
|
|
// Verify 101 response and Sec-WebSocket-Accept header
|
|
|
auto expected_accept = websocket_accept_key(client_key);
|
|
auto expected_accept = websocket_accept_key(client_key);
|
|
|
- return read_websocket_upgrade_response(strm, expected_accept, upgrade);
|
|
|
|
|
|
|
+ auto offered_subprotocols =
|
|
|
|
|
+ get_combined_header_value(req.headers, "Sec-WebSocket-Protocol");
|
|
|
|
|
+ return read_websocket_upgrade_response(strm, expected_accept,
|
|
|
|
|
+ offered_subprotocols, upgrade);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool is_ip_address(const std::string &host) {
|
|
inline bool is_ip_address(const std::string &host) {
|