Blame SOURCES/jdk8222527-rh1869530-host_header_for_proxies.patch

d5c0b6
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
d5c0b6
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
d5c0b6
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
d5c0b6
@@ -157,6 +157,7 @@
d5c0b6
                 return true;
d5c0b6
             };
d5c0b6
 
d5c0b6
+    private static final Predicate<String> IS_HOST = "host"::equalsIgnoreCase;
d5c0b6
     private static final Predicate<String> IS_PROXY_HEADER = (k) ->
d5c0b6
             k != null && k.length() > 6 && "proxy-".equalsIgnoreCase(k.substring(0,6));
d5c0b6
     private static final Predicate<String> NO_PROXY_HEADER =
d5c0b6
@@ -228,7 +229,8 @@
d5c0b6
 
d5c0b6
     public static final BiPredicate<String, String> PROXY_TUNNEL_FILTER =
d5c0b6
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_TUNNEL_DISABLED_SCHEMES,
d5c0b6
-                    IS_PROXY_HEADER);
d5c0b6
+                    // Allows Proxy-* and Host headers when establishing the tunnel.
d5c0b6
+                    IS_PROXY_HEADER.or(IS_HOST));
d5c0b6
     public static final BiPredicate<String, String> PROXY_FILTER =
d5c0b6
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_DISABLED_SCHEMES,
d5c0b6
                     ALL_HEADERS);
d5c0b6
diff --git a/test/jdk/java/net/httpclient/DigestEchoServer.java b/test/jdk/java/net/httpclient/DigestEchoServer.java
d5c0b6
--- a/test/jdk/java/net/httpclient/DigestEchoServer.java
d5c0b6
+++ b/test/jdk/java/net/httpclient/DigestEchoServer.java
d5c0b6
@@ -82,6 +82,8 @@
d5c0b6
             Boolean.parseBoolean(System.getProperty("test.debug", "false"));
d5c0b6
     public static final boolean NO_LINGER =
d5c0b6
             Boolean.parseBoolean(System.getProperty("test.nolinger", "false"));
d5c0b6
+    public static final boolean TUNNEL_REQUIRES_HOST =
d5c0b6
+            Boolean.parseBoolean(System.getProperty("test.requiresHost", "false"));
d5c0b6
     public enum HttpAuthType {
d5c0b6
         SERVER, PROXY, SERVER307, PROXY305
d5c0b6
         /* add PROXY_AND_SERVER and SERVER_PROXY_NONE */
d5c0b6
@@ -1524,6 +1526,36 @@
d5c0b6
             }
d5c0b6
         }
d5c0b6
 
d5c0b6
+        boolean badRequest(StringBuilder response, String hostport, List<String> hosts) {
d5c0b6
+            String message = null;
d5c0b6
+            if (hosts.isEmpty()) {
d5c0b6
+                message = "No host header provided\r\n";
d5c0b6
+            } else if (hosts.size() > 1) {
d5c0b6
+                message = "Multiple host headers provided\r\n";
d5c0b6
+                for (String h : hosts) {
d5c0b6
+                    message = message + "host: " + h + "\r\n";
d5c0b6
+                }
d5c0b6
+            } else {
d5c0b6
+                String h = hosts.get(0);
d5c0b6
+                if (!hostport.equalsIgnoreCase(h)
d5c0b6
+                        && !hostport.equalsIgnoreCase(h + ":80")
d5c0b6
+                        && !hostport.equalsIgnoreCase(h + ":443")) {
d5c0b6
+                    message = "Bad host provided: [" + h
d5c0b6
+                            + "] doesnot match [" + hostport + "]\r\n";
d5c0b6
+                }
d5c0b6
+            }
d5c0b6
+            if (message != null) {
d5c0b6
+                int length = message.getBytes(StandardCharsets.UTF_8).length;
d5c0b6
+                response.append("HTTP/1.1 400 BadRequest\r\n")
d5c0b6
+                        .append("Content-Length: " + length)
d5c0b6
+                        .append("\r\n\r\n")
d5c0b6
+                        .append(message);
d5c0b6
+                return true;
d5c0b6
+            }
d5c0b6
+
d5c0b6
+            return false;
d5c0b6
+        }
d5c0b6
+
d5c0b6
         boolean authorize(StringBuilder response, String requestLine, String headers) {
d5c0b6
             if (authorization != null) {
d5c0b6
                 return authorization.authorize(response, requestLine, headers);
d5c0b6
@@ -1637,6 +1669,7 @@
d5c0b6
                         assert connect.equalsIgnoreCase("connect");
d5c0b6
                         String hostport = tokenizer.nextToken();
d5c0b6
                         InetSocketAddress targetAddress;
d5c0b6
+                        List<String> hosts = new ArrayList<>();
d5c0b6
                         try {
d5c0b6
                             URI uri = new URI("https", hostport, "/", null, null);
d5c0b6
                             int port = uri.getPort();
d5c0b6
@@ -1661,9 +1694,30 @@
d5c0b6
                             System.out.println(now() + "Tunnel: Reading header: "
d5c0b6
                                                + (line = readLine(ccis)));
d5c0b6
                             headers.append(line).append("\r\n");
d5c0b6
+                            int index = line.indexOf(':');
d5c0b6
+                            if (index >= 0) {
d5c0b6
+                                String key = line.substring(0, index).trim();
d5c0b6
+                                if (key.equalsIgnoreCase("host")) {
d5c0b6
+                                    hosts.add(line.substring(index+1).trim());
d5c0b6
+                                }
d5c0b6
+                            }
d5c0b6
+                        }
d5c0b6
+                        StringBuilder response = new StringBuilder();
d5c0b6
+                        if (TUNNEL_REQUIRES_HOST) {
d5c0b6
+                            if (badRequest(response, hostport, hosts)) {
d5c0b6
+                                System.out.println(now() + "Tunnel: Sending " + response);
d5c0b6
+                                // send the 400 response
d5c0b6
+                                pw.print(response.toString());
d5c0b6
+                                pw.flush();
d5c0b6
+                                toClose.close();
d5c0b6
+                                continue;
d5c0b6
+                            } else {
d5c0b6
+                                assert hosts.size() == 1;
d5c0b6
+                                System.out.println(now()
d5c0b6
+                                        + "Tunnel: Host header verified " + hosts);
d5c0b6
+                            }
d5c0b6
                         }
d5c0b6
 
d5c0b6
-                        StringBuilder response = new StringBuilder();
d5c0b6
                         final boolean authorize = authorize(response, requestLine, headers.toString());
d5c0b6
                         if (!authorize) {
d5c0b6
                             System.out.println(now() + "Tunnel: Sending "
d5c0b6
diff --git a/test/jdk/java/net/httpclient/HttpsTunnelTest.java b/test/jdk/java/net/httpclient/HttpsTunnelTest.java
d5c0b6
--- a/test/jdk/java/net/httpclient/HttpsTunnelTest.java
d5c0b6
+++ b/test/jdk/java/net/httpclient/HttpsTunnelTest.java
d5c0b6
@@ -1,5 +1,5 @@
d5c0b6
 /*
d5c0b6
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
d5c0b6
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
d5c0b6
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
d5c0b6
  *
d5c0b6
  * This code is free software; you can redistribute it and/or modify it
d5c0b6
@@ -47,8 +47,9 @@
d5c0b6
  *          proxy P is downgraded to HTTP/1.1, then a new h2 request
d5c0b6
  *          going to a different host through the same proxy will not
d5c0b6
  *          be preemptively downgraded. That, is the stack should attempt
d5c0b6
- *          a new h2 connection to the new host.
d5c0b6
- * @bug 8196967
d5c0b6
+ *          a new h2 connection to the new host. It also verifies that
d5c0b6
+ *          the stack sends the appropriate "host" header to the proxy.
d5c0b6
+ * @bug 8196967 8222527
d5c0b6
  * @library /lib/testlibrary http2/server
d5c0b6
  * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpsTunnelTest
d5c0b6
  * @modules java.net.http/jdk.internal.net.http.common
d5c0b6
@@ -58,7 +59,10 @@
d5c0b6
  *          java.base/sun.net.www.http
d5c0b6
  *          java.base/sun.net.www
d5c0b6
  *          java.base/sun.net
d5c0b6
- * @run main/othervm -Djdk.internal.httpclient.debug=true HttpsTunnelTest
d5c0b6
+ * @run main/othervm -Dtest.requiresHost=true
d5c0b6
+ *                   -Djdk.httpclient.HttpClient.log=headers
d5c0b6
+ *                   -Djdk.internal.httpclient.debug=true HttpsTunnelTest
d5c0b6
+ *
d5c0b6
  */
d5c0b6
 
d5c0b6
 public class HttpsTunnelTest implements HttpServerAdapters {
d5c0b6
@@ -145,6 +149,7 @@
d5c0b6
             if (!lines.equals(respLines)) {
d5c0b6
                 throw new RuntimeException("Unexpected response 1: " + respLines);
d5c0b6
             }
d5c0b6
+
d5c0b6
             HttpRequest.BodyPublisher reqBody2 = HttpRequest.BodyPublishers.ofString(body);
d5c0b6
             HttpRequest req2 = HttpRequest
d5c0b6
                     .newBuilder(uri2)
d5c0b6
diff --git a/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java b/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java
d5c0b6
--- a/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java
d5c0b6
+++ b/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java
d5c0b6
@@ -1,5 +1,5 @@
d5c0b6
 /*
d5c0b6
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
d5c0b6
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
d5c0b6
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
d5c0b6
  *
d5c0b6
  * This code is free software; you can redistribute it and/or modify it
d5c0b6
@@ -23,7 +23,7 @@
d5c0b6
 
d5c0b6
 /**
d5c0b6
  * @test
d5c0b6
- * @bug 8087112
d5c0b6
+ * @bug 8087112 8222527
d5c0b6
  * @summary this test verifies that a client may provides authorization
d5c0b6
  *          headers directly when connecting with a server over SSL, and
d5c0b6
  *          it verifies that the client honor the jdk.http.auth.*.disabledSchemes
d5c0b6
@@ -43,9 +43,11 @@
d5c0b6
  *                   ProxyAuthDisabledSchemesSSL SSL
d5c0b6
  * @run main/othervm -Djdk.http.auth.proxying.disabledSchemes=Basic
d5c0b6
  *                   -Djdk.http.auth.tunneling.disabledSchemes=Basic
d5c0b6
+ *                   -Dtest.requiresHost=true
d5c0b6
  *                   ProxyAuthDisabledSchemesSSL SSL PROXY
d5c0b6
  * @run main/othervm -Djdk.http.auth.proxying.disabledSchemes=Digest
d5c0b6
  *                   -Djdk.http.auth.tunneling.disabledSchemes=Digest
d5c0b6
+ *                   -Dtest.requiresHost=true
d5c0b6
  *                   ProxyAuthDisabledSchemesSSL SSL PROXY
d5c0b6
  */
d5c0b6