SSLSocketTest.java revision 54ac4a62e86b216842a79f433d0919ac19c0ee54
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.javax.net.ssl;
18
19import java.io.InputStream;
20import java.io.OutputStream;
21import java.net.ServerSocket;
22import java.net.Socket;
23import java.net.SocketException;
24import java.net.SocketTimeoutException;
25import java.security.Principal;
26import java.security.cert.Certificate;
27import java.security.cert.CertificateException;
28import java.util.Arrays;
29import java.util.HashSet;
30import java.util.Set;
31import javax.net.ssl.HandshakeCompletedEvent;
32import javax.net.ssl.HandshakeCompletedListener;
33import javax.net.ssl.SSLContext;
34import javax.net.ssl.SSLException;
35import javax.net.ssl.SSLHandshakeException;
36import javax.net.ssl.SSLParameters;
37import javax.net.ssl.SSLPeerUnverifiedException;
38import javax.net.ssl.SSLProtocolException;
39import javax.net.ssl.SSLSession;
40import javax.net.ssl.SSLSocket;
41import javax.net.ssl.SSLSocketFactory;
42import junit.framework.TestCase;
43import libcore.java.security.StandardNames;
44import libcore.java.security.TestKeyStore;
45
46public class SSLSocketTest extends TestCase {
47
48    public void test_SSLSocket_getSupportedCipherSuites_names() throws Exception {
49        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
50        SSLSocket ssl = (SSLSocket) sf.createSocket();
51        String[] cipherSuites = ssl.getSupportedCipherSuites();
52        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
53        assertNotSame(cipherSuites, ssl.getSupportedCipherSuites());
54    }
55
56    public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception {
57        // note the rare usage of non-RSA keys
58        TestKeyStore testKeyStore
59                = TestKeyStore.create(new String[] { "RSA", "DSA", "EC", "EC_RSA" },
60                                      null,
61                                      null,
62                                      "rsa-dsa-ec",
63                                      TestKeyStore.localhost(),
64                                      0,
65                                      true,
66                                      null,
67                                      null);
68        if (StandardNames.IS_RI) {
69            test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore,
70                                                            StandardNames.JSSE_PROVIDER_NAME,
71                                                            StandardNames.JSSE_PROVIDER_NAME,
72                                                            true,
73                                                            true);
74        } else  {
75            test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore,
76                                                            "HarmonyJSSE",
77                                                            "HarmonyJSSE",
78                                                            false,
79                                                            false);
80            test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore,
81                                                            "AndroidOpenSSL",
82                                                            "AndroidOpenSSL",
83                                                            true,
84                                                            true);
85            test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore,
86                                                            "HarmonyJSSE",
87                                                            "AndroidOpenSSL",
88                                                            false,
89                                                            true);
90            test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore,
91                                                            "AndroidOpenSSL",
92                                                            "HarmonyJSSE",
93                                                            true,
94                                                            false);
95        }
96
97    }
98    private void test_SSLSocket_getSupportedCipherSuites_connect(TestKeyStore testKeyStore,
99                                                                 String clientProvider,
100                                                                 String serverProvider,
101                                                                 boolean clientSecureRenegotiation,
102                                                                 boolean serverSecureRenegotiation)
103            throws Exception {
104
105        String clientToServerString = "this is sent from the client to the server...";
106        String serverToClientString = "... and this from the server to the client";
107        byte[] clientToServer = clientToServerString.getBytes();
108        byte[] serverToClient = serverToClientString.getBytes();
109
110        TestSSLContext c = TestSSLContext.create(testKeyStore, testKeyStore,
111                                                 clientProvider, serverProvider);
112        String[] cipherSuites;
113        if (clientProvider.equals(serverProvider)) {
114            cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
115        } else {
116            String[] clientSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
117            String[] serverSuites = c.serverContext.getSocketFactory().getSupportedCipherSuites();
118            Set<String> ccs = new HashSet<String>(Arrays.asList(clientSuites));
119            Set<String> scs = new HashSet<String>(Arrays.asList(serverSuites));
120            Set<String> cs = new HashSet<String>(ccs);
121            cs.retainAll(scs);
122            cipherSuites = cs.toArray(new String[cs.size()]);
123        }
124
125        for (String cipherSuite : cipherSuites) {
126            try {
127                /*
128                 * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on
129                 * its own, but instead in conjunction with other
130                 * cipher suites.
131                 */
132                if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) {
133                    continue;
134                }
135                /*
136                 * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
137                 * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
138                 * #KRBRequire
139                 */
140                if (cipherSuite.startsWith("TLS_KRB5_")) {
141                    continue;
142                }
143
144                String[] clientCipherSuiteArray
145                        = (clientSecureRenegotiation
146                           ? new String[] { cipherSuite,
147                                            StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION }
148                           : new String[] { cipherSuite });
149                String[] serverCipherSuiteArray
150                        = (serverSecureRenegotiation
151                           ? new String[] { cipherSuite,
152                                            StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION }
153                           : new String[] { cipherSuite });
154                SSLSocket[] pair = TestSSLSocketPair.connect(c,
155                                                             clientCipherSuiteArray,
156                                                             serverCipherSuiteArray);
157
158                SSLSocket server = pair[0];
159                SSLSocket client = pair[1];
160                server.getOutputStream().write(serverToClient);
161                client.getOutputStream().write(clientToServer);
162                // arrays are too big to make sure we get back only what we expect
163                byte[] clientFromServer = new byte[serverToClient.length+1];
164                byte[] serverFromClient = new byte[clientToServer.length+1];
165                int readFromServer = client.getInputStream().read(clientFromServer);
166                int readFromClient = server.getInputStream().read(serverFromClient);
167                assertEquals(serverToClient.length, readFromServer);
168                assertEquals(clientToServer.length, readFromClient);
169                assertEquals(clientToServerString, new String(serverFromClient, 0, readFromClient));
170                assertEquals(serverToClientString, new String(clientFromServer, 0, readFromServer));
171                client.close();
172                server.close();
173            } catch (Exception e) {
174                throw new Exception("Problem trying to connect cipher suite " + cipherSuite
175                                    + " client=" + clientProvider
176                                    + " server=" + serverProvider,
177                                    e);
178            }
179        }
180        c.close();
181    }
182
183    public void test_SSLSocket_getEnabledCipherSuites() throws Exception {
184        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
185        SSLSocket ssl = (SSLSocket) sf.createSocket();
186        String[] cipherSuites = ssl.getEnabledCipherSuites();
187        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
188        assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
189    }
190
191    public void test_SSLSocket_setEnabledCipherSuites() throws Exception {
192        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
193        SSLSocket ssl = (SSLSocket) sf.createSocket();
194
195        try {
196            ssl.setEnabledCipherSuites(null);
197            fail();
198        } catch (IllegalArgumentException expected) {
199        }
200        try {
201            ssl.setEnabledCipherSuites(new String[1]);
202            fail();
203        } catch (IllegalArgumentException expected) {
204        }
205        try {
206            ssl.setEnabledCipherSuites(new String[] { "Bogus" } );
207            fail();
208        } catch (IllegalArgumentException expected) {
209        }
210
211        ssl.setEnabledCipherSuites(new String[0]);
212        ssl.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
213        ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
214    }
215
216    public void test_SSLSocket_getSupportedProtocols() throws Exception {
217        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
218        SSLSocket ssl = (SSLSocket) sf.createSocket();
219        String[] protocols = ssl.getSupportedProtocols();
220        StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
221        assertNotSame(protocols, ssl.getSupportedProtocols());
222    }
223
224    public void test_SSLSocket_getEnabledProtocols() throws Exception {
225        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
226        SSLSocket ssl = (SSLSocket) sf.createSocket();
227        String[] protocols = ssl.getEnabledProtocols();
228        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
229        assertNotSame(protocols, ssl.getEnabledProtocols());
230    }
231
232    public void test_SSLSocket_setEnabledProtocols() throws Exception {
233        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
234        SSLSocket ssl = (SSLSocket) sf.createSocket();
235
236        try {
237            ssl.setEnabledProtocols(null);
238            fail();
239        } catch (IllegalArgumentException expected) {
240        }
241        try {
242            ssl.setEnabledProtocols(new String[1]);
243            fail();
244        } catch (IllegalArgumentException expected) {
245        }
246        try {
247            ssl.setEnabledProtocols(new String[] { "Bogus" } );
248            fail();
249        } catch (IllegalArgumentException expected) {
250        }
251        ssl.setEnabledProtocols(new String[0]);
252        ssl.setEnabledProtocols(ssl.getEnabledProtocols());
253        ssl.setEnabledProtocols(ssl.getSupportedProtocols());
254    }
255
256    public void test_SSLSocket_getSession() throws Exception {
257        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
258        SSLSocket ssl = (SSLSocket) sf.createSocket();
259        SSLSession session = ssl.getSession();
260        assertNotNull(session);
261        assertFalse(session.isValid());
262    }
263
264    public void test_SSLSocket_startHandshake() throws Exception {
265        final TestSSLContext c = TestSSLContext.create();
266        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
267                                                                                       c.port);
268        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
269        Thread thread = new Thread(new Runnable () {
270            public void run() {
271                try {
272                    server.startHandshake();
273                    assertNotNull(server.getSession());
274                    try {
275                        server.getSession().getPeerCertificates();
276                        fail();
277                    } catch (SSLPeerUnverifiedException expected) {
278                    }
279                    Certificate[] localCertificates = server.getSession().getLocalCertificates();
280                    assertNotNull(localCertificates);
281                    TestKeyStore.assertChainLength(localCertificates);
282                    assertNotNull(localCertificates[0]);
283                    TestSSLContext.assertServerCertificateChain(c.serverTrustManager,
284                                                                localCertificates);
285                    TestSSLContext.assertCertificateInKeyStore(localCertificates[0],
286                                                               c.serverKeyStore);
287                } catch (RuntimeException e) {
288                    throw e;
289                } catch (Exception e) {
290                    throw new RuntimeException(e);
291                }
292            }
293        });
294        thread.start();
295        client.startHandshake();
296        assertNotNull(client.getSession());
297        assertNull(client.getSession().getLocalCertificates());
298        Certificate[] peerCertificates = client.getSession().getPeerCertificates();
299        assertNotNull(peerCertificates);
300        TestKeyStore.assertChainLength(peerCertificates);
301        assertNotNull(peerCertificates[0]);
302        TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
303                                                    peerCertificates);
304        TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
305        thread.join();
306        client.close();
307        server.close();
308        c.close();
309    }
310
311    public void test_SSLSocket_startHandshake_noKeyStore() throws Exception {
312        TestSSLContext c = TestSSLContext.create(null, null, null, null, null, null, null, null,
313                                                 SSLContext.getDefault(), SSLContext.getDefault());
314        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
315                                                                                       c.port);
316        try {
317            c.serverSocket.accept();
318            fail();
319        } catch (SSLException expected) {
320        }
321        client.close();
322        c.close();
323    }
324
325    public void test_SSLSocket_startHandshake_noClientCertificate() throws Exception {
326        TestSSLContext c = TestSSLContext.create();
327        SSLContext serverContext = c.serverContext;
328        SSLContext clientContext = c.clientContext;
329        SSLSocket client = (SSLSocket)
330            clientContext.getSocketFactory().createSocket(c.host, c.port);
331        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
332        Thread thread = new Thread(new Runnable () {
333            public void run() {
334                try {
335                    server.startHandshake();
336                } catch (RuntimeException e) {
337                    throw e;
338                } catch (Exception e) {
339                    throw new RuntimeException(e);
340                }
341            }
342        });
343        thread.start();
344        client.startHandshake();
345        thread.join();
346        client.close();
347        server.close();
348        c.close();
349    }
350
351    public void test_SSLSocket_HandshakeCompletedListener() throws Exception {
352        final TestSSLContext c = TestSSLContext.create();
353        final SSLSocket client = (SSLSocket)
354                c.clientContext.getSocketFactory().createSocket(c.host, c.port);
355        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
356        Thread thread = new Thread(new Runnable () {
357            public void run() {
358                try {
359                    server.startHandshake();
360                } catch (RuntimeException e) {
361                    throw e;
362                } catch (Exception e) {
363                    throw new RuntimeException(e);
364                }
365            }
366        });
367        thread.start();
368        final boolean[] handshakeCompletedListenerCalled = new boolean[1];
369        client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
370            public void handshakeCompleted(HandshakeCompletedEvent event) {
371                try {
372                    SSLSession session = event.getSession();
373                    String cipherSuite = event.getCipherSuite();
374                    Certificate[] localCertificates = event.getLocalCertificates();
375                    Certificate[] peerCertificates = event.getPeerCertificates();
376                    javax.security.cert.X509Certificate[] peerCertificateChain
377                            = event.getPeerCertificateChain();
378                    Principal peerPrincipal = event.getPeerPrincipal();
379                    Principal localPrincipal = event.getLocalPrincipal();
380                    Socket socket = event.getSocket();
381
382                    if (false) {
383                        System.out.println("Session=" + session);
384                        System.out.println("CipherSuite=" + cipherSuite);
385                        System.out.println("LocalCertificates=" + localCertificates);
386                        System.out.println("PeerCertificates=" + peerCertificates);
387                        System.out.println("PeerCertificateChain=" + peerCertificateChain);
388                        System.out.println("PeerPrincipal=" + peerPrincipal);
389                        System.out.println("LocalPrincipal=" + localPrincipal);
390                        System.out.println("Socket=" + socket);
391                    }
392
393                    assertNotNull(session);
394                    byte[] id = session.getId();
395                    assertNotNull(id);
396                    assertEquals(32, id.length);
397                    assertNotNull(c.clientContext.getClientSessionContext().getSession(id));
398
399                    assertNotNull(cipherSuite);
400                    assertTrue(Arrays.asList(
401                            client.getEnabledCipherSuites()).contains(cipherSuite));
402                    assertTrue(Arrays.asList(
403                            c.serverSocket.getEnabledCipherSuites()).contains(cipherSuite));
404
405                    assertNull(localCertificates);
406
407                    assertNotNull(peerCertificates);
408                    TestKeyStore.assertChainLength(peerCertificates);
409                    assertNotNull(peerCertificates[0]);
410                    TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
411                                                                peerCertificates);
412                    TestSSLContext.assertCertificateInKeyStore(peerCertificates[0],
413                                                               c.serverKeyStore);
414
415                    assertNotNull(peerCertificateChain);
416                    TestKeyStore.assertChainLength(peerCertificateChain);
417                    assertNotNull(peerCertificateChain[0]);
418                    TestSSLContext.assertCertificateInKeyStore(
419                        peerCertificateChain[0].getSubjectDN(), c.serverKeyStore);
420
421                    assertNotNull(peerPrincipal);
422                    TestSSLContext.assertCertificateInKeyStore(peerPrincipal, c.serverKeyStore);
423
424                    assertNull(localPrincipal);
425
426                    assertNotNull(socket);
427                    assertSame(client, socket);
428
429                    synchronized (handshakeCompletedListenerCalled) {
430                        handshakeCompletedListenerCalled[0] = true;
431                        handshakeCompletedListenerCalled.notify();
432                    }
433                    handshakeCompletedListenerCalled[0] = true;
434                } catch (RuntimeException e) {
435                    throw e;
436                } catch (Exception e) {
437                    throw new RuntimeException(e);
438                }
439            }
440        });
441        client.startHandshake();
442        thread.join();
443        if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) {
444            assertNotNull(c.serverContext.getServerSessionContext().getSession(
445                    client.getSession().getId()));
446        }
447        synchronized (handshakeCompletedListenerCalled) {
448            while (!handshakeCompletedListenerCalled[0]) {
449                handshakeCompletedListenerCalled.wait();
450            }
451        }
452        client.close();
453        server.close();
454        c.close();
455    }
456
457    public void test_SSLSocket_HandshakeCompletedListener_RuntimeException() throws Exception {
458        final TestSSLContext c = TestSSLContext.create();
459        final SSLSocket client = (SSLSocket)
460                c.clientContext.getSocketFactory().createSocket(c.host, c.port);
461        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
462        Thread thread = new Thread(new Runnable () {
463            public void run() {
464                try {
465                    server.startHandshake();
466                } catch (RuntimeException e) {
467                    throw e;
468                } catch (Exception e) {
469                    throw new RuntimeException(e);
470                }
471            }
472        });
473        thread.start();
474        client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
475            public void handshakeCompleted(HandshakeCompletedEvent event) {
476                throw new RuntimeException("RuntimeException from handshakeCompleted");
477            }
478        });
479        client.startHandshake();
480        thread.join();
481        client.close();
482        server.close();
483        c.close();
484    }
485
486    public void test_SSLSocket_getUseClientMode() throws Exception {
487        TestSSLContext c = TestSSLContext.create();
488        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
489                                                                                       c.port);
490        SSLSocket server = (SSLSocket) c.serverSocket.accept();
491        assertTrue(client.getUseClientMode());
492        assertFalse(server.getUseClientMode());
493        client.close();
494        server.close();
495        c.close();
496    }
497
498    public void test_SSLSocket_setUseClientMode() throws Exception {
499        // client is client, server is server
500        test_SSLSocket_setUseClientMode(true, false);
501        // client is server, server is client
502        test_SSLSocket_setUseClientMode(true, false);
503        // both are client
504        try {
505            test_SSLSocket_setUseClientMode(true, true);
506            fail();
507        } catch (SSLProtocolException expected) {
508        }
509
510        // both are server
511        try {
512            test_SSLSocket_setUseClientMode(false, false);
513            fail();
514        } catch (SocketTimeoutException expected) {
515        }
516    }
517
518    public void test_SSLSocket_setUseClientMode_afterHandshake() throws Exception {
519
520        // can't set after handshake
521        TestSSLEnginePair pair = TestSSLEnginePair.create(null);
522        try {
523            pair.server.setUseClientMode(false);
524            fail();
525        } catch (IllegalArgumentException expected) {
526        }
527        try {
528            pair.client.setUseClientMode(false);
529            fail();
530        } catch (IllegalArgumentException expected) {
531        }
532    }
533
534    private void test_SSLSocket_setUseClientMode(final boolean clientClientMode,
535                                                 final boolean serverClientMode)
536            throws Exception {
537        TestSSLContext c = TestSSLContext.create();
538        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
539                                                                                       c.port);
540        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
541
542        final SSLProtocolException[] sslProtocolException = new SSLProtocolException[1];
543        final SocketTimeoutException[] socketTimeoutException = new SocketTimeoutException[1];
544        Thread thread = new Thread(new Runnable () {
545            public void run() {
546                try {
547                    if (!serverClientMode) {
548                        server.setSoTimeout(1 * 1000);
549                    }
550                    server.setUseClientMode(serverClientMode);
551                    server.startHandshake();
552                } catch (SSLProtocolException e) {
553                    sslProtocolException[0] = e;
554                } catch (SocketTimeoutException e) {
555                    socketTimeoutException[0] = e;
556                } catch (RuntimeException e) {
557                    throw e;
558                } catch (Exception e) {
559                    throw new RuntimeException(e);
560                }
561            }
562        });
563        thread.start();
564        if (!clientClientMode) {
565            client.setSoTimeout(1 * 1000);
566        }
567        client.setUseClientMode(clientClientMode);
568        client.startHandshake();
569        thread.join();
570        if (sslProtocolException[0] != null) {
571            throw sslProtocolException[0];
572        }
573        if (socketTimeoutException[0] != null) {
574            throw socketTimeoutException[0];
575        }
576        client.close();
577        server.close();
578        c.close();
579    }
580
581    public void test_SSLSocket_untrustedServer() throws Exception {
582        TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCA2(),
583                                                 TestKeyStore.getServer());
584        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
585                                                                                       c.port);
586        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
587        Thread thread = new Thread(new Runnable () {
588            public void run() {
589                try {
590                    server.startHandshake();
591                } catch (RuntimeException e) {
592                    throw e;
593                } catch (Exception e) {
594                    throw new RuntimeException(e);
595                }
596            }
597        });
598        thread.start();
599        try {
600            client.startHandshake();
601            fail();
602        } catch (SSLHandshakeException expected) {
603            assertTrue(expected.getCause() instanceof CertificateException);
604        }
605        client.close();
606        server.close();
607        thread.join();
608    }
609
610    public void test_SSLSocket_clientAuth() throws Exception {
611        TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCertificate(),
612                                                 TestKeyStore.getServer());
613        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
614                                                                                       c.port);
615        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
616        Thread thread = new Thread(new Runnable () {
617            public void run() {
618                try {
619                    assertFalse(server.getWantClientAuth());
620                    assertFalse(server.getNeedClientAuth());
621
622                    // confirm turning one on by itself
623                    server.setWantClientAuth(true);
624                    assertTrue(server.getWantClientAuth());
625                    assertFalse(server.getNeedClientAuth());
626
627                    // confirm turning setting on toggles the other
628                    server.setNeedClientAuth(true);
629                    assertFalse(server.getWantClientAuth());
630                    assertTrue(server.getNeedClientAuth());
631
632                    // confirm toggling back
633                    server.setWantClientAuth(true);
634                    assertTrue(server.getWantClientAuth());
635                    assertFalse(server.getNeedClientAuth());
636
637                    server.startHandshake();
638
639                } catch (RuntimeException e) {
640                    throw e;
641                } catch (Exception e) {
642                    throw new RuntimeException(e);
643                }
644            }
645        });
646        thread.start();
647        client.startHandshake();
648        assertNotNull(client.getSession().getLocalCertificates());
649        TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
650        TestSSLContext.assertClientCertificateChain(c.clientTrustManager,
651                                                    client.getSession().getLocalCertificates());
652        thread.join();
653        client.close();
654        server.close();
655        c.close();
656    }
657
658    public void test_SSLSocket_getEnableSessionCreation() throws Exception {
659        TestSSLContext c = TestSSLContext.create();
660        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
661                                                                                       c.port);
662        SSLSocket server = (SSLSocket) c.serverSocket.accept();
663        assertTrue(client.getEnableSessionCreation());
664        assertTrue(server.getEnableSessionCreation());
665        client.close();
666        server.close();
667        c.close();
668    }
669
670    public void test_SSLSocket_setEnableSessionCreation_server() throws Exception {
671        TestSSLContext c = TestSSLContext.create();
672        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
673                                                                                       c.port);
674        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
675        Thread thread = new Thread(new Runnable () {
676            public void run() {
677                try {
678                    server.setEnableSessionCreation(false);
679                    try {
680                        server.startHandshake();
681                        fail();
682                    } catch (SSLException expected) {
683                    }
684                } catch (RuntimeException e) {
685                    throw e;
686                } catch (Exception e) {
687                    throw new RuntimeException(e);
688                }
689            }
690        });
691        thread.start();
692        try {
693            client.startHandshake();
694            fail();
695        } catch (SSLException expected) {
696        }
697        thread.join();
698        client.close();
699        server.close();
700        c.close();
701    }
702
703    public void test_SSLSocket_setEnableSessionCreation_client() throws Exception {
704        TestSSLContext c = TestSSLContext.create();
705        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
706                                                                                       c.port);
707        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
708        Thread thread = new Thread(new Runnable () {
709            public void run() {
710                try {
711                    try {
712                        server.startHandshake();
713                        fail();
714                    } catch (SSLException expected) {
715                    }
716                } catch (RuntimeException e) {
717                    throw e;
718                } catch (Exception e) {
719                    throw new RuntimeException(e);
720                }
721            }
722        });
723        thread.start();
724        client.setEnableSessionCreation(false);
725        try {
726            client.startHandshake();
727            fail();
728        } catch (SSLException expected) {
729        }
730        thread.join();
731        client.close();
732        server.close();
733        c.close();
734    }
735
736    public void test_SSLSocket_getSSLParameters() throws Exception {
737        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
738        SSLSocket ssl = (SSLSocket) sf.createSocket();
739
740        SSLParameters p = ssl.getSSLParameters();
741        assertNotNull(p);
742
743        String[] cipherSuites = p.getCipherSuites();
744        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
745        assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
746        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
747
748        String[] protocols = p.getProtocols();
749        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
750        assertNotSame(protocols, ssl.getEnabledProtocols());
751        assertEquals(Arrays.asList(protocols), Arrays.asList(ssl.getEnabledProtocols()));
752
753        assertEquals(p.getWantClientAuth(), ssl.getWantClientAuth());
754        assertEquals(p.getNeedClientAuth(), ssl.getNeedClientAuth());
755    }
756
757    public void test_SSLSocket_setSSLParameters() throws Exception {
758        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
759        SSLSocket ssl = (SSLSocket) sf.createSocket();
760        String[] defaultCipherSuites = ssl.getEnabledCipherSuites();
761        String[] defaultProtocols = ssl.getEnabledProtocols();
762        String[] supportedCipherSuites = ssl.getSupportedCipherSuites();
763        String[] supportedProtocols = ssl.getSupportedProtocols();
764
765        {
766            SSLParameters p = new SSLParameters();
767            ssl.setSSLParameters(p);
768            assertEquals(Arrays.asList(defaultCipherSuites),
769                         Arrays.asList(ssl.getEnabledCipherSuites()));
770            assertEquals(Arrays.asList(defaultProtocols),
771                         Arrays.asList(ssl.getEnabledProtocols()));
772        }
773
774        {
775            SSLParameters p = new SSLParameters(supportedCipherSuites,
776                                                supportedProtocols);
777            ssl.setSSLParameters(p);
778            assertEquals(Arrays.asList(supportedCipherSuites),
779                         Arrays.asList(ssl.getEnabledCipherSuites()));
780            assertEquals(Arrays.asList(supportedProtocols),
781                         Arrays.asList(ssl.getEnabledProtocols()));
782        }
783        {
784            SSLParameters p = new SSLParameters();
785
786            p.setNeedClientAuth(true);
787            assertFalse(ssl.getNeedClientAuth());
788            assertFalse(ssl.getWantClientAuth());
789            ssl.setSSLParameters(p);
790            assertTrue(ssl.getNeedClientAuth());
791            assertFalse(ssl.getWantClientAuth());
792
793            p.setWantClientAuth(true);
794            assertTrue(ssl.getNeedClientAuth());
795            assertFalse(ssl.getWantClientAuth());
796            ssl.setSSLParameters(p);
797            assertFalse(ssl.getNeedClientAuth());
798            assertTrue(ssl.getWantClientAuth());
799
800            p.setWantClientAuth(false);
801            assertFalse(ssl.getNeedClientAuth());
802            assertTrue(ssl.getWantClientAuth());
803            ssl.setSSLParameters(p);
804            assertFalse(ssl.getNeedClientAuth());
805            assertFalse(ssl.getWantClientAuth());
806        }
807    }
808
809    public void test_SSLSocket_close() throws Exception {
810        TestSSLSocketPair pair = TestSSLSocketPair.create();
811        SSLSocket server = pair.server;
812        SSLSocket client = pair.client;
813        assertFalse(server.isClosed());
814        assertFalse(client.isClosed());
815        InputStream input = client.getInputStream();
816        OutputStream output = client.getOutputStream();
817        server.close();
818        client.close();
819        assertTrue(server.isClosed());
820        assertTrue(client.isClosed());
821
822        // close after close is okay...
823        server.close();
824        client.close();
825
826        // ...so are a lot of other operations...
827        HandshakeCompletedListener l = new HandshakeCompletedListener () {
828            public void handshakeCompleted(HandshakeCompletedEvent e) {}
829        };
830        client.addHandshakeCompletedListener(l);
831        assertNotNull(client.getEnabledCipherSuites());
832        assertNotNull(client.getEnabledProtocols());
833        client.getEnableSessionCreation();
834        client.getNeedClientAuth();
835        assertNotNull(client.getSession());
836        assertNotNull(client.getSSLParameters());
837        assertNotNull(client.getSupportedProtocols());
838        client.getUseClientMode();
839        client.getWantClientAuth();
840        client.removeHandshakeCompletedListener(l);
841        client.setEnabledCipherSuites(new String[0]);
842        client.setEnabledProtocols(new String[0]);
843        client.setEnableSessionCreation(false);
844        client.setNeedClientAuth(false);
845        client.setSSLParameters(client.getSSLParameters());
846        client.setWantClientAuth(false);
847
848        // ...but some operations are expected to give SocketException...
849        try {
850            client.startHandshake();
851            fail();
852        } catch (SocketException expected) {
853        }
854        try {
855            client.getInputStream();
856            fail();
857        } catch (SocketException expected) {
858        }
859        try {
860            client.getOutputStream();
861            fail();
862        } catch (SocketException expected) {
863        }
864        try {
865            input.read();
866            fail();
867        } catch (SocketException expected) {
868        }
869        try {
870            input.read(null, -1, -1);
871            fail();
872        } catch (SocketException expected) {
873        }
874        try {
875            output.write(-1);
876            fail();
877        } catch (SocketException expected) {
878        }
879        try {
880            output.write(null, -1, -1);
881            fail();
882        } catch (SocketException expected) {
883        }
884
885        // ... and one gives IllegalArgumentException
886        try {
887            client.setUseClientMode(false);
888            fail();
889        } catch (IllegalArgumentException expected) {
890        }
891
892        pair.close();
893    }
894
895    /**
896     * b/3350645 Test to confirm that an SSLSocket.close() performing
897     * an SSL_shutdown does not throw an IOException if the peer
898     * socket has been closed.
899     */
900    public void test_SSLSocket_shutdownCloseOnClosedPeer() throws Exception {
901        TestSSLContext c = TestSSLContext.create();
902        final Socket underlying = new Socket(c.host, c.port);
903        final SSLSocket wrapping = (SSLSocket)
904                c.clientContext.getSocketFactory().createSocket(underlying,
905                                                                c.host.getHostName(),
906                                                                c.port,
907                                                                false);
908        Thread clientThread = new Thread(new Runnable () {
909            public void run() {
910                try {
911                    try {
912                        wrapping.startHandshake();
913                        wrapping.getOutputStream().write(42);
914                        // close the underlying socket,
915                        // so that no SSL shutdown is sent
916                        underlying.close();
917                        wrapping.close();
918                    } catch (SSLException expected) {
919                    }
920                } catch (RuntimeException e) {
921                    throw e;
922                } catch (Exception e) {
923                    throw new RuntimeException(e);
924                }
925            }
926        });
927        clientThread.start();
928
929        SSLSocket server = (SSLSocket) c.serverSocket.accept();
930        server.startHandshake();
931        server.getInputStream().read();
932        // wait for thread to finish so we know client is closed.
933        clientThread.join();
934        // close should cause an SSL_shutdown which will fail
935        // because the peer has closed, but it shouldn't throw.
936        server.close();
937    }
938
939    public void test_SSLSocket_setSoTimeout_basic() throws Exception {
940        ServerSocket listening = new ServerSocket(0);
941
942        Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
943        assertEquals(0, underlying.getSoTimeout());
944
945        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
946        Socket wrapping = sf.createSocket(underlying, null, -1, false);
947        assertEquals(0, wrapping.getSoTimeout());
948
949        // setting wrapper sets underlying and ...
950        wrapping.setSoTimeout(10);
951        assertEquals(10, wrapping.getSoTimeout());
952        assertEquals(10, underlying.getSoTimeout());
953
954        // ... getting wrapper inspects underlying
955        underlying.setSoTimeout(0);
956        assertEquals(0, wrapping.getSoTimeout());
957        assertEquals(0, underlying.getSoTimeout());
958    }
959
960    public void test_SSLSocket_setSoTimeout_wrapper() throws Exception {
961        if (StandardNames.IS_RI) {
962            // RI cannot handle this case
963            return;
964        }
965        ServerSocket listening = new ServerSocket(0);
966
967        // setSoTimeout applies to read, not connect, so connect first
968        Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
969        Socket server = listening.accept();
970
971        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
972        Socket clientWrapping = sf.createSocket(underlying, null, -1, false);
973
974        underlying.setSoTimeout(1);
975        try {
976            clientWrapping.getInputStream().read();
977            fail();
978        } catch (SocketTimeoutException expected) {
979        }
980
981        clientWrapping.close();
982        server.close();
983        underlying.close();
984        listening.close();
985    }
986
987    public void test_SSLSocket_interrupt() throws Exception {
988        ServerSocket listening = new ServerSocket(0);
989
990        for (int i = 0; i < 3; i++) {
991            Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
992            Socket server = listening.accept();
993
994            SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
995            Socket clientWrapping = sf.createSocket(underlying, null, -1, true);
996
997            switch (i) {
998                case 0:
999                    test_SSLSocket_interrupt_case(underlying, underlying);
1000                    break;
1001                case 1:
1002                    test_SSLSocket_interrupt_case(underlying, clientWrapping);
1003                    break;
1004                case 2:
1005                    test_SSLSocket_interrupt_case(clientWrapping, underlying);
1006                    break;
1007                case 3:
1008                    test_SSLSocket_interrupt_case(clientWrapping, clientWrapping);
1009                    break;
1010                default:
1011                    fail();
1012            }
1013
1014            server.close();
1015            underlying.close();
1016        }
1017        listening.close();
1018    }
1019
1020    private void test_SSLSocket_interrupt_case(Socket toRead, final Socket toClose)
1021            throws Exception {
1022        new Thread() {
1023            @Override
1024            public void run() {
1025                try {
1026                    Thread.sleep(1 * 1000);
1027                    toClose.close();
1028                } catch (Exception e) {
1029                    throw new RuntimeException(e);
1030                }
1031            }
1032        }.start();
1033        try {
1034            toRead.setSoTimeout(5 * 1000);
1035            toRead.getInputStream().read();
1036            fail();
1037        } catch (SocketTimeoutException e) {
1038            throw e;
1039        } catch (SocketException expected) {
1040        }
1041    }
1042
1043    public void test_TestSSLSocketPair_create() {
1044        TestSSLSocketPair test = TestSSLSocketPair.create();
1045        assertNotNull(test.c);
1046        assertNotNull(test.server);
1047        assertNotNull(test.client);
1048        assertTrue(test.server.isConnected());
1049        assertTrue(test.client.isConnected());
1050        assertFalse(test.server.isClosed());
1051        assertFalse(test.client.isClosed());
1052        assertNotNull(test.server.getSession());
1053        assertNotNull(test.client.getSession());
1054        assertTrue(test.server.getSession().isValid());
1055        assertTrue(test.client.getSession().isValid());
1056        test.close();
1057    }
1058
1059    /**
1060     * Not run by default by JUnit, but can be run by Vogar by
1061     * specifying it explictly (or with main method below)
1062     */
1063    public void stress_test_TestSSLSocketPair_create() {
1064        final boolean verbose = true;
1065        while (true) {
1066            TestSSLSocketPair test = TestSSLSocketPair.create();
1067            if (verbose) {
1068                System.out.println("client=" + test.client.getLocalPort()
1069                                   + " server=" + test.server.getLocalPort());
1070            } else {
1071                System.out.print("X");
1072            }
1073
1074            /*
1075              We don't close on purpose in this stress test to add
1076              races in file descriptors reuse when the garbage
1077              collector runs concurrently and finalizes sockets
1078            */
1079            // test.close();
1080
1081        }
1082    }
1083
1084    public static final void main (String[] args) {
1085        new SSLSocketTest().stress_test_TestSSLSocketPair_create();
1086    }
1087}
1088