From: Stefan Eissing Date: Sat, 27 Aug 2016 12:07:16 +0000 (+0000) Subject: mod_http2: using invalid header callback from nghttp2 1.14.0 onwards X-Git-Tag: 2.5.0-alpha~1194 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aec10f23cc8a2e4bec169daee89178ac60e4ba0e;p=thirdparty%2Fapache%2Fhttpd.git mod_http2: using invalid header callback from nghttp2 1.14.0 onwards git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1758003 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 4a4801092a8..3b57f5f91eb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_http2: if configured with nghttp2 1.14.0 and onward, invalid request + headers will immediately reset the stream with a PROTOCOL error. Feature + logged by module on startup as 'INVHD' in info message. + [Stefan Eissing] + *) mod_http2: fixed handling of stream buffers during shutdown. [Stefan Eissing] diff --git a/docs/log-message-tags/next-number b/docs/log-message-tags/next-number index 169efa8bd26..a82b2ee2a70 100644 --- a/docs/log-message-tags/next-number +++ b/docs/log-message-tags/next-number @@ -1 +1 @@ -3456 +3458 diff --git a/modules/http2/config2.m4 b/modules/http2/config2.m4 index a77ad808998..cccbbc8536f 100644 --- a/modules/http2/config2.m4 +++ b/modules/http2/config2.m4 @@ -154,6 +154,9 @@ dnl # nghttp2 >= 1.3.0: access to stream weights dnl # nghttp2 >= 1.5.0: changing stream priorities AC_CHECK_FUNCS([nghttp2_session_change_stream_priority], [APR_ADDTO(MOD_CPPFLAGS, ["-DH2_NG2_CHANGE_PRIO"])], []) +dnl # nghttp2 >= 1.14.0: invalid header callback + AC_CHECK_FUNCS([nghttp2_session_callbacks_set_on_invalid_header_callback], + [APR_ADDTO(MOD_CPPFLAGS, ["-DH2_NG2_INVALID_HEADER_CB"])], []) else AC_MSG_WARN([nghttp2 version is too old]) fi diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c index 79a2e82e82d..22f37e08578 100644 --- a/modules/http2/h2_proxy_session.c +++ b/modules/http2/h2_proxy_session.c @@ -94,7 +94,7 @@ static int proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc, * issues in case of error returned below. */ apr_brigade_cleanup(bb); if (status != APR_SUCCESS) { - ap_log_cerror(APLOG_MARK, APLOG_ERR, status, origin, APLOGNO(03357) + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, origin, APLOGNO(03357) "pass output failed to %pI (%s)", p_conn->addr, p_conn->hostname); } diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index 1cb0a59f2fb..31ae303c9d0 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -657,6 +657,27 @@ static int on_frame_send_cb(nghttp2_session *ngh2, return 0; } +#ifdef H2_NG2_INVALID_HEADER_CB +static int on_invalid_header_cb(nghttp2_session *ngh2, + const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + uint8_t flags, void *user_data) +{ + h2_session *session = user_data; + if (APLOGcdebug(session->c)) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03456) + "h2_session(%ld-%d): denying stream with invalid header " + "'%s: %s'", session->id, (int)frame->hd.stream_id, + apr_pstrndup(session->pool, (const char *)name, namelen), + apr_pstrndup(session->pool, (const char *)value, valuelen)); + } + return nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); +} +#endif + #define NGH2_SET_CALLBACK(callbacks, name, fn)\ nghttp2_session_callbacks_set_##name##_callback(callbacks, fn) @@ -679,7 +700,9 @@ static apr_status_t init_callbacks(conn_rec *c, nghttp2_session_callbacks **pcb) NGH2_SET_CALLBACK(*pcb, on_header, on_header_cb); NGH2_SET_CALLBACK(*pcb, send_data, on_send_data_cb); NGH2_SET_CALLBACK(*pcb, on_frame_send, on_frame_send_cb); - +#ifdef H2_NG2_INVALID_HEADER_CB + NGH2_SET_CALLBACK(*pcb, on_invalid_header, on_invalid_header_cb); +#endif return APR_SUCCESS; } @@ -728,7 +751,7 @@ static apr_status_t h2_session_shutdown_notice(h2_session *session) if (status == APR_SUCCESS) { status = h2_conn_io_flush(&session->io); } - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO() + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03457) "session(%ld): sent shutdown notice", session->id); return status; } diff --git a/modules/http2/mod_http2.c b/modules/http2/mod_http2.c index 06410612933..65ea3d6aa4e 100644 --- a/modules/http2/mod_http2.c +++ b/modules/http2/mod_http2.c @@ -60,6 +60,7 @@ static int h2_h2_fixups(request_rec *r); typedef struct { unsigned int change_prio : 1; unsigned int sha256 : 1; + unsigned int inv_headers : 1; } features; static features myfeats; @@ -84,16 +85,17 @@ static int h2_post_config(apr_pool_t *p, apr_pool_t *plog, const char *mod_h2_init_key = "mod_http2_init_counter"; nghttp2_info *ngh2; apr_status_t status; - const char *sep = ""; (void)plog;(void)ptemp; #ifdef H2_NG2_CHANGE_PRIO myfeats.change_prio = 1; - sep = "+"; #endif #ifdef H2_OPENSSL myfeats.sha256 = 1; #endif +#ifdef H2_NG2_INVALID_HEADER_CB + myfeats.inv_headers = 1; +#endif apr_pool_userdata_get(&data, mod_h2_init_key, s->process->pool); if ( data == NULL ) { @@ -108,8 +110,9 @@ static int h2_post_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error( APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(03090) "mod_http2 (v%s, feats=%s%s%s, nghttp2 %s), initializing...", MOD_HTTP2_VERSION, - myfeats.change_prio? "CHPRIO" : "", sep, - myfeats.sha256? "SHA256" : "", + myfeats.change_prio? "CHPRIO" : "", + myfeats.sha256? "+SHA256" : "", + myfeats.inv_headers? "+INVHD" : "", ngh2? ngh2->version_str : "unknown"); switch (h2_conn_mpm_type()) {