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 }