]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_http2: using invalid header callback from nghttp2 1.14.0 onwards
authorStefan Eissing <icing@apache.org>
Sat, 27 Aug 2016 12:07:16 +0000 (12:07 +0000)
committerStefan Eissing <icing@apache.org>
Sat, 27 Aug 2016 12:07:16 +0000 (12:07 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1758003 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/log-message-tags/next-number
modules/http2/config2.m4
modules/http2/h2_proxy_session.c
modules/http2/h2_session.c
modules/http2/mod_http2.c

diff --git a/CHANGES b/CHANGES
index 4a4801092a8956ca8dd84b31e77cc0ae7c213494..3b57f5f91eb9cf10e180d67ff04644ad7c7d88de 100644 (file)
--- 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]
      
index 169efa8bd26e4837bafefa6e14c2abee4541f6bc..a82b2ee2a7015a43e8f2b30243c0e178cd369ec1 100644 (file)
@@ -1 +1 @@
-3456
+3458
index a77ad8089980c12aead7b6e3b56cf316692d0f87..cccbbc8536f5aadd34e7cdcb36a7d7161794b2a4 100644 (file)
@@ -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
index 79a2e82e82d0d9363e31b8d29ab46bd0c42c5581..22f37e08578e20b2aff6ee90be23819565338493 100644 (file)
@@ -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);
     }
index 1cb0a59f2fb21989b8f41f8b7ee31cfe3197c886..31ae303c9d0fc274b1ca261d7dd9c1fcc17e5c3e 100644 (file)
@@ -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;
 }
index 06410612933ad3d9ab5daf0b961637ba7daabc97..65ea3d6aa4e294a317b352279e83264a6ada23d3 100644 (file)
@@ -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()) {