From 40ba1b334c3b9b61cae99a0964ebd681b6b33a07 Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 12 Oct 2020 09:33:47 +0200 Subject: [PATCH 1/2] Issue 4: Compare header keys without case sensitivity --- websocket/src/handshake.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/websocket/src/handshake.cpp b/websocket/src/handshake.cpp index 59749fe..3036485 100644 --- a/websocket/src/handshake.cpp +++ b/websocket/src/handshake.cpp @@ -1,5 +1,6 @@ #include "websocket.h" #include +#include // tolower namespace dmWebsocket { @@ -156,6 +157,20 @@ Result ReceiveHeaders(WebsocketConnection* conn) } #endif +static int dmStriCmp(const char* s1, const char* s2) +{ + for (;;) + { + if (!*s1 || !*s2 || tolower((unsigned char) *s1) != tolower((unsigned char) *s2)) + { + return (unsigned char) *s1 - (unsigned char) *s2; + } + s1++; + s2++; + } +} + + #if defined(__EMSCRIPTEN__) Result VerifyHeaders(WebsocketConnection* conn) { @@ -197,27 +212,36 @@ Result VerifyHeaders(WebsocketConnection* conn) *r = 0; r += 2; - if (strcmp(key, "Connection") == 0 && strcmp(value, "Upgrade") == 0) + if (dmStriCmp(key, "Connection") == 0 && dmStriCmp(value, "Upgrade") == 0) upgraded = true; - else if (strcmp(key, "Sec-WebSocket-Accept") == 0) + else if (dmStriCmp(key, "Sec-WebSocket-Accept") == 0) { - uint8_t client_key[32 + 40]; uint32_t client_key_len = sizeof(client_key); dmCrypt::Base64Encode(conn->m_Key, sizeof(conn->m_Key), client_key, &client_key_len); client_key[client_key_len] = 0; + DebugLog(2, "Secret key (base64): %s", client_key); + memcpy(client_key + client_key_len, RFC_MAGIC, strlen(RFC_MAGIC)); client_key_len += strlen(RFC_MAGIC); client_key[client_key_len] = 0; + DebugLog(2, "Secret key + RFC_MAGIC: %s", client_key); + uint8_t client_key_sha1[20]; dmCrypt::HashSha1(client_key, client_key_len, client_key_sha1); + DebugPrint(2, "Hashed key (sha1):", client_key_sha1, sizeof(client_key_sha1)); + client_key_len = sizeof(client_key); dmCrypt::Base64Encode(client_key_sha1, sizeof(client_key_sha1), client_key, &client_key_len); client_key[client_key_len] = 0; + DebugLog(2, "Client key (base64): %s", client_key); + + DebugLog(2, "Server key (base64): %s", value); + if (strcmp(value, (const char*)client_key) == 0) valid_key = true; } From 5b0a9960a88841f5a45287ffc20e84c1be02068b Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 12 Oct 2020 09:45:05 +0200 Subject: [PATCH 2/2] Check the response headers more thoroughly --- websocket/src/handshake.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/websocket/src/handshake.cpp b/websocket/src/handshake.cpp index 3036485..e85f356 100644 --- a/websocket/src/handshake.cpp +++ b/websocket/src/handshake.cpp @@ -191,7 +191,8 @@ Result VerifyHeaders(WebsocketConnection* conn) r = strstr(r, "\r\n") + 2; - bool upgraded = false; + bool connection = false; + bool upgrade = false; bool valid_key = false; const char* protocol = ""; @@ -212,8 +213,11 @@ Result VerifyHeaders(WebsocketConnection* conn) *r = 0; r += 2; + // Page 18 in https://tools.ietf.org/html/rfc6455#section-11.3.3 if (dmStriCmp(key, "Connection") == 0 && dmStriCmp(value, "Upgrade") == 0) - upgraded = true; + connection = true; + else if (dmStriCmp(key, "Upgrade") == 0 && dmStriCmp(value, "websocket") == 0) + upgrade = true; else if (dmStriCmp(key, "Sec-WebSocket-Accept") == 0) { uint8_t client_key[32 + 40]; @@ -255,16 +259,19 @@ Result VerifyHeaders(WebsocketConnection* conn) conn->m_Buffer[size] = 0; conn->m_HasHandshakeData = conn->m_BufferSize != 0 ? 1 : 0; - if (!upgraded) + if (!connection) + dmLogError("Failed to find the Connection keyword in the response headers"); + if (!upgrade) dmLogError("Failed to find the Upgrade keyword in the response headers"); if (!valid_key) dmLogError("Failed to find valid key in the response headers"); - if (!(upgraded && valid_key)) { + bool ok = connection && upgrade && valid_key; + if (!ok) { dmLogError("Response:\n\"%s\"\n", conn->m_Buffer); } - return (upgraded && valid_key) ? RESULT_OK : RESULT_HANDSHAKE_FAILED; + return ok ? RESULT_OK : RESULT_HANDSHAKE_FAILED; } #endif