1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

hpack: pseudoheader check improvement

This commit is contained in:
Andy Green 2017-11-10 08:56:44 +08:00
parent 6bc92f7592
commit 46ee0713de
5 changed files with 72 additions and 32 deletions

View file

@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 2.8.9)
# General Advice
#
# For selecting between DEBUG / RELEASE, use -DCMAKE_BUILD_TYPE=DEBUG or =RELEASE
# debug builds include source level debug info and extra logging
if(NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
endif()

View file

@ -712,6 +712,38 @@ lws_hpack_use_idx_hdr(struct lws *wsi, int idx, int known_token)
return 0;
}
static uint8_t lws_header_implies_psuedoheader_map[] = {
0x07, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00 /* <-64 */,
0x0e /* <- 72 */, 0x04 /* <- 80 */, 0, 0, 0, 0
};
static int
lws_hpack_handle_pseudo_rules(struct lws *nwsi, struct lws *wsi, int m)
{
if (m == LWS_HPACK_IGNORE_ENTRY || m == -1)
return 0;
if (wsi->seen_nonpseudoheader &&
(lws_header_implies_psuedoheader_map[m >> 3] & (1 << (m & 7)))) {
lwsl_notice("lws tok %d seems to be a pseudoheader\n", m);
/*
* it's not legal to see a
* pseudoheader after normal
* headers
*/
lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
"Pseudoheader after normal hdrs");
return 1;
}
if (!(lws_header_implies_psuedoheader_map[m >> 3] & (1 << (m & 7))))
wsi->seen_nonpseudoheader = 1;
return 0;
}
int lws_hpack_interpret(struct lws *wsi, unsigned char c)
{
struct lws *nwsi = lws_get_network_wsi(wsi);
@ -743,6 +775,7 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c)
h2n->ext_count = 0;
h2n->hpack_hdr_len = 0;
h2n->unknown_header = 0;
wsi->u.hdr.parser_state = 255;
if (c & 0x80) { /* 1.... indexed header field only */
/* just a possibly-extended integer */
@ -762,6 +795,12 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c)
"hdr index 0 seen");
return 1;
}
m = lws_token_from_index(wsi, h2n->hdr_idx,
NULL, NULL, NULL);
if (lws_hpack_handle_pseudo_rules(nwsi, wsi, m))
return 1;
lwsl_header("HPKT_INDEXED_HDR_7: hdr %d\n", c & 0x7f);
if (lws_hpack_use_idx_hdr(wsi, c & 0x7f, -1)) {
lwsl_header("%s: idx hdr wr fail\n", __func__);
@ -1113,6 +1152,7 @@ swallow:
wsi->u.hdr.parser_state == WSI_TOKEN_SKIPPING) {
h2n->unknown_header = 1;
wsi->u.hdr.parser_state = -1;
wsi->seen_nonpseudoheader = 1;
}
}
@ -1132,6 +1172,7 @@ swallow:
* we have got both the header and value
*/
m = -1;
switch (h2n->hpack_type) {
/*
* These are the only two that insert to the dyntable
@ -1187,39 +1228,26 @@ add_it:
if (h2n->hdr_idx != LWS_HPACK_IGNORE_ENTRY && lws_frag_end(wsi))
return 1;
if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
h2n->hpack_type == HPKT_INDEXED_HDR_6_VALUE_INCR ||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) {
m = wsi->u.hdr.parser_state;
if (m == 255)
m = -1;
} else
m = lws_token_from_index(wsi, h2n->hdr_idx, NULL, NULL,
NULL);
if (h2n->hpack_type != HPKT_INDEXED_HDR_6_VALUE_INCR) {
if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) {
m = wsi->u.hdr.parser_state;
if (m == 255)
m = -1;
} else {
m = lws_token_from_index(wsi, h2n->hdr_idx, NULL, NULL,
NULL);
//lwsl_notice("token from index(%d) says %d\n", h2n->hdr_idx, m);
}
}
if (m != -1 && m != LWS_HPACK_IGNORE_ENTRY)
lws_dump_header(wsi, m);
if (h2n->seen_nonpseudoheader && (
m == WSI_TOKEN_HTTP_COLON_AUTHORITY ||
m == WSI_TOKEN_HTTP_COLON_METHOD ||
m == WSI_TOKEN_HTTP_COLON_PATH ||
m == WSI_TOKEN_HTTP_COLON_SCHEME)) {
/*
* it's not legal to see a
* pseudoheader after normal
* headers
*/
lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR,
"Pseudoheader after normal hdrs");
if (lws_hpack_handle_pseudo_rules(nwsi, wsi, m))
return 1;
}
if (m != WSI_TOKEN_HTTP_COLON_AUTHORITY &&
m != WSI_TOKEN_HTTP_COLON_METHOD &&
m != WSI_TOKEN_HTTP_COLON_PATH &&
m != WSI_TOKEN_HTTP_COLON_SCHEME)
h2n->seen_nonpseudoheader = 1;
h2n->is_first_header_char = 1;
h2n->hpack = HPKS_TYPE;
@ -1229,6 +1257,8 @@ add_it:
return 0;
}
static int
lws_h2_num_start(int starting_bits, unsigned long num)
{

View file

@ -170,6 +170,7 @@ lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi,
h2n->highest_sid_opened = sid;
wsi->u.h2.my_sid = sid;
wsi->http2_substream = 1;
wsi->seen_nonpseudoheader = 0;
wsi->u.h2.parent_wsi = parent_wsi;
/* new guy's sibling is whoever was the first child before */
@ -1003,7 +1004,6 @@ lws_h2_parse_frame_header(struct lws *wsi)
h2n->cont_exp = !(h2n->flags & LWS_H2_FLAG_END_HEADERS);
h2n->cont_exp_sid = h2n->sid;
h2n->cont_exp_headers = 1;
h2n->seen_nonpseudoheader = 0;
lws_header_table_reset(h2n->swsi, 0);
update_end_headers:

View file

@ -537,9 +537,14 @@ LWS_VISIBLE int
lws_callback_on_writable_all_protocol(const struct lws_context *context,
const struct lws_protocols *protocol)
{
struct lws_vhost *vhost = context->vhost_list;
struct lws_vhost *vhost;
int n;
if (!context)
return 0;
vhost = context->vhost_list;
while (vhost) {
for (n = 0; n < vhost->count_protocols; n++)
if (protocol->callback ==

View file

@ -1681,7 +1681,6 @@ struct lws_h2_netconn {
unsigned int pad_length:1;
unsigned int collected_priority:1;
unsigned int is_first_header_char:1;
unsigned int seen_nonpseudoheader:1;
unsigned int zero_huff_padding:1;
unsigned int last_action_dyntable_resize:1;
@ -1970,6 +1969,7 @@ struct lws {
unsigned int hdr_parsing_completed:1;
unsigned int http2_substream:1;
unsigned int upgraded_to_http2:1;
unsigned int seen_nonpseudoheader:1;
unsigned int listener:1;
unsigned int user_space_externally_allocated:1;
unsigned int socket_is_permanently_unusable:1;