Home | History | Annotate | Download | only in ssl
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package tests.api.javax.net.ssl;
     17 
     18 import dalvik.annotation.AndroidOnly;
     19 import java.io.ByteArrayInputStream;
     20 import java.io.IOException;
     21 import java.io.InputStream;
     22 import java.net.InetAddress;
     23 import java.net.InetSocketAddress;
     24 import java.net.UnknownHostException;
     25 import java.security.KeyStore;
     26 import java.security.SecureRandom;
     27 import java.util.Arrays;
     28 import javax.net.ssl.HandshakeCompletedEvent;
     29 import javax.net.ssl.HandshakeCompletedListener;
     30 import javax.net.ssl.KeyManager;
     31 import javax.net.ssl.KeyManagerFactory;
     32 import javax.net.ssl.SSLContext;
     33 import javax.net.ssl.SSLServerSocket;
     34 import javax.net.ssl.SSLSocket;
     35 import javax.net.ssl.SSLSocketFactory;
     36 import javax.net.ssl.TrustManager;
     37 import javax.security.cert.X509Certificate;
     38 import junit.framework.TestCase;
     39 import libcore.io.Base64;
     40 import tests.api.javax.net.ssl.HandshakeCompletedEventTest.TestTrustManager;
     41 import tests.support.Support_PortManager;
     42 import libcore.java.security.StandardNames;
     43 
     44 public class SSLSocketTest extends TestCase {
     45 
     46     public class HandshakeCL implements HandshakeCompletedListener {
     47         public void handshakeCompleted(HandshakeCompletedEvent event) {
     48         }
     49     }
     50 
     51     /**
     52      * javax.net.ssl.SSLSocket#SSLSocket()
     53      */
     54     public void testConstructor_01() throws Exception {
     55         SSLSocket ssl = getSSLSocket();
     56         assertNotNull(ssl);
     57         ssl.close();
     58     }
     59 
     60     /**
     61      * javax.net.ssl.SSLSocket#SSLSocket(InetAddress address, int port)
     62      */
     63     public void testConstructor_02() throws UnknownHostException, IOException {
     64         int sport = startServer("Cons InetAddress,I");
     65         int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE};
     66 
     67         SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost(), sport);
     68         assertNotNull(ssl);
     69         assertEquals(sport, ssl.getPort());
     70         ssl.close();
     71 
     72         try {
     73             getSSLSocket(InetAddress.getLocalHost(), sport + 1);
     74             fail();
     75         } catch (IOException expected) {
     76         }
     77 
     78         for (int i = 0; i < invalidPort.length; i++) {
     79             try {
     80                 getSSLSocket(InetAddress.getLocalHost(), invalidPort[i]);
     81                 fail();
     82             } catch (IllegalArgumentException expected) {
     83             }
     84         }
     85     }
     86 
     87     /**
     88      * javax.net.ssl.SSLSocket#SSLSocket(InetAddress address, int port,
     89      *                                          InetAddress clientAddress, int clientPort)
     90      */
     91     public void testConstructor_03() throws UnknownHostException, IOException {
     92         int sport = startServer("Cons InetAddress,I,InetAddress,I");
     93         int portNumber = Support_PortManager.getNextPort();
     94 
     95         SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost(), sport,
     96                                      InetAddress.getLocalHost(), portNumber);
     97         assertNotNull(ssl);
     98         assertEquals(sport, ssl.getPort());
     99         assertEquals(portNumber, ssl.getLocalPort());
    100         ssl.close();
    101 
    102         try {
    103             getSSLSocket(InetAddress.getLocalHost(), 8081, InetAddress.getLocalHost(), 8082);
    104             fail();
    105         } catch (IOException expected) {
    106         }
    107 
    108         try {
    109             getSSLSocket(InetAddress.getLocalHost(), -1, InetAddress.getLocalHost(), sport + 1);
    110             fail();
    111         } catch (IllegalArgumentException expected) {
    112         }
    113         try {
    114             getSSLSocket(InetAddress.getLocalHost(), sport, InetAddress.getLocalHost(), -1);
    115             fail();
    116         } catch (IllegalArgumentException expected) {
    117         }
    118 
    119         try {
    120             getSSLSocket(InetAddress.getLocalHost(), Integer.MIN_VALUE,
    121                          InetAddress.getLocalHost(), sport + 1);
    122             fail();
    123         } catch (IOException expectedOnRI) {
    124             assertTrue(StandardNames.IS_RI);
    125         } catch (IllegalArgumentException expectedOnAndroid) {
    126             assertFalse(StandardNames.IS_RI);
    127         }
    128         try {
    129             getSSLSocket(InetAddress.getLocalHost(), sport,
    130                          InetAddress.getLocalHost(), Integer.MAX_VALUE);
    131             fail();
    132         } catch (IllegalArgumentException expectedOnAndroid) {
    133             assertFalse(StandardNames.IS_RI);
    134         }
    135     }
    136 
    137     /**
    138      * javax.net.ssl.SSLSocket#SSLSocket(String host, int port)
    139      */
    140     public void testConstructor_04() throws UnknownHostException, IOException {
    141         int sport = startServer("Cons String,I");
    142         int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE};
    143 
    144         SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost().getHostName(), sport);
    145         assertNotNull(ssl);
    146         assertEquals(sport, ssl.getPort());
    147         ssl.close();
    148 
    149         try {
    150             getSSLSocket("localhost", 8082);
    151             fail();
    152         } catch (IOException expected) {
    153         }
    154 
    155         for (int i = 0; i < invalidPort.length; i++) {
    156             try {
    157                 getSSLSocket(InetAddress.getLocalHost().getHostName(), invalidPort[i]);
    158                 fail();
    159             } catch (IllegalArgumentException expected) {
    160             }
    161         }
    162 
    163         try {
    164             getSSLSocket("bla-bla", sport);
    165             fail();
    166         } catch (UnknownHostException expected) {
    167         }
    168     }
    169 
    170     /**
    171      * javax.net.ssl.SSLSocket#SSLSocket(String host, int port, InetAddress clientAddress,
    172      *           int clientPort)
    173      */
    174     public void testConstructor_05() throws UnknownHostException, IOException {
    175         int sport = startServer("Cons String,I,InetAddress,I");
    176         int portNumber = Support_PortManager.getNextPort();
    177         int[] invalidPort = {-1, Integer.MIN_VALUE, 65536, Integer.MAX_VALUE};
    178 
    179         SSLSocket ssl = getSSLSocket(InetAddress.getLocalHost().getHostName(), sport,
    180                                      InetAddress.getLocalHost(), portNumber);
    181         assertNotNull(ssl);
    182         assertEquals(sport, ssl.getPort());
    183         assertEquals(portNumber, ssl.getLocalPort());
    184 
    185         try {
    186             getSSLSocket("localhost", 8081, InetAddress.getLocalHost(), 8082);
    187             fail();
    188         } catch (IOException expected) {
    189         }
    190 
    191         for (int i = 0; i < invalidPort.length; i++) {
    192             portNumber = Support_PortManager.getNextPort();
    193             try {
    194                 getSSLSocket(InetAddress.getLocalHost().getHostName(), invalidPort[i],
    195                              InetAddress.getLocalHost(), portNumber);
    196                 fail();
    197             } catch (IllegalArgumentException expected) {
    198             }
    199             try {
    200                 getSSLSocket(InetAddress.getLocalHost().getHostName(), sport,
    201                              InetAddress.getLocalHost(), invalidPort[i]);
    202                 fail();
    203             } catch (IllegalArgumentException expected) {
    204             }
    205         }
    206 
    207         portNumber = Support_PortManager.getNextPort();
    208         try {
    209             getSSLSocket("bla-bla", sport, InetAddress.getLocalHost(), portNumber);
    210             fail();
    211         } catch (UnknownHostException expected) {
    212         }
    213     }
    214 
    215     public void test_creationStressTest() throws Exception {
    216         // Test the default codepath, which uses /dev/urandom.
    217         SSLContext sslContext = SSLContext.getInstance("TLS");
    218         sslContext.init(null, null, null);
    219         for (int i = 0; i < 2048; ++i) {
    220             sslContext.getSocketFactory().createSocket().close();
    221         }
    222 
    223         // Test the other codepath, which copies a seed from a byte[].
    224         sslContext.init(null, null, new SecureRandom());
    225         for (int i = 0; i < 2048; ++i) {
    226             sslContext.getSocketFactory().createSocket().close();
    227         }
    228     }
    229 
    230     /**
    231      * javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener listener)
    232      */
    233     @AndroidOnly("RI doesn't throw the specified IAE")
    234     public void test_addHandshakeCompletedListener() throws IOException {
    235         SSLSocket ssl = getSSLSocket();
    236         HandshakeCompletedListener ls = new HandshakeCL();
    237         try {
    238             ssl.addHandshakeCompletedListener(null);
    239             fail();
    240         } catch (IllegalArgumentException expected) {
    241         }
    242         ssl.addHandshakeCompletedListener(ls);
    243         ssl.close();
    244     }
    245 
    246     /**
    247      * javax.net.ssl.SSLSocket#removeHandshakeCompletedListener(HandshakeCompletedListener listener)
    248      */
    249     public void test_removeHandshakeCompletedListener() throws IOException {
    250         SSLSocket ssl = getSSLSocket();
    251         HandshakeCompletedListener ls = new HandshakeCL();
    252         try {
    253             ssl.removeHandshakeCompletedListener(null);
    254             fail();
    255         } catch (IllegalArgumentException expected) {
    256         }
    257 
    258         try {
    259             ssl.removeHandshakeCompletedListener(ls);
    260         } catch (IllegalArgumentException expected) {
    261         }
    262 
    263         ssl.addHandshakeCompletedListener(ls);
    264         ssl.removeHandshakeCompletedListener(ls);
    265         ssl.close();
    266     }
    267 
    268     /**
    269      * javax.net.ssl.SSLSocket#setEnableSessionCreation(boolean flag)
    270      * javax.net.ssl.SSLSocket#getEnableSessionCreation()
    271      */
    272     public void test_EnableSessionCreation() throws IOException {
    273         SSLSocket ssl = getSSLSocket();
    274         assertTrue(ssl.getEnableSessionCreation());
    275         ssl.setEnableSessionCreation(false);
    276         assertFalse(ssl.getEnableSessionCreation());
    277         ssl.setEnableSessionCreation(true);
    278         assertTrue(ssl.getEnableSessionCreation());
    279         ssl.close();
    280     }
    281 
    282     /**
    283      * javax.net.ssl.SSLSocket#setNeedClientAuth(boolean need)
    284      * javax.net.ssl.SSLSocket#getNeedClientAuthCreation()
    285      */
    286     public void test_NeedClientAuth() throws UnknownHostException, IOException {
    287         SSLSocket ssl = getSSLSocket();
    288         ssl.setNeedClientAuth(true);
    289         assertTrue(ssl.getNeedClientAuth());
    290         ssl.setNeedClientAuth(false);
    291         assertFalse(ssl.getNeedClientAuth());
    292         ssl.close();
    293     }
    294 
    295     /**
    296      * javax.net.ssl.SSLSocket#setWantClientAuth(boolean want)
    297      * javax.net.ssl.SSLSocket#getWantClientAuthCreation()
    298      */
    299     public void test_WantClientAuth() throws UnknownHostException, IOException {
    300         SSLSocket ssl = getSSLSocket();
    301         ssl.setWantClientAuth(true);
    302         assertTrue(ssl.getWantClientAuth());
    303         ssl.setWantClientAuth(false);
    304         assertFalse(ssl.getWantClientAuth());
    305         ssl.close();
    306     }
    307 
    308     /**
    309      * javax.net.ssl.SSLSocket#getSupportedProtocols()
    310      */
    311     public void test_getSupportedProtocols() throws IOException {
    312         SSLSocket ssl = getSSLSocket();
    313         String[] res = ssl.getSupportedProtocols();
    314         assertTrue("No supported protocols found", res.length > 0);
    315         ssl.close();
    316     }
    317 
    318     /**
    319      * javax.net.ssl.SSLSocket#getEnabledProtocols()
    320      * javax.net.ssl.SSLSocket#setEnabledProtocols(String[] protocols)
    321      */
    322     public void test_EnabledProtocols() throws IOException {
    323         SSLSocket ssl = getSSLSocket();
    324         try {
    325             ssl.setEnabledProtocols(null);
    326             fail();
    327         } catch (IllegalArgumentException expected) {
    328         }
    329         ssl.setEnabledProtocols(new String[] {});
    330         try {
    331             ssl.setEnabledProtocols(new String[] {"blubb"});
    332             fail();
    333         } catch (IllegalArgumentException expected) {
    334         }
    335         ssl.setEnabledProtocols(ssl.getEnabledProtocols());
    336         String[] res = ssl.getEnabledProtocols();
    337         assertEquals("no enabled protocols set",
    338                      ssl.getEnabledProtocols().length, res.length);
    339         ssl.close();
    340     }
    341 
    342     /**
    343      * javax.net.ssl.SSLSocket#getSession()
    344      */
    345     public void test_getSession() throws IOException {
    346         SSLSocket ssl = getSSLSocket();
    347         assertNotNull(ssl.getSession());
    348         ssl.close();
    349     }
    350 
    351     /**
    352      * javax.net.ssl.SSLSocket#getSupportedCipherSuites()
    353      */
    354     public void test_getSupportedCipherSuites() throws IOException {
    355         SSLSocket ssl = getSSLSocket();
    356         String[] res = ssl.getSupportedCipherSuites();
    357         assertTrue("no supported cipher suites", res.length > 0);
    358         ssl.close();
    359     }
    360 
    361     /**
    362      * javax.net.ssl.SSLSocket#getEnabledCipherSuites()
    363      * javax.net.ssl.SSLSocket#setEnabledCipherSuites(String[] suites)
    364      */
    365     public void test_EnabledCipherSuites() throws IOException {
    366         SSLSocket ssl = getSSLSocket();
    367         try {
    368             ssl.setEnabledCipherSuites(null);
    369             fail();
    370         } catch (IllegalArgumentException expected) {
    371         }
    372         ssl.setEnabledCipherSuites(new String[] {});
    373         try {
    374             ssl.setEnabledCipherSuites(new String[] {"blubb"});
    375             fail();
    376         } catch (IllegalArgumentException expected) {
    377         }
    378         ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
    379         String[] res = ssl.getEnabledCipherSuites();
    380         assertNotNull("NULL result", res);
    381         assertEquals("not all supported cipher suites were enabled",
    382                      Arrays.asList(ssl.getSupportedCipherSuites()),
    383                      Arrays.asList(res));
    384         ssl.close();
    385     }
    386 
    387     /**
    388      * javax.net.ssl.SSLSocket#getUseClientMode()
    389      * javax.net.ssl.SSLSocket#setUseClientMode(boolean mode)
    390      */
    391     public void test_UseClientMode() throws IOException {
    392         SSLSocket ssl = getSSLSocket();
    393         assertTrue(ssl.getUseClientMode());
    394         ssl.setUseClientMode(false);
    395         assertFalse(ssl.getUseClientMode());
    396         ssl.close();
    397 
    398         ssl = getSSLSocket("localhost", startServer("UseClientMode"));
    399         try {
    400             ssl.startHandshake();
    401         } catch (IOException ioe) {
    402             //fail(ioe + " was thrown for method startHandshake()");
    403         }
    404         try {
    405             ssl.setUseClientMode(false);
    406             fail();
    407         } catch (IllegalArgumentException expected) {
    408         }
    409         ssl.close();
    410     }
    411 
    412     /**
    413      * javax.net.ssl.SSLSocket#startHandshake()
    414      */
    415     public void test_startHandshake() throws IOException {
    416         SSLSocket ssl = getSSLSocket();
    417         try {
    418             ssl.startHandshake();
    419             fail();
    420         } catch (IOException expected) {
    421         }
    422         ssl.close();
    423     }
    424 
    425     boolean useBKS = !StandardNames.IS_RI;
    426 
    427     private String PASSWORD = "android";
    428 
    429     private int port = Support_PortManager.getNextPort();
    430 
    431     private boolean serverReady = false;
    432 
    433     /**
    434      * Defines the keystore contents for the server, BKS version. Holds just a
    435      * single self-generated key. The subject name is "Test Server".
    436      */
    437     private static final String SERVER_KEYS_BKS = ""
    438             + "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41"
    439             + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
    440             + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
    441             + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw"
    442             + "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
    443             + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl"
    444             + "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy"
    445             + "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV"
    446             + "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG"
    447             + "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU"
    448             + "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV"
    449             + "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx"
    450             + "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR"
    451             + "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN"
    452             + "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs"
    453             + "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck"
    454             + "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM"
    455             + "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI"
    456             + "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f"
    457             + "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx"
    458             + "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt"
    459             + "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw"
    460             + "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl"
    461             + "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
    462 
    463     /**
    464      * Defines the keystore contents for the server, JKS version. Holds just a
    465      * single self-generated key. The subject name is "Test Server".
    466      */
    467     private static final String SERVER_KEYS_JKS = ""
    468             + "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC"
    469             + "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4"
    470             + "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du"
    471             + "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo"
    472             + "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk"
    473             + "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc"
    474             + "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3"
    475             + "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk"
    476             + "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH"
    477             + "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs"
    478             + "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq"
    479             + "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg"
    480             + "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu"
    481             + "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD"
    482             + "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH"
    483             + "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0"
    484             + "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w"
    485             + "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf"
    486             + "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg"
    487             + "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT"
    488             + "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB"
    489             + "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW"
    490             + "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY"
    491             + "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
    492 
    493     protected int startServer(String name) {
    494         String keys = useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS;
    495         TestServer server = new TestServer(true, keys);
    496         Thread serverThread = new Thread(server);
    497         serverThread.start();
    498         try {
    499             while (!serverReady) {
    500                 Exception e = server.getException();
    501                 if (e != null) {
    502                     throw new AssertionError(e);
    503                 }
    504                 Thread.currentThread().sleep(50);
    505             }
    506             // give the server 100 millis to accept
    507             Thread.currentThread().sleep(100);
    508         } catch (InterruptedException ignore) {
    509         }
    510         return server.sport;
    511     }
    512 
    513     /**
    514      * Implements a test SSL socket server. It wait for a connection on a given
    515      * port, requests client authentication (if specified), and read 256 bytes
    516      * from the socket.
    517      */
    518     class TestServer implements Runnable {
    519 
    520         public static final int CLIENT_AUTH_NONE = 0;
    521 
    522         public static final int CLIENT_AUTH_WANTED = 1;
    523 
    524         public static final int CLIENT_AUTH_NEEDED = 2;
    525 
    526         private TestTrustManager trustManager;
    527 
    528         private Exception exception;
    529 
    530         String keys;
    531 
    532         private boolean provideKeys;
    533 
    534         int sport;
    535 
    536         public TestServer(boolean provideKeys, String keys) {
    537             this.keys = keys;
    538             this.provideKeys = provideKeys;
    539 
    540             trustManager = new TestTrustManager();
    541         }
    542 
    543         public void run() {
    544             try {
    545                 KeyManager[] keyManagers = provideKeys ? getKeyManagers(keys) : null;
    546                 TrustManager[] trustManagers = new TrustManager[] { trustManager };
    547 
    548                 SSLContext sslContext = SSLContext.getInstance("TLS");
    549                 sslContext.init(keyManagers, trustManagers, null);
    550 
    551                 SSLServerSocket serverSocket = (SSLServerSocket)
    552                         sslContext.getServerSocketFactory().createServerSocket();
    553                 try {
    554                     serverSocket.bind(new InetSocketAddress(port));
    555                     sport = serverSocket.getLocalPort();
    556                     serverReady = true;
    557 
    558                     SSLSocket clientSocket = (SSLSocket)serverSocket.accept();
    559 
    560                     try {
    561                         InputStream stream = clientSocket.getInputStream();
    562                         try {
    563                             for (int i = 0; i < 256; i++) {
    564                                 int j = stream.read();
    565                                 if (i != j) {
    566                                     throw new RuntimeException("Error reading socket, expected " + i
    567                                                                + ", got " + j);
    568                                 }
    569                             }
    570                         } finally {
    571                             stream.close();
    572                         }
    573                     } finally {
    574                         clientSocket.close();
    575                     }
    576                 } finally {
    577                     serverSocket.close();
    578                 }
    579             } catch (Exception ex) {
    580                 exception = ex;
    581             }
    582         }
    583 
    584         public Exception getException() {
    585             return exception;
    586         }
    587 
    588         public X509Certificate[] getChain() {
    589             return trustManager.getChain();
    590         }
    591 
    592     }
    593 
    594     /**
    595      * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
    596      * for the result.
    597      */
    598     private KeyManager[] getKeyManagers(String keys) throws Exception {
    599         byte[] bytes = Base64.decode(keys.getBytes());
    600         InputStream inputStream = new ByteArrayInputStream(bytes);
    601 
    602         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    603         keyStore.load(inputStream, PASSWORD.toCharArray());
    604         inputStream.close();
    605 
    606         String algorithm = KeyManagerFactory.getDefaultAlgorithm();
    607         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    608         keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
    609 
    610         return keyManagerFactory.getKeyManagers();
    611     }
    612 
    613     private SSLSocket getSSLSocket() throws IOException {
    614         return (SSLSocket) SSLSocketFactory.getDefault().createSocket();
    615     }
    616 
    617     private SSLSocket getSSLSocket(InetAddress host, int port) throws IOException {
    618         return (SSLSocket) SSLSocketFactory.getDefault().createSocket(host, port);
    619     }
    620 
    621     private SSLSocket getSSLSocket(String host, int port) throws UnknownHostException, IOException {
    622         return (SSLSocket) SSLSocketFactory.getDefault().createSocket(host, port);
    623     }
    624 
    625     private SSLSocket getSSLSocket(InetAddress host, int port, InetAddress localHost, int localPort)
    626             throws IOException {
    627         return (SSLSocket) SSLSocketFactory.getDefault().createSocket(host,
    628                                                                       port,
    629                                                                       localHost,
    630                                                                       localPort);
    631     }
    632 
    633     private SSLSocket getSSLSocket(String host, int port, InetAddress localHost, int localPort)
    634             throws UnknownHostException, IOException {
    635         return (SSLSocket) SSLSocketFactory.getDefault().createSocket(host,
    636                                                                       port,
    637                                                                       localHost,
    638                                                                       localPort);
    639     }
    640 }
    641