1/*
2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 4480441
27 * @summary startHandshake giving wrong message when unconnected.
28 * @run main/othervm UnconnectedSocketWrongExceptions
29 *
30 *     SunJSSE does not support dynamic system properties, no way to re-use
31 *     system properties in samevm/agentvm mode.
32 *
33 * @author Brad Wetmore
34 */
35
36import java.io.*;
37import java.net.*;
38import javax.net.ssl.*;
39
40public class UnconnectedSocketWrongExceptions {
41
42    /*
43     * =============================================================
44     * Set the various variables needed for the tests, then
45     * specify what tests to run on each side.
46     */
47
48    /*
49     * Should we run the client or server in a separate thread?
50     * Both sides can throw exceptions, but do you have a preference
51     * as to which side should be the main thread.
52     */
53    static boolean separateServerThread = true;
54
55    /*
56     * Where do we find the keystores?
57     */
58    static String pathToStores = "../../../../javax/net/ssl/etc";
59    static String keyStoreFile = "keystore";
60    static String trustStoreFile = "truststore";
61    static String passwd = "passphrase";
62
63    /*
64     * Is the server ready to serve?
65     */
66    volatile static boolean serverReady = false;
67
68    /*
69     * Turn on SSL debugging?
70     */
71    static boolean debug = false;
72
73    /*
74     * If the client or server is doing some kind of object creation
75     * that the other side depends on, and that thread prematurely
76     * exits, you may experience a hang.  The test harness will
77     * terminate all hung threads after its timeout has expired,
78     * currently 3 minutes by default, but you might try to be
79     * smart about it....
80     */
81
82    /*
83     * Define the server side of the test.
84     *
85     * If the server prematurely exits, serverReady will be set to true
86     * to avoid infinite hangs.
87     */
88    void doServerSide() throws Exception {
89        SSLServerSocketFactory sslssf =
90            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
91        SSLServerSocket sslServerSocket =
92            (SSLServerSocket) sslssf.createServerSocket(serverPort);
93
94        serverPort = sslServerSocket.getLocalPort();
95
96        /*
97         * Signal Client, we're ready for his connect.
98         */
99        serverReady = true;
100
101        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
102
103        InputStream sslIS = sslSocket.getInputStream();
104        OutputStream sslOS = sslSocket.getOutputStream();
105
106        sslIS.read();
107        sslOS.write(85);
108        sslOS.flush();
109
110        sslSocket.close();
111    }
112
113    /*
114     * Define the client side of the test.
115     *
116     * If the server prematurely exits, serverReady will be set to true
117     * to avoid infinite hangs.
118     */
119    void doClientSide() throws Exception {
120
121        /*
122         * Wait for server to get started.
123         */
124        while (!serverReady) {
125            Thread.sleep(50);
126        }
127
128        SSLSocketFactory sslsf =
129            (SSLSocketFactory) SSLSocketFactory.getDefault();
130        SSLSocket sslSocket = (SSLSocket)
131            sslsf.createSocket();
132
133        InputStream sslIS;
134        OutputStream sslOS;
135
136        try {
137            System.out.print("getInputStream()...");
138            sslIS = sslSocket.getInputStream();
139            throw new Exception("getInputStream didn't throw properly");
140        } catch (SocketException e) {
141            System.out.println("Caught proper exception:  " + e.toString());
142        }
143
144        try {
145            System.out.print("getOutputStream()...");
146            sslOS = sslSocket.getOutputStream();
147            throw new Exception("getOutputStream didn't throw properly");
148        } catch (SocketException e) {
149            System.out.println("Caught proper exception:  " + e.toString());
150        }
151
152        try {
153            System.out.print("startHandshake()...");
154            sslSocket.startHandshake();
155            throw new Exception("startHandshake() didn't throw properly");
156        } catch (SocketException e) {
157            System.out.println("Caught proper exception:  " + e.toString());
158        }
159
160        InetSocketAddress addr = new InetSocketAddress(
161            "localhost", serverPort);
162        sslSocket.connect(addr, 2000);
163        sslOS = sslSocket.getOutputStream();
164        sslIS = sslSocket.getInputStream();
165
166        sslOS.write(280);
167        sslOS.flush();
168        System.out.println("reading: " + sslIS.read());
169
170        sslSocket.close();
171    }
172
173    /*
174     * =============================================================
175     * The remainder is just support stuff
176     */
177
178    // use any free port by default
179    volatile int serverPort = 0;
180
181    volatile Exception serverException = null;
182    volatile Exception clientException = null;
183
184    public static void main(String[] args) throws Exception {
185        String keyFilename =
186            System.getProperty("test.src", "./") + "/" + pathToStores +
187                "/" + keyStoreFile;
188        String trustFilename =
189            System.getProperty("test.src", "./") + "/" + pathToStores +
190                "/" + trustStoreFile;
191
192        System.setProperty("javax.net.ssl.keyStore", keyFilename);
193        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
194        System.setProperty("javax.net.ssl.trustStore", trustFilename);
195        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
196
197        if (debug)
198            System.setProperty("javax.net.debug", "all");
199
200        /*
201         * Start the tests.
202         */
203        new UnconnectedSocketWrongExceptions();
204    }
205
206    Thread clientThread = null;
207    Thread serverThread = null;
208
209    /*
210     * Primary constructor, used to drive remainder of the test.
211     *
212     * Fork off the other side, then do your work.
213     */
214    UnconnectedSocketWrongExceptions() throws Exception {
215        if (separateServerThread) {
216            startServer(true);
217            startClient(false);
218        } else {
219            startClient(true);
220            startServer(false);
221        }
222
223        /*
224         * Wait for other side to close down.
225         */
226        if (separateServerThread) {
227            serverThread.join();
228        } else {
229            clientThread.join();
230        }
231
232        /*
233         * When we get here, the test is pretty much over.
234         *
235         * If the main thread excepted, that propagates back
236         * immediately.  If the other thread threw an exception, we
237         * should report back.
238         */
239        if (serverException != null) {
240            System.out.print("Server Exception:");
241            throw serverException;
242        }
243        if (clientException != null) {
244            System.out.print("Client Exception:");
245            throw clientException;
246        }
247    }
248
249    void startServer(boolean newThread) throws Exception {
250        if (newThread) {
251            serverThread = new Thread() {
252                public void run() {
253                    try {
254                        doServerSide();
255                    } catch (Exception e) {
256                        /*
257                         * Our server thread just died.
258                         *
259                         * Release the client, if not active already...
260                         */
261                        System.err.println("Server died...");
262                        serverReady = true;
263                        serverException = e;
264                    }
265                }
266            };
267            serverThread.start();
268        } else {
269            doServerSide();
270        }
271    }
272
273    void startClient(boolean newThread) throws Exception {
274        if (newThread) {
275            clientThread = new Thread() {
276                public void run() {
277                    try {
278                        doClientSide();
279                    } catch (Exception e) {
280                        /*
281                         * Our client thread just died.
282                         */
283                        System.err.println("Client died...");
284                        clientException = e;
285                    }
286                }
287            };
288            clientThread.start();
289        } else {
290            doClientSide();
291        }
292    }
293}
294