File: B6216082.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (193 lines) | stat: -rw-r--r-- 7,333 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//

/*
 * @test
 * @bug 6216082
 * @summary  Redirect problem with HttpsURLConnection using a proxy
 * @modules java.base/sun.net.www
 * @library .. /test/lib
 * @build jdk.test.lib.NetworkConfiguration
 *        jdk.test.lib.Platform
 *        HttpCallback TestHttpsServer ClosedChannelList
 *        HttpTransaction TunnelProxy
 * @key intermittent
 * @run main/othervm B6216082
 */

import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.util.*;

import jdk.test.lib.NetworkConfiguration;

public class B6216082 {
    static SimpleHttpTransaction httpTrans;
    static TestHttpsServer server;
    static TunnelProxy proxy;

    // it seems there's no proxy ever if a url points to 'localhost',
    // even if proxy related properties are set. so we need to bind
    // our simple http proxy and http server to a non-loopback address
    static InetAddress firstNonLoAddress = null;

    public static void main(String[] args) throws Exception {
        HostnameVerifier reservedHV =
            HttpsURLConnection.getDefaultHostnameVerifier();
        try {
            // XXX workaround for CNFE
            Class.forName("java.nio.channels.ClosedByInterruptException");
            if (!setupEnv()) {
                return;
            }

            startHttpServer();

            // https.proxyPort can only be set after the TunnelProxy has been
            // created as it will use an ephemeral port.
            System.setProperty("https.proxyPort",
                        (new Integer(proxy.getLocalPort())).toString() );

            makeHttpCall();

            if (httpTrans.hasBadRequest) {
                throw new RuntimeException("Test failed : bad http request");
            }
        } finally {
            if (proxy != null) {
                proxy.terminate();
            }
            if (server != null) {
               server.terminate();
            }
            HttpsURLConnection.setDefaultHostnameVerifier(reservedHV);
        }
    }

    /*
     * Where do we find the keystores for ssl?
     */
    static String pathToStores = "../../../../../../javax/net/ssl/etc";
    static String keyStoreFile = "keystore";
    static String trustStoreFile = "truststore";
    static String passwd = "passphrase";
    public static boolean setupEnv() throws Exception {
        firstNonLoAddress = getNonLoAddress();
        if (firstNonLoAddress == null) {
            System.err.println("The test needs at least one non-loopback address to run. Quit now.");
            return false;
        }
        System.out.println(firstNonLoAddress.getHostAddress());
        // will use proxy
        System.setProperty( "https.proxyHost", firstNonLoAddress.getHostAddress());

        // setup properties to do ssl
        String keyFilename = System.getProperty("test.src", "./") + "/" +
                             pathToStores + "/" + keyStoreFile;
        String trustFilename = System.getProperty("test.src", "./") + "/" +
                               pathToStores + "/" + trustStoreFile;

        System.setProperty("javax.net.ssl.keyStore", keyFilename);
        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
        System.setProperty("javax.net.ssl.trustStore", trustFilename);
        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
        HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
        return true;
    }

    public static InetAddress getNonLoAddress() throws Exception {
        InetAddress lh = InetAddress.getByName("localhost");
        NetworkInterface loNIC = NetworkInterface.getByInetAddress(lh);

        NetworkConfiguration nc = NetworkConfiguration.probe();
        Optional<InetAddress> oaddr = nc.interfaces()
                .filter(nif -> !nif.getName().equalsIgnoreCase(loNIC.getName()))
                .flatMap(nif -> nc.addresses(nif))
                .filter(a -> !a.isLoopbackAddress())
                .findFirst();

        return oaddr.orElseGet(() -> null);
    }

    public static void startHttpServer() throws IOException {
        // Both the https server and the proxy let the
        // system pick up an ephemeral port.
        httpTrans = new SimpleHttpTransaction();
        server = new TestHttpsServer(httpTrans, 1, 10, 0);
        proxy = new TunnelProxy(1, 10, 0);
    }

    public static void makeHttpCall() throws Exception {
        System.out.println("https server listen on: " + server.getLocalPort());
        System.out.println("https proxy listen on: " + proxy.getLocalPort());
        URL url = new URL("https" , firstNonLoAddress.getHostAddress(),
                            server.getLocalPort(), "/");
        HttpURLConnection uc = (HttpURLConnection)url.openConnection();
        System.out.println(uc.getResponseCode());
        uc.disconnect();
    }

    static class NameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}

class SimpleHttpTransaction implements HttpCallback {
    public boolean hasBadRequest = false;

    /*
     * Our http server which simply redirect first call
     */
    public void request(HttpTransaction trans) {
        try {
            String path = trans.getRequestURI().getPath();
            if (path.equals("/")) {
                // the first call, redirect it
                String location = "/redirect";
                trans.addResponseHeader("Location", location);
                trans.sendResponse(302, "Moved Temporarily");
            } else {
                // if the bug exsits, it'll send 2 GET commands
                // check 2nd GET here
                String duplicatedGet = trans.getRequestHeader(null);
                if (duplicatedGet != null &&
                    duplicatedGet.toUpperCase().indexOf("GET") >= 0) {
                    trans.sendResponse(400, "Bad Request");
                    hasBadRequest = true;
                } else {
                    trans.sendResponse(200, "OK");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}