1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package org.apache.harmony.tests.javax.net.ssl;
19 
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.net.InetSocketAddress;
25 import java.security.KeyStore;
26 import java.security.cert.Certificate;
27 import java.security.cert.CertificateException;
28 import java.util.Base64;
29 import javax.net.ssl.HandshakeCompletedEvent;
30 import javax.net.ssl.HandshakeCompletedListener;
31 import javax.net.ssl.KeyManager;
32 import javax.net.ssl.KeyManagerFactory;
33 import javax.net.ssl.SSLContext;
34 import javax.net.ssl.SSLPeerUnverifiedException;
35 import javax.net.ssl.SSLServerSocket;
36 import javax.net.ssl.SSLSession;
37 import javax.net.ssl.SSLSocket;
38 import javax.net.ssl.SSLSocketFactory;
39 import javax.net.ssl.TrustManager;
40 import javax.net.ssl.X509TrustManager;
41 import javax.security.cert.X509Certificate;
42 import junit.framework.TestCase;
43 import org.apache.harmony.xnet.tests.support.mySSLSession;
44 
45 /**
46  * Tests for <code>HandshakeCompletedEvent</code> class constructors and methods.
47  *
48  */
49 public class HandshakeCompletedEventTest extends TestCase {
50 
51     private String certificate = "-----BEGIN CERTIFICATE-----\n"
52         + "MIICZTCCAdICBQL3AAC2MA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMSAw\n"
53         + "HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJl\n"
54         + "IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NzAyMjAwMDAwMDBa\n"
55         + "Fw05ODAyMjAyMzU5NTlaMIGWMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv\n"
56         + "cm5pYTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0\n"
57         + "ZW1zLCBJbmMuMSEwHwYDVQQLExhUZXN0IGFuZCBFdmFsdWF0aW9uIE9ubHkxGjAY\n"
58         + "BgNVBAMTEWFyZ29uLmVuZy5zdW4uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
59         + "iQKBgQCofmdY+PiUWN01FOzEewf+GaG+lFf132UpzATmYJkA4AEA/juW7jSi+LJk\n"
60         + "wJKi5GO4RyZoyimAL/5yIWDV6l1KlvxyKslr0REhMBaD/3Z3EsLTTEf5gVrQS6sT\n"
61         + "WMoSZAyzB39kFfsB6oUXNtV8+UKKxSxKbxvhQn267PeCz5VX2QIDAQABMA0GCSqG\n"
62         + "SIb3DQEBAgUAA34AXl3at6luiV/7I9MN5CXYoPJYI8Bcdc1hBagJvTMcmlqL2uOZ\n"
63         + "H9T5hNMEL9Tk6aI7yZPXcw/xI2K6pOR/FrMp0UwJmdxX7ljV6ZtUZf7pY492UqwC\n"
64         + "1777XQ9UEZyrKJvF5ntleeO0ayBqLGVKCWzWZX9YsXCpv47FNLZbupE=\n"
65         + "-----END CERTIFICATE-----\n";
66 
67 
68     /**
69      * @throws IOException
70      * javax.net.ssl.HandshakeCompletedEvent#HandshakeCompletedEvent(SSLSocket sock, SSLSession s)
71      */
test_Constructor()72     public final void test_Constructor() throws Exception {
73         mySSLSession session = new mySSLSession();
74         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
75         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
76         try {
77             new HandshakeCompletedEvent(null, null);
78             fail("Any exception wasn't thrown for null parameters");
79         } catch (Exception expected) {
80         }
81     }
82 
83     /**
84      * @throws IOException
85      * javax.net.ssl.HandshakeCompletedEvent#getCipherSuite()
86      */
test_getCipherSuite()87     public final void test_getCipherSuite() throws Exception {
88         mySSLSession session = new mySSLSession("localhost", 1080, null);
89         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
90         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
91         assertEquals("SuiteName", event.getCipherSuite());
92     }
93 
94     /**
95      * @throws IOException
96      * javax.net.ssl.HandshakeCompletedEvent#getLocalCertificates()
97      */
test_getLocalCertificates()98     public final void test_getLocalCertificates() throws Exception {
99         mySSLSession session = new mySSLSession("localhost", 1080, null);
100         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
101         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
102         assertNull(event.getLocalCertificates());
103     }
104 
105     /**
106      * @throws IOException
107      * javax.net.ssl.HandshakeCompletedEvent#getLocalPrincipal()
108      */
test_getLocalPrincipal()109     public final void test_getLocalPrincipal() throws Exception {
110         mySSLSession session = new mySSLSession("localhost", 1080, null);
111         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
112         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
113         assertNull(event.getLocalPrincipal());
114     }
115 
116     /**
117      * @throws IOException
118      * javax.net.ssl.HandshakeCompletedEvent#getPeerCertificateChain()
119      */
test_getPeerCertificateChain()120     public final void test_getPeerCertificateChain() throws Exception {
121         ByteArrayInputStream bis = new ByteArrayInputStream(certificate.getBytes());
122         mySSLSession session = new mySSLSession((X509Certificate[]) null);
123         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
124         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
125         try {
126             event.getPeerCertificateChain();
127             fail("SSLPeerUnverifiedException wasn't thrown");
128         } catch (SSLPeerUnverifiedException expected) {
129         }
130 
131         X509Certificate xc = X509Certificate.getInstance(bis);
132         X509Certificate[] xcs = {xc};
133         session = new mySSLSession(xcs);
134         event = new HandshakeCompletedEvent(socket, session);
135 
136         X509Certificate[] res = event.getPeerCertificateChain();
137         assertEquals(1, res.length);
138     }
139 
140     /**
141      * @throws IOException
142      * javax.net.ssl.HandshakeCompletedEvent#getPeerCertificates()
143      */
test_getPeerCertificates()144     public final void test_getPeerCertificates() throws IOException {
145         mySSLSession session = new mySSLSession("localhost", 1080, null);
146         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
147         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
148         try {
149             event.getPeerCertificates();
150             fail("SSLPeerUnverifiedException wasn't thrown");
151         } catch (SSLPeerUnverifiedException expected) {
152         }
153 
154         session = new mySSLSession((X509Certificate[]) null);
155         event = new HandshakeCompletedEvent(socket, session);
156         Certificate[] res = event.getPeerCertificates();
157         assertEquals(3, res.length);
158     }
159 
160     /**
161      * @throws IOException
162      * javax.net.ssl.HandshakeCompletedEvent#getPeerPrincipal()
163      */
test_getPeerPrincipal()164     public final void test_getPeerPrincipal() throws IOException {
165         mySSLSession session = new mySSLSession("localhost", 1080, null);
166         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
167         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
168         assertNull(event.getPeerPrincipal());
169     }
170 
171     /**
172      * @throws IOException
173      * javax.net.ssl.HandshakeCompletedEvent#getSession()
174      */
test_getSession()175     public final void test_getSession() throws IOException {
176         mySSLSession session = new mySSLSession("localhost", 1080, null);
177         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
178         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, session);
179         SSLSession ss = event.getSession();
180         assertNotNull(ss);
181         assertEquals(session, ss);
182     }
183 
184     /**
185      * @throws IOException
186      * javax.net.ssl.HandshakeCompletedEvent#getSocket()
187      */
test_getSocket()188     public final void test_getSocket() throws IOException {
189         SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
190         HandshakeCompletedEvent event = new HandshakeCompletedEvent(socket, null);
191         SSLSocket ss = event.getSocket();
192         assertNotNull(ss);
193         assertEquals(socket, ss);
194     }
195 
196 
197     // Regression test for CompletedHandshakeEvent not firing with a custom
198     // TrustManager
199 
200 
201     private SSLSocket socket;
202     private SSLServerSocket serverSocket;
203     private MyHandshakeListener listener;
204     private String host = "localhost";
205 
206     private String PASSWORD = "android";
207 
208     /**
209      * Defines the keystore contents for the server, BKS version. Holds just a
210      * single self-generated key. The subject name is "Test Server".
211      */
212     private static final String SERVER_KEYS_BKS =
213             "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41"
214             + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
215             + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
216             + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw"
217             + "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
218             + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl"
219             + "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy"
220             + "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV"
221             + "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG"
222             + "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU"
223             + "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV"
224             + "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx"
225             + "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR"
226             + "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN"
227             + "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs"
228             + "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck"
229             + "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM"
230             + "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI"
231             + "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f"
232             + "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx"
233             + "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt"
234             + "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw"
235             + "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl"
236             + "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
237 
238     /**
239      * Defines the keystore contents for the server, JKS version. Holds just a
240      * single self-generated key. The subject name is "Test Server".
241      */
242     private static final String SERVER_KEYS_JKS =
243             "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC"
244             + "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4"
245             + "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du"
246             + "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo"
247             + "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk"
248             + "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc"
249             + "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3"
250             + "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk"
251             + "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH"
252             + "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs"
253             + "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq"
254             + "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg"
255             + "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu"
256             + "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD"
257             + "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH"
258             + "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0"
259             + "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w"
260             + "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf"
261             + "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg"
262             + "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT"
263             + "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB"
264             + "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW"
265             + "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY"
266             + "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
267 
268     /**
269      * Defines the keystore contents for the client, JKS version. Holds just a
270      * single self-generated key. The subject name is "Test Client".
271      */
272     private static final String CLIENT_KEYS_JKS =
273             "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFhyMAAAArkwggK1MA4GCisGAQQBKgIRAQEFAASC"
274             + "AqGVSfXolBStZy4nnRNn4fAr+S7kfU2BS23wwW8uB2Ru3GvtLzlK9q08Gvq/LNqBafjyFTVL5FV5"
275             + "SED/8YomO5a98GpskSeRvytCiTBLJdgGhws5TOGekgIAcBROPGIyOtJPQ0HfOQs+BqgzGDHzHQhw"
276             + "u/8Tm6yQwiP+W/1I9B1QnaEztZA3mhTyMMJsmsFTYroGgAog885D5Cmzd8sYGfxec3R6I+xcmBAY"
277             + "eibR5kGpWwt1R+qMvRrtBqh5r6WSKhCBNax+SJVbtUNRiKyjKccdJg6fGqIWWeivwYTy0OhjA6b4"
278             + "NiZ/ZZs5pxFGWUj/Rlp0RYy8fCF6aw5/5s4Bf4MI6dPSqMG8Hf7sJR91GbcELyzPdM0h5lNavgit"
279             + "QPEzKeuDrGxhY1frJThBsNsS0gxeu+OgfJPEb/H4lpYX5IvuIGbWKcxoO9zq4/fimIZkdA8A+3eY"
280             + "mfDaowvy65NBVQPJSxaOyFhLHfeLqOeCsVENAea02vA7andZHTZehvcrqyKtm+z8ncHGRC2H9H8O"
281             + "jKwKHfxxrYY/jMAKLl00+PBb3kspO+BHI2EcQnQuMw/zr83OR9Meq4TJ0TMuNkApZELAeFckIBbS"
282             + "rBr8NNjAIfjuCTuKHhsTFWiHfk9ZIzigxXagfeDRiyVc6khOuF/bGorj23N2o7Rf3uLoU6PyXWi4"
283             + "uhctR1aL6NzxDoK2PbYCeA9hxbDv8emaVPIzlVwpPK3Ruvv9mkjcOhZ74J8bPK2fQmbplbOljcZi"
284             + "tZijOfzcO/11JrwhuJZRA6wanTqHoujgChV9EukVrmbWGGAcewFnAsSbFXIik7/+QznXaDIt5NgL"
285             + "H/Bcz4Z/fdV7Ae1eUaxKXdPbI//4J+8liVT/d8awjW2tldIaDlmGMR3aoc830+3mAAAAAQAFWC41"
286             + "MDkAAAJIMIICRDCCAa0CBEhHxLgwDQYJKoZIhvcNAQEEBQAwaTELMAkGA1UEBhMCVVMxEzARBgNV"
287             + "BAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01UVjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdB"
288             + "bmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVudDAeFw0wODA2MDUxMDQ5MjhaFw0wODA5MDMxMDQ5"
289             + "MjhaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzAN"
290             + "BgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBDbGllbnQwgZ8w"
291             + "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIK3Q+KiFbmCGg422TAo4gggdhMH6FJhiuz8DxRyeMKR"
292             + "UAfP4MK0wtc8N42waZ6OKvxpBFUy0BRfBsX0GD4Ku99yu9/tavSigTraeJtwV3WWRRjIqk7L3wX5"
293             + "cmgS2KSD43Y0rNUKrko26lnt9N4qiYRBSj+tcAN3Lx9+ptqk1LApAgMBAAEwDQYJKoZIhvcNAQEE"
294             + "BQADgYEANb7Q1GVSuy1RPJ0FmiXoMYCCtvlRLkmJphwxovK0cAQK12Vll+yAzBhHiQHy/RA11mng"
295             + "wYudC7u3P8X/tBT8GR1Yk7QW3KgFyPafp3lQBBCraSsfrjKj+dCLig1uBLUr4f68W8VFWZWWTHqp"
296             + "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw==";
297 
298     /**
299      * Defines the keystore contents for the client, BKS version. Holds just a
300      * single self-generated key. The subject name is "Test Client".
301      */
302     private static final String CLIENT_KEYS_BKS =
303             "AAAAAQAAABT4Rka6fxbFps98Y5k2VilmbibNkQAABfQEAAVteWtleQAAARpYl+POAAAAAQAFWC41"
304             + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU9TANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
305             + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
306             + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgQ2xpZW50MB4XDTA4MDYwNTExNTg0NVoXDTA4MDkw"
307             + "MzExNTg0NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
308             + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVu"
309             + "dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUvmWsQDHPpbDKK13Yez2/q54tTOmRml/qva"
310             + "2K6dZjkjSTW0iRuk7ztaVEvdJpfVIDv1oBsCI51ttyLHROy1epjF+GoL74mJb7fkcd0VOoSOTjtD"
311             + "+3GgZkHPAm5YmUYxiJXqxKKJJqMCTIW46eJaA2nAep9QIwZ14/NFAs4ObV8CAwEAATANBgkqhkiG"
312             + "9w0BAQUFAAOBgQCJrCr3hZQFDlLIfsSKI1/w+BLvyf4fubOid0pBxfklR8KBNPTiqjSmu7pd/C/F"
313             + "1FR8CdZUDoPflZHCOU+fj5r5KUC1HyigY/tEUvlforBpfB0uCF+tXW4DbUfOWhfMtLV4nCOJOOZg"
314             + "awfZLJWBJouLKOp427vDftxTSB+Ks8YjlgAAAqwAAAAU+NH6TtrzjyDdCXm5B6Vo7xX5G4YAAAZx"
315             + "EAUkcZtmykn7YdaYxC1jRFJ+GEJpC8nZVg83QClVuCSIS8a5f8Hl44Bk4oepOZsPzhtz3RdVzDVi"
316             + "RFfoyZFsrk9F5bDTVJ6sQbb/1nfJkLhZFXokka0vND5AXMSoD5Bj1Fqem3cK7fSUyqKvFoRKC3XD"
317             + "FQvhqoam29F1rbl8FaYdPvhhZo8TfZQYUyUKwW+RbR44M5iHPx+ykieMe/C/4bcM3z8cwIbYI1aO"
318             + "gjQKS2MK9bs17xaDzeAh4sBKrskFGrDe+2dgvrSKdoakJhLTNTBSG6m+rzqMSCeQpafLKMSjTSSz"
319             + "+KoQ9bLyax8cbvViGGju0SlVhquloZmKOfHr8TukIoV64h3uCGFOVFtQjCYDOq6NbfRvMh14UVF5"
320             + "zgDIGczoD9dMoULWxBmniGSntoNgZM+QP6Id7DBasZGKfrHIAw3lHBqcvB5smemSu7F4itRoa3D8"
321             + "N7hhUEKAc+xA+8NKmXfiCBoHfPHTwDvt4IR7gWjeP3Xv5vitcKQ/MAfO5RwfzkYCXQ3FfjfzmsE1"
322             + "1IfLRDiBj+lhQSulhRVStKI88Che3M4JUNGKllrc0nt1pWa1vgzmUhhC4LSdm6trTHgyJnB6OcS9"
323             + "t2furYjK88j1AuB4921oxMxRm8c4Crq8Pyuf+n3YKi8Pl2BzBtw++0gj0ODlgwut8SrVj66/nvIB"
324             + "jN3kLVahR8nZrEFF6vTTmyXi761pzq9yOVqI57wJGx8o3Ygox1p+pWUPl1hQR7rrhUbgK/Q5wno9"
325             + "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef"
326             + "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
327 
328 
329     /**
330      * Implements the actual test case. Launches a server and a client, requires
331      * client authentication and checks the certificates afterwards (not in the
332      * usual sense, we just make sure that we got the expected certificates,
333      * because our self-signed test certificates are not valid.)
334      */
335 
testClientAuth()336     public void testClientAuth() throws Exception {
337 
338         boolean useBKS = true;
339 
340         listener = new MyHandshakeListener();
341         String serverKeys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS);
342         String clientKeys = (useBKS ? CLIENT_KEYS_BKS : CLIENT_KEYS_JKS);
343         TestServer server = new TestServer(true,
344                                            TestServer.CLIENT_AUTH_WANTED, serverKeys);
345         TestClient client = new TestClient(true, clientKeys);
346 
347         Thread serverThread = new Thread(server);
348         Thread clientThread = new Thread(client);
349 
350         serverThread.start();
351         Thread.currentThread().sleep(3000);
352         clientThread.start();
353 
354         serverThread.join();
355         clientThread.join();
356 
357         // The server must have completed without an exception.
358         Exception e = server.getException();
359         if (e != null) {
360             e.printStackTrace();
361         }
362 
363         // The client must have completed without an exception.
364         e = client.getException();
365         if (e != null) {
366             e.printStackTrace();
367         }
368 
369         assertNull(e);
370 
371         assertTrue(listener.completeDone);
372     }
373 
374     /**
375      * Implements a test SSL socket server. It wait for a connection on a given
376      * port, requests client authentication (if specified), reads 256 bytes
377      * from the socket, and writes 256 bytes to the socket.
378      */
379     class TestServer implements Runnable {
380 
381         public static final int CLIENT_AUTH_NONE = 0;
382 
383         public static final int CLIENT_AUTH_WANTED = 1;
384 
385         public static final int CLIENT_AUTH_NEEDED = 2;
386 
387         private TestTrustManager trustManager;
388 
389         private Exception exception;
390 
391         String keys;
392 
393         private int clientAuth;
394 
395         private boolean provideKeys;
396 
TestServer(boolean provideKeys, int clientAuth, String keys)397         public TestServer(boolean provideKeys, int clientAuth, String keys) throws Exception {
398             this.keys = keys;
399             this.clientAuth = clientAuth;
400             this.provideKeys = provideKeys;
401 
402             trustManager = new TestTrustManager();
403 
404             KeyManager[] keyManagers = provideKeys ? getKeyManagers(keys) : null;
405             TrustManager[] trustManagers = new TrustManager[] { trustManager };
406 
407             SSLContext sslContext = SSLContext.getInstance("TLS");
408             sslContext.init(keyManagers, trustManagers, null);
409 
410             serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket();
411 
412             if (clientAuth == CLIENT_AUTH_WANTED) {
413                 serverSocket.setWantClientAuth(true);
414             } else if (clientAuth == CLIENT_AUTH_NEEDED) {
415                 serverSocket.setNeedClientAuth(true);
416             } else {
417                 serverSocket.setWantClientAuth(false);
418             }
419 
420             serverSocket.bind(new InetSocketAddress(0));
421         }
422 
run()423         public void run() {
424             try {
425                 SSLSocket clientSocket = (SSLSocket)serverSocket.accept();
426 
427                 InputStream istream = clientSocket.getInputStream();
428 
429                 for (int i = 0; i < 256; i++) {
430                     int j = istream.read();
431                     assertEquals(i, j);
432                 }
433 
434                 OutputStream ostream = clientSocket.getOutputStream();
435 
436                 for (int i = 0; i < 256; i++) {
437                     ostream.write(i);
438                 }
439 
440                 ostream.flush();
441                 ostream.close();
442 
443                 clientSocket.close();
444                 serverSocket.close();
445 
446             } catch (Exception ex) {
447                 exception = ex;
448             }
449         }
450 
getException()451         public Exception getException() {
452             return exception;
453         }
454 
getChain()455         public X509Certificate[] getChain() {
456             return trustManager.getChain();
457         }
458 
459     }
460 
461     /**
462      * Implements a test SSL socket client. It open a connection to localhost on
463      * a given port, writes 256 bytes to the socket, and reads 256 bytes from the
464      * socket.
465      */
466     class TestClient implements Runnable {
467 
468         private TestTrustManager trustManager;
469 
470         private Exception exception;
471 
472         private String keys;
473 
474         private boolean provideKeys;
475 
TestClient(boolean provideKeys, String keys)476         public TestClient(boolean provideKeys, String keys) {
477             this.keys = keys;
478             this.provideKeys = provideKeys;
479 
480             trustManager = new TestTrustManager();
481         }
482 
run()483         public void run() {
484             try {
485                 KeyManager[] keyManagers = provideKeys ? getKeyManagers(keys) : null;
486                 TrustManager[] trustManagers = new TrustManager[] { trustManager };
487 
488                 SSLContext sslContext = SSLContext.getInstance("TLS");
489                 sslContext.init(keyManagers, trustManagers, null);
490 
491                 SSLSocket socket = (SSLSocket)sslContext.getSocketFactory().createSocket();
492 
493                 socket.connect(serverSocket.getLocalSocketAddress());
494                 socket.addHandshakeCompletedListener(listener);
495                 socket.startHandshake();
496 
497                 OutputStream ostream = socket.getOutputStream();
498 
499                 for (int i = 0; i < 256; i++) {
500                     ostream.write(i);
501                 }
502 
503                 ostream.flush();
504 
505                 InputStream istream = socket.getInputStream();
506 
507                 for (int i = 0; i < 256; i++) {
508                     int j = istream.read();
509                     assertEquals(i, j);
510                 }
511 
512                 istream.close();
513 
514                 socket.close();
515 
516             } catch (Exception ex) {
517                 exception = ex;
518             }
519         }
520 
getException()521         public Exception getException() {
522             return exception;
523         }
524 
getChain()525         public X509Certificate[] getChain() {
526             return trustManager.getChain();
527         }
528     }
529 
530     /**
531      * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
532      * for the result.
533      */
getKeyManagers(String keys)534     private KeyManager[] getKeyManagers(String keys) throws Exception {
535         byte[] bytes = Base64.getDecoder().decode(keys.getBytes());
536         InputStream inputStream = new ByteArrayInputStream(bytes);
537 
538         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
539         keyStore.load(inputStream, PASSWORD.toCharArray());
540         inputStream.close();
541 
542         String algorithm = KeyManagerFactory.getDefaultAlgorithm();
543         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
544         keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
545 
546         return keyManagerFactory.getKeyManagers();
547     }
548 
549 
550     /**
551      * Implements basically a fake TrustManager. It stores the certificate
552      * chain it sees, so it can later be queried.
553      */
554     public static class TestTrustManager implements X509TrustManager {
555 
556         private X509Certificate[] chain;
557 
558         private String authType;
559 
checkClientTrusted(X509Certificate[] chain, String authType)560         public void checkClientTrusted(X509Certificate[] chain, String authType) {
561             this.chain = chain;
562             this.authType = authType;
563         }
564 
checkServerTrusted(X509Certificate[] chain, String authType)565         public void checkServerTrusted(X509Certificate[] chain, String authType) {
566             this.chain = chain;
567             this.authType = authType;
568         }
569 
getAcceptedIssuers()570         public java.security.cert.X509Certificate[] getAcceptedIssuers() {
571             return new java.security.cert.X509Certificate[0];
572         }
573 
getChain()574         public X509Certificate[] getChain() {
575             return chain;
576         }
577 
getAuthType()578         public String getAuthType() {
579             return authType;
580         }
581 
checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType)582         public void checkClientTrusted(
583                 java.security.cert.X509Certificate[] chain, String authType)
584                 throws CertificateException {
585 
586         }
587 
checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType)588         public void checkServerTrusted(
589                 java.security.cert.X509Certificate[] chain, String authType)
590                 throws CertificateException {
591 
592         }
593 
594     }
595 
596     class MyHandshakeListener implements HandshakeCompletedListener {
597 
598         public boolean completeDone;
599 
MyHandshakeListener()600         MyHandshakeListener() {
601             completeDone = false;
602         }
603 
handshakeCompleted(HandshakeCompletedEvent event)604         public void handshakeCompleted(HandshakeCompletedEvent event) {
605             if (event != null) completeDone = true;
606         }
607     }
608 }
609