Compare commits

...
Sign in to create a new pull request.

8 commits

Author SHA1 Message Date
Andy Green
4bc6f95974 fuzzer handle junk after upgrade header
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-21 11:00:34 +08:00
Andy Green
496e0af86e more return code checking
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 17:01:47 +08:00
Andy Green
40f4bc9c1c parser issue_char audit
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 09:12:31 +08:00
Andy Green
edd3a2d6bb test server http dont print junk if string too long
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 09:12:31 +08:00
Andy Green
88b9682e22 avoid using deallocated things during context dedtroy
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 09:12:31 +08:00
Andy Green
6d5143548d remove double free attempts from no ACCEPT server response cleanup path
The generic wsi close code is smart enough to clean up after these allocations itself

Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 08:44:07 +08:00
Andy Green
53ebe46d75 fuzzer eliminate hsecond ah free path firing assert sentinel
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 08:43:40 +08:00
Andy Green
26ba55a6fc fuzzer rx overflow mitigate
Signed-off-by: Andy Green <andy.green@linaro.org>
2016-01-20 08:40:14 +08:00
8 changed files with 90 additions and 56 deletions

View file

@ -516,18 +516,18 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
* Now let's confirm it sent all the necessary headers
*/
if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
lwsl_info("no ACCEPT\n");
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
isErrorCodeReceived = 1;
goto bail3;
}
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
if (!p) {
lwsl_info("no URI\n");
goto bail3;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
lwsl_info("no ACCEPT\n");
isErrorCodeReceived = 1;
goto bail3;
}
if (p && strncmp(p, "101", 3)) {
lwsl_warn(
"lws_client_handshake: got bad HTTP response '%s'\n", p);
@ -719,7 +719,7 @@ check_accept:
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p,
wsi->u.hdr.ah->initial_handshake_hash_base64);
goto bail2;
}
@ -767,6 +767,7 @@ check_accept:
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
goto bail2;
}
wsi->u.ws.rx_ubuf_alloc = n;
lwsl_info("Allocating client RX buffer %d\n", n);
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
@ -804,7 +805,6 @@ check_accept:
return 0;
bail3:
lws_free2(wsi->u.ws.rx_user_buffer);
close_reason = LWS_CLOSE_STATUS_NOSTATUS;
bail2:
@ -822,10 +822,7 @@ bail2:
lwsl_info("closing connection due to bail2 connection error\n");
/* free up his parsing allocations */
lws_free2(wsi->u.hdr.ah);
/* closing will free up his parsing allocations */
libwebsocket_close_and_free_session(context, wsi, close_reason);
return 1;

View file

@ -299,6 +299,8 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
if (!context)
return;
context->being_destroyed = 1;
#ifdef LWS_LATENCY
if (context->worst_latency_info[0])
lwsl_notice("Worst latency: %s\n", context->worst_latency_info);

View file

@ -388,7 +388,8 @@ libwebsockets_get_addresses(struct libwebsocket_context *context,
if (addr4.sin_family == AF_UNSPEC)
return -1;
lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len);
if (lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len) == NULL)
return -1;
return 0;
}

View file

@ -185,16 +185,27 @@ static int issue_char(struct libwebsocket *wsi, unsigned char c)
return -1;
}
if( wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len >=
if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len >=
wsi->u.hdr.current_token_limit) {
lwsl_warn("header %i exceeds limit\n", wsi->u.hdr.parser_state);
return 1;
};
}
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
if (c)
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
/* Insert a null character when we *hit* the limit: */
if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len == wsi->u.hdr.current_token_limit) {
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
lwsl_warn("excessive header content 2\n");
return -1;
}
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
lwsl_warn("header %i exceeds limit %d\n",
wsi->u.hdr.parser_state, wsi->u.hdr.current_token_limit);
}
return 0;
}
@ -270,7 +281,8 @@ int libwebsocket_parse(
case URIES_SEEN_PERCENT_H1:
if (char_to_hex(c) < 0) {
/* regurgitate */
issue_char(wsi, '%');
if (issue_char(wsi, '%') < 0)
return -1;
wsi->u.hdr.ues = URIES_IDLE;
/* regurgitate + assess */
if (libwebsocket_parse(context, wsi, wsi->u.hdr.esc_stash) < 0)
@ -294,6 +306,8 @@ int libwebsocket_parse(
switch (wsi->u.hdr.ups) {
case URIPS_IDLE:
if (!c)
return -1;
/* issue the first / always */
if (c == '/')
wsi->u.hdr.ups = URIPS_SEEN_SLASH;
@ -356,7 +370,8 @@ int libwebsocket_parse(
if (c == '?') { /* start of URI arguments */
/* seal off uri header */
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
if (issue_char(wsi, '\0') < 0)
return -1;
/* move to using WSI_TOKEN_HTTP_URI_ARGS */
wsi->u.hdr.ah->next_frag_index++;
@ -504,13 +519,8 @@ start_fragment:
wsi->u.hdr.ah->frags[n].next_frag_index =
wsi->u.hdr.ah->next_frag_index;
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
lwsl_warn("excessive header content\n");
if (issue_char(wsi, ' ') < 0)
return -1;
}
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = ' ';
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
break;
/* skipping arg part of a name we didn't recognize */
@ -820,6 +830,10 @@ handle_first:
return 1;
}
if (wsi->u.ws.rx_user_buffer_head + LWS_SEND_BUFFER_PRE_PADDING >= wsi->u.ws.rx_ubuf_alloc) {
lwsl_err("Attempted overflow\n");
return -1;
}
if (wsi->u.ws.all_zero_nonce)
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
(wsi->u.ws.rx_user_buffer_head++)] = c;

View file

@ -503,6 +503,8 @@ struct libwebsocket_context {
#endif
struct lws_token_limits *token_limits;
void *user_space;
unsigned int being_destroyed:1;
};
enum {
@ -776,6 +778,7 @@ struct _lws_header_related {
struct _lws_websocket_related {
char *rx_user_buffer;
int rx_user_buffer_head;
unsigned int rx_ubuf_alloc;
unsigned char frame_masking_nonce_04[4];
unsigned char frame_mask_index;
size_t rx_packet_length;

View file

@ -270,8 +270,7 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
bail:
/* free up his parsing allocations */
lws_free_header_table(wsi);
/* caller will free up his parsing allocations */
return -1;
}

View file

@ -137,7 +137,14 @@ int lws_context_init_server(struct lws_context_creation_info *info,
int
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
{
struct libwebsocket_context *context = wsi->protocol->owning_server;
struct libwebsocket_context *context;
if (!wsi)
return 0;
context = wsi->protocol->owning_server;
if (context->being_destroyed)
return 0;
/* there is no pending change */
if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
@ -340,6 +347,8 @@ int lws_handshake_server(struct libwebsocket_context *context,
/* LWS_CONNMODE_WS_SERVING */
while (len--) {
assert(wsi->mode == LWS_CONNMODE_HTTP_SERVING);
if (libwebsocket_parse(context, wsi, *(*buf)++)) {
lwsl_info("libwebsocket_parse failed\n");
goto bail_nuke_ah;
@ -355,33 +364,39 @@ int lws_handshake_server(struct libwebsocket_context *context,
/* is this websocket protocol or normal http 1.0? */
if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
!lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
ah = wsi->u.hdr.ah;
lws_union_transition(wsi, LWS_CONNMODE_HTTP_SERVING_ACCEPTED);
wsi->state = WSI_STATE_HTTP;
wsi->u.http.fd = LWS_INVALID_FILE;
/* expose it at the same offset as u.hdr */
wsi->u.http.ah = ah;
n = lws_http_action(context, wsi);
return n;
if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
"websocket")) {
lwsl_info("Upgrade to ws\n");
goto upgrade_ws;
}
#ifdef LWS_USE_HTTP2
if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
"h2c-14")) {
lwsl_info("Upgrade to h2c-14\n");
goto upgrade_h2c;
}
#endif
lwsl_err("Unknown upgrade\n");
/* dunno what he wanted to upgrade to */
goto bail_nuke_ah;
}
if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
"websocket"))
goto upgrade_ws;
#ifdef LWS_USE_HTTP2
if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
"h2c-14"))
goto upgrade_h2c;
#endif
/* dunno what he wanted to upgrade to */
goto bail_nuke_ah;
/* no upgrade ack... he remained as HTTP */
lwsl_info("No upgrade\n");
ah = wsi->u.hdr.ah;
lws_union_transition(wsi, LWS_CONNMODE_HTTP_SERVING_ACCEPTED);
wsi->state = WSI_STATE_HTTP;
wsi->u.http.fd = LWS_INVALID_FILE;
/* expose it at the same offset as u.hdr */
wsi->u.http.ah = ah;
n = lws_http_action(context, wsi);
return n;
#ifdef LWS_USE_HTTP2
upgrade_h2c:
@ -561,15 +576,16 @@ upgrade_ws:
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
return 1;
}
wsi->u.ws.rx_ubuf_alloc = n;
lwsl_info("Allocating RX buffer %d\n", n);
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
lwsl_warn("Failed to set SNDBUF to %d", n);
return 1;
}
lwsl_parser("accepted v%02d connection\n", wsi->ietf_spec_revision);
lwsl_parser("accepted v%02d connection\n",
wsi->ietf_spec_revision);
return 0;
} /* while all chars are handled */
return 0;

View file

@ -105,7 +105,7 @@ struct per_session_data__http {
static void
dump_handshake_info(struct libwebsocket *wsi)
{
int n = 0;
int n = 0, len;
char buf[256];
const unsigned char *c;
@ -116,12 +116,14 @@ dump_handshake_info(struct libwebsocket *wsi)
continue;
}
if (!lws_hdr_total_length(wsi, n)) {
len = lws_hdr_total_length(wsi, n);
if (!len || len > sizeof(buf) - 1) {
n++;
continue;
}
lws_hdr_copy(wsi, buf, sizeof buf, n);
buf[sizeof(buf) - 1] = '\0';
fprintf(stderr, " %s = %s\n", (char *)c, buf);
n++;