Merge pull request #10 from defold/issue-4-case-insensitive-header

Issue 4: Compare header keys without case sensitivity
This commit is contained in:
Mathias Westerdahl 2020-10-12 09:59:55 +02:00 committed by GitHub
commit dc1d57d661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,5 +1,6 @@
#include "websocket.h"
#include <dmsdk/dlib/socket.h>
#include <ctype.h> // 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)
{
@ -176,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 = "";
@ -197,27 +213,39 @@ Result VerifyHeaders(WebsocketConnection* conn)
*r = 0;
r += 2;
if (strcmp(key, "Connection") == 0 && strcmp(value, "Upgrade") == 0)
upgraded = true;
else if (strcmp(key, "Sec-WebSocket-Accept") == 0)
// Page 18 in https://tools.ietf.org/html/rfc6455#section-11.3.3
if (dmStriCmp(key, "Connection") == 0 && dmStriCmp(value, "Upgrade") == 0)
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];
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;
}
@ -231,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