File: EndingDotHostname.java

package info (click to toggle)
openjdk-23 23.0.2%2B7-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 815,324 kB
  • sloc: java: 5,632,909; cpp: 1,303,022; xml: 1,237,193; ansic: 419,177; asm: 404,932; objc: 20,978; sh: 15,486; javascript: 11,040; python: 6,802; makefile: 2,331; perl: 357; awk: 351; sed: 172; pascal: 103; exp: 26; jsp: 24; csh: 3
file content (251 lines) | stat: -rw-r--r-- 9,220 bytes parent folder | download | duplicates (14)
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*
 * Copyright (C) 2022 THL A29 Limited, a Tencent company. 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.
 */

/**
 * @test
 * @bug 8065422
 * @summary Trailing dot in hostname causes TLS handshake to fail
 * @library /javax/net/ssl/templates
 * @run main/othervm --add-opens java.base/sun.security.ssl=ALL-UNNAMED
 *      -Djdk.net.hosts.file=hostsForExample EndingDotHostname
 */

import javax.net.ssl.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class EndingDotHostname {
    public static void main(String[] args) throws Exception {
        System.setProperty("jdk.net.hosts.file", "hostsForExample");
        (new EndingDotHostname()).run();
    }

    public void run() throws Exception {
        bootUp();
    }

    // =================================================
    // Stuffs to boot up the client-server mode testing.
    private Thread serverThread = null;
    private volatile Exception serverException = null;
    private volatile Exception clientException = null;

    // Is the server ready to serve?
    protected final CountDownLatch serverCondition = new CountDownLatch(1);

    // Is the client ready to handshake?
    protected final CountDownLatch clientCondition = new CountDownLatch(1);

    // What's the server port?  Use any free port by default
    protected volatile int serverPort = 0;

    // Boot up the testing, used to drive remainder of the test.
    private void bootUp() throws Exception {
        Exception startException = null;
        try {
            startServer();
            startClient();
        } catch (Exception e) {
            startException = e;
        }

        // Wait for other side to close down.
        if (serverThread != null) {
            serverThread.join();
        }

        // The test is pretty much over. Which side threw an exception?
        Exception local = clientException;
        Exception remote = serverException;

        Exception exception = null;

        // Check various exception conditions.
        if ((local != null) && (remote != null)) {
            // If both failed, return the curthread's exception.
            local.initCause(remote);
            exception = local;
        } else if (local != null) {
            exception = local;
        } else if (remote != null) {
            exception = remote;
        } else if (startException != null) {
            exception = startException;
        }

        // If there was an exception *AND* a startException, output it.
        if (exception != null) {
            if (exception != startException && startException != null) {
                exception.addSuppressed(startException);
            }
            throw exception;
        }

        // Fall-through: no exception to throw!
    }

    private void startServer() {
        serverThread = new Thread(() -> {
            try {
                doServerSide();
            } catch (Exception e) {
                // Our server thread just died. Release the client,
                // if not active already...
                serverException = e;
            }
        });

        serverThread.start();
    }

    private void startClient() {
        try {
            doClientSide();
        } catch (Exception e) {
            clientException = e;
        }
    }

    protected void doServerSide() throws Exception {
        // kick off the server side service
        SSLContext context = SSLExampleCert.createServerSSLContext();
        SSLServerSocketFactory sslssf = context.getServerSocketFactory();

        SSLServerSocket sslServerSocket =
                (SSLServerSocket)sslssf.createServerSocket();
        sslServerSocket.bind(new InetSocketAddress(
                InetAddress.getLoopbackAddress(), 0));
        serverPort = sslServerSocket.getLocalPort();

        // Signal the client, the server is ready to accept connection.
        serverCondition.countDown();

        // Try to accept a connection in 30 seconds.
        SSLSocket sslSocket;
        try {
            sslServerSocket.setSoTimeout(30000);
            sslSocket = (SSLSocket)sslServerSocket.accept();
        } catch (SocketTimeoutException ste) {
            // Ignore the test case if no connection within 30 seconds.
            System.out.println(
                    "No incoming client connection in 30 seconds. " +
                            "Ignore in server side.");
            return;
        } finally {
            sslServerSocket.close();
        }

        // handle the connection
        try {
            // Is it the expected client connection?
            //
            // Naughty test cases or third party routines may try to
            // connection to this server port unintentionally.  In
            // order to mitigate the impact of unexpected client
            // connections and avoid intermittent failure, it should
            // be checked that the accepted connection is really linked
            // to the expected client.
            boolean clientIsReady =
                    clientCondition.await(30L, TimeUnit.SECONDS);

            if (clientIsReady) {
                // Run the application in server side.
                runServerApplication(sslSocket);
            } else {    // Otherwise, ignore
                // We don't actually care about plain socket connections
                // for TLS communication testing generally.  Just ignore
                // the test if the accepted connection is not linked to
                // the expected client or the client connection timeout
                // in 30 seconds.
                System.out.println(
                        "The client is not the expected one or timeout. " +
                                "Ignore in server side.");
            }
        } finally {
            sslSocket.close();
        }
    }

    // Define the server side application of the test for the specified socket.
    protected void runServerApplication(SSLSocket socket) throws Exception {
        // here comes the test logic
        InputStream sslIS = socket.getInputStream();
        OutputStream sslOS = socket.getOutputStream();

        sslIS.read();
        sslOS.write(85);
        sslOS.flush();
    }

    protected void doClientSide() throws Exception {
        // Wait for server to get started.
        //
        // The server side takes care of the issue if the server cannot
        // get started in 90 seconds.  The client side would just ignore
        // the test case if the serer is not ready.
        boolean serverIsReady =
                serverCondition.await(90L, TimeUnit.SECONDS);
        if (!serverIsReady) {
            System.out.println(
                    "The server is not ready yet in 90 seconds. " +
                            "Ignore in client side.");
            return;
        }

        SSLContext context = SSLExampleCert.createClientSSLContext();
        SSLSocketFactory sslsf = context.getSocketFactory();

        try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(
                "www.example.com.", serverPort)) {
            // OK, here the client and server get connected.
            SSLParameters sslParameters = sslSocket.getSSLParameters();
            sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
            sslSocket.setSSLParameters(sslParameters);

            // Signal the server, the client is ready to communicate.
            clientCondition.countDown();

            // There is still a chance in theory that the server thread may
            // wait client-ready timeout and then quit.  The chance should
            // be really rare so we don't consider it until it becomes a
            // real problem.

            // Run the application in client side.
            runClientApplication(sslSocket);
        }
    }

    // Define the client side application of the test for the specified socket.
    protected void runClientApplication(SSLSocket socket) throws Exception {
        InputStream sslIS = socket.getInputStream();
        OutputStream sslOS = socket.getOutputStream();

        sslOS.write(280);
        sslOS.flush();
        sslIS.read();
    }
}