reject an unoffered subprotocol in read_websocket_upgrade_response (#2595)

* reject an unoffered subprotocol in the ws client handshake

* test the subprotocol check through WebSocketClient so the split build compiles

* Trim comments in the subprotocol check

---------

Co-authored-by: yhirose <yuji.hirose.bug@gmail.com>
This commit is contained in:
metsw24-max
2026-10-04 18:21:39 -04:00
committed by GitHub
co-authored by yhirose
parent d59f3e438c
commit 4fcbc08f2d
2 changed files with 71 additions and 4 deletions
+25 -4
View File
@@ -8272,9 +8272,11 @@ struct WebSocketUpgradeResponse {
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
const auto bufsiz = 2048;
char buf[bufsiz];
@@ -8331,6 +8333,22 @@ inline bool read_websocket_upgrade_response(Stream &strm,
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;
}
@@ -10328,7 +10346,10 @@ inline bool perform_websocket_handshake(Stream &strm, Request &req,
// Verify 101 response and Sec-WebSocket-Accept header
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) {