1/*
2 * Copyright (c) 2003, 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 4969799
27 * @summary javax.net.ssl.SSLSocket.SSLSocket(InetAddress,int) shouldn't
28 *              throw exception
29 * @run main/othervm CloseSocketException
30 *
31 *     SunJSSE does not support dynamic system properties, no way to re-use
32 *     system properties in samevm/agentvm mode.
33 *
34 * This is making sure that starting a new handshake throws the right
35 * exception.  There is a similar test for SSLEngine.
36 *
37 * @author Brad Wetmore
38 */
39
40import java.io.*;
41import java.net.*;
42import javax.net.ssl.*;
43
44public class CloseSocketException {
45
46    /*
47     * =============================================================
48     * Set the various variables needed for the tests, then
49     * specify what tests to run on each side.
50     */
51
52    /*
53     * Should we run the client or server in a separate thread?
54     * Both sides can throw exceptions, but do you have a preference
55     * as to which side should be the main thread.
56     */
57    static boolean separateServerThread = false;
58
59    /*
60     * Where do we find the keystores?
61     */
62    static String pathToStores = "../../../../javax/net/ssl/etc";
63    static String keyStoreFile = "keystore";
64    static String trustStoreFile = "truststore";
65    static String passwd = "passphrase";
66
67    /*
68     * Is the server ready to serve?
69     */
70    volatile static boolean serverReady = false;
71
72    /*
73     * Turn on SSL debugging?
74     */
75    static boolean debug = false;
76
77    /*
78     * If the client or server is doing some kind of object creation
79     * that the other side depends on, and that thread prematurely
80     * exits, you may experience a hang.  The test harness will
81     * terminate all hung threads after its timeout has expired,
82     * currently 3 minutes by default, but you might try to be
83     * smart about it....
84     */
85
86    /*
87     * Define the server side of the test.
88     *
89     * If the server prematurely exits, serverReady will be set to true
90     * to avoid infinite hangs.
91     */
92    void doServerSide() throws Exception {
93        SSLServerSocketFactory sslssf =
94            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
95        SSLServerSocket sslServerSocket =
96            (SSLServerSocket) sslssf.createServerSocket(serverPort);
97
98        serverPort = sslServerSocket.getLocalPort();
99
100        /*
101         * Signal Client, we're ready for his connect.
102         */
103        serverReady = true;
104
105        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
106        InputStream sslIS = sslSocket.getInputStream();
107        OutputStream sslOS = sslSocket.getOutputStream();
108
109        sslIS.read();
110        sslOS.write(85);
111        sslOS.flush();
112
113        sslSocket.close();
114    }
115
116    /*
117     * Define the client side of the test.
118     *
119     * If the server prematurely exits, serverReady will be set to true
120     * to avoid infinite hangs.
121     */
122    void doClientSide() throws Exception {
123
124        /*
125         * Wait for server to get started.
126         */
127        while (!serverReady) {
128            Thread.sleep(50);
129        }
130
131        SSLSocketFactory sslsf =
132            (SSLSocketFactory) SSLSocketFactory.getDefault();
133        SSLSocket sslSocket = (SSLSocket)
134            sslsf.createSocket("localhost", serverPort);
135
136        InputStream sslIS = sslSocket.getInputStream();
137        OutputStream sslOS = sslSocket.getOutputStream();
138
139        sslOS.write(280);
140        sslOS.flush();
141        sslIS.read();
142
143        sslSocket.close();
144
145        try {
146            sslSocket.startHandshake();
147            throw new Exception("TEST FAILED:  didn't throw SSLException");
148        } catch (IOException e) {
149            System.out.println("TEST PASSED:  Caught right Exception");
150        }
151    }
152
153    /*
154     * =============================================================
155     * The remainder is just support stuff
156     */
157
158    // use any free port by default
159    volatile int serverPort = 0;
160
161    volatile Exception serverException = null;
162    volatile Exception clientException = null;
163
164    public static void main(String[] args) throws Exception {
165        String keyFilename =
166            System.getProperty("test.src", "./") + "/" + pathToStores +
167                "/" + keyStoreFile;
168        String trustFilename =
169            System.getProperty("test.src", "./") + "/" + pathToStores +
170                "/" + trustStoreFile;
171
172        System.setProperty("javax.net.ssl.keyStore", keyFilename);
173        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
174        System.setProperty("javax.net.ssl.trustStore", trustFilename);
175        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
176
177        if (debug)
178            System.setProperty("javax.net.debug", "all");
179
180        /*
181         * Start the tests.
182         */
183        new CloseSocketException();
184    }
185
186    Thread clientThread = null;
187    Thread serverThread = null;
188
189    /*
190     * Primary constructor, used to drive remainder of the test.
191     *
192     * Fork off the other side, then do your work.
193     */
194    CloseSocketException() throws Exception {
195        try {
196            if (separateServerThread) {
197                startServer(true);
198                startClient(false);
199            } else {
200                startClient(true);
201                startServer(false);
202            }
203        } catch (Exception e) {
204            // swallow for now.  Show later
205        }
206
207        /*
208         * Wait for other side to close down.
209         */
210        if (separateServerThread) {
211            serverThread.join();
212        } else {
213            clientThread.join();
214        }
215
216        /*
217         * When we get here, the test is pretty much over.
218         * Which side threw the error?
219         */
220        Exception local;
221        Exception remote;
222        String whichRemote;
223
224        if (separateServerThread) {
225            remote = serverException;
226            local = clientException;
227            whichRemote = "server";
228        } else {
229            remote = clientException;
230            local = serverException;
231            whichRemote = "client";
232        }
233
234        /*
235         * If both failed, return the curthread's exception, but also
236         * print the remote side Exception
237         */
238        if ((local != null) && (remote != null)) {
239            System.out.println(whichRemote + " also threw:");
240            remote.printStackTrace();
241            System.out.println();
242            throw local;
243        }
244
245        if (remote != null) {
246            throw remote;
247        }
248
249        if (local != null) {
250            throw local;
251        }
252    }
253
254    void startServer(boolean newThread) throws Exception {
255        if (newThread) {
256            serverThread = new Thread() {
257                public void run() {
258                    try {
259                        doServerSide();
260                    } catch (Exception e) {
261                        /*
262                         * Our server thread just died.
263                         *
264                         * Release the client, if not active already...
265                         */
266                        System.err.println("Server died...");
267                        serverReady = true;
268                        serverException = e;
269                    }
270                }
271            };
272            serverThread.start();
273        } else {
274            try {
275                doServerSide();
276            } catch (Exception e) {
277                serverException = e;
278            } finally {
279                serverReady = true;
280            }
281        }
282    }
283
284    void startClient(boolean newThread) throws Exception {
285        if (newThread) {
286            clientThread = new Thread() {
287                public void run() {
288                    try {
289                        doClientSide();
290                    } catch (Exception e) {
291                        /*
292                         * Our client thread just died.
293                         */
294                        System.err.println("Client died...");
295                        clientException = e;
296                    }
297                }
298            };
299            clientThread.start();
300        } else {
301            try {
302                doClientSide();
303            } catch (Exception e) {
304                clientException = e;
305            }
306        }
307    }
308}
309