security harden http parser a bit

Drop the connection during parsing for a few more cases that can't be legit.

Take care about trying to free rxflow_buffer only if we reached a connmode
where it exists

Change behaviour on setting unknown HTTP method to kill connection

Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Andy Green 2013-02-12 12:52:39 +08:00
parent d579a7d89a
commit 3ee9b31054
3 changed files with 36 additions and 14 deletions

View file

@ -105,6 +105,19 @@ libwebsocket_read(struct libwebsocket_context *context,
if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
!lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
/* it's not websocket.... shall we accept it as http? */
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
lwsl_warn("Missing URI in HTTP request\n");
/* drop the header info */
if (wsi->u.hdr.ah)
free(wsi->u.hdr.ah);
goto bail;
}
lwsl_info("HTTP request for '%s'\n", lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
wsi->state = WSI_STATE_HTTP;
n = 0;
if (wsi->protocol->callback)

View file

@ -343,9 +343,16 @@ just_kill_connection:
if ((old_state == WSI_STATE_ESTABLISHED ||
wsi->mode == LWS_CONNMODE_WS_SERVING ||
wsi->mode == LWS_CONNMODE_WS_CLIENT) && wsi->u.ws.rx_user_buffer) {
free(wsi->u.ws.rx_user_buffer);
wsi->u.ws.rx_user_buffer = NULL;
wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
if (wsi->u.ws.rx_user_buffer) {
free(wsi->u.ws.rx_user_buffer);
wsi->u.ws.rx_user_buffer = NULL;
}
if (wsi->u.ws.rxflow_buffer) {
free(wsi->u.ws.rxflow_buffer);
wsi->u.ws.rxflow_buffer = NULL;
}
}
/* tell the user it's all over for this guy */
@ -389,9 +396,6 @@ just_kill_connection:
}
#endif
if (wsi->u.ws.rxflow_buffer)
free(wsi->u.ws.rxflow_buffer);
/* lwsl_info("closing fd=%d\n", wsi->sock); */
#ifdef LWS_OPENSSL_SUPPORT

View file

@ -470,7 +470,13 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
if (wsi->u.hdr.name_buffer_pos ==
sizeof(wsi->u.hdr.name_buffer) - 1) {
/* did we see HTTP token yet? */
if (!wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI]) {
lwsl_info("junk before method\n");
return -1;
}
/* name bigger than we can handle, skip until next */
wsi->u.hdr.name_buffer_pos = 0;
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
break;
}
@ -490,14 +496,13 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
break;
}
/* hm it's an unknown http method in fact */
if (c == ' ') {
lwsl_info("Unknown method %s\n",
wsi->u.hdr.name_buffer);
/* treat it as GET */
wsi->u.hdr.parser_state = WSI_TOKEN_GET_URI;
goto start_fragment;
}
/*
* hm it's an unknown http method in fact,
* treat as dangerous
*/
lwsl_info("Unknown method - dropping\n");
return -1;
}
if (lextable[wsi->u.hdr.lextable_pos + 1] == 0) {