Added optional per-header length limits:
- libwebsockets.h: - * added struct lws_token_limits * added token limits pointer to lws_context_creation_info - private-libwebsockets.h: added token limits pointer to lws_context_creation_info - context.c: copy token limits in create_context - client.c / server.c: pass context when invoking libwebsocket_parse - parsers.c: - * libwebsocket_parse takes context pointer * issue_char takes context pointer and checks header length against context limits, if defined * issue_char returns 1 (not -1/0) for header too long, and spill: sets the state to WSI_TOKEN_SKIPPING
This commit is contained in:
parent
b57e7a0e2e
commit
74b4a65745
6 changed files with 39 additions and 12 deletions
|
@ -411,7 +411,7 @@ int lws_client_socket_service(struct libwebsocket_context *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (libwebsocket_parse(wsi, c)) {
|
||||
if (libwebsocket_parse(context, wsi, c)) {
|
||||
lwsl_warn("problems parsing header\n");
|
||||
goto bail3;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
context->listen_service_extraseen = 0;
|
||||
context->protocols = info->protocols;
|
||||
context->token_limits = info->token_limits;
|
||||
context->listen_port = info->port;
|
||||
context->http_proxy_port = 0;
|
||||
context->http_proxy_address[0] = '\0';
|
||||
|
|
|
@ -341,6 +341,10 @@ enum lws_token_indexes {
|
|||
WSI_INIT_TOKEN_MUXURL,
|
||||
};
|
||||
|
||||
struct lws_token_limits {
|
||||
unsigned short token_limit[WSI_TOKEN_COUNT];
|
||||
};
|
||||
|
||||
/*
|
||||
* From RFC 6455
|
||||
1000
|
||||
|
@ -947,6 +951,7 @@ struct lws_context_creation_info {
|
|||
const char *iface;
|
||||
struct libwebsocket_protocols *protocols;
|
||||
struct libwebsocket_extension *extensions;
|
||||
struct lws_token_limits *token_limits;
|
||||
const char *ssl_cert_filepath;
|
||||
const char *ssl_private_key_filepath;
|
||||
const char *ssl_ca_filepath;
|
||||
|
|
|
@ -165,12 +165,22 @@ static char char_to_hex(const char c)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int issue_char(struct libwebsocket *wsi, unsigned char c)
|
||||
static int issue_char(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( context->token_limits &&
|
||||
(wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len >=
|
||||
context->token_limits->token_limit[wsi->u.hdr.parser_state]) ) {
|
||||
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++;
|
||||
|
@ -178,7 +188,9 @@ static int issue_char(struct libwebsocket *wsi, unsigned char c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
||||
int libwebsocket_parse(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
@ -234,7 +246,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
if (c == ' ') {
|
||||
/* enforce starting with / */
|
||||
if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len)
|
||||
if (issue_char(wsi, '/') < 0)
|
||||
if (issue_char(context, wsi, '/') < 0)
|
||||
return -1;
|
||||
c = '\0';
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
|
@ -253,7 +265,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
case URIES_SEEN_PERCENT:
|
||||
if (char_to_hex(c) < 0) {
|
||||
/* regurgitate */
|
||||
if (issue_char(wsi, '%') < 0)
|
||||
if (issue_char(context, wsi, '%') < 0)
|
||||
return -1;
|
||||
wsi->u.hdr.ues = URIES_IDLE;
|
||||
/* continue on to assess c */
|
||||
|
@ -266,10 +278,10 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
case URIES_SEEN_PERCENT_H1:
|
||||
if (char_to_hex(c) < 0) {
|
||||
/* regurgitate */
|
||||
issue_char(wsi, '%');
|
||||
issue_char(context, wsi, '%');
|
||||
wsi->u.hdr.ues = URIES_IDLE;
|
||||
/* regurgitate + assess */
|
||||
if (libwebsocket_parse(wsi, wsi->u.hdr.esc_stash) < 0)
|
||||
if (libwebsocket_parse(context, wsi, wsi->u.hdr.esc_stash) < 0)
|
||||
return -1;
|
||||
/* continue on to assess c */
|
||||
break;
|
||||
|
@ -332,7 +344,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
}
|
||||
/* it was like /.dir ... regurgitate the . */
|
||||
wsi->u.hdr.ups = URIPS_IDLE;
|
||||
issue_char(wsi, '.');
|
||||
issue_char(context, wsi, '.');
|
||||
break;
|
||||
|
||||
case URIPS_SEEN_SLASH_DOT_DOT:
|
||||
|
@ -383,8 +395,15 @@ check_eol:
|
|||
}
|
||||
|
||||
spill:
|
||||
if (issue_char(wsi, c) < 0)
|
||||
return -1;
|
||||
{
|
||||
int issue_result = issue_char(context, wsi, c);
|
||||
if (issue_result < 0) {
|
||||
return -1;
|
||||
}
|
||||
else if(issue_result > 0) {
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
};
|
||||
};
|
||||
swallow:
|
||||
/* per-protocol end of headers management */
|
||||
|
||||
|
|
|
@ -432,6 +432,7 @@ struct libwebsocket_context {
|
|||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *extensions;
|
||||
#endif
|
||||
struct lws_token_limits *token_limits;
|
||||
void *user_space;
|
||||
};
|
||||
|
||||
|
@ -645,7 +646,8 @@ LWS_EXTERN int
|
|||
libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_parse(struct libwebsocket *wsi, unsigned char c);
|
||||
libwebsocket_parse(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_b64_selftest(void);
|
||||
|
|
|
@ -179,7 +179,7 @@ int lws_handshake_server(struct libwebsocket_context *context,
|
|||
/* LWS_CONNMODE_WS_SERVING */
|
||||
|
||||
while (len--) {
|
||||
if (libwebsocket_parse(wsi, *(*buf)++)) {
|
||||
if (libwebsocket_parse(context, wsi, *(*buf)++)) {
|
||||
lwsl_info("libwebsocket_parse failed\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue