]> granicus.if.org Git - curl/commitdiff
http2: verify :athority in push promise requests
authorDaniel Stenberg <daniel@haxx.se>
Mon, 18 Feb 2019 08:10:01 +0000 (09:10 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 20 Feb 2019 07:18:02 +0000 (08:18 +0100)
RFC 7540 says we should verify that the push is for an "authoritative"
server. We make sure of this by only allowing push with an :athority
header that matches the host that was asked for in the URL.

Fixes #3577
Reported-by: Nicolas Grekas
Bug: https://curl.haxx.se/mail/lib-2019-02/0057.html
Closes #3581

lib/http2.c

index 2884c7152aa5df1c970d1f7f12cceb8453fcc355..b5c53cdf60299329882915e310f03e224db3281e 100644 (file)
@@ -969,6 +969,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
     char *h;
 
+    if(!strcmp(":authority", (const char *)name)) {
+      /* psuedo headers are lower case */
+      int rc = 0;
+      char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
+      if(!check)
+        /* no memory */
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+      if(!Curl_strcasecompare(check, (const char *)value)) {
+        /* This is push is not for the same authority that was asked for in
+         * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
+         * PUSH_PROMISE for which the server is not authoritative as a stream
+         * error of type PROTOCOL_ERROR."
+         */
+        (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+                                        stream_id, NGHTTP2_PROTOCOL_ERROR);
+        rc = NGHTTP2_ERR_CALLBACK_FAILURE;
+      }
+      free(check);
+      if(rc)
+        return rc;
+    }
+
     if(!stream->push_headers) {
       stream->push_headers_alloc = 10;
       stream->push_headers = malloc(stream->push_headers_alloc *