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