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 
     17 package tests.api.javax.net.ssl;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import libcore.io.Base64;
     22 
     23 import java.io.ByteArrayInputStream;
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.net.InetAddress;
     27 import java.security.KeyStore;
     28 import java.security.SecureRandom;
     29 import java.util.Arrays;
     30 
     31 import javax.net.ssl.KeyManager;
     32 import javax.net.ssl.KeyManagerFactory;
     33 import javax.net.ssl.SSLContext;
     34 import javax.net.ssl.SSLServerSocket;
     35 
     36 public class SSLServerSocketTest extends TestCase {
     37 
     38     // set to true if on Android, false if on RI
     39     boolean useBKS = true;
     40 
     41     /**
     42      * Additional class for SSLServerSocket constructor verification
     43      */
     44     class mySSLServerSocket extends SSLServerSocket {
     45 
     46         public mySSLServerSocket() throws IOException{
     47             super();
     48         }
     49 
     50         public mySSLServerSocket(int port) throws IOException{
     51             super(port);
     52         }
     53 
     54         public mySSLServerSocket(int port, int backlog) throws IOException{
     55             super(port, backlog);
     56         }
     57 
     58         public mySSLServerSocket(int port, int backlog, InetAddress address) throws IOException{
     59             super(port, backlog, address);
     60         }
     61 
     62         public String[] getSupportedCipherSuites() {
     63             return null;
     64         }
     65 
     66         public void setEnabledCipherSuites(String[] suites) {
     67 
     68         }
     69 
     70         public String[] getEnabledCipherSuites() {
     71             return null;
     72         }
     73 
     74         public String[] getSupportedProtocols() {
     75             return null;
     76         }
     77 
     78         public String[] getEnabledProtocols() {
     79             return null;
     80         }
     81 
     82         public void setEnabledProtocols(String[] protocols) {
     83 
     84         }
     85 
     86         public void setEnableSessionCreation(boolean flag) {
     87 
     88         }
     89 
     90         public boolean getEnableSessionCreation() {
     91             return false;
     92         }
     93 
     94         public void setNeedClientAuth(boolean need) {
     95 
     96         }
     97 
     98         public boolean getNeedClientAuth() {
     99             return false;
    100         }
    101 
    102         public boolean getUseClientMode() {
    103             return false;
    104         }
    105 
    106         public void setUseClientMode(boolean mode) {
    107 
    108         }
    109 
    110         public boolean getWantClientAuth() {
    111             return false;
    112         }
    113         public void setWantClientAuth(boolean mode) {
    114 
    115         }
    116     }
    117 
    118     /**
    119      * javax.net.ssl.SSLServerSocket#SSLServerSocket()
    120      */
    121     public void testConstructor() throws Exception {
    122         SSLServerSocket ssl = new mySSLServerSocket();
    123     }
    124 
    125     /**
    126      * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port)
    127      */
    128     public void testConstructor_I() throws Exception {
    129         int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE};
    130 
    131         SSLServerSocket ssl = new mySSLServerSocket(0);
    132 
    133         for (int i = 0; i < port_invalid.length; i++) {
    134             try {
    135                 new mySSLServerSocket(port_invalid[i]);
    136                 fail("IllegalArgumentException should be thrown");
    137             } catch (IllegalArgumentException expected) {
    138             }
    139         }
    140 
    141         try {
    142             new mySSLServerSocket(ssl.getLocalPort());
    143             fail("IOException Expected when opening an already opened port");
    144         } catch (IOException expected) {
    145         }
    146     }
    147 
    148     /**
    149      * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog)
    150      */
    151     public void testConstructor_II() throws Exception {
    152         mySSLServerSocket ssl = new mySSLServerSocket(0, 1);
    153         int[] port_invalid = {-1, Integer.MIN_VALUE, Integer.MAX_VALUE};
    154 
    155         for (int i = 0; i < port_invalid.length; i++) {
    156             try {
    157                 new mySSLServerSocket(port_invalid[i], 1);
    158                 fail("IllegalArgumentException should be thrown");
    159             } catch (IllegalArgumentException expected) {
    160             }
    161         }
    162 
    163         try {
    164             new mySSLServerSocket(ssl.getLocalPort(), 1);
    165             fail("IOException should be thrown");
    166         } catch (IOException expected) {
    167         }
    168     }
    169 
    170     /**
    171      * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog, InetAddress address)
    172      */
    173     public void testConstructor_IIInetAddress() throws Exception {
    174         // A null InetAddress is okay.
    175         new mySSLServerSocket(0, 0, null);
    176 
    177         int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE};
    178 
    179         mySSLServerSocket ssl = new mySSLServerSocket(0, 0, InetAddress.getLocalHost());
    180 
    181         for (int i = 0; i < port_invalid.length; i++) {
    182             try {
    183                 new mySSLServerSocket(port_invalid[i], 1, InetAddress.getLocalHost());
    184                 fail("IllegalArgumentException should be thrown");
    185             } catch (IllegalArgumentException expected) {
    186             }
    187         }
    188 
    189         try {
    190             new mySSLServerSocket(ssl.getLocalPort(), 0, InetAddress.getLocalHost());
    191             fail("IOException should be thrown for");
    192         } catch (IOException expected) {
    193         }
    194     }
    195 
    196     /**
    197      * @throws Exception
    198      * javax.net.ssl.SSLServerSocket#getSupportedCipherSuites()
    199      */
    200     public void test_getSupportedCipherSuites() throws Exception {
    201         SSLServerSocket sss = getSSLServerSocket();
    202         String[] res = sss.getSupportedCipherSuites();
    203         assertNotNull("NULL result", res);
    204         assertTrue("no supported cipher suites available.", res.length > 0);
    205     }
    206 
    207     /**
    208      * @throws IOException
    209      * javax.net.ssl.SSLServerSocket#getEnabledCipherSuites()
    210      * javax.net.ssl.SSLServerSocket#setEnabledCipherSuites(String[] suites)
    211      */
    212     public void test_EnabledCipherSuites() throws Exception {
    213         SSLServerSocket sss = getSSLServerSocket();
    214         try {
    215             sss.setEnabledCipherSuites(null);
    216         } catch (IllegalArgumentException iae) {
    217             //expected
    218         }
    219         String[] unsupportedCipherSuites = {"unsupported"};
    220         try {
    221             sss.setEnabledCipherSuites(unsupportedCipherSuites);
    222         } catch (IllegalArgumentException iae) {
    223             //expected
    224         }
    225         int count = sss.getSupportedCipherSuites().length;
    226         assertTrue("No supported cipher suites", count > 0);
    227         sss.setEnabledCipherSuites(sss.getSupportedCipherSuites());
    228         String[] res = sss.getEnabledCipherSuites();
    229         assertNotNull("NULL result", res);
    230         assertEquals("not all supported cipher suites were enabled",
    231                      Arrays.asList(sss.getSupportedCipherSuites()),
    232                      Arrays.asList(res));
    233     }
    234 
    235     /**
    236      * @throws IOException
    237      * javax.net.ssl.SSLServerSocket#getSupportedProtocols()
    238      */
    239     public void test_getSupportedProtocols() throws Exception {
    240         SSLServerSocket sss = getSSLServerSocket();
    241         String[] res = sss.getSupportedCipherSuites();
    242         assertNotNull("NULL result", res);
    243         assertTrue("no supported protocols available.", res.length > 0);
    244     }
    245 
    246     /**
    247      * @throws IOException
    248      * javax.net.ssl.SSLServerSocket#getEnabledProtocols()
    249      * javax.net.ssl.SSLServerSocket#setEnabledProtocols(String[] protocols)
    250      */
    251     public void test_EnabledProtocols() throws Exception {
    252         SSLServerSocket sss = getSSLServerSocket();
    253         try {
    254             sss.setEnabledProtocols(null);
    255         } catch (IllegalArgumentException iae) {
    256             //expected
    257         }
    258         String[] unsupportedProtocols = {"unsupported"};
    259         try {
    260             sss.setEnabledProtocols(unsupportedProtocols);
    261         } catch (IllegalArgumentException iae) {
    262             //expected
    263         }
    264         int count = sss.getSupportedProtocols().length;
    265         assertTrue("No supported protocols", count > 0);
    266         sss.setEnabledProtocols(sss.getSupportedProtocols());
    267         String[] res = sss.getEnabledProtocols();
    268         assertNotNull("NULL result", res);
    269         assertTrue("no enabled protocols.", res.length == count);
    270     }
    271 
    272     /**
    273      * @throws IOException
    274      * javax.net.ssl.SSLServerSocket#setEnableSessionCreation(boolean flag)
    275      * javax.net.ssl.SSLServerSocket#getEnableSessionCreation()
    276      */
    277     public void test_EnableSessionCreation() throws Exception {
    278         SSLServerSocket sss = getSSLServerSocket();
    279         assertTrue(sss.getEnableSessionCreation());
    280         sss.setEnableSessionCreation(false);
    281         assertFalse(sss.getEnableSessionCreation());
    282         sss.setEnableSessionCreation(true);
    283         assertTrue(sss.getEnableSessionCreation());
    284     }
    285 
    286     /**
    287      * @throws IOException
    288      * javax.net.ssl.SSLServerSocket#setNeedClientAuth(boolean need)
    289      * javax.net.ssl.SSLServerSocket#getNeedClientAuthCreation()
    290      */
    291     public void test_NeedClientAuth() throws Exception {
    292         SSLServerSocket sss = getSSLServerSocket();
    293         sss.setNeedClientAuth(true);
    294         assertTrue(sss.getNeedClientAuth());
    295         sss.setNeedClientAuth(false);
    296         assertFalse(sss.getNeedClientAuth());
    297     }
    298 
    299     /**
    300      * @throws IOException
    301      * javax.net.ssl.SSLServerSocket#getUseClientMode()
    302      * javax.net.ssl.SSLServerSocket#setUseClientMode(boolean mode)
    303      */
    304     public void test_UseClientMode() throws Exception {
    305         SSLServerSocket sss = getSSLServerSocket();
    306         sss.setUseClientMode(false);
    307         assertFalse(sss.getUseClientMode());
    308         sss.setUseClientMode(true);
    309         assertTrue(sss.getUseClientMode());
    310     }
    311 
    312     /**
    313      * @throws IOException
    314      * javax.net.ssl.SSLServerSocket#setWantClientAuth(boolean want)
    315      * javax.net.ssl.SSLServerSocket#getWantClientAuthCreation()
    316      */
    317     public void test_WantClientAuth() throws Exception {
    318         SSLServerSocket sss = getSSLServerSocket();
    319         sss.setWantClientAuth(true);
    320         assertTrue(sss.getWantClientAuth());
    321         sss.setWantClientAuth(false);
    322         assertFalse(sss.getWantClientAuth());
    323     }
    324 
    325 
    326     /**
    327      * Defines the keystore contents for the server, BKS version. Holds just a
    328      * single self-generated key. The subject name is "Test Server".
    329      */
    330     private static final String SERVER_KEYS_BKS =
    331         "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
    332         "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
    333         "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
    334         "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
    335         "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
    336         "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
    337         "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
    338         "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
    339         "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
    340         "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
    341         "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
    342         "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
    343         "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
    344         "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
    345         "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
    346         "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
    347         "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
    348         "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
    349         "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
    350         "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
    351         "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
    352         "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
    353         "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
    354         "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
    355 
    356     /**
    357      * Defines the keystore contents for the server, JKS version. Holds just a
    358      * single self-generated key. The subject name is "Test Server".
    359      */
    360     private static final String SERVER_KEYS_JKS =
    361         "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC" +
    362         "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4" +
    363         "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du" +
    364         "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo" +
    365         "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk" +
    366         "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc" +
    367         "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3" +
    368         "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk" +
    369         "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH" +
    370         "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs" +
    371         "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq" +
    372         "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg" +
    373         "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu" +
    374         "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD" +
    375         "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH" +
    376         "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0" +
    377         "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w" +
    378         "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf" +
    379         "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg" +
    380         "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT" +
    381         "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB" +
    382         "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW" +
    383         "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY" +
    384         "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
    385 
    386     private String PASSWORD = "android";
    387 
    388     /**
    389      * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
    390      * for the result.
    391      */
    392     private KeyManager[] getKeyManagers() throws Exception {
    393         String keys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS);
    394         byte[] bytes = Base64.decode(keys.getBytes());
    395         InputStream inputStream = new ByteArrayInputStream(bytes);
    396 
    397         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    398         keyStore.load(inputStream, PASSWORD.toCharArray());
    399         inputStream.close();
    400 
    401         String algorithm = KeyManagerFactory.getDefaultAlgorithm();
    402         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    403         keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
    404 
    405         return keyManagerFactory.getKeyManagers();
    406     }
    407 
    408     private SSLServerSocket getSSLServerSocket() throws Exception {
    409         SSLContext context = SSLContext.getInstance("TLS");
    410         context.init(getKeyManagers(), null, null);
    411         SSLServerSocket sss = (SSLServerSocket) context.getServerSocketFactory()
    412                 .createServerSocket();
    413         return sss;
    414     }
    415 
    416     public void test_creationStressTest() throws Exception {
    417         KeyManager[] keyManagers = getKeyManagers();
    418         // Test the default codepath, which uses /dev/urandom.
    419         SSLContext sslContext = SSLContext.getInstance("TLS");
    420         sslContext.init(keyManagers, null, null);
    421         for (int i = 0; i < 2048; ++i) {
    422             sslContext.getServerSocketFactory().createServerSocket().close();
    423         }
    424 
    425         // Test the other codepath, which copies a seed from a byte[].
    426         sslContext.init(keyManagers, null, new SecureRandom());
    427         for (int i = 0; i < 2048; ++i) {
    428             sslContext.getServerSocketFactory().createServerSocket().close();
    429         }
    430     }
    431 }
    432