|
| 1 | +From 314fdb876cae7b8b57932adbdab40cb8a9148cfc Mon Sep 17 00:00:00 2001 |
| 2 | +From: AllSpark < [email protected]> |
| 3 | +Date: Sat, 13 Sep 2025 06:29:24 +0000 |
| 4 | +Subject: [PATCH] ws: get a new mask for each new outgoing frame |
| 5 | + |
| 6 | +- Move mask generation from accept to frame send: generate a fresh 4-byte |
| 7 | + random mask for every outgoing frame in ws_enc_write_head. |
| 8 | +- Allow forcing zero mask in DEBUGBUILD via CURL_WS_FORCE_ZERO_MASK env. |
| 9 | +- Remove mask generation and printing from Curl_ws_accept and update log |
| 10 | + message to not leak mask bytes. |
| 11 | + |
| 12 | +Reported-by: Calvin Ruocco |
| 13 | +Closes: #18496 |
| 14 | +Signed-off-by: Azure Linux Security Servicing Account < [email protected]> |
| 15 | +Upstream-reference: AI Backport of https://github.com/curl/curl/commit/84db7a9eae8468c0445b15aa806fa.patch |
| 16 | +--- |
| 17 | + Utilities/cmcurl/lib/ws.c | 24 ++++++++++++++++-------- |
| 18 | + 1 file changed, 16 insertions(+), 8 deletions(-) |
| 19 | + |
| 20 | +diff --git a/Utilities/cmcurl/lib/ws.c b/Utilities/cmcurl/lib/ws.c |
| 21 | +index 6ccf9e65..476b7ad9 100644 |
| 22 | +--- a/Utilities/cmcurl/lib/ws.c |
| 23 | ++++ b/Utilities/cmcurl/lib/ws.c |
| 24 | +@@ -544,6 +544,7 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data, |
| 25 | + unsigned char head[14]; |
| 26 | + size_t hlen; |
| 27 | + ssize_t n; |
| 28 | ++ CURLcode result; |
| 29 | + |
| 30 | + if(payload_len < 0) { |
| 31 | + failf(data, "WS: starting new frame with negative payload length %" |
| 32 | +@@ -615,6 +616,20 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data, |
| 33 | + enc->payload_remain = enc->payload_len = payload_len; |
| 34 | + ws_enc_info(enc, data, "sending"); |
| 35 | + |
| 36 | ++ /* 4 bytes random */ |
| 37 | ++ |
| 38 | ++ result = Curl_rand(data, (unsigned char *)&enc->mask, sizeof(enc->mask)); |
| 39 | ++ if(result) { |
| 40 | ++ *err = result; |
| 41 | ++ return -1; |
| 42 | ++ } |
| 43 | ++ |
| 44 | ++#ifdef DEBUGBUILD |
| 45 | ++ if(getenv("CURL_WS_FORCE_ZERO_MASK")) |
| 46 | ++ /* force the bit mask to 0x00000000, effectively disabling masking */ |
| 47 | ++ memset(&enc->mask, 0, sizeof(enc->mask)); |
| 48 | ++#endif |
| 49 | ++ |
| 50 | + /* add 4 bytes mask */ |
| 51 | + memcpy(&head[hlen], &enc->mask, 4); |
| 52 | + hlen += 4; |
| 53 | +@@ -805,14 +820,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data, |
| 54 | + subprotocol not requested by the client), the client MUST Fail |
| 55 | + the WebSocket Connection. */ |
| 56 | + |
| 57 | +- /* 4 bytes random */ |
| 58 | +- |
| 59 | +- result = Curl_rand(data, (unsigned char *)&ws->enc.mask, |
| 60 | +- sizeof(ws->enc.mask)); |
| 61 | +- if(result) |
| 62 | +- return result; |
| 63 | +- infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x", |
| 64 | +- ws->enc.mask[0], ws->enc.mask[1], ws->enc.mask[2], ws->enc.mask[3]); |
| 65 | ++ infof(data, "[WS] Received 101, switch to WebSocket"); |
| 66 | + |
| 67 | + /* Install our client writer that decodes WS frames payload */ |
| 68 | + result = Curl_cwriter_create(&ws_dec_writer, data, &ws_cw_decode, |
| 69 | +-- |
| 70 | +2.45.4 |
| 71 | + |
0 commit comments