nghttpx: Reset stream if invalid header field is received in h2

This commit is contained in:
Tatsuhiro Tsujikawa 2016-08-28 00:49:38 +09:00
parent 79b07f0ce2
commit 1064e017c6
2 changed files with 75 additions and 0 deletions

View File

@ -904,6 +904,47 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame,
}
} // namespace
namespace {
int on_invalid_header_callback2(nghttp2_session *session,
const nghttp2_frame *frame, nghttp2_rcbuf *name,
nghttp2_rcbuf *value, uint8_t flags,
void *user_data) {
auto http2session = static_cast<Http2Session *>(user_data);
auto sd = static_cast<StreamData *>(
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
if (!sd || !sd->dconn) {
return 0;
}
auto downstream = sd->dconn->get_downstream();
if (!downstream) {
return 0;
}
int32_t stream_id;
if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
stream_id = frame->push_promise.promised_stream_id;
} else {
stream_id = frame->hd.stream_id;
}
if (LOG_ENABLED(INFO)) {
auto namebuf = nghttp2_rcbuf_get_buf(name);
auto valuebuf = nghttp2_rcbuf_get_buf(value);
SSLOG(INFO, http2session)
<< "Invalid header field for stream_id=" << stream_id
<< " in frame type=" << static_cast<uint32_t>(frame->hd.type)
<< ": name=[" << StringRef{namebuf.base, namebuf.len} << "], value=["
<< StringRef{valuebuf.base, valuebuf.len} << "]";
}
http2session->submit_rst_stream(stream_id, NGHTTP2_PROTOCOL_ERROR);
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
} // namespace
namespace {
int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) {
@ -1486,6 +1527,9 @@ nghttp2_session_callbacks *create_http2_downstream_callbacks() {
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
on_header_callback2);
nghttp2_session_callbacks_set_on_invalid_header_callback2(
callbacks, on_invalid_header_callback2);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);

View File

@ -227,6 +227,34 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame,
}
} // namespace
namespace {
int on_invalid_header_callback2(nghttp2_session *session,
const nghttp2_frame *frame, nghttp2_rcbuf *name,
nghttp2_rcbuf *value, uint8_t flags,
void *user_data) {
auto upstream = static_cast<Http2Upstream *>(user_data);
auto downstream = static_cast<Downstream *>(
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
if (!downstream) {
return 0;
}
if (LOG_ENABLED(INFO)) {
auto namebuf = nghttp2_rcbuf_get_buf(name);
auto valuebuf = nghttp2_rcbuf_get_buf(value);
ULOG(INFO, upstream) << "Invalid header field for stream_id="
<< frame->hd.stream_id << ": name=["
<< StringRef{namebuf.base, namebuf.len} << "], value=["
<< StringRef{valuebuf.base, valuebuf.len} << "]";
}
upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR);
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
} // namespace
namespace {
int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) {
@ -852,6 +880,9 @@ nghttp2_session_callbacks *create_http2_upstream_callbacks() {
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
on_header_callback2);
nghttp2_session_callbacks_set_on_invalid_header_callback2(
callbacks, on_invalid_header_callback2);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);