From 5e787114678faa386c2b4b869967b61856d3e8d6 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Sat, 18 May 2013 10:29:03 +0100 Subject: [PATCH] Fixed masking in websocket code --- mongoose.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/mongoose.c b/mongoose.c index a4618322a..6194ded43 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3818,9 +3818,9 @@ static void send_websocket_handshake(struct mg_connection *conn) { static void read_websocket(struct mg_connection *conn) { unsigned char *buf = (unsigned char *) conn->buf + conn->request_len; - int n, stop = 0; + int bits, n, stop = 0; size_t i, len, mask_len, data_len, header_len, body_len; - char mem[4 * 1024], *data; + char mem[4 * 1024], mask[4], *data; assert(conn->content_len == 0); while (!stop) { @@ -3841,6 +3841,14 @@ static void read_websocket(struct mg_connection *conn) { } } + // Data layout is as follows: + // conn->buf buf + // v v frame1 | frame2 + // |---------------------|----------------|--------------|------- + // | |<--header_len-->|<--data_len-->| + // |<-conn->request_len->|<-----body_len----------->| + // |<-------------------conn->data_len------------->| + if (header_len > 0) { // Allocate space to hold websocket payload data = mem; @@ -3850,6 +3858,10 @@ static void read_websocket(struct mg_connection *conn) { break; } + // Save mask and bits, otherwise it may be clobbered by memmove below + bits = buf[0]; + memcpy(mask, buf + header_len - mask_len, mask_len); + // Read frame payload into the allocated buffer. assert(body_len >= header_len); if (data_len + header_len > body_len) { @@ -3868,15 +3880,15 @@ static void read_websocket(struct mg_connection *conn) { // Apply mask if necessary if (mask_len > 0) { for (i = 0; i < data_len; i++) { - data[i] ^= buf[header_len - mask_len + (i % 4)]; + data[i] ^= mask[i % 4]; } } // Exit the loop if callback signalled to exit, // or "connection close" opcode received. if ((conn->ctx->callbacks.websocket_data != NULL && - !conn->ctx->callbacks.websocket_data(conn, buf[0], data, data_len)) || - (buf[0] & 0xf) == 8) { // Opcode == 8, connection close + !conn->ctx->callbacks.websocket_data(conn, bits, data, data_len)) || + (bits & 0xf) == 8) { // Opcode == 8, connection close stop = 1; } -- GitLab