diff --git a/lib/Makefile.am b/lib/Makefile.am index cf467d80c..a0671892e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -39,7 +39,7 @@ endif if LIBCRYPTO else -dist_libwebsockets_la_SOURCES += md5.c sha-1.c +dist_libwebsockets_la_SOURCES += sha-1.c endif libwebsockets_la_CFLAGS=-Wall -std=gnu99 -pedantic -g diff --git a/lib/client-handshake.c b/lib/client-handshake.c index ff20b1749..d168084e3 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -270,34 +270,6 @@ libwebsocket_client_connect(struct libwebsocket_context *context, if (!wsi->c_callback) wsi->c_callback = context->protocols[0].callback; - /* set up appropriate masking */ - - wsi->xor_mask = xor_no_mask; - - switch (wsi->ietf_spec_revision) { - case 0: - break; - case 4: - wsi->xor_mask = xor_mask_04; - break; - case 5: - case 6: - case 7: - case 8: - case 13: - wsi->xor_mask = xor_mask_05; - break; - default: - lwsl_parser("Client ietf version %d not supported\n", - wsi->ietf_spec_revision); - goto oom4; - } - - /* force no mask if he asks for that though */ - - if (context->options & LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK) - wsi->xor_mask = xor_no_mask; - for (n = 0; n < WSI_TOKEN_COUNT; n++) { wsi->utf8_token[n].token = NULL; wsi->utf8_token[n].token_len = 0; @@ -340,11 +312,6 @@ libwebsocket_client_connect(struct libwebsocket_context *context, return __libwebsocket_client_connect_2(context, wsi); - -oom4: - if (wsi->c_protocol) - free(wsi->c_protocol); - oom3: if (wsi->c_origin) free(wsi->c_origin); diff --git a/lib/client-parser.c b/lib/client-parser.c index 8eea86960..ba0614756 100644 --- a/lib/client-parser.c +++ b/lib/client-parser.c @@ -28,7 +28,6 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) { int n; - unsigned char buf[20 + 4]; int callback_action = LWS_CALLBACK_CLIENT_RECEIVE; int handled; struct lws_tokens eff_buf; @@ -42,103 +41,9 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) case LWS_RXPS_NEW: switch (wsi->ietf_spec_revision) { - /* Firefox 4.0b6 likes this as of 30 Oct */ - case 0: - if (c == 0xff) - wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF; - if (c == 0) { - wsi->lws_rx_parse_state = - LWS_RXPS_EAT_UNTIL_76_FF; - wsi->rx_user_buffer_head = 0; - } - break; - case 4: - case 5: - case 6: - case 7: - case 8: + case 13: - /* - * 04 logical framing from the spec (all this is masked when - * incoming and has to be unmasked) - * - * We ignore the possibility of extension data because we don't - * negotiate any extensions at the moment. - * - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-------+-+-------------+-------------------------------+ - * |F|R|R|R| opcode|R| Payload len | Extended payload length | - * |I|S|S|S| (4) |S| (7) | (16/63) | - * |N|V|V|V| |V| | (if payload len==126/127) | - * | |1|2|3| |4| | | - * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + - * | Extended payload length continued, if payload len == 127 | - * + - - - - - - - - - - - - - - - +-------------------------------+ - * | | Extension data | - * +-------------------------------+ - - - - - - - - - - - - - - - + - * : : - * +---------------------------------------------------------------+ - * : Application data : - * +---------------------------------------------------------------+ - * - * We pass payload through to userland as soon as we get it, ignoring - * FIN. It's up to userland to buffer it up if it wants to see a - * whole unfragmented block of the original size (which may be up to - * 2^63 long!) - * - * Notice in v7 RSV4 is set to indicate 32-bit frame key is coming in - * after length, unlike extension data which is now deprecated, this - * does not impact the payload length calculation. - */ - - /* - * 04 spec defines the opcode like this: (1, 2, and 3 are - * "control frame" opcodes which may not be fragmented or - * have size larger than 126) - * - * frame-opcode = - * %x0 ; continuation frame - * / %x1 ; connection close - * / %x2 ; ping - * / %x3 ; pong - * / %x4 ; text frame - * / %x5 ; binary frame - * / %x6-F ; reserved - * - * FIN (b7) - */ - - if (wsi->ietf_spec_revision < 7) - switch (c & 0xf) { - case LWS_WS_OPCODE_04__CONTINUATION: - wsi->opcode = - LWS_WS_OPCODE_07__CONTINUATION; - break; - case LWS_WS_OPCODE_04__CLOSE: - wsi->opcode = LWS_WS_OPCODE_07__CLOSE; - break; - case LWS_WS_OPCODE_04__PING: - wsi->opcode = LWS_WS_OPCODE_07__PING; - break; - case LWS_WS_OPCODE_04__PONG: - wsi->opcode = LWS_WS_OPCODE_07__PONG; - break; - case LWS_WS_OPCODE_04__TEXT_FRAME: - wsi->opcode = - LWS_WS_OPCODE_07__TEXT_FRAME; - break; - case LWS_WS_OPCODE_04__BINARY_FRAME: - wsi->opcode = - LWS_WS_OPCODE_07__BINARY_FRAME; - break; - default: - lwsl_warn("reserved opcodes not " - "usable pre v7 protocol\n"); - return -1; - } - else - wsi->opcode = c & 0xf; + wsi->opcode = c & 0xf; wsi->rsv = (c & 0x70); wsi->final = !!((c >> 7) & 1); switch (wsi->opcode) { @@ -161,12 +66,6 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN: - if ((c & 0x80) && wsi->ietf_spec_revision < 7) { - lwsl_warn("Frame has extensions set illegally 4\n"); - /* kill the connection */ - return -1; - } - wsi->this_frame_masked = !!(c & 0x80); switch (c & 0x7f) { @@ -322,46 +221,6 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) } break; - case LWS_RXPS_EAT_UNTIL_76_FF: - if (c == 0xff) { - wsi->lws_rx_parse_state = LWS_RXPS_NEW; - goto issue; - } - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = c; - - if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER) - break; -issue: - if (wsi->protocol->callback) - wsi->protocol->callback(wsi->protocol->owning_server, - wsi, - LWS_CALLBACK_CLIENT_RECEIVE, - wsi->user_space, - &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], - wsi->rx_user_buffer_head); - wsi->rx_user_buffer_head = 0; - break; - case LWS_RXPS_SEEN_76_FF: - if (c) - break; - - lwsl_parser("Seen that client is requesting " - "a v76 close, sending ack\n"); - buf[0] = 0xff; - buf[1] = 0; - n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP); - if (n < 0) { - lwsl_warn("LWS_RXPS_SEEN_76_FF: ERROR writing to socket\n"); - return -1; - } - lwsl_parser(" v76 close ack sent, server closing skt\n"); - /* returning < 0 will get it closed in parent */ - return -1; - - case LWS_RXPS_PULLING_76_LENGTH: - break; - case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED: if ((!wsi->this_frame_masked) || wsi->all_zero_nonce) wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + @@ -369,7 +228,7 @@ issue: else wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + (wsi->rx_user_buffer_head++)] = - wsi->xor_mask(wsi, c); + c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; if (--wsi->rx_packet_length == 0) { wsi->lws_rx_parse_state = LWS_RXPS_NEW; diff --git a/lib/client.c b/lib/client.c index a11de1f4d..40b24fa37 100644 --- a/lib/client.c +++ b/lib/client.c @@ -310,10 +310,6 @@ int lws_client_interpret_server_handshake(struct libwebsocket_context *context, struct libwebsocket *wsi) { - unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + - MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING]; - char pkt[1024]; - char *p = &pkt[0]; const char *pc; int okay = 0; #ifndef LWS_NO_EXTENSIONS @@ -323,57 +319,7 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, int more = 1; const char *c; #endif - int len = 0; int n; - static const char magic_websocket_04_masking_guid[] = - "61AC5F19-FBBA-4540-B96F-6561F1AB40A8"; - - /* - * 00 / 76 --> - * - * HTTP/1.1 101 WebSocket Protocol Handshake - * Upgrade: WebSocket - * Connection: Upgrade - * Sec-WebSocket-Origin: http://127.0.0.1 - * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket - * - * xxxxxxxxxxxxxxxx - */ - - if (wsi->ietf_spec_revision == 0) { - if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len || - !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len || - !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len || - !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len - ) { - lwsl_parser("libwebsocket_client_handshake " - "missing required header(s)\n"); - pkt[len] = '\0'; - lwsl_parser("%s", pkt); - goto bail3; - } - - strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token); - if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) { - lwsl_warn("libwebsocket_client_handshake " - "server sent bad HTTP response '%s'\n", - wsi->utf8_token[WSI_TOKEN_HTTP].token); - goto bail3; - } - - if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len < 16) { - lwsl_parser("libwebsocket_client_handshake " - "challenge reply too short %d\n", - wsi->utf8_token[ - WSI_TOKEN_CHALLENGE].token_len); - pkt[len] = '\0'; - lwsl_parser("%s", pkt); - goto bail3; - - } - - goto select_protocol; - } /* * well, what the server sent looked reasonable for syntax. @@ -393,24 +339,6 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n", wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len); #endif - if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len || - !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len || - !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len || - !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len || - (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len && - wsi->ietf_spec_revision == 4) - ) { - lwsl_parser("libwebsocket_client_handshake " - "missing required header(s) revision=%d\n", wsi->ietf_spec_revision); - pkt[len] = '\0'; - lwsl_parser("%s", pkt); - goto bail3; - } - - /* - * Everything seems to be there, now take a closer look at what - * is in each header - */ strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token); if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) { @@ -438,7 +366,6 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context, goto bail3; } -select_protocol: pc = wsi->c_protocol; if (pc == NULL) lwsl_parser("lws_client_interpret_server_handshake: " @@ -608,20 +535,6 @@ check_extensions: check_accept: #endif - if (wsi->ietf_spec_revision == 0) { - - if (memcmp(wsi->initial_handshake_hash_base64, - wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) { - lwsl_warn("libwebsocket_client_handshake " - "failed 00 challenge compare\n"); - pkt[len] = '\0'; - lwsl_warn("%s", pkt); - goto bail2; - } - - goto accept_ok; - } - /* * Confirm his accept token is the one we precomputed */ @@ -635,21 +548,6 @@ check_accept: goto bail2; } - if (wsi->ietf_spec_revision == 4) { - /* - * Calculate the 04 masking key to use when - * sending data to server - */ - - strcpy((char *)buf, wsi->key_b64); - p = (char *)buf + strlen(wsi->key_b64); - strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token); - p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len; - strcpy(p, magic_websocket_04_masking_guid); - SHA1(buf, strlen((char *)buf), wsi->masking_key_04); - } -accept_ok: - /* allocate the per-connection user memory (if any) */ if (wsi->protocol->per_session_data_size && !libwebsocket_ensure_user_space(wsi)) @@ -708,46 +606,6 @@ bail2: return 1; } -void libwebsockets_00_spaceout(char *key, int spaces, int seed) -{ - char *p; - - key++; - while (spaces--) { - if (*key && (seed & 1)) - key++; - seed >>= 1; - - p = key + strlen(key); - while (p >= key) { - p[1] = p[0]; - p--; - } - *key++ = ' '; - } -} - -void libwebsockets_00_spam(char *key, int count, int seed) -{ - char *p; - - key++; - while (count--) { - - if (*key && (seed & 1)) - key++; - seed >>= 1; - - p = key + strlen(key); - while (p >= key) { - p[1] = p[0]; - p--; - } - *key++ = 0x21 + ((seed & 0xffff) % 15); - /* 4 would use it up too fast.. not like it matters */ - seed >>= 1; - } -} char * libwebsockets_generate_client_handshake(struct libwebsocket_context *context, @@ -819,96 +677,6 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, p += sprintf(p, "Pragma: no-cache\x0d\x0a" "Cache-Control: no-cache\x0d\x0a"); - if (wsi->ietf_spec_revision == 0) { - unsigned char spaces_1, spaces_2; - unsigned int max_1, max_2; - unsigned int num_1, num_2; - unsigned long product_1, product_2; - char key_1[40]; - char key_2[40]; - unsigned int seed; - unsigned int count; - char challenge[16]; - - libwebsockets_get_random(context, &spaces_1, sizeof(char)); - libwebsockets_get_random(context, &spaces_2, sizeof(char)); - - spaces_1 = (spaces_1 % 12) + 1; - spaces_2 = (spaces_2 % 12) + 1; - - max_1 = 4294967295 / spaces_1; - max_2 = 4294967295 / spaces_2; - - libwebsockets_get_random(context, &num_1, sizeof(int)); - libwebsockets_get_random(context, &num_2, sizeof(int)); - - num_1 = (num_1 % max_1); - num_2 = (num_2 % max_2); - - challenge[0] = num_1 >> 24; - challenge[1] = num_1 >> 16; - challenge[2] = num_1 >> 8; - challenge[3] = num_1; - challenge[4] = num_2 >> 24; - challenge[5] = num_2 >> 16; - challenge[6] = num_2 >> 8; - challenge[7] = num_2; - - product_1 = num_1 * spaces_1; - product_2 = num_2 * spaces_2; - - sprintf(key_1, "%lu", product_1); - sprintf(key_2, "%lu", product_2); - - libwebsockets_get_random(context, &seed, sizeof(int)); - libwebsockets_get_random(context, &count, sizeof(int)); - - libwebsockets_00_spam(key_1, (count % 12) + 1, seed); - - libwebsockets_get_random(context, &seed, sizeof(int)); - libwebsockets_get_random(context, &count, sizeof(int)); - - libwebsockets_00_spam(key_2, (count % 12) + 1, seed); - - libwebsockets_get_random(context, &seed, sizeof(int)); - - libwebsockets_00_spaceout(key_1, spaces_1, seed); - libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16); - - p += sprintf(p, "Upgrade: WebSocket\x0d\x0a" - "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a", - wsi->c_host); - if (wsi->c_origin) - p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin); - - if (wsi->c_protocol) - p += sprintf(p, "Sec-WebSocket-Protocol: %s" - "\x0d\x0a", wsi->c_protocol); - - p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a", key_1); - p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a", key_2); - - /* give userland a chance to append, eg, cookies */ - - context->protocols[0].callback(context, wsi, - LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, - NULL, &p, (pkt + sizeof(pkt)) - p - 12); - - p += sprintf(p, "\x0d\x0a"); - - if (libwebsockets_get_random(context, p, 8) != 8) - return NULL; - memcpy(&challenge[8], p, 8); - p += 8; - - /* precompute what we want to see from the server */ - - MD5((unsigned char *)challenge, 16, - (unsigned char *)wsi->initial_handshake_hash_base64); - - goto issue_hdr; - } - p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host); p += sprintf(p, "Upgrade: websocket\x0d\x0a" "Connection: Upgrade\x0d\x0a" @@ -917,15 +685,12 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, p += strlen(wsi->key_b64); p += sprintf(p, "\x0d\x0a"); if (wsi->c_origin) { - if (wsi->ietf_spec_revision == 13) { - p += sprintf(p, "Origin: %s\x0d\x0a", + if (wsi->ietf_spec_revision == 13) + p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin); + else + p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a", wsi->c_origin); - } - else { - p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a", - wsi->c_origin); - } - } + } if (wsi->c_protocol) p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a", wsi->c_protocol); @@ -1005,12 +770,6 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, wsi->initial_handshake_hash_base64, sizeof wsi->initial_handshake_hash_base64); -issue_hdr: - -#if 0 - puts(pkt); -#endif - /* done with these now */ free(wsi->c_path); diff --git a/lib/handshake.c b/lib/handshake.c index b04df7f93..3a03310de 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -94,7 +94,6 @@ libwebsocket_read(struct libwebsocket_context *context, #ifndef LWS_NO_SERVER /* LWS_CONNMODE_WS_SERVING */ - extern int handshake_00(struct libwebsocket_context *context, struct libwebsocket *wsi); extern int handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi); for (n = 0; n < len; n++) @@ -188,27 +187,7 @@ libwebsocket_read(struct libwebsocket_context *context, */ switch (wsi->ietf_spec_revision) { - case 0: /* applies to 76 and 00 */ - wsi->xor_mask = xor_no_mask; - if (handshake_00(context, wsi)) { - lwsl_info("handshake_00 has failed the connection\n"); - goto bail; - } - break; - case 4: /* 04 */ - wsi->xor_mask = xor_mask_04; - lwsl_parser("libwebsocket_parse calling handshake_04\n"); - if (handshake_0405(context, wsi)) { - lwsl_info("handshake_0405 has failed the connection\n"); - goto bail; - } - break; - case 5: - case 6: - case 7: - case 8: case 13: - wsi->xor_mask = xor_mask_05; lwsl_parser("libwebsocket_parse calling handshake_04\n"); if (handshake_0405(context, wsi)) { lwsl_info("handshake_0405 xor 05 has failed the connection\n"); diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 76dc3f5de..1d97782b4 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -483,12 +483,6 @@ int libwebsockets_get_random(struct libwebsocket_context *context, return n; } -unsigned char * -libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md) -{ - return SHA1(d, n, md); -} - int lws_send_pipe_choked(struct libwebsocket *wsi) { struct pollfd fds; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 0900fc2e1..f1395ef15 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -111,7 +111,6 @@ extern void lwsl_hexdump(void *buf, size_t len); #endif enum libwebsocket_context_options { - LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK = 1, LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2, LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4, }; diff --git a/lib/md5.c b/lib/md5.c deleted file mode 100644 index 042db3b8e..000000000 --- a/lib/md5.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Modified from Polarssl here - * http://polarssl.org/show_source?file=md5 - * under GPL2 or later - */ - -#include -#include - - -#define GET_ULONG_LE(n, b, i) \ -{ \ - (n) = ((unsigned long)(b)[i]) \ - | ((unsigned long)(b)[(i) + 1] << 8) \ - | ((unsigned long)(b)[(i) + 2] << 16) \ - | ((unsigned long)(b)[(i) + 3] << 24); \ -} - -#define PUT_ULONG_LE(n, b, i) \ -{ \ - (b)[i] = (unsigned char)(n); \ - (b)[(i) + 1] = (unsigned char)((n) >> 8); \ - (b)[(i) + 2] = (unsigned char)((n) >> 16); \ - (b)[(i) + 3] = (unsigned char)((n) >> 24); \ -} - -static const unsigned char md5_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const unsigned long state_init[] = { - 0, 0, 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 -}; - -static void -md5_process(unsigned long *state, const unsigned char *data) -{ - unsigned long X[16], A, B, C, D; - int v; - - for (v = 0; v < 16; v++) - GET_ULONG_LE(X[v], data, v << 2); - -#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a, b, c, d, k, s, t) { a += F(b, c, d) + X[k] + t; a = S(a, s) + b; } - - A = state[0]; - B = state[1]; - C = state[2]; - D = state[3]; - -#define F(x, y, z) (z ^ (x & (y ^ z))) - - P(A, B, C, D, 0, 7, 0xD76AA478); - P(D, A, B, C, 1, 12, 0xE8C7B756); - P(C, D, A, B, 2, 17, 0x242070DB); - P(B, C, D, A, 3, 22, 0xC1BDCEEE); - P(A, B, C, D, 4, 7, 0xF57C0FAF); - P(D, A, B, C, 5, 12, 0x4787C62A); - P(C, D, A, B, 6, 17, 0xA8304613); - P(B, C, D, A, 7, 22, 0xFD469501); - P(A, B, C, D, 8, 7, 0x698098D8); - P(D, A, B, C, 9, 12, 0x8B44F7AF); - P(C, D, A, B, 10, 17, 0xFFFF5BB1); - P(B, C, D, A, 11, 22, 0x895CD7BE); - P(A, B, C, D, 12, 7, 0x6B901122); - P(D, A, B, C, 13, 12, 0xFD987193); - P(C, D, A, B, 14, 17, 0xA679438E); - P(B, C, D, A, 15, 22, 0x49B40821); - -#undef F - -#define F(x, y, z) (y ^ (z & (x ^ y))) - - P(A, B, C, D, 1, 5, 0xF61E2562); - P(D, A, B, C, 6, 9, 0xC040B340); - P(C, D, A, B, 11, 14, 0x265E5A51); - P(B, C, D, A, 0, 20, 0xE9B6C7AA); - P(A, B, C, D, 5, 5, 0xD62F105D); - P(D, A, B, C, 10, 9, 0x02441453); - P(C, D, A, B, 15, 14, 0xD8A1E681); - P(B, C, D, A, 4, 20, 0xE7D3FBC8); - P(A, B, C, D, 9, 5, 0x21E1CDE6); - P(D, A, B, C, 14, 9, 0xC33707D6); - P(C, D, A, B, 3, 14, 0xF4D50D87); - P(B, C, D, A, 8, 20, 0x455A14ED); - P(A, B, C, D, 13, 5, 0xA9E3E905); - P(D, A, B, C, 2, 9, 0xFCEFA3F8); - P(C, D, A, B, 7, 14, 0x676F02D9); - P(B, C, D, A, 12, 20, 0x8D2A4C8A); - -#undef F - -#define F(x, y, z) (x ^ y ^ z) - - P(A, B, C, D, 5, 4, 0xFFFA3942); - P(D, A, B, C, 8, 11, 0x8771F681); - P(C, D, A, B, 11, 16, 0x6D9D6122); - P(B, C, D, A, 14, 23, 0xFDE5380C); - P(A, B, C, D, 1, 4, 0xA4BEEA44); - P(D, A, B, C, 4, 11, 0x4BDECFA9); - P(C, D, A, B, 7, 16, 0xF6BB4B60); - P(B, C, D, A, 10, 23, 0xBEBFBC70); - P(A, B, C, D, 13, 4, 0x289B7EC6); - P(D, A, B, C, 0, 11, 0xEAA127FA); - P(C, D, A, B, 3, 16, 0xD4EF3085); - P(B, C, D, A, 6, 23, 0x04881D05); - P(A, B, C, D, 9, 4, 0xD9D4D039); - P(D, A, B, C, 12, 11, 0xE6DB99E5); - P(C, D, A, B, 15, 16, 0x1FA27CF8); - P(B, C, D, A, 2, 23, 0xC4AC5665); - -#undef F - -#define F(x, y, z) (y ^ (x | ~z)) - - P(A, B, C, D, 0, 6, 0xF4292244); - P(D, A, B, C, 7, 10, 0x432AFF97); - P(C, D, A, B, 14, 15, 0xAB9423A7); - P(B, C, D, A, 5, 21, 0xFC93A039); - P(A, B, C, D, 12, 6, 0x655B59C3); - P(D, A, B, C, 3, 10, 0x8F0CCC92); - P(C, D, A, B, 10, 15, 0xFFEFF47D); - P(B, C, D, A, 1, 21, 0x85845DD1); - P(A, B, C, D, 8, 6, 0x6FA87E4F); - P(D, A, B, C, 15, 10, 0xFE2CE6E0); - P(C, D, A, B, 6, 15, 0xA3014314); - P(B, C, D, A, 13, 21, 0x4E0811A1); - P(A, B, C, D, 4, 6, 0xF7537E82); - P(D, A, B, C, 11, 10, 0xBD3AF235); - P(C, D, A, B, 2, 15, 0x2AD7D2BB); - P(B, C, D, A, 9, 21, 0xEB86D391); - -#undef F - - state[0] += A; - state[1] += B; - state[2] += C; - state[3] += D; -} - -static -void md5_update(unsigned long *state, unsigned char *buffer, - const unsigned char *input, int ilen) -{ - int fill; - unsigned long left; - - if (ilen <= 0) - return; - - left = state[0] & 0x3F; - fill = 64 - left; - - state[0] += ilen; - state[0] &= 0xFFFFFFFF; - - if (state[0] < (unsigned long)ilen) - state[1]++; - - if (left && ilen >= fill) { - memcpy(buffer + left, input, fill); - md5_process(&state[2], buffer); - input += fill; - ilen -= fill; - left = 0; - } - - while (ilen >= 64) { - md5_process(&state[2], input); - input += 64; - ilen -= 64; - } - - if (ilen > 0) - memcpy(buffer + left, input, ilen); -} - -void -MD5(const unsigned char *input, int ilen, unsigned char *output) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - unsigned long state[6]; - unsigned char buffer[64]; - - memcpy(&state[0], &state_init[0], sizeof(state_init)); - - md5_update(state, buffer, input, ilen); - - high = (state[0] >> 29) | (state[1] << 3); - low = state[0] << 3; - - PUT_ULONG_LE(low, msglen, 0); - PUT_ULONG_LE(high, msglen, 4); - - last = state[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - md5_update(state, buffer, md5_padding, padn); - md5_update(state, buffer, msglen, 8); - - PUT_ULONG_LE(state[2], output, 0); - PUT_ULONG_LE(state[3], output, 4); - PUT_ULONG_LE(state[4], output, 8); - PUT_ULONG_LE(state[5], output, 12); -} - diff --git a/lib/output.c b/lib/output.c index b5cf7eaab..d16451fca 100644 --- a/lib/output.c +++ b/lib/output.c @@ -28,7 +28,6 @@ static int libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi) { - char buf[4 + 20]; int n; /* fetch the per-frame nonce */ @@ -44,24 +43,6 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi) /* start masking from first byte of masking key buffer */ wsi->frame_mask_index = 0; - if (wsi->ietf_spec_revision != 4) - return 0; - - /* 04 only does SHA-1 more complex key */ - - /* - * the frame key is the frame nonce (4 bytes) followed by the - * connection masking key, hashed by SHA1 - */ - - memcpy(buf, wsi->frame_masking_nonce_04, 4); - - memcpy(buf + 4, wsi->masking_key_04, 20); - - /* concatenate the nonce with the connection key then hash it */ - - SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04); - return 0; } @@ -297,9 +278,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, int n; int pre = 0; int post = 0; - int shift = 7; - int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT && - wsi->xor_mask != xor_no_mask; + int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT; unsigned char *dropmask = NULL; unsigned char is_masked_bit = 0; #ifndef LWS_NO_EXTENSIONS @@ -352,138 +331,46 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, #endif switch (wsi->ietf_spec_revision) { - /* chrome likes this as of 30 Oct 2010 */ - /* Firefox 4.0b6 likes this as of 30 Oct 2010 */ - case 0: - if ((protocol & 0xf) == LWS_WRITE_BINARY) { - /* in binary mode we send 7-bit used length blocks */ - pre = 1; - while (len & (127 << shift)) { - pre++; - shift += 7; - } - n = 0; - shift -= 7; - while (shift >= 0) { - if (shift) - buf[0 - pre + n] = - ((len >> shift) & 127) | 0x80; - else - buf[0 - pre + n] = - ((len >> shift) & 127); - n++; - shift -= 7; - } - break; - } - - /* frame type = text, length-free spam mode */ - - pre = 1; - buf[-pre] = 0; - buf[len] = 0xff; /* EOT marker */ - post = 1; - break; - - case 7: - case 8: case 13: if (masked7) { pre += 4; dropmask = &buf[0 - pre]; is_masked_bit = 0x80; } - /* fallthru */ - case 4: - case 5: - case 6: + switch (protocol & 0xf) { case LWS_WRITE_TEXT: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__TEXT_FRAME; - else - n = LWS_WS_OPCODE_07__TEXT_FRAME; + n = LWS_WS_OPCODE_07__TEXT_FRAME; break; case LWS_WRITE_BINARY: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__BINARY_FRAME; - else - n = LWS_WS_OPCODE_07__BINARY_FRAME; + n = LWS_WS_OPCODE_07__BINARY_FRAME; break; case LWS_WRITE_CONTINUATION: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__CONTINUATION; - else - n = LWS_WS_OPCODE_07__CONTINUATION; + n = LWS_WS_OPCODE_07__CONTINUATION; break; case LWS_WRITE_CLOSE: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__CLOSE; - else - n = LWS_WS_OPCODE_07__CLOSE; + n = LWS_WS_OPCODE_07__CLOSE; /* - * v5 mandates the first byte of close packet - * in both client and server directions + * 06+ has a 2-byte status code in network order + * we can do this because we demand post-buf */ - switch (wsi->ietf_spec_revision) { - case 0: - case 4: - break; - case 5: - /* we can do this because we demand post-buf */ - - if (len < 1) - len = 1; - - switch (wsi->mode) { - case LWS_CONNMODE_WS_SERVING: - /* - lwsl_debug("LWS_WRITE_CLOSE S\n"); - */ - buf[0] = 'S'; - break; - case LWS_CONNMODE_WS_CLIENT: - /* - lwsl_debug("LWS_WRITE_CLOSE C\n"); - */ - buf[0] = 'C'; - break; - default: - break; - } - break; - default: - /* - * 06 has a 2-byte status code in network order - * we can do this because we demand post-buf - */ - - if (wsi->close_reason) { - /* reason codes count as data bytes */ - buf -= 2; - buf[0] = wsi->close_reason >> 8; - buf[1] = wsi->close_reason; - len += 2; - } - break; + if (wsi->close_reason) { + /* reason codes count as data bytes */ + buf -= 2; + buf[0] = wsi->close_reason >> 8; + buf[1] = wsi->close_reason; + len += 2; } break; case LWS_WRITE_PING: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__PING; - else - n = LWS_WS_OPCODE_07__PING; - + n = LWS_WS_OPCODE_07__PING; wsi->pings_vs_pongs++; break; case LWS_WRITE_PONG: - if (wsi->ietf_spec_revision < 7) - n = LWS_WS_OPCODE_04__PONG; - else - n = LWS_WS_OPCODE_07__PONG; + n = LWS_WS_OPCODE_07__PONG; break; default: lwsl_warn("libwebsocket_write: unknown write " @@ -534,72 +421,24 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, * the protocol demands it */ - if (wsi->mode == LWS_CONNMODE_WS_CLIENT && - wsi->ietf_spec_revision >= 4) { + if (wsi->mode == LWS_CONNMODE_WS_CLIENT) { - /* - * this is only useful for security tests where it's required - * to control the raw packet payload content - */ - - if (!(protocol & LWS_WRITE_CLIENT_IGNORE_XOR_MASK) && - wsi->xor_mask != xor_no_mask) { - - if (libwebsocket_0405_frame_mask_generate(wsi)) { - lwsl_err("libwebsocket_write: " - "frame mask generation failed\n"); - return 1; - } - - - if (wsi->ietf_spec_revision < 7) - /* - * use the XOR masking against everything we - * send past the frame key - */ - for (n = -pre; n < ((int)len + post); n++) - buf[n] = wsi->xor_mask(wsi, buf[n]); - else - /* - * in v7, just mask the payload - */ - for (n = 0; n < (int)len; n++) - dropmask[n + 4] = - wsi->xor_mask(wsi, dropmask[n + 4]); - - - if (wsi->ietf_spec_revision < 7) { - /* make space for the frame nonce in clear */ - pre += 4; - - dropmask = &buf[0 - pre]; - } - - if (dropmask) - /* copy the frame nonce into place */ - memcpy(dropmask, - wsi->frame_masking_nonce_04, 4); - - } else { - if (wsi->ietf_spec_revision < 7) { - - /* make space for the frame nonce in clear */ - pre += 4; - - buf[0 - pre] = 0; - buf[1 - pre] = 0; - buf[2 - pre] = 0; - buf[3 - pre] = 0; - } else { - if (dropmask && wsi->xor_mask != xor_no_mask) { - dropmask[0] = 0; - dropmask[1] = 0; - dropmask[2] = 0; - dropmask[3] = 0; - } - } + if (libwebsocket_0405_frame_mask_generate(wsi)) { + lwsl_err("libwebsocket_write: " + "frame mask generation failed\n"); + return 1; } + /* + * in v7, just mask the payload + */ + for (n = 4; n < (int)len + 4; n++) + dropmask[n] = dropmask[n] ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; + + if (dropmask) + /* copy the frame nonce into place */ + memcpy(dropmask, + wsi->frame_masking_nonce_04, 4); } send_raw: diff --git a/lib/parsers.c b/lib/parsers.c index c50353462..ea3a0ad86 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -528,10 +528,8 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) /* client parser? */ - if (wsi->ietf_spec_revision >= 4) { - lwsl_parser("04 header completed\n"); - wsi->parser_state = WSI_PARSING_COMPLETE; - } + lwsl_parser("04 header completed\n"); + wsi->parser_state = WSI_PARSING_COMPLETE; break; @@ -562,27 +560,6 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) return 0; } -unsigned char -xor_no_mask(struct libwebsocket *wsi, unsigned char c) -{ - return c; -} - -unsigned char -xor_mask_04(struct libwebsocket *wsi, unsigned char c) -{ - c ^= wsi->masking_key_04[wsi->frame_mask_index++]; - if (wsi->frame_mask_index == 20) - wsi->frame_mask_index = 0; - - return c; -} - -unsigned char -xor_mask_05(struct libwebsocket *wsi, unsigned char c) -{ - return c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; -} /** * lws_frame_is_binary: true if the current frame was sent in binary mode @@ -603,7 +580,6 @@ int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) { int n; - unsigned char buf[20 + 4]; struct lws_tokens eff_buf; #ifndef LWS_NO_EXTENSIONS int handled; @@ -618,27 +594,6 @@ libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) case LWS_RXPS_NEW: switch (wsi->ietf_spec_revision) { - /* Firefox 4.0b6 likes this as of 30 Oct 2010 */ - case 0: - if (c == 0xff) - wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF; - if (c == 0) { - wsi->lws_rx_parse_state = - LWS_RXPS_EAT_UNTIL_76_FF; - wsi->rx_user_buffer_head = 0; - } - break; - case 4: - case 5: - case 6: - wsi->all_zero_nonce = 1; - wsi->frame_masking_nonce_04[0] = c; - if (c) - wsi->all_zero_nonce = 0; - wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_1; - break; - case 7: - case 8: case 13: /* * no prepended frame key any more @@ -669,37 +624,6 @@ libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) if (c) wsi->all_zero_nonce = 0; - if (wsi->protocol->owning_server->options & - LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK) - goto post_mask; - - if (wsi->ietf_spec_revision > 4) - goto post_sha1; - - /* - * we are able to compute the frame key now - * it's a SHA1 of ( frame nonce we were just sent, concatenated - * with the connection masking key we computed at handshake - * time ) -- yeah every frame from the client invokes a SHA1 - * for no real reason so much for lightweight. - */ - - buf[0] = wsi->frame_masking_nonce_04[0]; - buf[1] = wsi->frame_masking_nonce_04[1]; - buf[2] = wsi->frame_masking_nonce_04[2]; - buf[3] = wsi->frame_masking_nonce_04[3]; - - memcpy(buf + 4, wsi->masking_key_04, 20); - - /* - * wsi->frame_mask_04 will be our recirculating 20-byte XOR key - * for this frame - */ - - SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04); - -post_sha1: - /* * start from the zero'th byte in the XOR key buffer since * this is the start of a frame with a new key @@ -707,7 +631,6 @@ post_sha1: wsi->frame_mask_index = 0; -post_mask: wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1; break; @@ -761,38 +684,8 @@ handle_first: * FIN (b7) */ - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); - - /* translate all incoming opcodes into v7+ map */ - if (wsi->ietf_spec_revision < 7) - switch (c & 0xf) { - case LWS_WS_OPCODE_04__CONTINUATION: - wsi->opcode = LWS_WS_OPCODE_07__CONTINUATION; - break; - case LWS_WS_OPCODE_04__CLOSE: - wsi->opcode = LWS_WS_OPCODE_07__CLOSE; - break; - case LWS_WS_OPCODE_04__PING: - wsi->opcode = LWS_WS_OPCODE_07__PING; - break; - case LWS_WS_OPCODE_04__PONG: - wsi->opcode = LWS_WS_OPCODE_07__PONG; - break; - case LWS_WS_OPCODE_04__TEXT_FRAME: - wsi->opcode = LWS_WS_OPCODE_07__TEXT_FRAME; - break; - case LWS_WS_OPCODE_04__BINARY_FRAME: - wsi->opcode = LWS_WS_OPCODE_07__BINARY_FRAME; - break; - default: - lwsl_warn("reserved opcodes not " - "usable pre v7 protocol\n"); - return -1; - } - else - wsi->opcode = c & 0xf; - wsi->rsv = (c & 0x70); + wsi->opcode = c & 0xf; + wsi->rsv = c & 0x70; wsi->final = !!((c >> 7) & 1); switch (wsi->opcode) { case LWS_WS_OPCODE_07__TEXT_FRAME: @@ -805,15 +698,6 @@ handle_first: case LWS_RXPS_04_FRAME_HDR_LEN: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); - - if ((c & 0x80) && wsi->ietf_spec_revision < 7) { - lwsl_warn("Frame has extensions set illegally 2\n"); - /* kill the connection */ - return -1; - } - wsi->this_frame_masked = !!(c & 0x80); switch (c & 0x7f) { @@ -844,17 +728,11 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN16_2: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); - wsi->rx_packet_length = c << 8; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1; break; case LWS_RXPS_04_FRAME_HDR_LEN16_1: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); - wsi->rx_packet_length |= c; if (wsi->this_frame_masked) wsi->lws_rx_parse_state = @@ -865,8 +743,6 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN64_8: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); if (c & 0x80) { lwsl_warn("b63 of length must be zero\n"); /* kill the connection */ @@ -881,8 +757,6 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN64_7: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); #if defined __LP64__ wsi->rx_packet_length |= ((size_t)c) << 48; #endif @@ -890,8 +764,6 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN64_6: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); #if defined __LP64__ wsi->rx_packet_length |= ((size_t)c) << 40; #endif @@ -899,8 +771,6 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN64_5: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); #if defined __LP64__ wsi->rx_packet_length |= ((size_t)c) << 32; #endif @@ -908,29 +778,21 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN64_4: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); wsi->rx_packet_length |= ((size_t)c) << 24; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3; break; case LWS_RXPS_04_FRAME_HDR_LEN64_3: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); wsi->rx_packet_length |= ((size_t)c) << 16; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2; break; case LWS_RXPS_04_FRAME_HDR_LEN64_2: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); wsi->rx_packet_length |= ((size_t)c) << 8; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1; break; case LWS_RXPS_04_FRAME_HDR_LEN64_1: - if (wsi->ietf_spec_revision < 7) - c = wsi->xor_mask(wsi, c); wsi->rx_packet_length |= ((size_t)c); if (wsi->this_frame_masked) wsi->lws_rx_parse_state = @@ -940,48 +802,6 @@ handle_first: LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; break; - case LWS_RXPS_EAT_UNTIL_76_FF: - - if (c == 0xff) { - wsi->lws_rx_parse_state = LWS_RXPS_NEW; - goto issue; - } - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = c; - - if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER) - break; -issue: - if (wsi->protocol->callback) - user_callback_handle_rxflow(wsi->protocol->callback, - wsi->protocol->owning_server, - wsi, LWS_CALLBACK_RECEIVE, - wsi->user_space, - &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], - wsi->rx_user_buffer_head); - wsi->rx_user_buffer_head = 0; - break; - case LWS_RXPS_SEEN_76_FF: - if (c) - break; - - lwsl_parser("Seen that client is requesting " - "a v76 close, sending ack\n"); - buf[0] = 0xff; - buf[1] = 0; - n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP); - if (n < 0) { - lwsl_warn("ERROR writing to socket"); - return -1; - } - lwsl_parser(" v76 close ack sent, server closing skt\n"); - /* returning < 0 will get it closed in parent */ - return -1; - - case LWS_RXPS_PULLING_76_LENGTH: - break; - - case LWS_RXPS_07_COLLECT_FRAME_KEY_1: wsi->frame_masking_nonce_04[0] = c; if (c) @@ -1015,14 +835,13 @@ issue: case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED: - if (wsi->ietf_spec_revision < 4 || - (wsi->all_zero_nonce && wsi->ietf_spec_revision >= 5)) + if (wsi->all_zero_nonce) wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + (wsi->rx_user_buffer_head++)] = c; else wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + (wsi->rx_user_buffer_head++)] = - wsi->xor_mask(wsi, c); + c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; if (--wsi->rx_packet_length == 0) { wsi->lws_rx_parse_state = LWS_RXPS_NEW; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 526a78872..42c899587 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -144,26 +144,6 @@ */ #define LWS_LISTEN_SERVICE_MODULO 10 -enum lws_websocket_opcodes_04 { - LWS_WS_OPCODE_04__CONTINUATION = 0, - LWS_WS_OPCODE_04__CLOSE = 1, - LWS_WS_OPCODE_04__PING = 2, - LWS_WS_OPCODE_04__PONG = 3, - LWS_WS_OPCODE_04__TEXT_FRAME = 4, - LWS_WS_OPCODE_04__BINARY_FRAME = 5, - - LWS_WS_OPCODE_04__RESERVED_6 = 6, - LWS_WS_OPCODE_04__RESERVED_7 = 7, - LWS_WS_OPCODE_04__RESERVED_8 = 8, - LWS_WS_OPCODE_04__RESERVED_9 = 9, - LWS_WS_OPCODE_04__RESERVED_A = 0xa, - LWS_WS_OPCODE_04__RESERVED_B = 0xb, - LWS_WS_OPCODE_04__RESERVED_C = 0xc, - LWS_WS_OPCODE_04__RESERVED_D = 0xd, - LWS_WS_OPCODE_04__RESERVED_E = 0xe, - LWS_WS_OPCODE_04__RESERVED_F = 0xf, -}; - enum lws_websocket_opcodes_07 { LWS_WS_OPCODE_07__CONTINUATION = 0, LWS_WS_OPCODE_07__TEXT_FRAME = 1, @@ -193,10 +173,6 @@ enum lws_connection_states { enum lws_rx_parse_state { LWS_RXPS_NEW, - LWS_RXPS_SEEN_76_FF, - LWS_RXPS_PULLING_76_LENGTH, - LWS_RXPS_EAT_UNTIL_76_FF, - LWS_RXPS_04_MASK_NONCE_1, LWS_RXPS_04_MASK_NONCE_2, LWS_RXPS_04_MASK_NONCE_3, @@ -350,7 +326,6 @@ struct libwebsocket { int frame_is_binary:1; int pings_vs_pongs; - unsigned char (*xor_mask)(struct libwebsocket *, unsigned char); char all_zero_nonce; enum lws_close_status close_reason; @@ -405,15 +380,6 @@ libwebsocket_read(struct libwebsocket_context *context, extern int lws_b64_selftest(void); -extern unsigned char -xor_no_mask(struct libwebsocket *wsi, unsigned char c); - -extern unsigned char -xor_mask_04(struct libwebsocket *wsi, unsigned char c); - -extern unsigned char -xor_mask_05(struct libwebsocket *wsi, unsigned char c); - extern struct libwebsocket * wsi_from_fd(struct libwebsocket_context *context, int fd); diff --git a/lib/server-handshake.c b/lib/server-handshake.c index 1fdb33274..2a0e886a5 100644 --- a/lib/server-handshake.c +++ b/lib/server-handshake.c @@ -25,184 +25,6 @@ #define LWS_CPYAPP_TOKEN(ptr, tok) { strcpy(p, wsi->utf8_token[tok].token); \ p += wsi->utf8_token[tok].token_len; } -static int -interpret_key(const char *key, unsigned long *result) -{ - char digits[20]; - int digit_pos = 0; - const char *p = key; - unsigned int spaces = 0; - unsigned long acc = 0; - int rem = 0; - - while (*p) { - if (!isdigit(*p)) { - p++; - continue; - } - if (digit_pos == sizeof(digits) - 1) - return -1; - digits[digit_pos++] = *p++; - } - digits[digit_pos] = '\0'; - if (!digit_pos) - return -2; - - while (*key) { - if (*key == ' ') - spaces++; - key++; - } - - if (!spaces) - return -3; - - p = &digits[0]; - while (*p) { - rem = (rem * 10) + ((*p++) - '0'); - acc = (acc * 10) + (rem / spaces); - rem -= (rem / spaces) * spaces; - } - - if (rem) { - lwsl_warn("nonzero handshake remainder\n"); - return -1; - } - - *result = acc; - - return 0; -} - - -int handshake_00(struct libwebsocket_context *context, struct libwebsocket *wsi) -{ - unsigned long key1, key2; - unsigned char sum[16]; - char *response; - char *p; - int n; - - /* Confirm we have all the necessary pieces */ - - if (!wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len || - !wsi->utf8_token[WSI_TOKEN_HOST].token_len || - !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len || - !wsi->utf8_token[WSI_TOKEN_KEY1].token_len || - !wsi->utf8_token[WSI_TOKEN_KEY2].token_len) - /* completed header processing, but missing some bits */ - goto bail; - - /* allocate the per-connection user memory (if any) */ - if (wsi->protocol->per_session_data_size && - !libwebsocket_ensure_user_space(wsi)) - goto bail; - - /* create the response packet */ - - /* make a buffer big enough for everything */ - - response = (char *)malloc(256 + - wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len + - wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len + - wsi->utf8_token[WSI_TOKEN_HOST].token_len + - wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len + - wsi->utf8_token[WSI_TOKEN_GET_URI].token_len + - wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len); - if (!response) { - lwsl_err("Out of memory for response buffer\n"); - goto bail; - } - - p = response; - LWS_CPYAPP(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a" - "Upgrade: WebSocket\x0d\x0a" - "Connection: Upgrade\x0d\x0a" - "Sec-WebSocket-Origin: "); - strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token); - p += wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len; -#ifdef LWS_OPENSSL_SUPPORT - if (wsi->ssl) { - LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Location: wss://"); - } else { - LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Location: ws://"); - } -#else - LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Location: ws://"); -#endif - - LWS_CPYAPP_TOKEN(p, WSI_TOKEN_HOST); - LWS_CPYAPP_TOKEN(p, WSI_TOKEN_GET_URI); - - if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) { - LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: "); - LWS_CPYAPP_TOKEN(p, WSI_TOKEN_PROTOCOL); - } - - LWS_CPYAPP(p, "\x0d\x0a\x0d\x0a"); - - /* convert the two keys into 32-bit integers */ - - if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1)) - goto bail; - if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2)) - goto bail; - - /* lay them out in network byte order (MSB first */ - - sum[0] = (unsigned char)(key1 >> 24); - sum[1] = (unsigned char)(key1 >> 16); - sum[2] = (unsigned char)(key1 >> 8); - sum[3] = (unsigned char)(key1); - sum[4] = (unsigned char)(key2 >> 24); - sum[5] = (unsigned char)(key2 >> 16); - sum[6] = (unsigned char)(key2 >> 8); - sum[7] = (unsigned char)(key2); - - /* follow them with the challenge token we were sent */ - - memcpy(&sum[8], wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 8); - - /* - * compute the md5sum of that 16-byte series and use as our - * payload after our headers - */ - - MD5(sum, 16, (unsigned char *)p); - p += 16; - - /* it's complete: go ahead and send it */ - - lwsl_parser("issuing response packet %d len\n", (int)(p - response)); -#ifdef _DEBUG - fwrite(response, 1, p - response, stderr); -#endif - n = libwebsocket_write(wsi, (unsigned char *)response, - p - response, LWS_WRITE_HTTP); - if (n < 0) { - lwsl_debug("handshake_00: ERROR writing to socket\n"); - goto bail; - } - - /* alright clean up and set ourselves into established state */ - - free(response); - wsi->state = WSI_STATE_ESTABLISHED; - wsi->lws_rx_parse_state = LWS_RXPS_NEW; - - /* notify user code that we're ready to roll */ - - if (wsi->protocol->callback) - wsi->protocol->callback(wsi->protocol->owning_server, - wsi, LWS_CALLBACK_ESTABLISHED, - wsi->user_space, NULL, 0); - - return 0; - -bail: - return -1; -} - /* * Perform the newer BASE64-encoded handshake scheme */ @@ -212,17 +34,11 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi) { static const char *websocket_magic_guid_04 = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - static const char *websocket_magic_guid_04_masking = - "61AC5F19-FBBA-4540-B96F-6561F1AB40A8"; char accept_buf[MAX_WEBSOCKET_04_KEY_LEN + 37]; - char nonce_buf[256]; - char mask_summing_buf[256 + MAX_WEBSOCKET_04_KEY_LEN + 37]; unsigned char hash[20]; int n; char *response; char *p; - char *m = mask_summing_buf; - int nonce_len = 0; int accept_len; #ifndef LWS_NO_EXTENSIONS char *c; @@ -287,38 +103,6 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi) strcpy(p, accept_buf); p += accept_len; - if (wsi->ietf_spec_revision == 4) { - LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Nonce: "); - - /* select the nonce */ - - n = libwebsockets_get_random(wsi->protocol->owning_server, - hash, 16); - if (n != 16) { - lwsl_err("Unable to read random device %s %d\n", - SYSTEM_RANDOM_FILEPATH, n); - if (wsi->user_space) - free(wsi->user_space); - goto bail; - } - - /* encode the nonce */ - - nonce_len = lws_b64_encode_string((const char *)hash, 16, - nonce_buf, sizeof nonce_buf); - if (nonce_len < 0) { - lwsl_err("Failed to base 64 encode the nonce\n"); - if (wsi->user_space) - free(wsi->user_space); - goto bail; - } - - /* apply the nonce */ - - strcpy(p, nonce_buf); - p += nonce_len; - } - if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) { LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: "); LWS_CPYAPP_TOKEN(p, WSI_TOKEN_PROTOCOL); @@ -447,30 +231,6 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi) LWS_CPYAPP(p, "\x0d\x0a\x0d\x0a"); - if (wsi->ietf_spec_revision == 4) { - - /* - * precompute the masking key the client will use from the SHA1 - * hash of ( base 64 client key we were sent, concatenated with - * the bse 64 nonce we sent, concatenated with a magic constant - * guid specified by the 04 standard ) - * - * We store the hash in the connection's wsi ready to use with - * undoing the masking the client has done on framed data it - * sends (we send our data to the client in clear). - */ - - strcpy(mask_summing_buf, wsi->utf8_token[WSI_TOKEN_KEY].token); - m += wsi->utf8_token[WSI_TOKEN_KEY].token_len; - strcpy(m, nonce_buf); - m += nonce_len; - strcpy(m, websocket_magic_guid_04_masking); - m += strlen(websocket_magic_guid_04_masking); - - SHA1((unsigned char *)mask_summing_buf, m - mask_summing_buf, - wsi->masking_key_04); - } - #ifndef LWS_NO_EXTENSIONS if (!lws_any_extension_handled(context, wsi, LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX, diff --git a/test-server/test-client.c b/test-server/test-client.c index 348196be8..b556a1707 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -184,7 +184,6 @@ static struct option options[] = { { "debug", required_argument, NULL, 'd' }, { "port", required_argument, NULL, 'p' }, { "ssl", no_argument, NULL, 's' }, - { "killmask", no_argument, NULL, 'k' }, { "version", required_argument, NULL, 'v' }, { "undeflated", no_argument, NULL, 'u' }, { "nomux", no_argument, NULL, 'n' }, @@ -213,7 +212,7 @@ int main(int argc, char **argv) goto usage; while (n >= 0) { - n = getopt_long(argc, argv, "nuv:khsp:d:l", options, NULL); + n = getopt_long(argc, argv, "nuv:hsp:d:l", options, NULL); if (n < 0) continue; switch (n) { @@ -229,9 +228,6 @@ int main(int argc, char **argv) case 'l': longlived = 1; break; - case 'k': - opts = LWS_WRITE_CLIENT_IGNORE_XOR_MASK; - break; case 'v': ietf_version = atoi(optarg); break; diff --git a/test-server/test-fraggle.c b/test-server/test-fraggle.c index abff7bc52..f2c8d7c29 100644 --- a/test-server/test-fraggle.c +++ b/test-server/test-fraggle.c @@ -231,7 +231,6 @@ static struct option options[] = { { "debug", required_argument, NULL, 'd' }, { "port", required_argument, NULL, 'p' }, { "ssl", no_argument, NULL, 's' }, - { "killmask", no_argument, NULL, 'k' }, { "interface", required_argument, NULL, 'i' }, { "client", no_argument, NULL, 'c' }, { NULL, 0, 0, 0 } @@ -255,11 +254,11 @@ int main(int argc, char **argv) int server_port = port; fprintf(stderr, "libwebsockets test fraggle\n" - "(C) Copyright 2010-2011 Andy Green " + "(C) Copyright 2010-2013 Andy Green " "licensed under LGPL2.1\n"); while (n >= 0) { - n = getopt_long(argc, argv, "ci:khsp:d:", options, NULL); + n = getopt_long(argc, argv, "ci:hsp:d:", options, NULL); if (n < 0) continue; switch (n) { @@ -269,9 +268,6 @@ int main(int argc, char **argv) case 's': use_ssl = 1; break; - case 'k': - opts = LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK; - break; case 'p': port = atoi(optarg); server_port = port; diff --git a/test-server/test-server.c b/test-server/test-server.c index 51b65ce60..c98fe0ff1 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -489,7 +489,6 @@ static struct option options[] = { { "debug", required_argument, NULL, 'd' }, { "port", required_argument, NULL, 'p' }, { "ssl", no_argument, NULL, 's' }, - { "killmask", no_argument, NULL, 'k' }, { "interface", required_argument, NULL, 'i' }, { "closetest", no_argument, NULL, 'c' }, #ifndef NO_DAEMONIZE @@ -523,7 +522,7 @@ int main(int argc, char **argv) #endif while (n >= 0) { - n = getopt_long(argc, argv, "ci:khsp:d:D", options, NULL); + n = getopt_long(argc, argv, "ci:hsp:d:D", options, NULL); if (n < 0) continue; switch (n) { @@ -539,9 +538,6 @@ int main(int argc, char **argv) case 's': use_ssl = 1; break; - case 'k': - opts = LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK; - break; case 'p': port = atoi(optarg); break;