1 /* 2 * Copyright (c) 2018, 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 import java.io.ByteArrayInputStream; 26 import java.io.InputStream; 27 import java.io.OutputStream; 28 import java.security.KeyFactory; 29 import java.security.KeyStore; 30 import java.security.Principal; 31 import java.security.PrivateKey; 32 import java.security.Security; 33 import java.security.cert.Certificate; 34 import java.security.cert.CertificateFactory; 35 import java.security.spec.PKCS8EncodedKeySpec; 36 import java.util.Base64; 37 import java.util.concurrent.CountDownLatch; 38 import java.util.concurrent.ExecutorService; 39 import java.util.concurrent.Executors; 40 import java.util.concurrent.ThreadFactory; 41 import javax.net.ssl.KeyManagerFactory; 42 import javax.net.ssl.SSLContext; 43 import javax.net.ssl.SSLServerSocket; 44 import javax.net.ssl.SSLServerSocketFactory; 45 import javax.net.ssl.SSLSocket; 46 import javax.net.ssl.SSLSocketFactory; 47 import javax.net.ssl.TrustManagerFactory; 48 49 /* 50 * @test 51 * @bug 8206355 52 * @summary Test principal that was sent to the peer during handshake. 53 * @run main/othervm TestSessionLocalPrincipal 54 */ 55 public class TestSessionLocalPrincipal { 56 main(String[] args)57 public static void main(String[] args) throws Exception { 58 59 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 60 for (String tlsProtocol : new String[]{ 61 "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}) { 62 for (boolean clientAuth : new boolean[]{true, false}) { 63 System.out.printf("Protocol %s: Client side auth enabled: %s%n", 64 tlsProtocol, clientAuth); 65 CountDownLatch serverReady = new CountDownLatch(1); 66 Server server = new Server(tlsProtocol, clientAuth, 67 serverReady); 68 server.start(); 69 70 // Wait till server is ready to accept connection. 71 serverReady.await(); 72 new Client(tlsProtocol, clientAuth, server.port).doClientSide(); 73 if (server.serverExc != null) { 74 throw new RuntimeException(server.serverExc); 75 } 76 } 77 } 78 } 79 80 public static class Server implements Runnable { 81 82 private volatile int port = 0; 83 private final String tlsProtocol; 84 private final boolean clientAuth; 85 private final CountDownLatch latch; 86 private volatile Exception serverExc; 87 Server(String tlsProtocol, boolean clientAuth, CountDownLatch latch)88 public Server(String tlsProtocol, boolean clientAuth, 89 CountDownLatch latch) { 90 this.tlsProtocol = tlsProtocol; 91 this.clientAuth = clientAuth; 92 this.latch = latch; 93 } 94 start()95 public void start() { 96 97 ExecutorService executor = null; 98 try { 99 executor = Executors.newCachedThreadPool(new ThreadFactory() { 100 @Override 101 public Thread newThread(Runnable r) { 102 Thread t = Executors.defaultThreadFactory() 103 .newThread(r); 104 t.setDaemon(true); 105 return t; 106 } 107 }); 108 executor.execute(this); 109 } finally { 110 if (executor != null) { 111 executor.shutdown(); 112 } 113 } 114 } 115 116 /* 117 * Define the server side operation. 118 */ doServerSide()119 void doServerSide() throws Exception { 120 121 SSLContext ctx = getSSLContext(tlsProtocol); 122 SSLServerSocketFactory sslssf = ctx.getServerSocketFactory(); 123 SSLServerSocket sslServerSocket 124 = (SSLServerSocket) sslssf.createServerSocket(port); 125 port = sslServerSocket.getLocalPort(); 126 System.out.println("Server listining on port: " + port); 127 sslServerSocket.setEnabledProtocols(new String[]{tlsProtocol}); 128 /* 129 * Signal Client, the server is ready to accept client request. 130 */ 131 latch.countDown(); 132 try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept()) { 133 sslSocket.setNeedClientAuth(this.clientAuth); 134 sslSocket.setSoTimeout(5000); 135 try (InputStream sslIS = sslSocket.getInputStream(); 136 OutputStream sslOS = sslSocket.getOutputStream();) { 137 sslIS.read(); 138 sslOS.write(85); 139 sslOS.flush(); 140 } 141 } finally { 142 sslServerSocket.close(); 143 } 144 } 145 146 @Override run()147 public void run() { 148 try { 149 doServerSide(); 150 } catch (Exception e) { 151 // Print the exception for debug purpose. 152 e.printStackTrace(System.out); 153 serverExc = e; 154 } 155 } 156 } 157 158 /* 159 * Define the client side of the test. 160 */ 161 public static class Client { 162 163 private final int serverPort; 164 private final String tlsProtocol; 165 private final boolean clientAuth; 166 Client(String tlsProtocol, boolean clientAuth, int serverPort)167 public Client(String tlsProtocol, boolean clientAuth, int serverPort) { 168 this.tlsProtocol = tlsProtocol; 169 this.clientAuth = clientAuth; 170 this.serverPort = serverPort; 171 } 172 doClientSide()173 void doClientSide() throws Exception { 174 175 SSLContext ctx = getSSLContext(this.tlsProtocol); 176 SSLSocketFactory sslsf = ctx.getSocketFactory(); 177 try (SSLSocket sslSocket 178 = (SSLSocket) sslsf.createSocket("localhost", serverPort)) { 179 sslSocket.setEnabledProtocols(new String[]{this.tlsProtocol}); 180 Principal principal = sslSocket.getSession().getLocalPrincipal(); 181 if (this.clientAuth && principal == null) { 182 throw new RuntimeException("Principal can not be null"); 183 } 184 if (!this.clientAuth && principal != null) { 185 throw new RuntimeException("Principal should be null"); 186 } 187 try (InputStream sslIS = sslSocket.getInputStream(); 188 OutputStream sslOS = sslSocket.getOutputStream()) { 189 sslOS.write(86); 190 sslOS.flush(); 191 sslIS.read(); 192 } 193 } 194 } 195 } 196 197 // get the ssl context getSSLContext(String tlsProtocol)198 protected static SSLContext getSSLContext(String tlsProtocol) 199 throws Exception { 200 201 // Generate certificate from cert string 202 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 203 204 // Create a key store 205 KeyStore ts = KeyStore.getInstance("PKCS12"); 206 KeyStore ks = KeyStore.getInstance("PKCS12"); 207 ts.load(null, null); 208 ks.load(null, null); 209 char passphrase[] = "passphrase".toCharArray(); 210 211 // Import the trusted cert 212 ts.setCertificateEntry("trusted-cert-" 213 + KeyType.rsa_pkcs1_sha256.getKeyType(), 214 cf.generateCertificate(new ByteArrayInputStream( 215 KeyType.rsa_pkcs1_sha256.getTrustedCert().getBytes()))); 216 217 boolean hasKeyMaterials = KeyType.rsa_pkcs1_sha256.getEndCert() != null 218 && KeyType.rsa_pkcs1_sha256.getPrivateKey() != null; 219 if (hasKeyMaterials) { 220 221 // Generate the private key. 222 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 223 Base64.getMimeDecoder().decode( 224 KeyType.rsa_pkcs1_sha256.getPrivateKey())); 225 KeyFactory kf = KeyFactory.getInstance( 226 KeyType.rsa_pkcs1_sha256.getKeyType()); 227 PrivateKey priKey = kf.generatePrivate(priKeySpec); 228 229 // Generate certificate chain 230 Certificate keyCert = cf.generateCertificate( 231 new ByteArrayInputStream( 232 KeyType.rsa_pkcs1_sha256.getEndCert().getBytes())); 233 Certificate[] chain = new Certificate[]{keyCert}; 234 235 // Import the key entry. 236 ks.setKeyEntry("cert-" + KeyType.rsa_pkcs1_sha256.getKeyType(), 237 priKey, passphrase, chain); 238 } 239 240 // Create SSL context 241 TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); 242 tmf.init(ts); 243 244 SSLContext context = SSLContext.getInstance(tlsProtocol); 245 if (hasKeyMaterials) { 246 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 247 kmf.init(ks, passphrase); 248 context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 249 } else { 250 context.init(null, tmf.getTrustManagers(), null); 251 } 252 return context; 253 } 254 } 255 256 enum KeyType { 257 258 rsa_pkcs1_sha256( 259 "RSA", 260 /** 261 * Signature Algorithm: sha256WithRSAEncryption 262 * Issuer: CN = localhost 263 * Validity Not Before: Jun 4 15:22:04 2018 GMT 264 * Not After: May 30 15:22:04 2038 GMT 265 * Subject: CN = localhost 266 * Public Key Algorithm: rsaEncryption 267 */ 268 "-----BEGIN CERTIFICATE-----\n" 269 + "MIIDBjCCAe6gAwIBAgIUc8yTYekR2LuXkkCJYqWlS/pBMKIwDQYJKoZIhvcNAQEL\n" 270 + "BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE4MDYwNDE1MjIwNFoXDTM4MDUz\n" 271 + "MDE1MjIwNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF\n" 272 + "AAOCAQ8AMIIBCgKCAQEA2jDPGMogc9dq2w5b+FHqbfaGPokRmyObiU8y/l/dqkM5\n" 273 + "9IV+qj8VQUI4NtpdCTWr16812z4AjXrk5HIBrECfQbHPUcm1rme5YVZ0WxV0+Ufy\n" 274 + "hDmrGwDLhkxGqc3hOhRrlF2wdXeUfjIzhvS9+S/401++t/jvq+cqFF1BHnzYOu+l\n" 275 + "nbi/o95Oqo8MlwiRqg3xy3fNRfqXk7DWy+QT8s+Vc3Pcj1EW6K0iJJ23BVTdv6YT\n" 276 + "Ja5IKiWL4XsLht3fWvZwF+PoYfKb+JYflt0rafpxg9xkowe7GnGh2SpV7bJaH/QN\n" 277 + "3PTFEKQWgWHjWwjR171GOzSaEgaklvKde6+zNWeYKwIDAQABo1AwTjAdBgNVHQ4E\n" 278 + "FgQUqCtGe8/Ky4O6pH7xeTUy9yrv4n0wHwYDVR0jBBgwFoAUqCtGe8/Ky4O6pH7x\n" 279 + "eTUy9yrv4n0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAuqch30im\n" 280 + "M09sARarbfK3OExqYK2xoyuUscgTqQNDpNL2gMdXY9e0lTmGVgw9pVYtNZPZRxem\n" 281 + "jR5an2XegvG9qVU6vLENDwLCqZgsTb2gvmXngiG8NVcYd81GNqD228mkgBosNJku\n" 282 + "6BR+C8zlURzsNEt657eVvIp9ObGomdAbWhpdqihBD180PP18DIBWopyfHfJtT5FA\n" 283 + "U2kSPBp+P1EtdceW0zfwv3rF8hwRbnQBzuoYrZfn2PiMYaGUqOgbqUltCMD/Dp9G\n" 284 + "xK0nfAXEwIqHWWnijGwAd6YrszMjBUcSGmlehdF+XZK6jHNlw64RB4WTfavr+rY0\n" 285 + "dTe6g4o5GYr9nQ==\n" 286 + "-----END CERTIFICATE-----\n", 287 // 288 // Private key. 289 // 290 "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaMM8YyiBz12rb\n" 291 + "Dlv4Uept9oY+iRGbI5uJTzL+X92qQzn0hX6qPxVBQjg22l0JNavXrzXbPgCNeuTk\n" 292 + "cgGsQJ9Bsc9RybWuZ7lhVnRbFXT5R/KEOasbAMuGTEapzeE6FGuUXbB1d5R+MjOG\n" 293 + "9L35L/jTX763+O+r5yoUXUEefNg676WduL+j3k6qjwyXCJGqDfHLd81F+peTsNbL\n" 294 + "5BPyz5Vzc9yPURborSIknbcFVN2/phMlrkgqJYvhewuG3d9a9nAX4+hh8pv4lh+W\n" 295 + "3Stp+nGD3GSjB7sacaHZKlXtslof9A3c9MUQpBaBYeNbCNHXvUY7NJoSBqSW8p17\n" 296 + "r7M1Z5grAgMBAAECggEAHs/7vw10TcejEHJTrJqs14CT7qresKDzqw1jLycMn6nE\n" 297 + "unJLs/EaqE+Yrq5hqxZIQTo+CcsUuuYbAuPStqedleJtW6h3nryJImTaI67BCR8O\n" 298 + "8XtPXY3cMAf/hqVLZC9UDey5Ka2Ma9HdEvbnCRSsN/VycnqWJhmMCLouowaQZqoE\n" 299 + "VopscUix8GqELv0vEo2CszZfUjtSVbNTlNgwDf5U7eSKXMuFsnSn/LE7AMvHsEyo\n" 300 + "HatxogwlM/WjpTnf/WIeJY3VhaK10IsP6OEgUn/p4VtI2DQ/TJdgYrvD5vhjY8ip\n" 301 + "XuUPuPILRvJWo8dRXJqa4diXB12q5YhP8iiOp4BgkQKBgQD1GtlOR+JVgOzpQ11h\n" 302 + "s5/iJOsczee80pQscbSRJnzSsIaP9WM8CyJgvbPxIQxLUQeYnxM/bxNKkpJtzxRK\n" 303 + "pob+v4NoRn8PTpqbOp1obmWJT7uHTaoeavQo7r7uZI4i3eEgHCCQkMzpqzz7UFTY\n" 304 + "2Yst7bBTPUivlSVQQBEc8bLpeQKBgQDj47EjpAlh8DmJRTElg58t+XJehXGTqmlx\n" 305 + "nYu8DQLSzGbOQ/Z4srakC1mkM0LHCmULIIWk3KhV1GBCeArv7DlZ9A1SkI95bsq9\n" 306 + "GBeQpovL0PXKkOOWMJBklP/CTECO4eyA8r6c1d8wytBb6MrJ8bi74DdT+JlFjK5A\n" 307 + "zNoeNx6JwwKBgQCehIPABeuSYvRVlDTDqFkh98B6+4wBaatc5xjhuyOFW5dbaVeJ\n" 308 + "kKXmLSpAK6B44WnpQhA/uUWfuBWtoPy9nt+1yARjnxwzuSFyfUEqNiPC32coBYmd\n" 309 + "bIyGIIopQa1PTXJ4wtgoxw1PnmitHHITYPaLeKrN2te0fuAH+7dVodeU+QKBgAct\n" 310 + "VJbaw7Dh7+3yz+lui8TW5lMzwK/13fxGCfCSOFSLO3Gjkk+a0UW5VclmE+RQ333K\n" 311 + "OGtIx8RsO9vcC/wiZGwA06qWAu7AHoJ2D8fudtikbBlFFuXUAbgpOSTVYfMeCmTF\n" 312 + "QFuQIMdYm9dJLZnOkxLXrOZoHeui0poX2Ya6FawhAoGAAI/QCyDbuvnJzGmjSbvl\n" 313 + "5Ndr9lNAansCXaUzXuVLp6dD6PnB8HVCE8tdETZrcXseyTBeltaxAhj+tCybJvDO\n" 314 + "sV8UmPR0w9ibExmUIVGX5BpoRlB/KWxEG3ar/wJbUZVZ2oSdIAZvCvdbN956SLDg\n" 315 + "Pg5M5wrRqs71s2EiIJd0HrU=" 316 ); 317 private final String keyType; 318 private final String trustedCert; 319 private final String endCert; 320 private final String privateKey; 321 KeyType(String keyType, String selfCert, String privateKey)322 private KeyType(String keyType, String selfCert, String privateKey) { 323 this.keyType = keyType; 324 this.trustedCert = selfCert; 325 this.endCert = selfCert; 326 this.privateKey = privateKey; 327 } 328 getKeyType()329 public String getKeyType() { 330 return keyType; 331 } 332 getTrustedCert()333 public String getTrustedCert() { 334 return trustedCert; 335 } 336 getEndCert()337 public String getEndCert() { 338 return endCert; 339 } 340 getPrivateKey()341 public String getPrivateKey() { 342 return privateKey; 343 } 344 } 345