ServerIdentityTest.java revision 9372:171791e63397
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 4328195
27 * @summary Need to include the alternate subject DN for certs,
28 *          https should check for this
29 * @run main/othervm ServerIdentityTest
30 *
31 *     SunJSSE does not support dynamic system properties, no way to re-use
32 *     system properties in samevm/agentvm mode.
33 *
34 * @author Yingxian Wang
35 */
36
37import java.io.*;
38import java.net.*;
39import javax.net.ssl.*;
40import java.security.KeyStore;
41
42public class ServerIdentityTest {
43
44    /*
45     * =============================================================
46     * Set the various variables needed for the tests, then
47     * specify what tests to run on each side.
48     */
49
50    /*
51     * Should we run the client or server in a separate thread?
52     * Both sides can throw exceptions, but do you have a preference
53     * as to which side should be the main thread.
54     */
55    static boolean separateServerThread = true;
56
57    /*
58     * Where do we find the keystores?
59     */
60    static String pathToStores = "./";
61    static String[] keyStoreFiles = {"dnsstore", "ipstore"};
62    static String[] trustStoreFiles = {"dnsstore", "ipstore"};
63    static String passwd = "changeit";
64
65    /*
66     * Is the server ready to serve?
67     */
68    boolean serverReady = false;
69
70    /*
71     * Turn on SSL debugging?
72     */
73    static boolean debug = false;
74
75    /*
76     * If the client or server is doing some kind of object creation
77     * that the other side depends on, and that thread prematurely
78     * exits, you may experience a hang.  The test harness will
79     * terminate all hung threads after its timeout has expired,
80     * currently 3 minutes by default, but you might try to be
81     * smart about it....
82     */
83
84    /*
85     * Define the server side of the test.
86     *
87     * If the server prematurely exits, serverReady will be set to true
88     * to avoid infinite hangs.
89     */
90    void doServerSide() throws Exception {
91        SSLServerSocketFactory sslssf =
92            context.getServerSocketFactory();
93        SSLServerSocket sslServerSocket =
94            (SSLServerSocket) sslssf.createServerSocket(serverPort);
95        serverPort = sslServerSocket.getLocalPort();
96
97        /*
98         * Signal Client, we're ready for his connect.
99         */
100        serverReady = true;
101
102        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
103        OutputStream sslOS = sslSocket.getOutputStream();
104        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sslOS));
105        bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
106        bw.flush();
107        Thread.sleep(2000);
108        sslSocket.getSession().invalidate();
109        sslSocket.close();
110    }
111
112    /*
113     * Define the client side of the test.
114     *
115     * If the server prematurely exits, serverReady will be set to true
116     * to avoid infinite hangs.
117     */
118    void doClientSide() throws Exception {
119        /*
120         * Wait for server to get started.
121         */
122        while (!serverReady) {
123            Thread.sleep(50);
124        }
125        String host = iphost? "127.0.0.1": "localhost";
126        URL url = new URL("https://"+host+":"+serverPort+"/index.html");
127
128        HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
129        InputStream is = urlc.getInputStream();
130        is.close();
131    }
132
133    /*
134     * =============================================================
135     * The remainder is just support stuff
136     */
137
138    volatile int serverPort = 0;
139
140    volatile Exception serverException = null;
141    volatile Exception clientException = null;
142
143    public static void main(String[] args) throws Exception {
144        SSLSocketFactory reservedSFactory =
145                HttpsURLConnection.getDefaultSSLSocketFactory();
146        try {
147            for (int i = 0; i < keyStoreFiles.length; i++) {
148                String keyFilename =
149                    System.getProperty("test.src", ".") + "/" + pathToStores +
150                    "/" + keyStoreFiles[i];
151                String trustFilename =
152                    System.getProperty("test.src", ".") + "/" + pathToStores +
153                    "/" + trustStoreFiles[i];
154
155                System.setProperty("javax.net.ssl.keyStore", keyFilename);
156                System.setProperty("javax.net.ssl.keyStorePassword", passwd);
157                System.setProperty("javax.net.ssl.trustStore", trustFilename);
158                System.setProperty("javax.net.ssl.trustStorePassword", passwd);
159
160                if (debug)
161                    System.setProperty("javax.net.debug", "all");
162                SSLContext context = SSLContext.getInstance("SSL");
163
164                KeyManager[] kms = new KeyManager[1];
165                KeyStore ks = KeyStore.getInstance("JKS");
166                FileInputStream fis = new FileInputStream(keyFilename);
167                ks.load(fis, passwd.toCharArray());
168                fis.close();
169                KeyManager km = new MyKeyManager(ks, passwd.toCharArray());
170                kms[0] = km;
171                context.init(kms, null, null);
172                HttpsURLConnection.setDefaultSSLSocketFactory(
173                     context.getSocketFactory());
174
175                /*
176                 * Start the tests.
177                 */
178                System.out.println("Testing " + keyFilename);
179                new ServerIdentityTest(context, keyStoreFiles[i]);
180            }
181        } finally {
182            HttpsURLConnection.setDefaultSSLSocketFactory(reservedSFactory);
183        }
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    SSLContext context;
195    boolean iphost = false;
196    ServerIdentityTest(SSLContext context, String keystore)
197        throws Exception {
198        this.context = context;
199        iphost = keystore.equals("ipstore");
200        if (separateServerThread) {
201            startServer(true);
202            startClient(false);
203        } else {
204            startClient(true);
205            startServer(false);
206        }
207
208        /*
209         * Wait for other side to close down.
210         */
211        if (separateServerThread) {
212            serverThread.join();
213        } else {
214            clientThread.join();
215        }
216
217        /*
218         * When we get here, the test is pretty much over.
219         *
220         * If the main thread excepted, that propagates back
221         * immediately.  If the other thread threw an exception, we
222         * should report back.
223         */
224        if (serverException != null)
225            throw serverException;
226        if (clientException != null)
227            throw clientException;
228    }
229
230    void startServer(boolean newThread) throws Exception {
231        if (newThread) {
232            serverThread = new Thread() {
233                public void run() {
234                    try {
235                        doServerSide();
236                    } catch (Exception e) {
237                        e.printStackTrace();
238                        /*
239                         * Our server thread just died.
240                         *
241                         * Release the client, if not active already...
242                         */
243                        System.err.println("Server died...");
244                        serverReady = true;
245                        serverException = e;
246                    }
247                }
248            };
249            serverThread.start();
250        } else {
251            doServerSide();
252        }
253    }
254
255    void startClient(boolean newThread) throws Exception {
256        if (newThread) {
257            clientThread = new Thread() {
258                public void run() {
259                    try {
260                        doClientSide();
261                    } catch (Exception e) {
262                        /*
263                         * Our client thread just died.
264                         */
265                        System.err.println("Client died...");
266                        clientException = e;
267                    }
268                }
269            };
270            clientThread.start();
271        } else {
272            doClientSide();
273        }
274    }
275}
276