1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 //
  27 // SunJSSE does not support dynamic system properties, no way to re-use
  28 // system properties in samevm/agentvm mode.
  29 //
  30 
  31 /*
  32  * @test
  33  * @bug 7068321
  34  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
  35  * @run main/othervm SSLSocketSNISensitive PKIX www.example.com
  36  * @run main/othervm SSLSocketSNISensitive SunX509 www.example.com
  37  * @run main/othervm SSLSocketSNISensitive PKIX www.example.net
  38  * @run main/othervm SSLSocketSNISensitive SunX509 www.example.net
  39  * @run main/othervm SSLSocketSNISensitive PKIX www.invalid.com
  40  * @run main/othervm SSLSocketSNISensitive SunX509 www.invalid.com
  41  */
  42 
  43 import java.net.*;
  44 import java.util.*;
  45 import java.io.*;
  46 import javax.net.ssl.*;
  47 import java.security.KeyStore;
  48 import java.security.KeyFactory;
  49 import java.security.cert.Certificate;
  50 import java.security.cert.X509Certificate;
  51 import java.security.cert.CertificateFactory;
  52 import java.security.spec.*;
  53 import java.security.interfaces.*;
  54 import java.util.Base64;
  55 
  56 
  57 public class SSLSocketSNISensitive {
  58 
  59     /*
  60      * =============================================================
  61      * Set the various variables needed for the tests, then
  62      * specify what tests to run on each side.
  63      */
  64 
  65     /*
  66      * Should we run the client or server in a separate thread?
  67      * Both sides can throw exceptions, but do you have a preference
  68      * as to which side should be the main thread.
  69      */
  70     static boolean separateServerThread = false;
  71 
  72     /*
  73      * Where do we find the keystores?
  74      */
  75     // Certificates and key used in the test.
  76     static String trustedCertStr =
  77         "-----BEGIN CERTIFICATE-----\n" +
  78         "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
  79         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
  80         "MTIwNDE3MTIwNjA3WhcNMzMwMzI4MTIwNjA3WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
  81         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
  82         "KoZIhvcNAQEBBQADgY0AMIGJAoGBANY+7Enp+1S566kLcKk+qe4Ki6BxaHGZ+v7r\n" +
  83         "vLksx9IQZCbAEf4YLbrZhKzKD3SPIJXyxPFwknAknIh3Knk8mViOZks7T8L3GnJr\n" +
  84         "TBaVvDyTzDJum/QYiahfO2qpfN/Oya2UILmqsBAeLyWpzbQsAyWBXfoUtkOUgnzK\n" +
  85         "fk6QAKYrAgMBAAGjgaUwgaIwHQYDVR0OBBYEFEtmQi7jT1ijXOafPsfkrLwSVu9e\n" +
  86         "MGMGA1UdIwRcMFqAFEtmQi7jT1ijXOafPsfkrLwSVu9eoT+kPTA7MQswCQYDVQQG\n" +
  87         "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
  88         "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
  89         "BQADgYEAkKWxMc4+ODk5WwLXXweB8/IKfVfrizNn0KLEgsZ6xNXFIXDpiPGAFcgl\n" +
  90         "MzFO424JgyvUulsUc/X16Cnuwwntkk6KUG7vEV7h4o9sAV7Cax3gfQE/EZFb4ybn\n" +
  91         "aBm1UsujMKd/ovqbbbxJbmOWzCeo0QfIGleDEyh3NBBZ0i11Kiw=\n" +
  92         "-----END CERTIFICATE-----";
  93 
  94     // web server certificate, www.example.com
  95     static String targetCertStr_A =
  96         "-----BEGIN CERTIFICATE-----\n" +
  97         "MIICVTCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
  98         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
  99         "MTIwNDE3MTIwNjA4WhcNMzIwMTAzMTIwNjA4WjBVMQswCQYDVQQGEwJVUzENMAsG\n" +
 100         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" +
 101         "BAMTD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" +
 102         "4zFp3PZNzsd3ZwG6FNNWO9eSN+UBymlf8oCwpKJM2tIinmMWvWIXnlx/2UXIfSAq\n" +
 103         "QEG3aXkAFyEiGGpQlBbqcfrESsHsiz2pnnm5dG2v/eS0Bwz1jmcuNmwnh3UQw2Vl\n" +
 104         "+BLk8ukdrLjiCT8jARiHExYf1Xg+wUqQ9y8NV26hdaUCAwEAAaNPME0wCwYDVR0P\n" +
 105         "BAQDAgPoMB0GA1UdDgQWBBQwtx+gqzn2w4y82brXlp7tqBYEZDAfBgNVHSMEGDAW\n" +
 106         "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQAJWo8B6Ud+\n" +
 107         "/OU+UcZLihlfMX02OSlK2ZB7mfqpj2G3JT9yb0A+VbY3uuajmaYYIIxl3kXGz/n8\n" +
 108         "M2Q/Ux/MDxG+IFKHC26Kuj4dAQgzjq2pILVPTE2QnaQTNCsgVZtTaC47SG9FRSoC\n" +
 109         "qvnIvn/oTpKSqus76I1cR4joDtiV2OEuVw==\n" +
 110         "-----END CERTIFICATE-----";
 111 
 112     // Private key in the format of PKCS#8
 113     static String targetPrivateKey_A =
 114         "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMxadz2Tc7Hd2cB\n" +
 115         "uhTTVjvXkjflAcppX/KAsKSiTNrSIp5jFr1iF55cf9lFyH0gKkBBt2l5ABchIhhq\n" +
 116         "UJQW6nH6xErB7Is9qZ55uXRtr/3ktAcM9Y5nLjZsJ4d1EMNlZfgS5PLpHay44gk/\n" +
 117         "IwEYhxMWH9V4PsFKkPcvDVduoXWlAgMBAAECgYAqX2nuIyXp3fvgA0twXOYlbRRB\n" +
 118         "Rn3qAXM6qFPJsNeCrFR2k+aG1cev6nKR1FkLNTeMGnWZv06MAcr5IML8i7WXyG4C\n" +
 119         "LY/C0gedn94FDKFlln+bTENwQTGjn4lKysDA+IuNpasTeMCajbic+dPByhIdTOjZ\n" +
 120         "iMCyxbLfpk40zQopVQJBAPyfGmkeHB3GjdbdgujWCGKb2UxBa4O8dy3O4l2yizTn\n" +
 121         "uUqMGcwGY4ciNSVvZQ7jKo4vDmkSuYib4/woPChaNfMCQQDmO0BQuSWYGNtSwV35\n" +
 122         "lafZfX1dNCLKm1iNA6A12evXgvQiE9WT4mqionig0VZW16HtiY4/BkHOcos/K9Um\n" +
 123         "ARQHAkA8mkaRtSF1my5nv1gqVz5Hua+VdZQ/VDUbDiiL5cszc+ulkJqXsWirAG/T\n" +
 124         "fTe3LJQG7A7+8fkEZrF4yoY0AAA1AkEAotokezULj5N9iAL5SzL9wIzQYV4ggfny\n" +
 125         "YATBjXXxKccakwQ+ndWZIiMUeoS4ssLialhTgucVI0fIkU2a/r/ifwJAc6e+5Pvh\n" +
 126         "MghQj/U788Od/v6rgqz/NGsduZ7uilCMcWiwA73OR2MHMH/OIuoofuEPrfuV9isV\n" +
 127         "xVXhgpKfP/pdOA==";
 128 
 129     // web server certificate, www.example.net
 130     static String targetCertStr_B =
 131         "-----BEGIN CERTIFICATE-----\n" +
 132         "MIICVTCCAb6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
 133         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
 134         "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" +
 135         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" +
 136         "BAMTD3d3dy5leGFtcGxlLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" +
 137         "2VlzF1fvWYczDChrUeJiLJ1M/dIShCaOTfYGiXfQGEZCAWTacUclwr+rVMnZ75/c\n" +
 138         "wwg5pNdXRijxMil8DBTS1gFcIFQhosLHvzIAe6ULlg/xB+/L6KBz+NTWfo/2KF6t\n" +
 139         "xatmcToNrCcwi7eUOfbzQje65Tizs56jJYem2m7Rk0ECAwEAAaNPME0wCwYDVR0P\n" +
 140         "BAQDAgPoMB0GA1UdDgQWBBQT/FR0cAWcZQ7h0X79KGki34OSQjAfBgNVHSMEGDAW\n" +
 141         "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQB67cPIT6fz\n" +
 142         "6Ws8fBpYgW2ad4ci66i1WduBD9CpGFE+jRK2feRj6hvYBXocKj0AMWUFIEB2E3hA\n" +
 143         "oIjxcf1GxIpHVl9DjlhxqXbA0Ktl7/NGNRlDSLTizOTl3FB1mMTlOGvXDVmpcFhl\n" +
 144         "HuoP1hYvhTsBwPx5igGNchuPtDIUzL2mXw==\n" +
 145         "-----END CERTIFICATE-----";
 146 
 147     static String targetPrivateKey_B =
 148         "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANlZcxdX71mHMwwo\n" +
 149         "a1HiYiydTP3SEoQmjk32Bol30BhGQgFk2nFHJcK/q1TJ2e+f3MMIOaTXV0Yo8TIp\n" +
 150         "fAwU0tYBXCBUIaLCx78yAHulC5YP8Qfvy+igc/jU1n6P9ihercWrZnE6DawnMIu3\n" +
 151         "lDn280I3uuU4s7OeoyWHptpu0ZNBAgMBAAECgYEAl19H26sfhD+32rDPxZCgBShs\n" +
 152         "dZ33zVe45i0Bcn4iTLWpxKTDyf7eGps4rO2DvfKdYqt40ggzvSZIjUH9JcDe8GmG\n" +
 153         "d3m0ILB7pg4jsFlpyeHpTO8grPLxA1G9s3o0DoFpz/rooqgFfe/DrRDmRoOSkgfV\n" +
 154         "/gseIbgJHRO/Ctyvdh0CQQD6uFd0HxhH1jl/JzvPzIH4LSnPcdEh9zsMEb6uzh75\n" +
 155         "9qL+IHD5N2I/pYZTKqDFIwhJf701+LKag55AX/zrDt7rAkEA3e00AbnwanDMa6Wj\n" +
 156         "+gFekUQveSVra38LiihzCkyVvQpFjbiF1rUhSNQ0dpU5/hmrYF0C6H9VXAesfkUY\n" +
 157         "WhpDgwJAYjgZOop77piDycZK7isFt32p5XSHIzFBVocVFlH1XKM8UyXOXDNQL/Le\n" +
 158         "XnJSrSf+NRzvuNcG0PVC56Ey6brXpQJAY4M4vcltt5zq3R5CQBmbGRJ1IyKXX3Vx\n" +
 159         "bDslEqoyvri7ZYgnY5aG3UxiVgYmIf3KrgQnCLAIS6MZQumiuMxsFwJAK5pEG063\n" +
 160         "9ngUof4fDMvZphqZjZR1zMKz/V/9ge0DWBINaqFgsgebNu+MyImsC8C6WKjGmV/2\n" +
 161         "f1MY0D7sC2vU/Q==";
 162 
 163     // web server certificate, www.invalid.com
 164     static String targetCertStr_C =
 165         "-----BEGIN CERTIFICATE-----\n" +
 166         "MIICVTCCAb6gAwIBAgIBAzANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
 167         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
 168         "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" +
 169         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" +
 170         "BAMTD3d3dy5pbnZhbGlkLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" +
 171         "q6MyQwzCr2nJ41l0frmHL0qULSyW51MhevBC+1W28i0LE/efrmpwV3LdnlQEGFak\n" +
 172         "DLDwtnff3iru8dSMcA7KdWVkivsE7ZTP+qFDaWBAy7XXiSsv6yZ2Nh4jJb0YcD28\n" +
 173         "45zk2nAl5Az1/PuoTi1vpQxzFZKuBm1HGgz3MEZvBvMCAwEAAaNPME0wCwYDVR0P\n" +
 174         "BAQDAgPoMB0GA1UdDgQWBBRRMifrND015Nm8N6gV5X7cg1YjjjAfBgNVHSMEGDAW\n" +
 175         "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQBjkUO6Ri/B\n" +
 176         "uDC2gDMIyL5+NTe/1dPPQYM4HhCNa/KQYvU5lzCKO9Vpa+i+nyrUNNXUu8Tkyq4Y\n" +
 177         "A+aGSm6+FT/i9rFwkYUdorBtD3KfQiwTIWrVERXBkWI5iZNaVZhx0TFy4vUpf65d\n" +
 178         "QtwkbHpC66fdKc2EdLXkuY9KkmtZZJJ7YA==\n" +
 179         "-----END CERTIFICATE-----";
 180 
 181     static String targetPrivateKey_C =
 182         "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKujMkMMwq9pyeNZ\n" +
 183         "dH65hy9KlC0sludTIXrwQvtVtvItCxP3n65qcFdy3Z5UBBhWpAyw8LZ3394q7vHU\n" +
 184         "jHAOynVlZIr7BO2Uz/qhQ2lgQMu114krL+smdjYeIyW9GHA9vOOc5NpwJeQM9fz7\n" +
 185         "qE4tb6UMcxWSrgZtRxoM9zBGbwbzAgMBAAECgYASJDK40Y12Wvki1Z6xkkyOnBRj\n" +
 186         "XfYpRykfxGtgA2RN3qLwHlk7Zzaul46DIKA6LlYynTUkJDF+Ww1cdDnP0lBlwcmM\n" +
 187         "iD0ck3zYyYBLhQHuVbkK3SYE+ANRhM0icvvqANP2at/U4awQcPNEae/KCiecLNu3\n" +
 188         "CJGqyhPDdrEAqPuJGQJBAN46pQC6l3yrcSYE2s53jSmsm2HVVOFlFXjU6k/RMTxG\n" +
 189         "FfDJtGUAOQ37rPQ06ugr/gjLAmmPp+FXozaBdA32D80CQQDFuGRgv3WYqbglIcRL\n" +
 190         "JRs6xlj9w1F97s/aiUenuwhIPNiUoRbV7mnNuZ/sGF0svOVE7SazRjuFX6UqL9Y9\n" +
 191         "HzG/AkEA170pCI8cl4w8eUNHRB9trGKEKjMXhwVCFh7lJf2ZBcGodSzr8w2HVhrZ\n" +
 192         "Ke7hiemDYffrbJ1oxmv05+o+x3r0lQJBAL6adVm2+FyFMFnLZXmzeb59O4jWY5bt\n" +
 193         "Qz6/HG6bpO5OidMuP99YCHMkQQDOs/PO3Y5GuAoW6IY4n/Y9S2B80+0CQBl1/H9/\n" +
 194         "0n/vrb6vW6Azds49tuS82RFAnOhtwTyBEajs08WF8rZQ3WD2RHJnH0+jjfL0anIp\n" +
 195         "dQBSeNN7s7b6rRk=";
 196 
 197     // This is a certificate for client
 198     static String targetCertStr_D=
 199         "-----BEGIN CERTIFICATE-----\n" +
 200         "MIICVDCCAb2gAwIBAgIBBTANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
 201         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
 202         "MTIwNDE3MTIwNjEwWhcNMzIwMTAzMTIwNjEwWjBUMQswCQYDVQQGEwJVUzENMAsG\n" +
 203         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxFzAVBgNV\n" +
 204         "BAMTDkludGVyT3AgVGVzdGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo\n" +
 205         "Q/KoAIAC2ljFfW2KwjnxTzi4NQJeUuk2seqKpsAY8x4O5dvixzUl6142zmljapqi\n" +
 206         "bJloQVpfB+CEc5/l4h5gzGRVzkuqP1oPzDrpZ5GsvmvuHenV/TzCIgX1cLETzQVt\n" +
 207         "6Rk06okoBPnw3hDJEJiEc1Rv7HCE8p/p+SaiHrskwwIDAQABo08wTTALBgNVHQ8E\n" +
 208         "BAMCA+gwHQYDVR0OBBYEFPr91O33RIGfFSqza2AwQIgE4QswMB8GA1UdIwQYMBaA\n" +
 209         "FEtmQi7jT1ijXOafPsfkrLwSVu9eMA0GCSqGSIb3DQEBBAUAA4GBANIDFYgAhoj3\n" +
 210         "B8u1YpqeoEp2Lt9TwrYBshaIrbmBPCwCGio0JIsoov3n8BCSg5F+8MnOtPl+TjeO\n" +
 211         "0Ug+7guPdCk/wg8YNxLHgSsQlpcNJDjWiErqmUPVrg5BPPQb65qMund6KTmMN0y6\n" +
 212         "4EbSmxRpZO/N0/5oK4umTk0EeXKNekBj\n" +
 213         "-----END CERTIFICATE-----";
 214 
 215     static String targetPrivateKey_D =
 216         "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOhD8qgAgALaWMV9\n" +
 217         "bYrCOfFPOLg1Al5S6Tax6oqmwBjzHg7l2+LHNSXrXjbOaWNqmqJsmWhBWl8H4IRz\n" +
 218         "n+XiHmDMZFXOS6o/Wg/MOulnkay+a+4d6dX9PMIiBfVwsRPNBW3pGTTqiSgE+fDe\n" +
 219         "EMkQmIRzVG/scITyn+n5JqIeuyTDAgMBAAECgYBw37yIKp4LRONJLnhSq6sO+0n8\n" +
 220         "Mz6waiiN/Q6XTQwj09pysQAYCGlqwSRrDAqpVsBJWO+Ae+oYLrLMi4hUZnwN75v3\n" +
 221         "pe1nXlrD11RmPLXwBxqFxNSvAs2FgLHZEtwHI7Bn8KybT/8bGkQ8csLceInYtMDD\n" +
 222         "MuTyy2KRk/pj60zIKQJBAPgebQiAH6viFQ88AwHaNvQhlUfwmSC1i6f8LVoeqaHC\n" +
 223         "lnP0LJBwlyDeeEInhHrCR2ibnCB6I/Pig+49XQgabK8CQQDvpJwuGEbsOO+3rkJJ\n" +
 224         "OpOw4toG0QJZdRnT6l8I6BlboQRZSfFh+lGGahvFXkxc4KdUpJ7QPtXU7HHk6Huk\n" +
 225         "8RYtAkA9CW8VGj+wTuuTVdX/jKjcIa7RhbSFwWNbrcOSWdys+Gt+luCnn6rt4QyA\n" +
 226         "aaxDbquWZkFgE+voQR7nap0KM0XtAkAznd0WAJymHM1lXt9gLoHJQ9N6TGKZKiPa\n" +
 227         "BU1a+cMcfV4WbVrUo7oTnZ9Fr73681iXXq3mZOJh7lvJ1llreZIxAkBEnbiTgEf4\n" +
 228         "tvku68jHcRbRPmdS7CBSWNEBaHLOm4pUSTcxVTKKMHw7vmM5/UYUxJ8QNKCYxn6O\n" +
 229         "+vtiBwBawwzN";
 230 
 231     static String[] serverCerts = {targetCertStr_A,
 232                                 targetCertStr_B, targetCertStr_C};
 233     static String[] serverKeys  = {targetPrivateKey_A,
 234                                 targetPrivateKey_B, targetPrivateKey_C};
 235     static String[] clientCerts = {targetCertStr_D};
 236     static String[] clientKeys  = {targetPrivateKey_D};
 237 
 238     static char passphrase[] = "passphrase".toCharArray();
 239 
 240     /*
 241      * Is the server ready to serve?
 242      */
 243     volatile static boolean serverReady = false;
 244 
 245     /*
 246      * Turn on SSL debugging?
 247      */
 248     static boolean debug = false;
 249 
 250     /*
 251      * Define the server side of the test.
 252      *
 253      * If the server prematurely exits, serverReady will be set to true
 254      * to avoid infinite hangs.
 255      */
 256     void doServerSide() throws Exception {
 257         SSLContext context = generateSSLContext(false);
 258         SSLServerSocketFactory sslssf = context.getServerSocketFactory();
 259         SSLServerSocket sslServerSocket =
 260             (SSLServerSocket)sslssf.createServerSocket(serverPort);
 261         serverPort = sslServerSocket.getLocalPort();
 262 
 263         /*
 264          * Signal Client, we're ready for his connect.
 265          */
 266         serverReady = true;
 267 
 268         SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
 269         try {
 270             sslSocket.setSoTimeout(5000);
 271             sslSocket.setSoLinger(true, 5);
 272 
 273             InputStream sslIS = sslSocket.getInputStream();
 274             OutputStream sslOS = sslSocket.getOutputStream();
 275 
 276             sslIS.read();
 277             sslOS.write('A');
 278             sslOS.flush();
 279 
 280             SSLSession session = sslSocket.getSession();
 281             checkCertificate(session.getLocalCertificates(),
 282                                                 clientRequestedHostname);
 283         } finally {
 284             sslSocket.close();
 285             sslServerSocket.close();
 286         }
 287     }
 288 
 289     /*
 290      * Define the client side of the test.
 291      *
 292      * If the server prematurely exits, serverReady will be set to true
 293      * to avoid infinite hangs.
 294      */
 295     void doClientSide() throws Exception {
 296 
 297         /*
 298          * Wait for server to get started.
 299          */
 300         while (!serverReady) {
 301             Thread.sleep(50);
 302         }
 303 
 304         SSLContext context = generateSSLContext(true);
 305         SSLSocketFactory sslsf = context.getSocketFactory();
 306 
 307         SSLSocket sslSocket =
 308             (SSLSocket)sslsf.createSocket("localhost", serverPort);
 309 
 310         SNIHostName serverName = new SNIHostName(clientRequestedHostname);
 311         List<SNIServerName> serverNames = new ArrayList<>(1);
 312         serverNames.add(serverName);
 313         SSLParameters params = sslSocket.getSSLParameters();
 314         params.setServerNames(serverNames);
 315         sslSocket.setSSLParameters(params);
 316 
 317         try {
 318             sslSocket.setSoTimeout(5000);
 319             sslSocket.setSoLinger(true, 5);
 320 
 321             InputStream sslIS = sslSocket.getInputStream();
 322             OutputStream sslOS = sslSocket.getOutputStream();
 323 
 324             sslOS.write('B');
 325             sslOS.flush();
 326             sslIS.read();
 327 
 328             SSLSession session = sslSocket.getSession();
 329             checkCertificate(session.getPeerCertificates(),
 330                                                 clientRequestedHostname);
 331         } finally {
 332             sslSocket.close();
 333         }
 334     }
 335 
 336     private static void checkCertificate(Certificate[] certs,
 337             String hostname) throws Exception {
 338         if (certs != null && certs.length != 0) {
 339             X509Certificate x509Cert = (X509Certificate)certs[0];
 340 
 341             String subject = x509Cert.getSubjectX500Principal().getName();
 342 
 343             if (!subject.contains(hostname)) {
 344                 throw new Exception(
 345                         "Not the expected certificate: " + subject);
 346             }
 347         }
 348     }
 349 
 350     /*
 351      * =============================================================
 352      * The remainder is just support stuff
 353      */
 354     private static String tmAlgorithm;             // trust manager
 355     private static String clientRequestedHostname; // server name indication
 356 
 357     private static void parseArguments(String[] args) {
 358         tmAlgorithm = args[0];
 359         clientRequestedHostname = args[1];
 360     }
 361 
 362     private static SSLContext generateSSLContext(boolean isClient)
 363             throws Exception {
 364 
 365         // generate certificate from cert string
 366         CertificateFactory cf = CertificateFactory.getInstance("X.509");
 367 
 368         // create a key store
 369         KeyStore ks = KeyStore.getInstance("JKS");
 370         ks.load(null, null);
 371 
 372         // import the trused cert
 373         ByteArrayInputStream is =
 374                     new ByteArrayInputStream(trustedCertStr.getBytes());
 375         Certificate trusedCert = cf.generateCertificate(is);
 376         is.close();
 377 
 378         ks.setCertificateEntry("RSA Export Signer", trusedCert);
 379 
 380         String[] certStrs = null;
 381         String[] keyStrs = null;
 382         if (isClient) {
 383             certStrs = clientCerts;
 384             keyStrs = clientKeys;
 385         } else {
 386             certStrs = serverCerts;
 387             keyStrs = serverKeys;
 388         }
 389 
 390         for (int i = 0; i < certStrs.length; i++) {
 391             // generate the private key.
 392             String keySpecStr = keyStrs[i];
 393             PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
 394                                 Base64.getMimeDecoder().decode(keySpecStr));
 395             KeyFactory kf = KeyFactory.getInstance("RSA");
 396             RSAPrivateKey priKey =
 397                     (RSAPrivateKey)kf.generatePrivate(priKeySpec);
 398 
 399             // generate certificate chain
 400             String keyCertStr = certStrs[i];
 401             is = new ByteArrayInputStream(keyCertStr.getBytes());
 402             Certificate keyCert = cf.generateCertificate(is);
 403             is.close();
 404 
 405             Certificate[] chain = new Certificate[2];
 406             chain[0] = keyCert;
 407             chain[1] = trusedCert;
 408 
 409             // import the key entry.
 410             ks.setKeyEntry("key-entry-" + i, priKey, passphrase, chain);
 411         }
 412 
 413         // create SSL context
 414         TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
 415         tmf.init(ks);
 416 
 417         SSLContext ctx = SSLContext.getInstance("TLS");
 418         KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
 419         kmf.init(ks, passphrase);
 420 
 421         ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 422         ks = null;
 423 
 424         return ctx;
 425     }
 426 
 427     // use any free port by default
 428     volatile int serverPort = 0;
 429 
 430     volatile Exception serverException = null;
 431     volatile Exception clientException = null;
 432 
 433     public static void main(String[] args) throws Exception {
 434         if (debug)
 435             System.setProperty("javax.net.debug", "all");
 436 
 437         /*
 438          * Get the customized arguments.
 439          */
 440         parseArguments(args);
 441 
 442         /*
 443          * Start the tests.
 444          */
 445         new SSLSocketSNISensitive();
 446     }
 447 
 448     Thread clientThread = null;
 449     Thread serverThread = null;
 450 
 451     /*
 452      * Primary constructor, used to drive remainder of the test.
 453      *
 454      * Fork off the other side, then do your work.
 455      */
 456     SSLSocketSNISensitive() throws Exception {
 457         try {
 458             if (separateServerThread) {
 459                 startServer(true);
 460                 startClient(false);
 461             } else {
 462                 startClient(true);
 463                 startServer(false);
 464             }
 465         } catch (Exception e) {
 466             // swallow for now.  Show later
 467         }
 468 
 469         /*
 470          * Wait for other side to close down.
 471          */
 472         if (separateServerThread) {
 473             serverThread.join();
 474         } else {
 475             clientThread.join();
 476         }
 477 
 478         /*
 479          * When we get here, the test is pretty much over.
 480          * Which side threw the error?
 481          */
 482         Exception local;
 483         Exception remote;
 484         String whichRemote;
 485 
 486         if (separateServerThread) {
 487             remote = serverException;
 488             local = clientException;
 489             whichRemote = "server";
 490         } else {
 491             remote = clientException;
 492             local = serverException;
 493             whichRemote = "client";
 494         }
 495 
 496         /*
 497          * If both failed, return the curthread's exception, but also
 498          * print the remote side Exception
 499          */
 500         if ((local != null) && (remote != null)) {
 501             System.out.println(whichRemote + " also threw:");
 502             remote.printStackTrace();
 503             System.out.println();
 504             throw local;
 505         }
 506 
 507         if (remote != null) {
 508             throw remote;
 509         }
 510 
 511         if (local != null) {
 512             throw local;
 513         }
 514     }
 515 
 516     void startServer(boolean newThread) throws Exception {
 517         if (newThread) {
 518             serverThread = new Thread() {
 519                 public void run() {
 520                     try {
 521                         doServerSide();
 522                     } catch (Exception e) {
 523                         /*
 524                          * Our server thread just died.
 525                          *
 526                          * Release the client, if not active already...
 527                          */
 528                         System.err.println("Server died, because of " + e);
 529                         serverReady = true;
 530                         serverException = e;
 531                     }
 532                 }
 533             };
 534             serverThread.start();
 535         } else {
 536             try {
 537                 doServerSide();
 538             } catch (Exception e) {
 539                 serverException = e;
 540             } finally {
 541                 serverReady = true;
 542             }
 543         }
 544     }
 545 
 546     void startClient(boolean newThread) throws Exception {
 547         if (newThread) {
 548             clientThread = new Thread() {
 549                 public void run() {
 550                     try {
 551                         doClientSide();
 552                     } catch (Exception e) {
 553                         /*
 554                          * Our client thread just died.
 555                          */
 556                         System.err.println("Client died, because of " + e);
 557                         clientException = e;
 558                     }
 559                 }
 560             };
 561             clientThread.start();
 562         } else {
 563             try {
 564                 doClientSide();
 565             } catch (Exception e) {
 566                 clientException = e;
 567             }
 568         }
 569     }
 570 }