summaryrefslogtreecommitdiffstats
path: root/modules/http2/h2_stream.c
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2016-12-04 23:06:30 +0100
committerStefan Eissing <icing@apache.org>2016-12-04 23:06:30 +0100
commitc671673db96e286e2321d5babf05c767cb76a1ef (patch)
tree3a010f268ebaf21c2baae6bc3c0f673dc8285834 /modules/http2/h2_stream.c
parentChanges done by Daniel, reviewed by me, adding the html files and meta file t... (diff)
downloadapache2-c671673db96e286e2321d5babf05c767cb76a1ef.tar.xz
apache2-c671673db96e286e2321d5babf05c767cb76a1ef.zip
SECURITY: CVE-2016-8740
mod_http2: properly crafted, endless HTTP/2 CONTINUATION frames could be used to exhaust all server's memory. Reported by: Naveen Tiwari <naveen.tiwari@asu.edu> and CDF/SEFCOM at Arizona State University git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1772576 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--modules/http2/h2_stream.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c
index 2d179d0b0f..d31193909c 100644
--- a/modules/http2/h2_stream.c
+++ b/modules/http2/h2_stream.c
@@ -333,45 +333,50 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
const char *name, size_t nlen,
const char *value, size_t vlen)
{
+ int error = 0;
ap_assert(stream);
- if (!stream->has_response) {
- if (name[0] == ':') {
- if ((vlen) > stream->session->s->limit_req_line) {
- /* pseudo header: approximation of request line size check */
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
- "h2_stream(%ld-%d): pseudo header %s too long",
- stream->session->id, stream->id, name);
- return h2_stream_set_error(stream,
- HTTP_REQUEST_URI_TOO_LARGE);
- }
- }
- else if ((nlen + 2 + vlen) > stream->session->s->limit_req_fieldsize) {
- /* header too long */
+ if (stream->has_response) {
+ return APR_EINVAL;
+ }
+ ++stream->request_headers_added;
+ if (name[0] == ':') {
+ if ((vlen) > stream->session->s->limit_req_line) {
+ /* pseudo header: approximation of request line size check */
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
- "h2_stream(%ld-%d): header %s too long",
+ "h2_stream(%ld-%d): pseudo header %s too long",
stream->session->id, stream->id, name);
- return h2_stream_set_error(stream,
- HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+ error = HTTP_REQUEST_URI_TOO_LARGE;
}
-
- if (name[0] != ':') {
- ++stream->request_headers_added;
- if (stream->request_headers_added
- > stream->session->s->limit_req_fields) {
- /* too many header lines */
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
- "h2_stream(%ld-%d): too many header lines",
- stream->session->id, stream->id);
- return h2_stream_set_error(stream,
- HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
- }
+ }
+ else if ((nlen + 2 + vlen) > stream->session->s->limit_req_fieldsize) {
+ /* header too long */
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
+ "h2_stream(%ld-%d): header %s too long",
+ stream->session->id, stream->id, name);
+ error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
+ }
+
+ if (stream->request_headers_added
+ > stream->session->s->limit_req_fields + 4) {
+ /* too many header lines, include 4 pseudo headers */
+ if (stream->request_headers_added
+ > stream->session->s->limit_req_fields + 4 + 100) {
+ /* yeah, right */
+ return APR_ECONNRESET;
}
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
+ "h2_stream(%ld-%d): too many header lines",
+ stream->session->id, stream->id);
+ error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
}
if (h2_stream_is_scheduled(stream)) {
return add_trailer(stream, name, nlen, value, vlen);
}
+ else if (error) {
+ return h2_stream_set_error(stream, error);
+ }
else {
if (!stream->rtmp) {
stream->rtmp = h2_req_create(stream->id, stream->pool,