1ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom/*
2ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project
3ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom *
4ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * you may not use this file except in compliance with the License.
6ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * You may obtain a copy of the License at
7ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom *
8ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom *
10ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
11ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * See the License for the specific language governing permissions and
14ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom * limitations under the License.
15ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom */
16ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.javax.net.ssl;
18ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
192216155c3066236eb450f307983019f69a10303dKenny Rootimport static java.nio.charset.StandardCharsets.UTF_8;
202216155c3066236eb450f307983019f69a10303dKenny Root
21fb30da617fb979e7ae98c5a22b926aa15c6f2502Alex Klyubinimport java.io.ByteArrayInputStream;
2227088efe0caca697e257e08d41387af8130364e0Kenny Rootimport java.io.Closeable;
23fb30da617fb979e7ae98c5a22b926aa15c6f2502Alex Klyubinimport java.io.DataInputStream;
240007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubinimport java.io.EOFException;
25783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstromimport java.io.IOException;
265f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstromimport java.io.InputStream;
275f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstromimport java.io.OutputStream;
28283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstromimport java.lang.Thread.UncaughtExceptionHandler;
29615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport java.lang.reflect.Method;
30a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.math.BigInteger;
319f7c676c1937bdafce079cf02a67ac121296a335Kenny Rootimport java.net.InetAddress;
3251cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstromimport java.net.InetSocketAddress;
33a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstromimport java.net.ServerSocket;
34ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport java.net.Socket;
355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstromimport java.net.SocketException;
36ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport java.net.SocketTimeoutException;
37a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.AlgorithmParameters;
38a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.InvalidAlgorithmParameterException;
39a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.InvalidKeyException;
40a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.InvalidParameterException;
41a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.Key;
42b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport java.security.KeyManagementException;
43b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport java.security.NoSuchAlgorithmException;
44ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport java.security.Principal;
45aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport java.security.PrivateKey;
46a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.Provider;
47a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.PublicKey;
48a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.SecureRandom;
49a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.Security;
50a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.Signature;
51a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.SignatureException;
52a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.SignatureSpi;
53ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport java.security.cert.Certificate;
542915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstromimport java.security.cert.CertificateException;
55aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport java.security.cert.X509Certificate;
5672ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Rootimport java.security.interfaces.ECKey;
57a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.interfaces.ECPrivateKey;
5872ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Rootimport java.security.interfaces.RSAKey;
59a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.interfaces.RSAPrivateKey;
60a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.spec.AlgorithmParameterSpec;
61a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport java.security.spec.ECParameterSpec;
62b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport java.util.ArrayList;
63ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport java.util.Arrays;
64b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Rootimport java.util.Collections;
65b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport java.util.List;
66783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstromimport java.util.concurrent.Callable;
67783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstromimport java.util.concurrent.ExecutorService;
68783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstromimport java.util.concurrent.Executors;
69783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstromimport java.util.concurrent.Future;
706ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Rootimport java.util.concurrent.ThreadFactory;
710007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubinimport java.util.concurrent.TimeUnit;
72a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.BadPaddingException;
73a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.Cipher;
74a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.CipherSpi;
75a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.IllegalBlockSizeException;
76a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.NoSuchPaddingException;
77c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubinimport javax.crypto.SecretKey;
78a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Rootimport javax.crypto.ShortBufferException;
79c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubinimport javax.crypto.spec.SecretKeySpec;
800007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubinimport javax.net.ServerSocketFactory;
8158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Rootimport javax.net.SocketFactory;
82b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Rootimport javax.net.ssl.ExtendedSSLSession;
834557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.HandshakeCompletedEvent;
844557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.HandshakeCompletedListener;
85aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.KeyManager;
86b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Rootimport javax.net.ssl.SNIHostName;
87b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Rootimport javax.net.ssl.SNIMatcher;
88b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Rootimport javax.net.ssl.SNIServerName;
894557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLContext;
904557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLException;
912915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstromimport javax.net.ssl.SSLHandshakeException;
924557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLParameters;
934557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLPeerUnverifiedException;
944557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLProtocolException;
959f7c676c1937bdafce079cf02a67ac121296a335Kenny Rootimport javax.net.ssl.SSLServerSocket;
964557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLSession;
974557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLSocket;
984557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLSocketFactory;
9901b7734160977458d44d1fb179984fd91672f08dKenny Rootimport javax.net.ssl.StandardConstants;
100aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.TrustManager;
101aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.X509KeyManager;
1028c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstromimport javax.net.ssl.X509TrustManager;
103ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstromimport junit.framework.TestCase;
1045f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstromimport libcore.java.security.StandardNames;
1055f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstromimport libcore.java.security.TestKeyStore;
106b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.handshake.CipherSuite;
107b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.handshake.ClientHello;
108b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.handshake.CompressionMethod;
109c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Rootimport libcore.tlswire.handshake.EllipticCurve;
110c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Rootimport libcore.tlswire.handshake.EllipticCurvesHelloExtension;
111fb30da617fb979e7ae98c5a22b926aa15c6f2502Alex Klyubinimport libcore.tlswire.handshake.HandshakeMessage;
112b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.handshake.HelloExtension;
113b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.handshake.ServerNameHelloExtension;
114fb30da617fb979e7ae98c5a22b926aa15c6f2502Alex Klyubinimport libcore.tlswire.record.TlsProtocols;
115fb30da617fb979e7ae98c5a22b926aa15c6f2502Alex Klyubinimport libcore.tlswire.record.TlsRecord;
116b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport libcore.tlswire.util.TlsProtocolVersion;
11726f2557b26ea23326178f029e07a8adbfc27d0bfNeil Fullerimport tests.net.DelegatingSSLSocketFactory;
118b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport tests.util.ForEachRunner;
119b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubinimport tests.util.Pair;
120ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
121ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrompublic class SSLSocketTest extends TestCase {
122ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
123f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    public void test_SSLSocket_defaultConfiguration() throws Exception {
124782740701db73dd2dc4fef9df8cde270b0e631a4Alex Klyubin        SSLConfigurationAsserts.assertSSLSocketDefaultConfiguration(
125f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin                (SSLSocket) SSLSocketFactory.getDefault().createSocket());
126f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    }
127f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin
128f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    public void test_SSLSocket_getSupportedCipherSuites_returnsCopies() throws Exception {
1298ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
1308ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
131f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin        assertNotSame(ssl.getSupportedCipherSuites(), ssl.getSupportedCipherSuites());
132ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
133ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
134204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception {
135a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom        // note the rare usage of non-RSA keys
136101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson        TestKeyStore testKeyStore = new TestKeyStore.Builder()
137101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA")
138101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                .aliasPrefix("rsa-dsa-ec")
139101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                .ca(true)
140101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                .build();
1411f1dc0af2c01f2a2b6cf4907ecb21b4e05982e2bKenny Root        StringBuilder error = new StringBuilder();
1422cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin        test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore, error);
1431f1dc0af2c01f2a2b6cf4907ecb21b4e05982e2bKenny Root        if (error.length() > 0) {
1441f1dc0af2c01f2a2b6cf4907ecb21b4e05982e2bKenny Root            throw new Exception("One or more problems in "
1451f1dc0af2c01f2a2b6cf4907ecb21b4e05982e2bKenny Root                    + "test_SSLSocket_getSupportedCipherSuites_connect:\n" + error);
1466882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        }
1476882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom    }
1486882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom    private void test_SSLSocket_getSupportedCipherSuites_connect(TestKeyStore testKeyStore,
1491f1dc0af2c01f2a2b6cf4907ecb21b4e05982e2bKenny Root                                                                 StringBuilder error)
1506882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom            throws Exception {
1516882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom
1526882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        String clientToServerString = "this is sent from the client to the server...";
1536882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        String serverToClientString = "... and this from the server to the client";
1542216155c3066236eb450f307983019f69a10303dKenny Root        byte[] clientToServer = clientToServerString.getBytes(UTF_8);
1552216155c3066236eb450f307983019f69a10303dKenny Root        byte[] serverToClient = serverToClientString.getBytes(UTF_8);
1566882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom
157c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        KeyManager pskKeyManager = PSKKeyManagerProxy.getConscryptPSKKeyManager(
158c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                new PSKKeyManagerProxy() {
159c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            @Override
160c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            protected SecretKey getKey(String identityHint, String identity, Socket socket) {
1612216155c3066236eb450f307983019f69a10303dKenny Root                return new SecretKeySpec("Just an arbitrary key".getBytes(UTF_8), "RAW");
162c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            }
163c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        });
164c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        TestSSLContext c = TestSSLContext.createWithAdditionalKeyManagers(
165c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                testKeyStore, testKeyStore,
166c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                new KeyManager[] {pskKeyManager}, new KeyManager[] {pskKeyManager});
167c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin
1682cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin        String[] cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
1694ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom
170204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        for (String cipherSuite : cipherSuites) {
171aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            boolean errorExpected = StandardNames.IS_RI && cipherSuite.endsWith("_SHA256");
172a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom            try {
173a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                /*
1746c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on
1756c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 * its own, but instead in conjunction with other
1766c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 * cipher suites.
1776c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 */
1786c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) {
1796c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                    continue;
1806c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                }
1816c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                /*
182e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                 * Similarly with the TLS_FALLBACK_SCSV suite, it is not
183e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                 * a selectable suite, but is used in conjunction with
184e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                 * other cipher suites.
185e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                 */
186e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                if (cipherSuite.equals(StandardNames.CIPHER_SUITE_FALLBACK)) {
187e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    continue;
188e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                }
189e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                /*
190a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                 * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
1916c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
1926c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom                 * #KRBRequire
193a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                 */
194a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                if (cipherSuite.startsWith("TLS_KRB5_")) {
195a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                    continue;
196a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                }
1976c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom
1982cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin                String[] clientCipherSuiteArray = new String[] {
1992cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin                        cipherSuite,
2002cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin                        StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION };
2012cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin                String[] serverCipherSuiteArray = clientCipherSuiteArray;
202ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom                SSLSocket[] pair = TestSSLSocketPair.connect(c,
203ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom                                                             clientCipherSuiteArray,
204ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom                                                             serverCipherSuiteArray);
205a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom
206a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                SSLSocket server = pair[0];
207a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                SSLSocket client = pair[1];
208038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin
209038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                // Check that the client can read the message sent by the server
210a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                server.getOutputStream().write(serverToClient);
211038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                byte[] clientFromServer = new byte[serverToClient.length];
21227088efe0caca697e257e08d41387af8130364e0Kenny Root                readFully(client.getInputStream(), clientFromServer);
213038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                assertEquals(serverToClientString, new String(clientFromServer));
214038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin
215038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                // Check that the server can read the message sent by the client
216a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                client.getOutputStream().write(clientToServer);
217038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                byte[] serverFromClient = new byte[clientToServer.length];
21827088efe0caca697e257e08d41387af8130364e0Kenny Root                readFully(server.getInputStream(), serverFromClient);
219038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                assertEquals(clientToServerString, new String(serverFromClient));
220038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin
221038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                // Check that the server and the client cannot read anything else
222038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                // (reads should time out)
223038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                server.setSoTimeout(10);
224038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                try {
225038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                  server.getInputStream().read();
226038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                  fail();
227038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                } catch (IOException expected) {}
228038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                client.setSoTimeout(10);
229038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                try {
230038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                  client.getInputStream().read();
231038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                  fail();
232038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin                } catch (IOException expected) {}
233038cb91ddb127750737055649f6171dc1af3985aAlex Klyubin
234a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom                client.close();
235b4bb9aba620d8a363fb3617b25839093caf39cf4Brian Carlstrom                server.close();
236aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                assertFalse(errorExpected);
237aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            } catch (Exception maybeExpected) {
238aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                if (!errorExpected) {
2392cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin                    String message = ("Problem trying to connect cipher suite " + cipherSuite);
24039d69d058be0c1a4555aeed4a237c2af05ae39c6Brian Carlstrom                    System.out.println(message);
24139d69d058be0c1a4555aeed4a237c2af05ae39c6Brian Carlstrom                    maybeExpected.printStackTrace();
24239d69d058be0c1a4555aeed4a237c2af05ae39c6Brian Carlstrom                    error.append(message);
24339d69d058be0c1a4555aeed4a237c2af05ae39c6Brian Carlstrom                    error.append('\n');
244aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                }
245204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            }
246204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        }
247f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
248204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    }
249204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom
250f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    public void test_SSLSocket_getEnabledCipherSuites_returnsCopies() throws Exception {
2518ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
2528ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
253f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin        assertNotSame(ssl.getEnabledCipherSuites(), ssl.getEnabledCipherSuites());
254ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
255ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
256ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin    public void test_SSLSocket_setEnabledCipherSuites_storesCopy() throws Exception {
257ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
258ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        SSLSocket ssl = (SSLSocket) sf.createSocket();
259ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        String[] array = new String[] {ssl.getEnabledCipherSuites()[0]};
260ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        String originalFirstElement = array[0];
261ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        ssl.setEnabledCipherSuites(array);
262ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        array[0] = "Modified after having been set";
263ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        assertEquals(originalFirstElement, ssl.getEnabledCipherSuites()[0]);
264ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin    }
265ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin
266ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    public void test_SSLSocket_setEnabledCipherSuites() throws Exception {
2678ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
2688ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
269ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
270ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
271ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledCipherSuites(null);
272ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
273e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
274ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
275ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
276ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledCipherSuites(new String[1]);
277ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
278e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
279ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
280ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
281ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledCipherSuites(new String[] { "Bogus" } );
282ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
283e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
284ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
285ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
286ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledCipherSuites(new String[0]);
287ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
288ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
289358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin
290358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin        // Check that setEnabledCipherSuites affects getEnabledCipherSuites
291358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin        String[] cipherSuites = new String[] { ssl.getSupportedCipherSuites()[0] };
292358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin        ssl.setEnabledCipherSuites(cipherSuites);
293358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
294ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
295ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
296f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    public void test_SSLSocket_getSupportedProtocols_returnsCopies() throws Exception {
2978ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
2988ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
299f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin        assertNotSame(ssl.getSupportedProtocols(), ssl.getSupportedProtocols());
300ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
301ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
302f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin    public void test_SSLSocket_getEnabledProtocols_returnsCopies() throws Exception {
3038ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
3048ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
305f605c6822da13b32cd3643415a707882b62a3e91Alex Klyubin        assertNotSame(ssl.getEnabledProtocols(), ssl.getEnabledProtocols());
306ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
307ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
308ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin    public void test_SSLSocket_setEnabledProtocols_storesCopy() throws Exception {
309ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
310ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        SSLSocket ssl = (SSLSocket) sf.createSocket();
311ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        String[] array = new String[] {ssl.getEnabledProtocols()[0]};
312ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        String originalFirstElement = array[0];
313ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        ssl.setEnabledProtocols(array);
314ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        array[0] = "Modified after having been set";
315ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin        assertEquals(originalFirstElement, ssl.getEnabledProtocols()[0]);
316ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin    }
317ee109f62e99f43bcf8b78c857af430be9cf02985Alex Klyubin
318ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    public void test_SSLSocket_setEnabledProtocols() throws Exception {
3198ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
3208ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
321ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
322ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
323ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledProtocols(null);
324ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
325e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
326ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
327ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
328ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledProtocols(new String[1]);
329ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
330e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
331ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
332ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
333ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            ssl.setEnabledProtocols(new String[] { "Bogus" } );
334ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
335e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (IllegalArgumentException expected) {
336ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
337ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledProtocols(new String[0]);
338ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledProtocols(ssl.getEnabledProtocols());
339ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        ssl.setEnabledProtocols(ssl.getSupportedProtocols());
340358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin
341358552b505a8985ec9ed3691d0a6d590b60d620fAlex Klyubin        // Check that setEnabledProtocols affects getEnabledProtocols
3423ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root        for (String protocol : ssl.getSupportedProtocols()) {
3433ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root            if ("SSLv2Hello".equals(protocol)) {
3443ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                try {
3453ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                    ssl.setEnabledProtocols(new String[] { protocol });
3463ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                    fail("Should fail when SSLv2Hello is set by itself");
3473ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                } catch (IllegalArgumentException expected) {}
3483ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root            } else {
3493ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                String[] protocols = new String[] { protocol };
3503ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                ssl.setEnabledProtocols(protocols);
3513ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                assertEquals(Arrays.deepToString(protocols),
3523ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root                        Arrays.deepToString(ssl.getEnabledProtocols()));
3533ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root            }
3543ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root        }
355ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
356ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
357ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    public void test_SSLSocket_getSession() throws Exception {
3588ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
3598ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
3608ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom        SSLSession session = ssl.getSession();
361ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(session);
362ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertFalse(session.isValid());
363ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
364ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
36501b7734160977458d44d1fb179984fd91672f08dKenny Root    public void test_SSLSocket_getHandshakeSession() throws Exception {
36601b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
36701b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLSocket ssl = (SSLSocket) sf.createSocket();
36801b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLSession session = ssl.getHandshakeSession();
36901b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNull(session);
37001b7734160977458d44d1fb179984fd91672f08dKenny Root    }
37101b7734160977458d44d1fb179984fd91672f08dKenny Root
372ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    public void test_SSLSocket_startHandshake() throws Exception {
373bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        final TestSSLContext c = TestSSLContext.create();
374059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
375059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
376ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
377783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
378783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
379783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
380783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.startHandshake();
381783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertNotNull(server.getSession());
38201b7734160977458d44d1fb179984fd91672f08dKenny Root                assertNull(server.getHandshakeSession());
383ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                try {
384783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    server.getSession().getPeerCertificates();
385783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    fail();
386783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                } catch (SSLPeerUnverifiedException expected) {
387ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                }
388783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                Certificate[] localCertificates = server.getSession().getLocalCertificates();
389783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertNotNull(localCertificates);
390783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                TestKeyStore.assertChainLength(localCertificates);
391783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertNotNull(localCertificates[0]);
392783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                TestSSLContext.assertServerCertificateChain(c.serverTrustManager,
393783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                                                            localCertificates);
394783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                TestSSLContext.assertCertificateInKeyStore(localCertificates[0],
395783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                                                           c.serverKeyStore);
396783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
397ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
398ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
399783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
400ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.startHandshake();
401ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(client.getSession());
402ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNull(client.getSession().getLocalCertificates());
403ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        Certificate[] peerCertificates = client.getSession().getPeerCertificates();
404ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(peerCertificates);
405059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestKeyStore.assertChainLength(peerCertificates);
406ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(peerCertificates[0]);
407059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
408059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                    peerCertificates);
409059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
410783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
411f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
412f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
413f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
414ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
415ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
416b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom    private static final class SSLServerSessionIdCallable implements Callable<byte[]> {
417b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        private final SSLSocket server;
418b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        private SSLServerSessionIdCallable(SSLSocket server) {
419b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom            this.server = server;
420b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        }
421b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        @Override public byte[] call() throws Exception {
422b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom            server.startHandshake();
423b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom            assertNotNull(server.getSession());
424b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom            assertNotNull(server.getSession().getId());
425b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom            return server.getSession().getId();
426b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        }
427b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom    }
428b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
429b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom    public void test_SSLSocket_confirmSessionReuse() throws Exception {
430b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final TestSSLContext c = TestSSLContext.create();
431b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final ExecutorService executor = Executors.newSingleThreadExecutor();
432b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
4336309be4c19bb991aab3778575ce7bc6750c674eeKenny Root        final SSLSocket client1 = (SSLSocket) c.clientContext.getSocketFactory()
4346309be4c19bb991aab3778575ce7bc6750c674eeKenny Root                .createSocket(c.host.getHostName(), c.port);
435b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final SSLSocket server1 = (SSLSocket) c.serverSocket.accept();
436b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final Future<byte[]> future1 = executor.submit(new SSLServerSessionIdCallable(server1));
437b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        client1.startHandshake();
438b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertNotNull(client1.getSession());
439b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertNotNull(client1.getSession().getId());
440b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final byte[] clientSessionId1 = client1.getSession().getId();
441b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final byte[] serverSessionId1 = future1.get();
442b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertTrue(Arrays.equals(clientSessionId1, serverSessionId1));
443b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        client1.close();
444b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        server1.close();
445b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
4466309be4c19bb991aab3778575ce7bc6750c674eeKenny Root        final SSLSocket client2 = (SSLSocket) c.clientContext.getSocketFactory()
4476309be4c19bb991aab3778575ce7bc6750c674eeKenny Root                .createSocket(c.host.getHostName(), c.port);
448b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final SSLSocket server2 = (SSLSocket) c.serverSocket.accept();
449b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final Future<byte[]> future2 = executor.submit(new SSLServerSessionIdCallable(server2));
450b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        client2.startHandshake();
451b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertNotNull(client2.getSession());
452b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertNotNull(client2.getSession().getId());
453b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final byte[] clientSessionId2 = client2.getSession().getId();
454b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        final byte[] serverSessionId2 = future2.get();
455b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertTrue(Arrays.equals(clientSessionId2, serverSessionId2));
456b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        client2.close();
457b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        server2.close();
458b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
459b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        assertTrue(Arrays.equals(clientSessionId1, clientSessionId2));
460b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
461b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        executor.shutdown();
462b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom        c.close();
463b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom    }
464b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom
465def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root    public void test_SSLSocket_NoEnabledCipherSuites_Failure() throws Exception {
466def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        TestSSLContext c = TestSSLContext.create(null, null, null, null, null, null, null, null,
467def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                SSLContext.getDefault(), SSLContext.getDefault());
468def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
469def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                c.port);
470def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        client.setEnabledCipherSuites(new String[0]);
471def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
472def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
473def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        Future<Void> future = executor.submit(new Callable<Void>() {
474def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root            @Override
475def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root            public Void call() throws Exception {
476def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                try {
477def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                    server.startHandshake();
478def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                    fail();
479def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                } catch (SSLHandshakeException expected) {
480def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                }
481def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root                return null;
482def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root            }
483def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        });
484def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        executor.shutdown();
485def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        try {
486def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root            client.startHandshake();
487def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root            fail();
488def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        } catch (SSLHandshakeException expected) {
489def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        }
490def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        future.get();
491def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        server.close();
492def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        client.close();
493def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root        c.close();
494def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root    }
495def50a267d0100fa560cf7bbcd0b9a9d5f5e068fKenny Root
49617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_startHandshake_noKeyStore() throws Exception {
4976882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        TestSSLContext c = TestSSLContext.create(null, null, null, null, null, null, null, null,
4986882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                                 SSLContext.getDefault(), SSLContext.getDefault());
499059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
500059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
501bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
502bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        ExecutorService executor = Executors.newSingleThreadExecutor();
503bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        Future<Void> future = executor.submit(new Callable<Void>() {
504bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin            @Override public Void call() throws Exception {
505bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin                try {
506bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin                    server.startHandshake();
507bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin                    fail();
508bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin                } catch (SSLHandshakeException expected) {
509aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                }
510bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin                return null;
511aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
512bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        });
513bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        executor.shutdown();
514bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        try {
515bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin            client.startHandshake();
516bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin            fail();
517bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        } catch (SSLHandshakeException expected) {
51817c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        }
519bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        future.get();
520bccd4e67d528d52d368e4bbd319621ba2cc15e5fAlex Klyubin        server.close();
521f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
522f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
523ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
524ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
525e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    public void test_SSLSocket_startHandshake_noClientCertificate() throws Exception {
526059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestSSLContext c = TestSSLContext.create();
527059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLContext serverContext = c.serverContext;
528059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLContext clientContext = c.clientContext;
529e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        SSLSocket client = (SSLSocket)
530059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            clientContext.getSocketFactory().createSocket(c.host, c.port);
531059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
532783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
533783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
534783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
535783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.startHandshake();
536783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
537e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            }
538e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        });
539783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
540e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        client.startHandshake();
541783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
542f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
543f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
544f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
545e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    }
546e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom
54717c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_HandshakeCompletedListener() throws Exception {
548bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        final TestSSLContext c = TestSSLContext.create();
549059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        final SSLSocket client = (SSLSocket)
550059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                c.clientContext.getSocketFactory().createSocket(c.host, c.port);
55117c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
552783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
553783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
554783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
555783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.startHandshake();
556783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
557ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
558ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
559783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
560ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        final boolean[] handshakeCompletedListenerCalled = new boolean[1];
561ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
5622216155c3066236eb450f307983019f69a10303dKenny Root            @Override
5638ee2e66dc0ef38f4fbdf0fd649abc6e47876c9afBrian Carlstrom            public void handshakeCompleted(HandshakeCompletedEvent event) {
564ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                try {
565ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    SSLSession session = event.getSession();
566ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    String cipherSuite = event.getCipherSuite();
567ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    Certificate[] localCertificates = event.getLocalCertificates();
568ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    Certificate[] peerCertificates = event.getPeerCertificates();
569e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                    javax.security.cert.X509Certificate[] peerCertificateChain
570e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                            = event.getPeerCertificateChain();
571ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    Principal peerPrincipal = event.getPeerPrincipal();
572ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    Principal localPrincipal = event.getLocalPrincipal();
573ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    Socket socket = event.getSocket();
574ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
575ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    if (false) {
576ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        System.out.println("Session=" + session);
577ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        System.out.println("CipherSuite=" + cipherSuite);
578101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                        System.out.println("LocalCertificates="
579101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                                + Arrays.toString(localCertificates));
580101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                        System.out.println("PeerCertificates="
581101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                                + Arrays.toString(peerCertificates));
582101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                        System.out.println("PeerCertificateChain="
583101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson                                + Arrays.toString(peerCertificateChain));
584ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        System.out.println("PeerPrincipal=" + peerPrincipal);
585ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        System.out.println("LocalPrincipal=" + localPrincipal);
586ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        System.out.println("Socket=" + socket);
587ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    }
588ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
589ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(session);
590ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    byte[] id = session.getId();
591ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(id);
592ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertEquals(32, id.length);
593059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    assertNotNull(c.clientContext.getClientSessionContext().getSession(id));
594ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
595ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(cipherSuite);
596e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                    assertTrue(Arrays.asList(
597e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                            client.getEnabledCipherSuites()).contains(cipherSuite));
598e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                    assertTrue(Arrays.asList(
599e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom                            c.serverSocket.getEnabledCipherSuites()).contains(cipherSuite));
600ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
601ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNull(localCertificates);
602ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
603ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(peerCertificates);
604059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    TestKeyStore.assertChainLength(peerCertificates);
605ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(peerCertificates[0]);
606059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    TestSSLContext.assertServerCertificateChain(c.clientTrustManager,
607059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                peerCertificates);
608059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    TestSSLContext.assertCertificateInKeyStore(peerCertificates[0],
609059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                               c.serverKeyStore);
610ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
611ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(peerCertificateChain);
612059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    TestKeyStore.assertChainLength(peerCertificateChain);
613ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(peerCertificateChain[0]);
614204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                    TestSSLContext.assertCertificateInKeyStore(
615059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                        peerCertificateChain[0].getSubjectDN(), c.serverKeyStore);
616ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
617ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(peerPrincipal);
618059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    TestSSLContext.assertCertificateInKeyStore(peerPrincipal, c.serverKeyStore);
619ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
620ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNull(localPrincipal);
621ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
622ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertNotNull(socket);
623ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    assertSame(client, socket);
624ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
62570bf6bc3ad78ed9a0a7a5767381ad6c25debbd70Kenny Root                    assertTrue(socket instanceof SSLSocket);
62601b7734160977458d44d1fb179984fd91672f08dKenny Root                    assertNull(((SSLSocket) socket).getHandshakeSession());
62770bf6bc3ad78ed9a0a7a5767381ad6c25debbd70Kenny Root
628cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom                    synchronized (handshakeCompletedListenerCalled) {
629cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom                        handshakeCompletedListenerCalled[0] = true;
630cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom                        handshakeCompletedListenerCalled.notify();
631cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom                    }
632ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    handshakeCompletedListenerCalled[0] = true;
633ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                } catch (RuntimeException e) {
634ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    throw e;
635ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                } catch (Exception e) {
636ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    throw new RuntimeException(e);
637ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                }
638ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
639ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
640ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.startHandshake();
641783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
6420c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) {
643059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            assertNotNull(c.serverContext.getServerSessionContext().getSession(
6440c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                    client.getSession().getId()));
6450c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        }
646cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom        synchronized (handshakeCompletedListenerCalled) {
647cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom            while (!handshakeCompletedListenerCalled[0]) {
648cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom                handshakeCompletedListenerCalled.wait();
649cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom            }
650cac49819d66d7928fe524ccd3eb93590120d9d30Brian Carlstrom        }
651f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
652f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
653f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
654ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
655ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
656283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom    private static final class TestUncaughtExceptionHandler implements UncaughtExceptionHandler {
657283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        Throwable actualException;
658283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        @Override public void uncaughtException(Thread thread, Throwable ex) {
659283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom            assertNull(actualException);
660283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom            actualException = ex;
661283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        }
662283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom    }
663283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom
664e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    public void test_SSLSocket_HandshakeCompletedListener_RuntimeException() throws Exception {
665283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        final Thread self = Thread.currentThread();
666283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        final UncaughtExceptionHandler original = self.getUncaughtExceptionHandler();
667283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom
668283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        final RuntimeException expectedException = new RuntimeException("expected");
669283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        final TestUncaughtExceptionHandler test = new TestUncaughtExceptionHandler();
670283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        self.setUncaughtExceptionHandler(test);
671283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom
672e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        final TestSSLContext c = TestSSLContext.create();
673059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        final SSLSocket client = (SSLSocket)
674059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                c.clientContext.getSocketFactory().createSocket(c.host, c.port);
675e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
676783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
677783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
678783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
679783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.startHandshake();
680783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
681e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            }
682e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        });
683783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
684e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
6852216155c3066236eb450f307983019f69a10303dKenny Root            @Override
686e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            public void handshakeCompleted(HandshakeCompletedEvent event) {
687283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom                throw expectedException;
688e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            }
689e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        });
690e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        client.startHandshake();
691783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
692f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
693f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
694f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
695283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom
696283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        assertSame(expectedException, test.actualException);
697283a5d1ff99659815a3fae78b9eab2ce856a908aBrian Carlstrom        self.setUncaughtExceptionHandler(original);
698e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    }
699e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom
70017c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_getUseClientMode() throws Exception {
70117c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
702059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
703059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
70417c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        SSLSocket server = (SSLSocket) c.serverSocket.accept();
705ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertTrue(client.getUseClientMode());
70617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        assertFalse(server.getUseClientMode());
707f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
708f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
709f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
710ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
711ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
71217c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_setUseClientMode() throws Exception {
713ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        // client is client, server is server
71417c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        test_SSLSocket_setUseClientMode(true, false);
715ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        // client is server, server is client
71617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        test_SSLSocket_setUseClientMode(true, false);
717ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        // both are client
718ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
71917c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom            test_SSLSocket_setUseClientMode(true, true);
720ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
721e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (SSLProtocolException expected) {
722aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertTrue(StandardNames.IS_RI);
723aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        } catch (SSLHandshakeException expected) {
724aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertFalse(StandardNames.IS_RI);
725ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
726ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
727ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        // both are server
728ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
72917c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom            test_SSLSocket_setUseClientMode(false, false);
730ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
731e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (SocketTimeoutException expected) {
732ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
733ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
734ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
73517c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    private void test_SSLSocket_setUseClientMode(final boolean clientClientMode,
73617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom                                                 final boolean serverClientMode)
737ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            throws Exception {
73817c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
739059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
740059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
74117c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
74217c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom
743783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
744783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<IOException> future = executor.submit(new Callable<IOException>() {
745783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public IOException call() throws Exception {
746ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                try {
747ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    if (!serverClientMode) {
748ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                        server.setSoTimeout(1 * 1000);
749ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    }
750ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    server.setUseClientMode(serverClientMode);
751ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                    server.startHandshake();
752783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    return null;
753aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                } catch (SSLHandshakeException e) {
754783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    return e;
755ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                } catch (SocketTimeoutException e) {
756783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    return e;
757ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                }
758ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
759ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
760783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
761ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        if (!clientClientMode) {
762ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            client.setSoTimeout(1 * 1000);
763ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
764ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.setUseClientMode(clientClientMode);
765ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.startHandshake();
766783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        IOException ioe = future.get();
767783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        if (ioe != null) {
768783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            throw ioe;
769ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
770f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
771f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
772f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
773ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
774ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
775783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom    public void test_SSLSocket_setUseClientMode_afterHandshake() throws Exception {
776783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
777783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        // can't set after handshake
778a784bce5655435d8641f7d384c8da3fab018c491Kenny Root        TestSSLSocketPair pair = TestSSLSocketPair.create();
779783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        try {
780783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            pair.server.setUseClientMode(false);
781783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            fail();
782783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        } catch (IllegalArgumentException expected) {
783783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        }
784783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        try {
785783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            pair.client.setUseClientMode(false);
786783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            fail();
787783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        } catch (IllegalArgumentException expected) {
788783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        }
789783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom    }
790783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
7912915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom    public void test_SSLSocket_untrustedServer() throws Exception {
7922915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCA2(),
7932915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom                                                 TestKeyStore.getServer());
7942915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
7952915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom                                                                                       c.port);
7962915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
797783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
798783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
799783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
8002915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom                try {
8012915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom                    server.startHandshake();
8024d8e05bc051c080e81f873a2d62b3c4867f485afKenny Root                    fail();
803aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                } catch (SSLHandshakeException expected) {
8042915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom                }
805783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
8062915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom            }
8072915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        });
808783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
8092915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        try {
8102915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom            client.startHandshake();
8112915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom            fail();
8122915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        } catch (SSLHandshakeException expected) {
8132915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom            assertTrue(expected.getCause() instanceof CertificateException);
8142915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstrom        }
815a660f1cceca91b728df45656b14321b56eb16fa5Kenny Root        future.get();
816a3d357bd346336f7ff304a9a26c81e93f67f98e6Brian Carlstrom        client.close();
817a3d357bd346336f7ff304a9a26c81e93f67f98e6Brian Carlstrom        server.close();
818a660f1cceca91b728df45656b14321b56eb16fa5Kenny Root        c.close();
819ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
820ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
82117c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_clientAuth() throws Exception {
822059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestSSLContext c = TestSSLContext.create(TestKeyStore.getClientCertificate(),
823059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                 TestKeyStore.getServer());
824059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
825059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
82617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
827783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
828783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
829783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
830783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertFalse(server.getWantClientAuth());
831783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertFalse(server.getNeedClientAuth());
832783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
833783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                // confirm turning one on by itself
834783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.setWantClientAuth(true);
835783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertTrue(server.getWantClientAuth());
836783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertFalse(server.getNeedClientAuth());
837783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
838783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                // confirm turning setting on toggles the other
839783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.setNeedClientAuth(true);
840783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertFalse(server.getWantClientAuth());
841783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertTrue(server.getNeedClientAuth());
842783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
843783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                // confirm toggling back
844783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.setWantClientAuth(true);
845783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertTrue(server.getWantClientAuth());
846783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                assertFalse(server.getNeedClientAuth());
847783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
848783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.startHandshake();
849783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
850ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
851ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
852783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
853ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.startHandshake();
854ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(client.getSession().getLocalCertificates());
855059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
856059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        TestSSLContext.assertClientCertificateChain(c.clientTrustManager,
857059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                    client.getSession().getLocalCertificates());
858783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
859f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
860f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
861f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
862ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
863ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
864aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom    public void test_SSLSocket_clientAuth_bogusAlias() throws Exception {
865aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
866aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        SSLContext clientContext = SSLContext.getInstance("TLS");
867aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        X509KeyManager keyManager = new X509KeyManager() {
868aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public String chooseClientAlias(String[] keyType,
869aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                                                      Principal[] issuers,
870aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                                                      Socket socket) {
871aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                return "bogus";
872aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
873aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public String chooseServerAlias(String keyType,
874aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                                                      Principal[] issuers,
875aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                                                      Socket socket) {
876aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                throw new AssertionError();
877aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
878aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public X509Certificate[] getCertificateChain(String alias) {
879aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                // return null for "bogus" alias
880aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                return null;
881aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
882aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public String[] getClientAliases(String keyType, Principal[] issuers) {
883aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                throw new AssertionError();
884aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
885aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public String[] getServerAliases(String keyType, Principal[] issuers) {
886aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                throw new AssertionError();
887aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
888aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            @Override public PrivateKey getPrivateKey(String alias) {
889aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                // return null for "bogus" alias
890aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                return null;
891aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
892aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        };
893aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        clientContext.init(new KeyManager[] { keyManager },
894aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                           new TrustManager[] { c.clientTrustManager },
895aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                           null);
896aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(c.host,
897aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                                                                                     c.port);
898aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
899783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
900783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
901783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
902aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                try {
903aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                    server.setNeedClientAuth(true);
904aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                    server.startHandshake();
905aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                    fail();
906aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                } catch (SSLHandshakeException expected) {
907aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom                }
908783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
909aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            }
910aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        });
911aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom
912783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
913aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        try {
914aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            client.startHandshake();
915aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            fail();
916aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        } catch (SSLHandshakeException expected) {
917aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            // before we would get a NullPointerException from passing
918aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            // due to the null PrivateKey return by the X509KeyManager.
919aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        }
920783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
921aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        client.close();
922aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        server.close();
923aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        c.close();
924aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom    }
925aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom
926a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    public void test_SSLSocket_clientAuth_OpaqueKey_RSA() throws Exception {
927a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientCertificate());
928a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
929a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
930a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    public void test_SSLSocket_clientAuth_OpaqueKey_EC_RSA() throws Exception {
931a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientEcRsaCertificate());
932a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
933a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
934a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    public void test_SSLSocket_clientAuth_OpaqueKey_EC_EC() throws Exception {
935a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientEcEcCertificate());
936a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
937a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
938a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    private void run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore keyStore) throws Exception {
939a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        try {
940a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            Security.insertProviderAt(new OpaqueProvider(), 1);
941a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
942a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            final TestSSLContext c = TestSSLContext.create(keyStore, TestKeyStore.getServer());
943a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            SSLContext clientContext = SSLContext.getInstance("TLS");
944a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            final X509KeyManager delegateKeyManager = (X509KeyManager) c.clientKeyManagers[0];
945a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            X509KeyManager keyManager = new X509KeyManager() {
946a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
947a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public String chooseClientAlias(String[] keyType, Principal[] issuers,
948a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                        Socket socket) {
949a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return delegateKeyManager.chooseClientAlias(keyType, issuers, socket);
950a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
951a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
952a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
953a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public String chooseServerAlias(String keyType, Principal[] issuers,
954a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                        Socket socket) {
955a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return delegateKeyManager.chooseServerAlias(keyType, issuers, socket);
956a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
957a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
958a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
959a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public X509Certificate[] getCertificateChain(String alias) {
960a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return delegateKeyManager.getCertificateChain(alias);
961a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
962a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
963a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
964a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public String[] getClientAliases(String keyType, Principal[] issuers) {
965a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return delegateKeyManager.getClientAliases(keyType, issuers);
966a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
967a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
968a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
969a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public String[] getServerAliases(String keyType, Principal[] issuers) {
970a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return delegateKeyManager.getServerAliases(keyType, issuers);
971a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
972a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
973a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
974a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public PrivateKey getPrivateKey(String alias) {
975a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    PrivateKey privKey = delegateKeyManager.getPrivateKey(alias);
976a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    if (privKey instanceof RSAPrivateKey) {
977a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                        return new OpaqueDelegatingRSAPrivateKey((RSAPrivateKey) privKey);
978a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    } else if (privKey instanceof ECPrivateKey) {
979a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                        return new OpaqueDelegatingECPrivateKey((ECPrivateKey) privKey);
980a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    } else {
981a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                        return null;
982a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    }
983a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
984a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            };
985a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            clientContext.init(new KeyManager[] {
986a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    keyManager
987a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }, new TrustManager[] {
988a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    c.clientTrustManager
989a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }, null);
990a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(c.host,
991a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    c.port);
992a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            final SSLSocket server = (SSLSocket) c.serverSocket.accept();
993a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            ExecutorService executor = Executors.newSingleThreadExecutor();
994a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            Future<Void> future = executor.submit(new Callable<Void>() {
995a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                @Override
996a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                public Void call() throws Exception {
997a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    server.setNeedClientAuth(true);
998a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    server.startHandshake();
999a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    return null;
1000a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                }
1001a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            });
1002a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            executor.shutdown();
1003a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            client.startHandshake();
1004a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            assertNotNull(client.getSession().getLocalCertificates());
1005a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
1006a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            TestSSLContext.assertClientCertificateChain(c.clientTrustManager,
1007a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                    client.getSession().getLocalCertificates());
1008a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            future.get();
1009a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            client.close();
1010a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            server.close();
1011a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            c.close();
1012a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        } finally {
1013a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            Security.removeProvider(OpaqueProvider.NAME);
1014a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1015a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1016a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1017a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    @SuppressWarnings("serial")
1018a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    public static class OpaqueProvider extends Provider {
1019a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public static final String NAME = "OpaqueProvider";
1020a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1021a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public OpaqueProvider() {
1022a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            super(NAME, 1.0, "test provider");
1023a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1024a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            put("Signature.NONEwithRSA", OpaqueSignatureSpi.RSA.class.getName());
1025a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            put("Signature.NONEwithECDSA", OpaqueSignatureSpi.ECDSA.class.getName());
1026a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            put("Cipher.RSA/ECB/NoPadding", OpaqueCipherSpi.class.getName());
1027a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1028a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1029a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1030a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    protected static class OpaqueSignatureSpi extends SignatureSpi {
1031a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        private final String algorithm;
1032a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1033a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        private Signature delegate;
1034a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1035a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected OpaqueSignatureSpi(String algorithm) {
1036a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            this.algorithm = algorithm;
1037a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1038a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1039a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public final static class RSA extends OpaqueSignatureSpi {
1040a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            public RSA() {
1041a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                super("NONEwithRSA");
1042a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }
1043a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1044a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1045a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public final static class ECDSA extends OpaqueSignatureSpi {
1046a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            public ECDSA() {
1047a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                super("NONEwithECDSA");
1048a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }
1049a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1050a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1051a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1052a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
1053a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            fail("Cannot verify");
1054a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1055a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1056a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1057a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
1058a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            DelegatingPrivateKey opaqueKey = (DelegatingPrivateKey) privateKey;
1059a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            try {
1060a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                delegate = Signature.getInstance(algorithm);
1061a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            } catch (NoSuchAlgorithmException e) {
1062a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throw new InvalidKeyException(e);
1063a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }
1064a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.initSign(opaqueKey.getDelegate());
1065a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1066a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1067a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1068a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineUpdate(byte b) throws SignatureException {
1069a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.update(b);
1070a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1071a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1072a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1073a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
1074a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.update(b, off, len);
1075a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1076a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1077a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1078a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected byte[] engineSign() throws SignatureException {
1079a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.sign();
1080a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1081a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1082a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1083a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
1084a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.verify(sigBytes);
1085a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1086a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1087a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @SuppressWarnings("deprecation")
1088a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1089a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineSetParameter(String param, Object value)
1090a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws InvalidParameterException {
1091a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.setParameter(param, value);
1092a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1093a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1094a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @SuppressWarnings("deprecation")
1095a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1096a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected Object engineGetParameter(String param) throws InvalidParameterException {
1097a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getParameter(param);
1098a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1099a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1100a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1101a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    public static class OpaqueCipherSpi extends CipherSpi {
1102a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        private Cipher delegate;
1103a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1104a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public OpaqueCipherSpi() {
1105a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1106a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1107a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1108a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
1109a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            fail();
1110a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1111a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1112a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1113a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineSetPadding(String padding) throws NoSuchPaddingException {
1114a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            fail();
1115a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1116a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1117a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1118a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected int engineGetBlockSize() {
1119a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getBlockSize();
1120a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1121a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1122a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1123a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected int engineGetOutputSize(int inputLen) {
1124a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getOutputSize(inputLen);
1125a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1126a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1127a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1128a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected byte[] engineGetIV() {
1129a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getIV();
1130a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1131a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1132a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1133a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected AlgorithmParameters engineGetParameters() {
1134a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getParameters();
1135a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1136a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1137a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1138a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineInit(int opmode, Key key, SecureRandom random)
1139a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws InvalidKeyException {
1140a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            getCipher();
1141a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.init(opmode, key, random);
1142a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1143a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1144a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void getCipher() throws InvalidKeyException {
1145a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            try {
1146a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                delegate = Cipher.getInstance("RSA/ECB/NoPadding");
1147a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
1148a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throw new InvalidKeyException(e);
1149a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            }
1150a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1151a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1152a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1153a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
1154a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                SecureRandom random)
1155a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws InvalidKeyException, InvalidAlgorithmParameterException {
1156a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            getCipher();
1157a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.init(opmode, key, params, random);
1158a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1159a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1160a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1161a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
1162a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                SecureRandom random)
1163a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws InvalidKeyException, InvalidAlgorithmParameterException {
1164a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            getCipher();
1165a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            delegate.init(opmode, key, params, random);
1166a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1167a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1168a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1169a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
1170a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.update(input, inputOffset, inputLen);
1171a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1172a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1173a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1174a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
1175a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                int outputOffset) throws ShortBufferException {
1176a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.update(input, inputOffset, inputLen, output, outputOffset);
1177a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1178a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1179a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1180a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
1181a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws IllegalBlockSizeException, BadPaddingException {
1182a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.update(input, inputOffset, inputLen);
1183a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1184a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1185a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1186a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
1187a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                int outputOffset)
1188a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root                throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
1189a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.doFinal(input, inputOffset, inputLen, output, outputOffset);
1190a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1191a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1192a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1193a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    private interface DelegatingPrivateKey {
1194a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        PrivateKey getDelegate();
1195a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1196a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1197a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    @SuppressWarnings("serial")
119872ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Root    private static class OpaqueDelegatingECPrivateKey
119972ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Root            implements ECKey, PrivateKey, DelegatingPrivateKey {
1200a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        private final ECPrivateKey delegate;
1201a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1202a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public OpaqueDelegatingECPrivateKey(ECPrivateKey delegate) {
1203a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            this.delegate = delegate;
1204a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1205a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1206a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1207a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public PrivateKey getDelegate() {
1208a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate;
1209a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1210a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1211a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1212a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public String getAlgorithm() {
1213a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getAlgorithm();
1214a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1215a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1216a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1217a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public String getFormat() {
1218a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return null;
1219a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1220a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1221a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1222a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public byte[] getEncoded() {
1223a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return null;
1224a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1225a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1226a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1227a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public ECParameterSpec getParams() {
1228a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getParams();
1229a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1230a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1231a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1232a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    @SuppressWarnings("serial")
123372ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Root    private static class OpaqueDelegatingRSAPrivateKey
123472ac463cd5718d2e5aa439e569c26cc0576f4962Kenny Root            implements RSAKey, PrivateKey, DelegatingPrivateKey {
1235a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        private final RSAPrivateKey delegate;
1236a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1237a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public OpaqueDelegatingRSAPrivateKey(RSAPrivateKey delegate) {
1238a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            this.delegate = delegate;
1239a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1240a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1241a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1242a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public String getAlgorithm() {
1243a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getAlgorithm();
1244a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1245a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1246a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1247a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public String getFormat() {
1248a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return null;
1249a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1250a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1251a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1252a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public byte[] getEncoded() {
1253a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return null;
1254a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1255a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1256a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1257a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public BigInteger getModulus() {
1258a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate.getModulus();
1259a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1260a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
1261a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        @Override
1262a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        public PrivateKey getDelegate() {
1263a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root            return delegate;
1264a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root        }
1265a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root    }
1266a86c73bb4b81906c965a55de48e38dd4e44f49e6Kenny Root
12678c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom    public void test_SSLSocket_TrustManagerRuntimeException() throws Exception {
12688c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
12698c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        SSLContext clientContext = SSLContext.getInstance("TLS");
12708c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        X509TrustManager trustManager = new X509TrustManager() {
12718c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            @Override public void checkClientTrusted(X509Certificate[] chain, String authType)
12728c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                    throws CertificateException {
12738c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                throw new AssertionError();
12748c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            }
12758c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            @Override public void checkServerTrusted(X509Certificate[] chain, String authType)
12768c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                    throws CertificateException {
12778c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                throw new RuntimeException();  // throw a RuntimeException from custom TrustManager
12788c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            }
12798c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            @Override public X509Certificate[] getAcceptedIssuers() {
12808c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                throw new AssertionError();
12818c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            }
12828c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        };
12838c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        clientContext.init(null, new TrustManager[] { trustManager }, null);
12848c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(c.host,
12858c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                                                                                     c.port);
12868c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
12878c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
12888c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
12898c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            @Override public Void call() throws Exception {
12904d8e05bc051c080e81f873a2d62b3c4867f485afKenny Root                try {
12914d8e05bc051c080e81f873a2d62b3c4867f485afKenny Root                    server.startHandshake();
1292a660f1cceca91b728df45656b14321b56eb16fa5Kenny Root                    fail();
12934d8e05bc051c080e81f873a2d62b3c4867f485afKenny Root                } catch (SSLHandshakeException expected) {
12944d8e05bc051c080e81f873a2d62b3c4867f485afKenny Root                }
12958c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom                return null;
12968c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            }
12978c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        });
12988c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom
12998c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        executor.shutdown();
13008c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        try {
13018c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            client.startHandshake();
13028c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            fail();
13038c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        } catch (SSLHandshakeException expected) {
13048c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom            // before we would get a RuntimeException from checkServerTrusted.
13058c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        }
13068c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        future.get();
13078c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        client.close();
13088c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        server.close();
13098c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom        c.close();
13108c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom    }
13118c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom
131217c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_getEnableSessionCreation() throws Exception {
131317c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
1314059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
1315059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
131617c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        SSLSocket server = (SSLSocket) c.serverSocket.accept();
1317ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertTrue(client.getEnableSessionCreation());
131817c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        assertTrue(server.getEnableSessionCreation());
1319f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
1320f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
1321f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
1322ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
1323ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
132417c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_setEnableSessionCreation_server() throws Exception {
132517c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
1326059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
1327059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
132817c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
1329783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
1330783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
1331783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
1332783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                server.setEnableSessionCreation(false);
1333ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                try {
1334783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    server.startHandshake();
1335783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    fail();
1336783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                } catch (SSLException expected) {
1337ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                }
1338783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
1339ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
1340ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
1341783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
1342ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
1343ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            client.startHandshake();
1344ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
1345e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (SSLException expected) {
1346ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
1347783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
1348f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
1349f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
1350f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
1351ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
1352ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
135317c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom    public void test_SSLSocket_setEnableSessionCreation_client() throws Exception {
135417c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
1355059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
1356059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                                                       c.port);
135717c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
1358783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
1359783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
1360783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
1361ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                try {
1362783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    server.startHandshake();
1363783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    fail();
1364783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                } catch (SSLException expected) {
1365ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom                }
1366783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
1367ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            }
1368ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        });
1369783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
1370ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        client.setEnableSessionCreation(false);
1371ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        try {
1372ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            client.startHandshake();
1373ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom            fail();
1374e9505132a9a878aa77b0fb40a40dd55c9e6affe7Brian Carlstrom        } catch (SSLException expected) {
1375ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        }
1376783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
1377f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        client.close();
1378f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        server.close();
1379f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        c.close();
1380ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
1381ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom
13820c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    public void test_SSLSocket_getSSLParameters() throws Exception {
13830c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
13840c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
13850c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
13860c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        SSLParameters p = ssl.getSSLParameters();
13870c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertNotNull(p);
13880c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
13890c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] cipherSuites = p.getCipherSuites();
13900c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
13910c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
13920c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
13930c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] protocols = p.getProtocols();
13940c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertNotSame(protocols, ssl.getEnabledProtocols());
13950c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertEquals(Arrays.asList(protocols), Arrays.asList(ssl.getEnabledProtocols()));
13960c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
13970c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertEquals(p.getWantClientAuth(), ssl.getWantClientAuth());
13980c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertEquals(p.getNeedClientAuth(), ssl.getNeedClientAuth());
139901b7734160977458d44d1fb179984fd91672f08dKenny Root
140001b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNull(p.getEndpointIdentificationAlgorithm());
140101b7734160977458d44d1fb179984fd91672f08dKenny Root        p.setEndpointIdentificationAlgorithm(null);
140201b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNull(p.getEndpointIdentificationAlgorithm());
140301b7734160977458d44d1fb179984fd91672f08dKenny Root        p.setEndpointIdentificationAlgorithm("HTTPS");
140401b7734160977458d44d1fb179984fd91672f08dKenny Root        assertEquals("HTTPS", p.getEndpointIdentificationAlgorithm());
140501b7734160977458d44d1fb179984fd91672f08dKenny Root        p.setEndpointIdentificationAlgorithm("FOO");
140601b7734160977458d44d1fb179984fd91672f08dKenny Root        assertEquals("FOO", p.getEndpointIdentificationAlgorithm());
14070c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    }
14080c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14090c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    public void test_SSLSocket_setSSLParameters() throws Exception {
14100c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
14110c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        SSLSocket ssl = (SSLSocket) sf.createSocket();
14120c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] defaultCipherSuites = ssl.getEnabledCipherSuites();
14130c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] defaultProtocols = ssl.getEnabledProtocols();
14140c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] supportedCipherSuites = ssl.getSupportedCipherSuites();
14150c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        String[] supportedProtocols = ssl.getSupportedProtocols();
14160c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14170c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        {
14180c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            SSLParameters p = new SSLParameters();
14190c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            ssl.setSSLParameters(p);
14200c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertEquals(Arrays.asList(defaultCipherSuites),
14210c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                         Arrays.asList(ssl.getEnabledCipherSuites()));
14220c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertEquals(Arrays.asList(defaultProtocols),
14230c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                         Arrays.asList(ssl.getEnabledProtocols()));
14240c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        }
14250c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14260c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        {
14270c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            SSLParameters p = new SSLParameters(supportedCipherSuites,
14280c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                                supportedProtocols);
14290c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            ssl.setSSLParameters(p);
14300c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertEquals(Arrays.asList(supportedCipherSuites),
14310c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                         Arrays.asList(ssl.getEnabledCipherSuites()));
14320c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertEquals(Arrays.asList(supportedProtocols),
14330c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                         Arrays.asList(ssl.getEnabledProtocols()));
14340c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        }
14350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        {
14360c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            SSLParameters p = new SSLParameters();
14370c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14380c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            p.setNeedClientAuth(true);
14390c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getNeedClientAuth());
14400c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getWantClientAuth());
14410c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            ssl.setSSLParameters(p);
14420c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertTrue(ssl.getNeedClientAuth());
14430c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getWantClientAuth());
14440c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14450c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            p.setWantClientAuth(true);
14460c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertTrue(ssl.getNeedClientAuth());
14470c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getWantClientAuth());
14480c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            ssl.setSSLParameters(p);
14490c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getNeedClientAuth());
14500c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertTrue(ssl.getWantClientAuth());
14510c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14520c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            p.setWantClientAuth(false);
14530c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getNeedClientAuth());
14540c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertTrue(ssl.getWantClientAuth());
14550c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            ssl.setSSLParameters(p);
14560c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getNeedClientAuth());
14570c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            assertFalse(ssl.getWantClientAuth());
14580c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        }
14590c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    }
14600c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom
14615f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    public void test_SSLSocket_close() throws Exception {
14625f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        TestSSLSocketPair pair = TestSSLSocketPair.create();
14635f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        SSLSocket server = pair.server;
14645f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        SSLSocket client = pair.client;
14655f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertFalse(server.isClosed());
14665f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertFalse(client.isClosed());
14675f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        InputStream input = client.getInputStream();
14685f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        OutputStream output = client.getOutputStream();
14695f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        server.close();
14705f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.close();
14715f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertTrue(server.isClosed());
14725f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertTrue(client.isClosed());
14735f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
14745f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        // close after close is okay...
14755f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        server.close();
14765f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.close();
14775f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
14785f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        // ...so are a lot of other operations...
14795f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        HandshakeCompletedListener l = new HandshakeCompletedListener () {
14802216155c3066236eb450f307983019f69a10303dKenny Root            @Override
14815f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            public void handshakeCompleted(HandshakeCompletedEvent e) {}
14825f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        };
14835f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.addHandshakeCompletedListener(l);
14845f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertNotNull(client.getEnabledCipherSuites());
14855f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertNotNull(client.getEnabledProtocols());
14865f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.getEnableSessionCreation();
14875f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.getNeedClientAuth();
14885f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertNotNull(client.getSession());
14895f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertNotNull(client.getSSLParameters());
14905f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertNotNull(client.getSupportedProtocols());
14915f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.getUseClientMode();
14925f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.getWantClientAuth();
14935f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.removeHandshakeCompletedListener(l);
14945f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setEnabledCipherSuites(new String[0]);
14955f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setEnabledProtocols(new String[0]);
14965f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setEnableSessionCreation(false);
14975f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setNeedClientAuth(false);
14985f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setSSLParameters(client.getSSLParameters());
14995f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        client.setWantClientAuth(false);
15005f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
15015f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        // ...but some operations are expected to give SocketException...
15025f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15035f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            client.startHandshake();
15045f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15055f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
15065f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15075f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15085f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            client.getInputStream();
15095f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15105f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
15115f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15125f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15135f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            client.getOutputStream();
15145f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15155f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
15165f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15175f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15185f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            input.read();
15195f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15205f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
15215f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15225f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15235f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            input.read(null, -1, -1);
15245f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
1525aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        } catch (NullPointerException expected) {
1526aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertTrue(StandardNames.IS_RI);
15275f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
1528aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertFalse(StandardNames.IS_RI);
15295f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15305f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15315f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            output.write(-1);
15325f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15335f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
15345f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            output.write(null, -1, -1);
15375f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
1538aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom        } catch (NullPointerException expected) {
1539aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertTrue(StandardNames.IS_RI);
15405f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (SocketException expected) {
1541aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom            assertFalse(StandardNames.IS_RI);
15425f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
15435f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
15445f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        // ... and one gives IllegalArgumentException
15455f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        try {
15465f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            client.setUseClientMode(false);
15475f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            fail();
15485f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        } catch (IllegalArgumentException expected) {
15495f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
1550f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
1551f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        pair.close();
15525f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    }
15535f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
15541c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom    /**
15551c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom     * b/3350645 Test to confirm that an SSLSocket.close() performing
15561c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom     * an SSL_shutdown does not throw an IOException if the peer
15571c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom     * socket has been closed.
15581c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom     */
15591c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom    public void test_SSLSocket_shutdownCloseOnClosedPeer() throws Exception {
15601c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
15611c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        final Socket underlying = new Socket(c.host, c.port);
15621c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        final SSLSocket wrapping = (SSLSocket)
15631c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom                c.clientContext.getSocketFactory().createSocket(underlying,
15641c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom                                                                c.host.getHostName(),
15651c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom                                                                c.port,
15661c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom                                                                false);
1567783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
1568783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> clientFuture = executor.submit(new Callable<Void>() {
1569783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
1570783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                wrapping.startHandshake();
1571783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                wrapping.getOutputStream().write(42);
1572783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                // close the underlying socket,
1573783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                // so that no SSL shutdown is sent
1574783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                underlying.close();
1575783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                wrapping.close();
1576783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
15771c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom            }
15781c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        });
1579783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
15801c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom
15811c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        SSLSocket server = (SSLSocket) c.serverSocket.accept();
15821c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        server.startHandshake();
15831c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        server.getInputStream().read();
15841c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        // wait for thread to finish so we know client is closed.
1585783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        clientFuture.get();
15861c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        // close should cause an SSL_shutdown which will fail
15871c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        // because the peer has closed, but it shouldn't throw.
15881c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom        server.close();
15891c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom    }
15901c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom
159101b7734160977458d44d1fb179984fd91672f08dKenny Root    public void test_SSLSocket_endpointIdentification_Success() throws Exception {
159201b7734160977458d44d1fb179984fd91672f08dKenny Root        final TestSSLContext c = TestSSLContext.create();
159301b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
159401b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLParameters p = client.getSSLParameters();
159501b7734160977458d44d1fb179984fd91672f08dKenny Root        p.setEndpointIdentificationAlgorithm("HTTPS");
159601b7734160977458d44d1fb179984fd91672f08dKenny Root        client.connect(new InetSocketAddress(c.host, c.port));
159701b7734160977458d44d1fb179984fd91672f08dKenny Root        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
159801b7734160977458d44d1fb179984fd91672f08dKenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
159901b7734160977458d44d1fb179984fd91672f08dKenny Root        Future<Void> future = executor.submit(new Callable<Void>() {
160001b7734160977458d44d1fb179984fd91672f08dKenny Root            @Override public Void call() throws Exception {
160101b7734160977458d44d1fb179984fd91672f08dKenny Root                server.startHandshake();
160201b7734160977458d44d1fb179984fd91672f08dKenny Root                assertNotNull(server.getSession());
160301b7734160977458d44d1fb179984fd91672f08dKenny Root                try {
160401b7734160977458d44d1fb179984fd91672f08dKenny Root                    server.getSession().getPeerCertificates();
160501b7734160977458d44d1fb179984fd91672f08dKenny Root                    fail();
160601b7734160977458d44d1fb179984fd91672f08dKenny Root                } catch (SSLPeerUnverifiedException expected) {
160701b7734160977458d44d1fb179984fd91672f08dKenny Root                }
160801b7734160977458d44d1fb179984fd91672f08dKenny Root                Certificate[] localCertificates = server.getSession().getLocalCertificates();
160901b7734160977458d44d1fb179984fd91672f08dKenny Root                assertNotNull(localCertificates);
161001b7734160977458d44d1fb179984fd91672f08dKenny Root                TestKeyStore.assertChainLength(localCertificates);
161101b7734160977458d44d1fb179984fd91672f08dKenny Root                assertNotNull(localCertificates[0]);
161201b7734160977458d44d1fb179984fd91672f08dKenny Root                TestSSLContext.assertCertificateInKeyStore(localCertificates[0],
161301b7734160977458d44d1fb179984fd91672f08dKenny Root                                                           c.serverKeyStore);
161401b7734160977458d44d1fb179984fd91672f08dKenny Root                return null;
161501b7734160977458d44d1fb179984fd91672f08dKenny Root            }
161601b7734160977458d44d1fb179984fd91672f08dKenny Root        });
161701b7734160977458d44d1fb179984fd91672f08dKenny Root        executor.shutdown();
161801b7734160977458d44d1fb179984fd91672f08dKenny Root        client.startHandshake();
161901b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNotNull(client.getSession());
162001b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNull(client.getSession().getLocalCertificates());
162101b7734160977458d44d1fb179984fd91672f08dKenny Root        Certificate[] peerCertificates = client.getSession().getPeerCertificates();
162201b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNotNull(peerCertificates);
162301b7734160977458d44d1fb179984fd91672f08dKenny Root        TestKeyStore.assertChainLength(peerCertificates);
162401b7734160977458d44d1fb179984fd91672f08dKenny Root        assertNotNull(peerCertificates[0]);
162501b7734160977458d44d1fb179984fd91672f08dKenny Root        TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
162601b7734160977458d44d1fb179984fd91672f08dKenny Root        future.get();
162701b7734160977458d44d1fb179984fd91672f08dKenny Root        client.close();
162801b7734160977458d44d1fb179984fd91672f08dKenny Root        server.close();
162901b7734160977458d44d1fb179984fd91672f08dKenny Root        c.close();
163001b7734160977458d44d1fb179984fd91672f08dKenny Root    }
163101b7734160977458d44d1fb179984fd91672f08dKenny Root
163201b7734160977458d44d1fb179984fd91672f08dKenny Root    public void test_SSLSocket_endpointIdentification_Failure() throws Exception {
163301b7734160977458d44d1fb179984fd91672f08dKenny Root        final TestSSLContext c = TestSSLContext.create();
16341ce90cc78f833da6ff674fb2028f2560938313ecKenny Root        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
163501b7734160977458d44d1fb179984fd91672f08dKenny Root        SSLParameters p = client.getSSLParameters();
163601b7734160977458d44d1fb179984fd91672f08dKenny Root        p.setEndpointIdentificationAlgorithm("HTTPS");
163701b7734160977458d44d1fb179984fd91672f08dKenny Root        client.setSSLParameters(p);
16381ce90cc78f833da6ff674fb2028f2560938313ecKenny Root        client.connect(c.getLoopbackAsHostname("unmatched.example.com", c.port));
163901b7734160977458d44d1fb179984fd91672f08dKenny Root        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
164001b7734160977458d44d1fb179984fd91672f08dKenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
164101b7734160977458d44d1fb179984fd91672f08dKenny Root        Future<Void> future = executor.submit(new Callable<Void>() {
164201b7734160977458d44d1fb179984fd91672f08dKenny Root            @Override public Void call() throws Exception {
164301b7734160977458d44d1fb179984fd91672f08dKenny Root                try {
164401b7734160977458d44d1fb179984fd91672f08dKenny Root                    server.startHandshake();
164501b7734160977458d44d1fb179984fd91672f08dKenny Root                    fail("Should receive SSLHandshakeException as server");
164601b7734160977458d44d1fb179984fd91672f08dKenny Root                } catch (SSLHandshakeException expected) {
164701b7734160977458d44d1fb179984fd91672f08dKenny Root                }
164801b7734160977458d44d1fb179984fd91672f08dKenny Root                return null;
164901b7734160977458d44d1fb179984fd91672f08dKenny Root            }
165001b7734160977458d44d1fb179984fd91672f08dKenny Root        });
165101b7734160977458d44d1fb179984fd91672f08dKenny Root        executor.shutdown();
165201b7734160977458d44d1fb179984fd91672f08dKenny Root        try {
165301b7734160977458d44d1fb179984fd91672f08dKenny Root            client.startHandshake();
165401b7734160977458d44d1fb179984fd91672f08dKenny Root            fail("Should throw when hostname does not match expected");
165501b7734160977458d44d1fb179984fd91672f08dKenny Root        } catch (SSLHandshakeException expected) {
165601b7734160977458d44d1fb179984fd91672f08dKenny Root        } finally {
165701b7734160977458d44d1fb179984fd91672f08dKenny Root            try {
165801b7734160977458d44d1fb179984fd91672f08dKenny Root                future.get();
165901b7734160977458d44d1fb179984fd91672f08dKenny Root            } finally {
166001b7734160977458d44d1fb179984fd91672f08dKenny Root                client.close();
166101b7734160977458d44d1fb179984fd91672f08dKenny Root                server.close();
166201b7734160977458d44d1fb179984fd91672f08dKenny Root                c.close();
166301b7734160977458d44d1fb179984fd91672f08dKenny Root            }
166401b7734160977458d44d1fb179984fd91672f08dKenny Root        }
166501b7734160977458d44d1fb179984fd91672f08dKenny Root    }
166601b7734160977458d44d1fb179984fd91672f08dKenny Root
1667a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    public void test_SSLSocket_setSoTimeout_basic() throws Exception {
1668a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        ServerSocket listening = new ServerSocket(0);
1669a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1670a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
1671a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        assertEquals(0, underlying.getSoTimeout());
1672a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1673a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
1674a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        Socket wrapping = sf.createSocket(underlying, null, -1, false);
1675a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        assertEquals(0, wrapping.getSoTimeout());
1676a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1677a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // setting wrapper sets underlying and ...
1678615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        int expectedTimeoutMillis = 1000;  // 10 was too small because it was affected by rounding
1679fc1332710b0af3bbe658535a257048cf8c7577f2Brian Carlstrom        wrapping.setSoTimeout(expectedTimeoutMillis);
16806566167989735858978d062a4385104ce5eca7e3Neil Fuller        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
16816566167989735858978d062a4385104ce5eca7e3Neil Fuller        assertTrue(Math.abs(expectedTimeoutMillis - wrapping.getSoTimeout()) <= 10);
16826566167989735858978d062a4385104ce5eca7e3Neil Fuller        assertTrue(Math.abs(expectedTimeoutMillis - underlying.getSoTimeout()) <= 10);
1683a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1684a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // ... getting wrapper inspects underlying
1685a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        underlying.setSoTimeout(0);
1686a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        assertEquals(0, wrapping.getSoTimeout());
1687a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        assertEquals(0, underlying.getSoTimeout());
1688a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    }
1689a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1690a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    public void test_SSLSocket_setSoTimeout_wrapper() throws Exception {
1691a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom        if (StandardNames.IS_RI) {
1692a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom            // RI cannot handle this case
1693a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom            return;
1694a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom        }
1695a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        ServerSocket listening = new ServerSocket(0);
1696a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1697a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // setSoTimeout applies to read, not connect, so connect first
1698a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
1699a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        Socket server = listening.accept();
1700a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1701a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
1702a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        Socket clientWrapping = sf.createSocket(underlying, null, -1, false);
1703a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1704a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        underlying.setSoTimeout(1);
1705a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        try {
1706a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom            clientWrapping.getInputStream().read();
1707a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom            fail();
1708a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        } catch (SocketTimeoutException expected) {
1709a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        }
1710a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1711a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        clientWrapping.close();
1712a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        server.close();
1713a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        underlying.close();
1714a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        listening.close();
1715a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    }
1716a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1717615225a35dbd838210270b282d1196deff643b51Brian Carlstrom    public void test_SSLSocket_setSoWriteTimeout() throws Exception {
1718615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        if (StandardNames.IS_RI) {
1719615225a35dbd838210270b282d1196deff643b51Brian Carlstrom            // RI does not support write timeout on sockets
1720615225a35dbd838210270b282d1196deff643b51Brian Carlstrom            return;
1721615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        }
1722615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
1723615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        final TestSSLContext c = TestSSLContext.create();
172451cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
172551cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom
172651cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // Try to make the client SO_SNDBUF size as small as possible
172751cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // (it can default to 512k or even megabytes).  Note that
172851cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // socket(7) says that the kernel will double the request to
172951cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // leave room for its own book keeping and that the minimal
173051cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // value will be 2048. Also note that tcp(7) says the value
173151cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // needs to be set before connect(2).
173251cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        int sendBufferSize = 1024;
173351cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        client.setSendBufferSize(sendBufferSize);
173451cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        sendBufferSize = client.getSendBufferSize();
173551cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom
173651cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // In jb-mr2 it was found that we need to also set SO_RCVBUF
173751cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // to a minimal size or the write would not block. While
173851cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // tcp(2) says the value has to be set before listen(2), it
173951cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        // seems fine to set it before accept(2).
174051cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        final int recvBufferSize = 128;
174151cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        c.serverSocket.setReceiveBufferSize(recvBufferSize);
174251cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom
174351cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom        client.connect(new InetSocketAddress(c.host, c.port));
174451cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom
1745615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
1746615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
1747615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
1748615225a35dbd838210270b282d1196deff643b51Brian Carlstrom            @Override public Void call() throws Exception {
1749615225a35dbd838210270b282d1196deff643b51Brian Carlstrom                server.startHandshake();
1750615225a35dbd838210270b282d1196deff643b51Brian Carlstrom                return null;
1751615225a35dbd838210270b282d1196deff643b51Brian Carlstrom            }
1752615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        });
1753615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        executor.shutdown();
1754615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        client.startHandshake();
1755615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
1756615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        // Reflection is used so this can compile on the RI
175770b79a2cc89dd2845582001cd3f2a8cf8301ce6cKenny Root        String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
17582216155c3066236eb450f307983019f69a10303dKenny Root        Class<?> actualClass = client.getClass();
1759615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        assertEquals(expectedClassName, actualClass.getName());
1760615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        Method setSoWriteTimeout = actualClass.getMethod("setSoWriteTimeout",
17612216155c3066236eb450f307983019f69a10303dKenny Root                                                         new Class<?>[] { Integer.TYPE });
1762615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        setSoWriteTimeout.invoke(client, 1);
1763615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
1764615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
1765615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        try {
176651cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom            // Add extra space to the write to exceed the send buffer
176751cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom            // size and cause the write to block.
176851cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom            final int extra = 1;
176951cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom            client.getOutputStream().write(new byte[sendBufferSize + extra]);
1770615225a35dbd838210270b282d1196deff643b51Brian Carlstrom            fail();
1771615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        } catch (SocketTimeoutException expected) {
1772615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        }
1773615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
1774615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        future.get();
1775615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        client.close();
1776615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        server.close();
1777615225a35dbd838210270b282d1196deff643b51Brian Carlstrom        c.close();
1778615225a35dbd838210270b282d1196deff643b51Brian Carlstrom    }
1779615225a35dbd838210270b282d1196deff643b51Brian Carlstrom
17809f7c676c1937bdafce079cf02a67ac121296a335Kenny Root    public void test_SSLSocket_reusedNpnSocket() throws Exception {
17819f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        if (StandardNames.IS_RI) {
17829f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            // RI does not support NPN/ALPN
17839f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            return;
17849f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        }
17859f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
17869f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        byte[] npnProtocols = new byte[] {
17879f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                8, 'h', 't', 't', 'p', '/', '1', '.', '1'
17889f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        };
17899f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
17909f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        final TestSSLContext c = TestSSLContext.create();
17919f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
17929f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
17939f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        // Reflection is used so this can compile on the RI
17949f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
17959f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        Class<?> actualClass = client.getClass();
17969f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        assertEquals(expectedClassName, actualClass.getName());
17979f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        Method setNpnProtocols = actualClass.getMethod("setNpnProtocols", byte[].class);
17989f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
17999f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
18009f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18019f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        // First connection with NPN set on client and server
18029f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        {
18039f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            setNpnProtocols.invoke(client, npnProtocols);
18049f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.connect(new InetSocketAddress(c.host, c.port));
18059f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18069f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            final SSLSocket server = (SSLSocket) c.serverSocket.accept();
18079f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            assertEquals(expectedClassName, server.getClass().getName());
18089f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            setNpnProtocols.invoke(server, npnProtocols);
18099f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18109f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            Future<Void> future = executor.submit(new Callable<Void>() {
18119f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                @Override
18129f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                public Void call() throws Exception {
18139f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                    server.startHandshake();
18149f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                    return null;
18159f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                }
18169f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            });
18179f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.startHandshake();
18189f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18199f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            future.get();
18209f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.close();
18219f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            server.close();
18229f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        }
18239f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18249f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        // Second connection with client NPN already set on the SSL context, but
18259f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        // without server NPN set.
18269f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        {
18279f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            SSLServerSocket serverSocket = (SSLServerSocket) c.serverContext
18289f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                    .getServerSocketFactory().createServerSocket(0);
18299f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            InetAddress host = InetAddress.getLocalHost();
18309f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            int port = serverSocket.getLocalPort();
18319f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18329f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
18339f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.connect(new InetSocketAddress(host, port));
18349f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18359f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            final SSLSocket server = (SSLSocket) serverSocket.accept();
18369f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18379f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            Future<Void> future = executor.submit(new Callable<Void>() {
18389f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                @Override
18399f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                public Void call() throws Exception {
18409f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                    server.startHandshake();
18419f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                    return null;
18429f7c676c1937bdafce079cf02a67ac121296a335Kenny Root                }
18439f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            });
18449f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.startHandshake();
18459f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18469f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            future.get();
18479f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            client.close();
18489f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            server.close();
18499f7c676c1937bdafce079cf02a67ac121296a335Kenny Root            serverSocket.close();
18509f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        }
18519f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
18529f7c676c1937bdafce079cf02a67ac121296a335Kenny Root        c.close();
18539f7c676c1937bdafce079cf02a67ac121296a335Kenny Root    }
18549f7c676c1937bdafce079cf02a67ac121296a335Kenny Root
185584f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom    public void test_SSLSocket_interrupt() throws Exception {
185636f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        test_SSLSocket_interrupt_case(true, true);
185736f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        test_SSLSocket_interrupt_case(true, false);
185836f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        test_SSLSocket_interrupt_case(false, true);
1859d255af15f749d98cf06fe72fdf46ccf3988f10d2Narayan Kamath        test_SSLSocket_interrupt_case(false, false);
186084f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom    }
186184f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom
186236f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom    private void test_SSLSocket_interrupt_case(boolean readUnderlying, boolean closeUnderlying)
186384f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom            throws Exception {
186436f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
186536f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        ServerSocket listening = new ServerSocket(0);
186636f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
186736f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
186836f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        Socket server = listening.accept();
186936f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
187036f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
187136f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        Socket clientWrapping = sf.createSocket(underlying, null, -1, true);
187236f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
187336f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        final Socket toRead = (readUnderlying) ? underlying : clientWrapping;
187436f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        final Socket toClose = (closeUnderlying) ? underlying : clientWrapping;
187536f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
1876783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        ExecutorService executor = Executors.newSingleThreadExecutor();
1877783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> future = executor.submit(new Callable<Void>() {
1878783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
1879783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                Thread.sleep(1 * 1000);
1880783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                toClose.close();
1881783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
188284f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom            }
1883783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        });
1884783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
188584f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom        try {
188636f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom            toRead.setSoTimeout(5 * 1000);
188784f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom            toRead.getInputStream().read();
188884f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom            fail();
188984f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom        } catch (SocketTimeoutException e) {
189084f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom            throw e;
189184f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom        } catch (SocketException expected) {
189284f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom        }
1893783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        future.get();
189436f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom
189536f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        server.close();
189636f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        underlying.close();
189736f1c15a1cb2e66b8852ea51f7a82c4ccc9ac886Brian Carlstrom        listening.close();
1898783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom    }
1899783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
1900783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom    /**
1901783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom     * b/7014266 Test to confirm that an SSLSocket.close() on one
19026ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root     * thread will interrupt another thread blocked reading on the same
1903783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom     * socket.
1904783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom     */
1905783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom    public void test_SSLSocket_interrupt_read() throws Exception {
19069ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro        final int readingTimeoutMillis = 5000;
1907783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        TestSSLContext c = TestSSLContext.create();
1908783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        final Socket underlying = new Socket(c.host, c.port);
1909783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        final SSLSocket wrapping = (SSLSocket)
1910783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                c.clientContext.getSocketFactory().createSocket(underlying,
1911783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                                                                c.host.getHostName(),
1912783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                                                                c.port,
1913783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                                                                false);
19146ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root
19156ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        // Create our own thread group so we can inspect the stack state later.
19166ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        final ThreadGroup clientGroup = new ThreadGroup("client");
19176ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
19186ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            @Override
19196ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            public Thread newThread(Runnable r) {
19206ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                return new Thread(clientGroup, r);
19216ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            }
19226ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        });
19236ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root
1924783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        Future<Void> clientFuture = executor.submit(new Callable<Void>() {
1925783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            @Override public Void call() throws Exception {
1926783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                try {
1927783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    wrapping.startHandshake();
1928783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    assertFalse(StandardNames.IS_RI);
19299ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                    wrapping.setSoTimeout(readingTimeoutMillis);
1930783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                    assertEquals(-1, wrapping.getInputStream().read());
1931783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                } catch (Exception e) {
19329ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                    if (!StandardNames.IS_RI) {
19339ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                        throw e;
19349ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                    }
1935783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                }
1936783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom                return null;
1937783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom            }
1938783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        });
1939783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        executor.shutdown();
1940783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom
1941783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        SSLSocket server = (SSLSocket) c.serverSocket.accept();
1942783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        server.startHandshake();
19436ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root
19446ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        /*
19456ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root         * Wait for the client to at least be in the "read" method before
19466ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root         * calling close()
19476ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root         */
19486ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        Thread[] threads = new Thread[1];
19496ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        clientGroup.enumerate(threads);
19506ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        if (threads[0] != null) {
19516ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            boolean clientInRead = false;
19526ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            while (!clientInRead) {
19536ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                StackTraceElement[] elements = threads[0].getStackTrace();
19546ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                for (StackTraceElement element : elements) {
19556ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                    if ("read".equals(element.getMethodName())) {
19569ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                        // The client might be executing "read" but still not have reached the
19579ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                        // point in which it's blocked reading. This is causing flakiness
19589ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                        // (b/24367646). Delaying for a fraction of the timeout.
19599ada7e3ea3c181bf43a20481c15a5715d129d7cbSergio Giro                        Thread.sleep(1000);
19606ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                        clientInRead = true;
19616ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                        break;
19626ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                    }
19636ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root                }
19646ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root            }
19656ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root        }
19666ced3e6c746117d4145515a11762cff3de3c1fa9Kenny Root
1967783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        wrapping.close();
1968783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        clientFuture.get();
1969783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom        server.close();
197084f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom    }
197184f161268b8ae93a9046c40ca8381aa92148f2f6Brian Carlstrom
19720c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    public void test_TestSSLSocketPair_create() {
197317c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom        TestSSLSocketPair test = TestSSLSocketPair.create();
1974ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(test.c);
1975ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(test.server);
1976ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(test.client);
1977bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        assertTrue(test.server.isConnected());
1978bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        assertTrue(test.client.isConnected());
19795f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertFalse(test.server.isClosed());
19805f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        assertFalse(test.client.isClosed());
1981ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(test.server.getSession());
1982ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom        assertNotNull(test.client.getSession());
19830c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertTrue(test.server.getSession().isValid());
19840c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertTrue(test.client.getSession().isValid());
1985f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        test.close();
1986ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom    }
1987bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
1988b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    public void test_SSLSocket_ClientHello_record_size() throws Exception {
19890007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // This test checks the size of ClientHello of the default SSLSocket. TLS/SSL handshakes
19900007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // with older/unpatched F5/BIG-IP appliances are known to stall and time out when
19910007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // the fragment containing ClientHello is between 256 and 511 (inclusive) bytes long.
1992b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        SSLContext sslContext = SSLContext.getInstance("TLS");
1993b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        sslContext.init(null, null, null);
1994b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
1995b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        sslSocketFactory = new DelegatingSSLSocketFactory(sslSocketFactory) {
1996b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            @Override
199726f2557b26ea23326178f029e07a8adbfc27d0bfNeil Fuller            protected SSLSocket configureSocket(SSLSocket socket) {
1998b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                // Enable SNI extension on the socket (this is typically enabled by default)
1999b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                // to increase the size of ClientHello.
2000b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                try {
2001b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    Method setHostname =
2002b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                            socket.getClass().getMethod("setHostname", String.class);
2003b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    setHostname.invoke(socket, "sslsockettest.androidcts.google.com");
2004b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                } catch (NoSuchMethodException ignored) {
2005b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                } catch (Exception e) {
2006b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    throw new RuntimeException("Failed to enable SNI", e);
2007b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                }
2008b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2009b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                // Enable Session Tickets extension on the socket (this is typically enabled
2010b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                // by default) to increase the size of ClientHello.
2011b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                try {
2012b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    Method setUseSessionTickets =
2013b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                            socket.getClass().getMethod(
2014b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                                    "setUseSessionTickets", boolean.class);
2015b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    setUseSessionTickets.invoke(socket, true);
2016b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                } catch (NoSuchMethodException ignored) {
2017b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                } catch (Exception e) {
2018b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    throw new RuntimeException("Failed to enable Session Tickets", e);
2019b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                }
202026f2557b26ea23326178f029e07a8adbfc27d0bfNeil Fuller                return socket;
2021b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2022b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        };
2023b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2024b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        TlsRecord firstReceivedTlsRecord = captureTlsHandshakeFirstTlsRecord(sslSocketFactory);
2025b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals("TLS record type", TlsProtocols.HANDSHAKE, firstReceivedTlsRecord.type);
2026b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        HandshakeMessage handshakeMessage = HandshakeMessage.read(
2027b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                new DataInputStream(new ByteArrayInputStream(firstReceivedTlsRecord.fragment)));
2028b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals("HandshakeMessage type",
2029b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                HandshakeMessage.TYPE_CLIENT_HELLO, handshakeMessage.type);
2030b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        int fragmentLength = firstReceivedTlsRecord.fragment.length;
2031b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        if ((fragmentLength >= 256) && (fragmentLength <= 511)) {
2032b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            fail("Fragment containing ClientHello is of dangerous length: "
2033b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    + fragmentLength + " bytes");
2034b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }
2035b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2036b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2037b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    public void test_SSLSocket_ClientHello_cipherSuites() throws Exception {
2038b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
2039b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            @Override
2040b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            public void run(SSLSocketFactory sslSocketFactory) throws Exception {
2041b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
204281885494e46596c796cdcb5037b91d92915b65a7Kenny Root                final String[] cipherSuites;
204381885494e46596c796cdcb5037b91d92915b65a7Kenny Root
204481885494e46596c796cdcb5037b91d92915b65a7Kenny Root                // RFC 5746 allows you to send an empty "renegotiation_info" extension *or*
204581885494e46596c796cdcb5037b91d92915b65a7Kenny Root                // a special signaling cipher suite. The TLS API has no way to check or
204681885494e46596c796cdcb5037b91d92915b65a7Kenny Root                // indicate that a certain TLS extension should be used.
204781885494e46596c796cdcb5037b91d92915b65a7Kenny Root                HelloExtension renegotiationInfoExtension = clientHello.findExtensionByType(
204881885494e46596c796cdcb5037b91d92915b65a7Kenny Root                        HelloExtension.TYPE_RENEGOTIATION_INFO);
204981885494e46596c796cdcb5037b91d92915b65a7Kenny Root                if (renegotiationInfoExtension != null &&
205081885494e46596c796cdcb5037b91d92915b65a7Kenny Root                        renegotiationInfoExtension.data.length == 1 &&
205181885494e46596c796cdcb5037b91d92915b65a7Kenny Root                        renegotiationInfoExtension.data[0] == 0) {
205281885494e46596c796cdcb5037b91d92915b65a7Kenny Root                    cipherSuites = new String[clientHello.cipherSuites.size() + 1];
205381885494e46596c796cdcb5037b91d92915b65a7Kenny Root                    cipherSuites[clientHello.cipherSuites.size()] =
205481885494e46596c796cdcb5037b91d92915b65a7Kenny Root                            StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION;
205581885494e46596c796cdcb5037b91d92915b65a7Kenny Root                } else {
205681885494e46596c796cdcb5037b91d92915b65a7Kenny Root                    cipherSuites = new String[clientHello.cipherSuites.size()];
205781885494e46596c796cdcb5037b91d92915b65a7Kenny Root                }
205881885494e46596c796cdcb5037b91d92915b65a7Kenny Root
2059b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                for (int i = 0; i < clientHello.cipherSuites.size(); i++) {
2060b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    CipherSuite cipherSuite = clientHello.cipherSuites.get(i);
2061b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    cipherSuites[i] = cipherSuite.getAndroidName();
2062b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                }
2063b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                StandardNames.assertDefaultCipherSuites(cipherSuites);
2064b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2065b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }, getSSLSocketFactoriesToTest());
2066b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2067b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2068c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root    public void test_SSLSocket_ClientHello_supportedCurves() throws Exception {
2069c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root        ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
2070c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root            @Override
2071c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root            public void run(SSLSocketFactory sslSocketFactory) throws Exception {
2072c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
2073c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root
2074c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                EllipticCurvesHelloExtension ecExtension = (EllipticCurvesHelloExtension)
2075c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                        clientHello.findExtensionByType(HelloExtension.TYPE_ELLIPTIC_CURVES);
2076c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                final String[] supportedCurves;
2077c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                if (ecExtension == null) {
2078c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                    supportedCurves = new String[0];
2079c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                } else {
2080c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                    assertTrue(ecExtension.wellFormed);
2081c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                    supportedCurves = new String[ecExtension.supported.size()];
2082c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                    for (int i = 0; i < ecExtension.supported.size(); i++) {
2083c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                        EllipticCurve curve = ecExtension.supported.get(i);
2084c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                        supportedCurves[i] = curve.toString();
2085c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                    }
2086c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                }
2087c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root
2088c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root                StandardNames.assertDefaultEllipticCurves(supportedCurves);
2089c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root            }
2090c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root        }, getSSLSocketFactoriesToTest());
2091c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root    }
2092c97ba7f9b6a7621a55b95a7d5fd00cdffd6f09d5Kenny Root
2093b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    public void test_SSLSocket_ClientHello_clientProtocolVersion() throws Exception {
2094b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
2095b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            @Override
2096b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            public void run(SSLSocketFactory sslSocketFactory) throws Exception {
2097b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
2098b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                assertEquals(TlsProtocolVersion.TLSv1_2, clientHello.clientVersion);
2099b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2100b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }, getSSLSocketFactoriesToTest());
2101b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2102b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2103b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    public void test_SSLSocket_ClientHello_compressionMethods() throws Exception {
2104b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
2105b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            @Override
2106b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            public void run(SSLSocketFactory sslSocketFactory) throws Exception {
2107b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
2108b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                assertEquals(Arrays.asList(CompressionMethod.NULL), clientHello.compressionMethods);
2109b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2110b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }, getSSLSocketFactoriesToTest());
2111b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2112b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2113b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    public void test_SSLSocket_ClientHello_SNI() throws Exception {
2114b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
2115b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            @Override
2116b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            public void run(SSLSocketFactory sslSocketFactory) throws Exception {
2117b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
2118b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                ServerNameHelloExtension sniExtension = (ServerNameHelloExtension)
2119b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                        clientHello.findExtensionByType(HelloExtension.TYPE_SERVER_NAME);
2120b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                assertNotNull(sniExtension);
2121b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                assertEquals(Arrays.asList("localhost.localdomain"), sniExtension.hostnames);
2122b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2123b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }, getSSLSocketFactoriesToTest());
2124b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2125b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2126b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    private List<Pair<String, SSLSocketFactory>> getSSLSocketFactoriesToTest()
2127b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            throws NoSuchAlgorithmException, KeyManagementException {
2128b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        List<Pair<String, SSLSocketFactory>> result =
2129b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                new ArrayList<Pair<String, SSLSocketFactory>>();
2130b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        result.add(Pair.of("default", (SSLSocketFactory) SSLSocketFactory.getDefault()));
2131b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        for (String sslContextProtocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
2132b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            SSLContext sslContext = SSLContext.getInstance(sslContextProtocol);
2133b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            if (StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT.equals(sslContextProtocol)) {
2134b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                continue;
2135b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            }
2136b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            sslContext.init(null, null, null);
2137b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            result.add(Pair.of(
2138b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    "SSLContext(\"" + sslContext.getProtocol() + "\")",
2139b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    sslContext.getSocketFactory()));
2140b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        }
2141b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        return result;
2142b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2143b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2144b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    private ClientHello captureTlsHandshakeClientHello(SSLSocketFactory sslSocketFactory)
2145b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            throws Exception {
2146b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        TlsRecord record = captureTlsHandshakeFirstTlsRecord(sslSocketFactory);
2147b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals("TLS record type", TlsProtocols.HANDSHAKE, record.type);
2148b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ByteArrayInputStream fragmentIn = new ByteArrayInputStream(record.fragment);
2149b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        HandshakeMessage handshakeMessage = HandshakeMessage.read(new DataInputStream(fragmentIn));
2150b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals("HandshakeMessage type",
2151b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                HandshakeMessage.TYPE_CLIENT_HELLO, handshakeMessage.type);
2152b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        // Assert that the fragment does not contain any more messages
2153b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals(0, fragmentIn.available());
2154b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2155b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        return (ClientHello) handshakeMessage;
2156b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2157b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2158b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    private TlsRecord captureTlsHandshakeFirstTlsRecord(SSLSocketFactory sslSocketFactory)
2159b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            throws Exception {
2160b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        byte[] firstReceivedChunk = captureTlsHandshakeFirstTransmittedChunkBytes(sslSocketFactory);
2161b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        ByteArrayInputStream firstReceivedChunkIn = new ByteArrayInputStream(firstReceivedChunk);
2162b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        TlsRecord record = TlsRecord.read(new DataInputStream(firstReceivedChunkIn));
2163b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        // Assert that the chunk does not contain any more data
2164b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        assertEquals(0, firstReceivedChunkIn.available());
2165b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2166b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin        return record;
2167b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    }
2168b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin
2169b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin    private byte[] captureTlsHandshakeFirstTransmittedChunkBytes(
2170b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            final SSLSocketFactory sslSocketFactory) throws Exception {
21710007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // Since there's no straightforward way to obtain a ClientHello from SSLSocket, this test
21720007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // does the following:
21730007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // 1. Creates a listening server socket (a plain one rather than a TLS/SSL one).
21740007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // 2. Creates a client SSLSocket, which connects to the server socket and initiates the
21750007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        //    TLS/SSL handshake.
21760007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // 3. Makes the server socket accept an incoming connection on the server socket, and reads
21770007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        //    the first chunk of data received. This chunk is assumed to be the ClientHello.
21780007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // NOTE: Steps 2 and 3 run concurrently.
21790007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        ServerSocket listeningSocket = null;
21800007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        ExecutorService executorService = Executors.newFixedThreadPool(2);
21810007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin
21820007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // Some Socket operations are not interruptible via Thread.interrupt for some reason. To
21830007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        // work around, we unblock these sockets using Socket.close.
21840007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        final Socket[] sockets = new Socket[2];
21850007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        try {
21860007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            // 1. Create the listening server socket.
21870007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            listeningSocket = ServerSocketFactory.getDefault().createServerSocket(0);
21880007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            final ServerSocket finalListeningSocket = listeningSocket;
21890007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            // 2. (in background) Wait for an incoming connection and read its first chunk.
21900007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            final Future<byte[]> readFirstReceivedChunkFuture =
21910007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    executorService.submit(new Callable<byte[]>() {
21920007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        @Override
21930007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        public byte[] call() throws Exception {
21940007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            Socket socket = finalListeningSocket.accept();
21950007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            sockets[1] = socket;
21960007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            try {
21970007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                byte[] buffer = new byte[64 * 1024];
21980007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                int bytesRead = socket.getInputStream().read(buffer);
21990007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                if (bytesRead == -1) {
22000007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                    throw new EOFException("Failed to read anything");
22010007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                }
22020007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                                return Arrays.copyOf(buffer, bytesRead);
22030007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            } finally {
220427088efe0caca697e257e08d41387af8130364e0Kenny Root                                closeQuietly(socket);
22050007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            }
22060007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        }
22070007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    });
22080007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin
22090007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            // 3. Create a client socket, connect it to the server socket, and start the TLS/SSL
22100007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            //    handshake.
22110007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            executorService.submit(new Callable<Void>() {
22120007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                @Override
22130007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                public Void call() throws Exception {
2214b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                    Socket client = new Socket();
22150007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    sockets[0] = client;
22160007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    try {
22170007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        client.connect(finalListeningSocket.getLocalSocketAddress());
22180007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        // Initiate the TLS/SSL handshake which is expected to fail as soon as the
22190007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        // server socket receives a ClientHello.
22200007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        try {
2221b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
2222b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                                    client,
2223b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                                    "localhost.localdomain",
2224b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                                    finalListeningSocket.getLocalPort(),
2225b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                                    true);
2226b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin                            sslSocket.startHandshake();
22270007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            fail();
22280007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                            return null;
22290007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        } catch (IOException expected) {}
22300007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                        return null;
22310007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    } finally {
223227088efe0caca697e257e08d41387af8130364e0Kenny Root                        closeQuietly(client);
22330007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                    }
22340007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                }
22350007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            });
22360007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin
22370007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            // Wait for the ClientHello to arrive
2238b1fe85cc976c676eb50ff886596c93e04fd71d82Alex Klyubin            return readFirstReceivedChunkFuture.get(10, TimeUnit.SECONDS);
22390007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        } finally {
22400007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            executorService.shutdownNow();
224127088efe0caca697e257e08d41387af8130364e0Kenny Root            closeQuietly(listeningSocket);
224227088efe0caca697e257e08d41387af8130364e0Kenny Root            closeQuietly(sockets[0]);
224327088efe0caca697e257e08d41387af8130364e0Kenny Root            closeQuietly(sockets[1]);
22440007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
22450007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin                fail("Timed out while waiting for the test to shut down");
22460007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin            }
22470007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin        }
22480007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin    }
22490007cf607af1bcc958b584242bb5d8d191ee22c4Alex Klyubin
22504e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath    // http://b/18428603
22514e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath    public void test_SSLSocket_getPortWithSNI() throws Exception {
22524e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath        TestSSLContext context = TestSSLContext.create();
22534e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath
22544e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath        SSLSocket client = null;
22554e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath        try {
22564e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            client = (SSLSocket) context.clientContext.getSocketFactory().createSocket();
22574e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            client.connect(new InetSocketAddress(context.host, context.port));
22584e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            try {
22594e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath                // This is crucial to reproducing issue 18428603.
22604e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath                Method setHostname = client.getClass().getMethod("setHostname", String.class);
22614e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath                setHostname.invoke(client, "sslsockettest.androidcts.google.com");
22624e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            } catch (NoSuchMethodException ignored) {
22634e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            }
22644e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath
22654e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            assertTrue(client.getPort() > 0);
22664e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath        } finally {
22674e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            client.close();
22684e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath            context.close();
22694e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath        }
22704e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath    }
22714e05c844ea6c6359345b66120182d4d86fc9e22bNarayan Kamath
2272b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root    public void test_SSLSocket_SNIHostName() throws Exception {
2273b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        TestSSLContext c = TestSSLContext.create();
2274b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2275b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
2276b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        SSLParameters clientParams = client.getSSLParameters();
2277b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        clientParams.setServerNames(Collections.singletonList(
2278b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root                (SNIServerName) new SNIHostName("www.example.com")));
2279b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        client.setSSLParameters(clientParams);
2280b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2281b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        SSLParameters serverParams = c.serverSocket.getSSLParameters();
2282b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        serverParams.setSNIMatchers(Collections.singletonList(
2283b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root                SNIHostName.createSNIMatcher("www\\.example\\.com")));
2284b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        c.serverSocket.setSSLParameters(serverParams);
2285b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2286b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        client.connect(new InetSocketAddress(c.host, c.port));
2287b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        final SSLSocket server = (SSLSocket) c.serverSocket.accept();
2288b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2289b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
2290b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        Future<Void> future = executor.submit(new Callable<Void>() {
2291b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root            @Override public Void call() throws Exception {
2292b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root                client.startHandshake();
2293b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root                return null;
2294b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root            }
2295b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        });
2296b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        executor.shutdown();
2297b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        server.startHandshake();
2298b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2299b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        SSLSession serverSession = server.getSession();
2300f4c5da45b0c9ff0992e6d29c89953ed3ae820843Neil Fuller        assertTrue(serverSession instanceof ExtendedSSLSession);
2301b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        ExtendedSSLSession extendedServerSession = (ExtendedSSLSession) serverSession;
2302b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        List<SNIServerName> requestedNames = extendedServerSession.getRequestedServerNames();
2303b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        assertNotNull(requestedNames);
2304b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        assertEquals(1, requestedNames.size());
2305b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        SNIServerName serverName = requestedNames.get(0);
2306ab1a6e203cb03add037f1c2e48e1a8aabcbdfc55Kenny Root        assertEquals(StandardConstants.SNI_HOST_NAME, serverName.getType());
2307b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        assertTrue(serverName instanceof SNIHostName);
2308b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        SNIHostName serverHostName = (SNIHostName) serverName;
2309b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root        assertEquals("www.example.com", serverHostName.getAsciiName());
2310b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root    }
2311b96141a0e46ce6e769c70565bec7ec3fdd58d717Kenny Root
2312e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root    public void test_SSLSocket_sendsTlsFallbackScsv_Fallback_Success() throws Exception {
2313e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        TestSSLContext context = TestSSLContext.create();
2314e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2315e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final SSLSocket client = (SSLSocket)
2316e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            context.clientContext.getSocketFactory().createSocket(context.host, context.port);
2317e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final SSLSocket server = (SSLSocket) context.serverSocket.accept();
2318e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2319e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final String[] serverCipherSuites = server.getEnabledCipherSuites();
2320e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
2321e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
2322e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
2323e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2324e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        ExecutorService executor = Executors.newFixedThreadPool(2);
2325e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        Future<Void> s = executor.submit(new Callable<Void>() {
23262216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2327e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                public Void call() throws Exception {
2328e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    server.setEnabledProtocols(new String[] { "TLSv1.2" });
2329e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    server.setEnabledCipherSuites(serverCipherSuites);
2330e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    server.startHandshake();
2331e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    return null;
2332e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                }
2333e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            });
2334e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        Future<Void> c = executor.submit(new Callable<Void>() {
23352216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2336e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                public Void call() throws Exception {
2337e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    client.setEnabledProtocols(new String[] { "TLSv1.2" });
2338e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    client.setEnabledCipherSuites(clientCipherSuites);
2339e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    client.startHandshake();
2340e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    return null;
2341e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                }
2342e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            });
2343e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        executor.shutdown();
2344e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2345e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        s.get();
2346e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        c.get();
2347e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        client.close();
2348e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        server.close();
2349e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        context.close();
2350e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root    }
2351e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2352bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller    // Confirms that communication without the TLS_FALLBACK_SCSV cipher works as it always did.
2353bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller    public void test_SSLSocket_sendsNoTlsFallbackScsv_Fallback_Success() throws Exception {
2354bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        TestSSLContext context = TestSSLContext.create();
2355bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
2356bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        final SSLSocket client = (SSLSocket)
2357bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller            context.clientContext.getSocketFactory().createSocket(context.host, context.port);
2358bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        final SSLSocket server = (SSLSocket) context.serverSocket.accept();
2359bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
2360bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        // Confirm absence of TLS_FALLBACK_SCSV.
2361bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        assertFalse(Arrays.asList(client.getEnabledCipherSuites())
2362bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                .contains(StandardNames.CIPHER_SUITE_FALLBACK));
2363bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
2364bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        ExecutorService executor = Executors.newFixedThreadPool(2);
2365bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        Future<Void> s = executor.submit(new Callable<Void>() {
23662216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2367bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                public Void call() throws Exception {
23688f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker                    server.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1" });
2369bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                    server.startHandshake();
2370bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                    return null;
2371bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                }
2372bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller            });
2373bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        Future<Void> c = executor.submit(new Callable<Void>() {
23742216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2375bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                public Void call() throws Exception {
23768f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker                    client.setEnabledProtocols(new String[] { "TLSv1.1" });
2377bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                    client.startHandshake();
2378bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                    return null;
2379bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller                }
2380bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller            });
2381bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        executor.shutdown();
2382bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
2383bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        s.get();
2384bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        c.get();
2385bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        client.close();
2386bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        server.close();
2387bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        context.close();
2388bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller    }
2389bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
239043e063b43daab0962554639dda272428a59f3c24Kenny Root    private static void assertInappropriateFallbackIsCause(Throwable cause) {
239143e063b43daab0962554639dda272428a59f3c24Kenny Root        assertTrue(cause.getMessage(), cause.getMessage().contains("inappropriate fallback")
239243e063b43daab0962554639dda272428a59f3c24Kenny Root                || cause.getMessage().contains("INAPPROPRIATE_FALLBACK"));
239343e063b43daab0962554639dda272428a59f3c24Kenny Root    }
239443e063b43daab0962554639dda272428a59f3c24Kenny Root
2395e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root    public void test_SSLSocket_sendsTlsFallbackScsv_InappropriateFallback_Failure() throws Exception {
2396e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        TestSSLContext context = TestSSLContext.create();
2397e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2398e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final SSLSocket client = (SSLSocket)
2399e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            context.clientContext.getSocketFactory().createSocket(context.host, context.port);
2400e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final SSLSocket server = (SSLSocket) context.serverSocket.accept();
2401e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2402e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final String[] serverCipherSuites = server.getEnabledCipherSuites();
2403bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller
2404bc1ea6573c76663718d441f7b0b849a91f3eefbdNeil Fuller        // Add TLS_FALLBACK_SCSV
2405e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
2406e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
2407e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
2408e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2409e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        ExecutorService executor = Executors.newFixedThreadPool(2);
2410e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        Future<Void> s = executor.submit(new Callable<Void>() {
24112216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2412e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                public Void call() throws Exception {
24138f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker                    server.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1" });
2414e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    server.setEnabledCipherSuites(serverCipherSuites);
2415e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    try {
2416e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                        server.startHandshake();
2417e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                        fail("Should result in inappropriate fallback");
2418e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    } catch (SSLHandshakeException expected) {
2419cce4d86d447d0e86f94035dd0285726c4025fae6Kenny Root                        Throwable cause = expected.getCause();
2420cce4d86d447d0e86f94035dd0285726c4025fae6Kenny Root                        assertEquals(SSLProtocolException.class, cause.getClass());
242143e063b43daab0962554639dda272428a59f3c24Kenny Root                        assertInappropriateFallbackIsCause(cause);
2422e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    }
2423e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    return null;
2424e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                }
2425e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            });
2426e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        Future<Void> c = executor.submit(new Callable<Void>() {
24272216155c3066236eb450f307983019f69a10303dKenny Root                @Override
2428e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                public Void call() throws Exception {
24298f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker                    client.setEnabledProtocols(new String[] { "TLSv1" });
2430e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    client.setEnabledCipherSuites(clientCipherSuites);
2431e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    try {
2432e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                        client.startHandshake();
2433e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                        fail("Should receive TLS alert inappropriate fallback");
2434e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    } catch (SSLHandshakeException expected) {
2435cce4d86d447d0e86f94035dd0285726c4025fae6Kenny Root                        Throwable cause = expected.getCause();
2436cce4d86d447d0e86f94035dd0285726c4025fae6Kenny Root                        assertEquals(SSLProtocolException.class, cause.getClass());
243743e063b43daab0962554639dda272428a59f3c24Kenny Root                        assertInappropriateFallbackIsCause(cause);
2438e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    }
2439e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                    return null;
2440e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root                }
2441e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root            });
2442e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        executor.shutdown();
2443e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
2444e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        s.get();
2445e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        c.get();
2446e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        client.close();
2447e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        server.close();
244858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        context.close();
244958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root    }
245058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
245158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root    public void test_SSLSocket_ClientGetsAlertDuringHandshake_HasGoodExceptionMessage()
245258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            throws Exception {
245358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        TestSSLContext context = TestSSLContext.create();
245458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
245558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        final ServerSocket listener = ServerSocketFactory.getDefault().createServerSocket(0);
245658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(
245758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                context.host, listener.getLocalPort());
245858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        final Socket server = listener.accept();
245958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
246058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        ExecutorService executor = Executors.newFixedThreadPool(2);
246158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        Future<Void> c = executor.submit(new Callable<Void>() {
24622216155c3066236eb450f307983019f69a10303dKenny Root            @Override
246358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            public Void call() throws Exception {
246458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                try {
246558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    client.startHandshake();
246658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    fail("Should receive handshake exception");
246758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                } catch (SSLHandshakeException expected) {
246858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    assertFalse(expected.getMessage().contains("SSL_ERROR_ZERO_RETURN"));
246958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    assertFalse(expected.getMessage().contains("You should never see this."));
247058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                }
247158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                return null;
247258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            }
247358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        });
247458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        Future<Void> s = executor.submit(new Callable<Void>() {
24752216155c3066236eb450f307983019f69a10303dKenny Root            @Override
247658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            public Void call() throws Exception {
247758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Wait until the client sends something.
247858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                byte[] scratch = new byte[8192];
247958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                server.getInputStream().read(scratch);
248058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
248158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Write a bogus TLS alert:
248258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // TLSv1.2 Record Layer: Alert (Level: Warning, Description: Protocol Version)
248358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                server.getOutputStream().write(new byte[] {
248458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x46
248558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                });
248658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
248758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // TLSv1.2 Record Layer: Alert (Level: Warning, Description: Close Notify)
248858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                server.getOutputStream().write(new byte[] {
248958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00
249058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                });
249158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
249258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                return null;
249358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            }
249458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        });
249558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
249658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
249758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        executor.shutdown();
249858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        c.get(5, TimeUnit.SECONDS);
249958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        s.get(5, TimeUnit.SECONDS);
250058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        client.close();
250158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        server.close();
250258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        listener.close();
250358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        context.close();
250458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root    }
250558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
250658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root    public void test_SSLSocket_ServerGetsAlertDuringHandshake_HasGoodExceptionMessage()
250758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            throws Exception {
250858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        TestSSLContext context = TestSSLContext.create();
250958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
251058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        final Socket client = SocketFactory.getDefault().createSocket(context.host, context.port);
251158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        final SSLSocket server = (SSLSocket) context.serverSocket.accept();
251258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
251358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        ExecutorService executor = Executors.newFixedThreadPool(2);
251458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        Future<Void> s = executor.submit(new Callable<Void>() {
25152216155c3066236eb450f307983019f69a10303dKenny Root            @Override
251658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            public Void call() throws Exception {
251758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                try {
251858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    server.startHandshake();
251958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    fail("Should receive handshake exception");
252058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                } catch (SSLHandshakeException expected) {
252158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    assertFalse(expected.getMessage().contains("SSL_ERROR_ZERO_RETURN"));
252258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                    assertFalse(expected.getMessage().contains("You should never see this."));
252358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                }
252458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                return null;
252558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            }
252658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        });
252758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        Future<Void> c = executor.submit(new Callable<Void>() {
25282216155c3066236eb450f307983019f69a10303dKenny Root            @Override
252958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            public Void call() throws Exception {
253058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Send bogus ClientHello:
253158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // TLSv1.2 Record Layer: Handshake Protocol: Client Hello
253258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                client.getOutputStream().write(new byte[] {
253358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x16, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0xb9,
253458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0xb5, (byte) 0x03,
253558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x03, (byte) 0x5a, (byte) 0x31, (byte) 0xba, (byte) 0x44,
253658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x24, (byte) 0xfd, (byte) 0xf0, (byte) 0x56, (byte) 0x46,
253758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xea, (byte) 0xee, (byte) 0x1c, (byte) 0x62, (byte) 0x8f,
253858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x18, (byte) 0x04, (byte) 0xbd, (byte) 0x1c, (byte) 0xbc,
253958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xbf, (byte) 0x6d, (byte) 0x84, (byte) 0x12, (byte) 0xe9,
254058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x94, (byte) 0xf5, (byte) 0x1c, (byte) 0x15, (byte) 0x3e,
254158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x79, (byte) 0x01, (byte) 0xe2, (byte) 0x00, (byte) 0x00,
254258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x28, (byte) 0xc0, (byte) 0x2b, (byte) 0xc0, (byte) 0x2c,
254358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xc0, (byte) 0x2f, (byte) 0xc0, (byte) 0x30, (byte) 0x00,
254458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x9e, (byte) 0x00, (byte) 0x9f, (byte) 0xc0, (byte) 0x09,
254558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xc0, (byte) 0x0a, (byte) 0xc0, (byte) 0x13, (byte) 0xc0,
254658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x14, (byte) 0x00, (byte) 0x33, (byte) 0x00, (byte) 0x39,
254758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xc0, (byte) 0x07, (byte) 0xc0, (byte) 0x11, (byte) 0x00,
254858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x9c, (byte) 0x00, (byte) 0x9d, (byte) 0x00, (byte) 0x2f,
254958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x35, (byte) 0x00, (byte) 0x05, (byte) 0x00,
255058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0xff, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x64,
255158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x04, (byte) 0x03,
255258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x0a,
255358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x32, (byte) 0x00,
255458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x0e, (byte) 0x00, (byte) 0x0d, (byte) 0x00, (byte) 0x19,
255558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x0c, (byte) 0x00,
255658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x18, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x0a,
255758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x16, (byte) 0x00, (byte) 0x17, (byte) 0x00,
255858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x08, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x07,
255958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x15, (byte) 0x00,
256058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x12,
256158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x00,
256258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0f,
256358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x11, (byte) 0x00,
256458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x0d, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x1e,
256558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x06, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x06,
256658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x03, (byte) 0x05, (byte) 0x01, (byte) 0x05, (byte) 0x02,
256758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x05, (byte) 0x03, (byte) 0x04, (byte) 0x01, (byte) 0x04,
256858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x03, (byte) 0x01,
256958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x03, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x02,
257058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x03,
257158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                });
257258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
257358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Wait until the server sends something.
257458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                byte[] scratch = new byte[8192];
257558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                client.getInputStream().read(scratch);
257658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
257758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Write a bogus TLS alert:
257858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // TLSv1.2 Record Layer: Alert (Level: Warning, Description:
257958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Protocol Version)
258058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                client.getOutputStream().write(new byte[] {
258158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x46
258258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                });
258358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
258458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // TLSv1.2 Record Layer: Alert (Level: Warning, Description:
258558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                // Close Notify)
258658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                client.getOutputStream().write(new byte[] {
258758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                        0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00
258858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                });
258958d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
259058d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root                return null;
259158d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root            }
259258d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        });
259358d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root
259458d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        executor.shutdown();
259558d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        c.get(5, TimeUnit.SECONDS);
259658d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        s.get(5, TimeUnit.SECONDS);
259758d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        client.close();
259858d0df7981667d3add1b94c57eb9d7e1b29dc2b1Kenny Root        server.close();
2599e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root        context.close();
2600e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root    }
2601e6a6e935e98f426c7000b2bf4086f87101f4441cKenny Root
26028f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker    public void test_SSLSocket_SSLv3Unsupported() throws Exception {
26038f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker        TestSSLContext context = TestSSLContext.create();
26048f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker
26058f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker        final SSLSocket client = (SSLSocket)
26068f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker            context.clientContext.getSocketFactory().createSocket();
26078f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker
2608621cb842e7656a5baa594a0d1f2a7a20fae270a4Kenny Root        // For app compatibility, SSLv3 is stripped out when setting only.
2609621cb842e7656a5baa594a0d1f2a7a20fae270a4Kenny Root        client.setEnabledProtocols(new String[] {"SSLv3"});
2610621cb842e7656a5baa594a0d1f2a7a20fae270a4Kenny Root        assertEquals(0, client.getEnabledProtocols().length);
26118f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker
26128f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker        try {
26138f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker            client.setEnabledProtocols(new String[] {"SSL"});
26148f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker            fail("SSLSocket should not support SSL protocol");
26158f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker        } catch (IllegalArgumentException expected) {
26168f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker        }
26178f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker    }
26188f2073552a3aa97ce95f8380f5cab1742d77de91Chad Brubaker
2619846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian    // We modified the toString() of SSLSocket, and it's based on the output
2620846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian    // of Socket.toString(), so we want to make sure that a change in
2621846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian    // Socket.toString() doesn't cause us to output nonsense.
2622846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian    public void test_SSLSocket_toString() throws Exception {
2623846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian        // The actual implementation from a security provider might do something
2624846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian        // special for its toString(), so we create our own implementation
2625846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian        SSLSocket socket = new SSLSocket() {
2626846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public String[] getSupportedCipherSuites() { return new String[0]; }
2627846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public String[] getEnabledCipherSuites() { return new String[0]; }
2628846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setEnabledCipherSuites(String[] strings) { }
2629846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public String[] getSupportedProtocols() { return new String[0]; }
2630846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public String[] getEnabledProtocols() { return new String[0]; }
2631846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setEnabledProtocols(String[] strings) { }
2632846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public SSLSession getSession() { return null; }
2633846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void addHandshakeCompletedListener(
2634846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian                    HandshakeCompletedListener handshakeCompletedListener) { }
2635846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void removeHandshakeCompletedListener(
2636846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian                    HandshakeCompletedListener handshakeCompletedListener) { }
2637846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void startHandshake() throws IOException { }
2638846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setUseClientMode(boolean b) { }
2639846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public boolean getUseClientMode() { return false; }
2640846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setNeedClientAuth(boolean b) { }
2641846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public boolean getNeedClientAuth() { return false; }
2642846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setWantClientAuth(boolean b) { }
2643846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public boolean getWantClientAuth() { return false; }
2644846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public void setEnableSessionCreation(boolean b) { }
2645846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian            @Override public boolean getEnableSessionCreation() { return false; }
2646846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian        };
2647846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian        assertTrue(socket.toString().startsWith("SSLSocket["));
2648846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian    }
2649846d0260638a42ed6b5bbca7fa5ea1ad92ce8858Adam Vartanian
2650bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
2651bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Not run by default by JUnit, but can be run by Vogar by
2652101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson     * specifying it explicitly (or with main method below)
2653bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
26540c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    public void stress_test_TestSSLSocketPair_create() {
2655bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        final boolean verbose = true;
2656bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        while (true) {
265717c744222e249ed5f7ab36e49ed11f9bb062a302Brian Carlstrom            TestSSLSocketPair test = TestSSLSocketPair.create();
2658bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (verbose) {
2659bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                System.out.println("client=" + test.client.getLocalPort()
2660bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                   + " server=" + test.server.getLocalPort());
2661bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            } else {
2662bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                System.out.print("X");
2663bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
2664f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
2665f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            /*
2666f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom              We don't close on purpose in this stress test to add
2667f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom              races in file descriptors reuse when the garbage
2668f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom              collector runs concurrently and finalizes sockets
2669f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            */
2670f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // test.close();
2671f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
2672bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
2673bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
2674bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
267527088efe0caca697e257e08d41387af8130364e0Kenny Root    private static final void readFully(InputStream in, byte[] dst) throws IOException {
267627088efe0caca697e257e08d41387af8130364e0Kenny Root        int offset = 0;
267727088efe0caca697e257e08d41387af8130364e0Kenny Root        int byteCount = dst.length;
267827088efe0caca697e257e08d41387af8130364e0Kenny Root        while (byteCount > 0) {
267927088efe0caca697e257e08d41387af8130364e0Kenny Root            int bytesRead = in.read(dst, offset, byteCount);
268027088efe0caca697e257e08d41387af8130364e0Kenny Root            if (bytesRead < 0) {
268127088efe0caca697e257e08d41387af8130364e0Kenny Root                throw new EOFException();
268227088efe0caca697e257e08d41387af8130364e0Kenny Root            }
268327088efe0caca697e257e08d41387af8130364e0Kenny Root            offset += bytesRead;
268427088efe0caca697e257e08d41387af8130364e0Kenny Root            byteCount -= bytesRead;
268527088efe0caca697e257e08d41387af8130364e0Kenny Root        }
268627088efe0caca697e257e08d41387af8130364e0Kenny Root    }
268727088efe0caca697e257e08d41387af8130364e0Kenny Root
268827088efe0caca697e257e08d41387af8130364e0Kenny Root    private static final void closeQuietly(Closeable socket) {
268927088efe0caca697e257e08d41387af8130364e0Kenny Root        if (socket != null) {
269027088efe0caca697e257e08d41387af8130364e0Kenny Root            try {
269127088efe0caca697e257e08d41387af8130364e0Kenny Root                socket.close();
269227088efe0caca697e257e08d41387af8130364e0Kenny Root            } catch (Exception ignored) {
269327088efe0caca697e257e08d41387af8130364e0Kenny Root            }
269427088efe0caca697e257e08d41387af8130364e0Kenny Root        }
269527088efe0caca697e257e08d41387af8130364e0Kenny Root    }
269627088efe0caca697e257e08d41387af8130364e0Kenny Root
2697101547d4a82ba21031dc7cb62018720dbd493758Jesse Wilson    public static void main (String[] args) {
26980c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        new SSLSocketTest().stress_test_TestSSLSocketPair_create();
2699bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
2700ebabb91c8c87ac2be2dca70ae343130f9755047fBrian Carlstrom}
2701