1 /*
   2  * Copyright (c) 1999, 2013, 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 package sun.security.ssl;
  27 
  28 import java.net.Socket;
  29 
  30 import java.io.*;
  31 import java.util.*;
  32 import java.security.*;
  33 import java.security.cert.*;
  34 import java.security.cert.Certificate;
  35 
  36 import javax.net.ssl.*;
  37 
  38 import sun.security.provider.certpath.AlgorithmChecker;
  39 import sun.security.action.GetPropertyAction;
  40 
  41 public abstract class SSLContextImpl extends SSLContextSpi {
  42 
  43     private static final Debug debug = Debug.getInstance("ssl");
  44 
  45     private final EphemeralKeyManager ephemeralKeyManager;
  46     private final SSLSessionContextImpl clientCache;
  47     private final SSLSessionContextImpl serverCache;
  48 
  49     private boolean isInitialized;
  50 
  51     private X509ExtendedKeyManager keyManager;
  52     private X509TrustManager trustManager;
  53     private SecureRandom secureRandom;
  54 
  55     // supported and default protocols
  56     private ProtocolList defaultServerProtocolList;
  57     private ProtocolList defaultClientProtocolList;
  58     private ProtocolList supportedProtocolList;
  59 
  60     // supported and default cipher suites
  61     private CipherSuiteList defaultServerCipherSuiteList;
  62     private CipherSuiteList defaultClientCipherSuiteList;
  63     private CipherSuiteList supportedCipherSuiteList;
  64 
  65     SSLContextImpl() {
  66         ephemeralKeyManager = new EphemeralKeyManager();
  67         clientCache = new SSLSessionContextImpl();
  68         serverCache = new SSLSessionContextImpl();
  69     }
  70 
  71     @Override
  72     protected void engineInit(KeyManager[] km, TrustManager[] tm,
  73                                 SecureRandom sr) throws KeyManagementException {
  74         isInitialized = false;
  75         keyManager = chooseKeyManager(km);
  76 
  77         if (tm == null) {
  78             try {
  79                 TrustManagerFactory tmf = TrustManagerFactory.getInstance(
  80                         TrustManagerFactory.getDefaultAlgorithm());
  81                 tmf.init((KeyStore)null);
  82                 tm = tmf.getTrustManagers();
  83             } catch (Exception e) {
  84                 // eat
  85             }
  86         }
  87         trustManager = chooseTrustManager(tm);
  88 
  89         if (sr == null) {
  90             secureRandom = JsseJce.getSecureRandom();
  91         } else {
  92             if (SunJSSE.isFIPS() &&
  93                         (sr.getProvider() != SunJSSE.cryptoProvider)) {
  94                 throw new KeyManagementException
  95                     ("FIPS mode: SecureRandom must be from provider "
  96                     + SunJSSE.cryptoProvider.getName());
  97             }
  98             secureRandom = sr;
  99         }
 100 
 101         /*
 102          * The initial delay of seeding the random number generator
 103          * could be long enough to cause the initial handshake on our
 104          * first connection to timeout and fail. Make sure it is
 105          * primed and ready by getting some initial output from it.
 106          */
 107         if (debug != null && Debug.isOn("sslctx")) {
 108             System.out.println("trigger seeding of SecureRandom");
 109         }
 110         secureRandom.nextInt();
 111         if (debug != null && Debug.isOn("sslctx")) {
 112             System.out.println("done seeding SecureRandom");
 113         }
 114         isInitialized = true;
 115     }
 116 
 117     private X509TrustManager chooseTrustManager(TrustManager[] tm)
 118             throws KeyManagementException {
 119         // We only use the first instance of X509TrustManager passed to us.
 120         for (int i = 0; tm != null && i < tm.length; i++) {
 121             if (tm[i] instanceof X509TrustManager) {
 122                 if (SunJSSE.isFIPS() &&
 123                         !(tm[i] instanceof X509TrustManagerImpl)) {
 124                     throw new KeyManagementException
 125                         ("FIPS mode: only SunJSSE TrustManagers may be used");
 126                 }
 127 
 128                 if (tm[i] instanceof X509ExtendedTrustManager) {
 129                     return (X509TrustManager)tm[i];
 130                 } else {
 131                     return new AbstractTrustManagerWrapper(
 132                                         (X509TrustManager)tm[i]);
 133                 }
 134             }
 135         }
 136 
 137         // nothing found, return a dummy X509TrustManager.
 138         return DummyX509TrustManager.INSTANCE;
 139     }
 140 
 141     private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
 142             throws KeyManagementException {
 143         for (int i = 0; kms != null && i < kms.length; i++) {
 144             KeyManager km = kms[i];
 145             if (!(km instanceof X509KeyManager)) {
 146                 continue;
 147             }
 148             if (SunJSSE.isFIPS()) {
 149                 // In FIPS mode, require that one of SunJSSE's own keymanagers
 150                 // is used. Otherwise, we cannot be sure that only keys from
 151                 // the FIPS token are used.
 152                 if ((km instanceof X509KeyManagerImpl)
 153                             || (km instanceof SunX509KeyManagerImpl)) {
 154                     return (X509ExtendedKeyManager)km;
 155                 } else {
 156                     // throw exception, we don't want to silently use the
 157                     // dummy keymanager without telling the user.
 158                     throw new KeyManagementException
 159                         ("FIPS mode: only SunJSSE KeyManagers may be used");
 160                 }
 161             }
 162             if (km instanceof X509ExtendedKeyManager) {
 163                 return (X509ExtendedKeyManager)km;
 164             }
 165             if (debug != null && Debug.isOn("sslctx")) {
 166                 System.out.println(
 167                     "X509KeyManager passed to " +
 168                     "SSLContext.init():  need an " +
 169                     "X509ExtendedKeyManager for SSLEngine use");
 170             }
 171             return new AbstractKeyManagerWrapper((X509KeyManager)km);
 172         }
 173 
 174         // nothing found, return a dummy X509ExtendedKeyManager
 175         return DummyX509KeyManager.INSTANCE;
 176     }
 177 
 178     @Override
 179     protected SSLSocketFactory engineGetSocketFactory() {
 180         if (!isInitialized) {
 181             throw new IllegalStateException(
 182                 "SSLContextImpl is not initialized");
 183         }
 184        return new SSLSocketFactoryImpl(this);
 185     }
 186 
 187     @Override
 188     protected SSLServerSocketFactory engineGetServerSocketFactory() {
 189         if (!isInitialized) {
 190             throw new IllegalStateException("SSLContext is not initialized");
 191         }
 192         return new SSLServerSocketFactoryImpl(this);
 193     }
 194 
 195     @Override
 196     protected SSLEngine engineCreateSSLEngine() {
 197         if (!isInitialized) {
 198             throw new IllegalStateException(
 199                 "SSLContextImpl is not initialized");
 200         }
 201         return new SSLEngineImpl(this);
 202     }
 203 
 204     @Override
 205     protected SSLEngine engineCreateSSLEngine(String host, int port) {
 206         if (!isInitialized) {
 207             throw new IllegalStateException(
 208                 "SSLContextImpl is not initialized");
 209         }
 210         return new SSLEngineImpl(this, host, port);
 211     }
 212 
 213     @Override
 214     protected SSLSessionContext engineGetClientSessionContext() {
 215         return clientCache;
 216     }
 217 
 218     @Override
 219     protected SSLSessionContext engineGetServerSessionContext() {
 220         return serverCache;
 221     }
 222 
 223     SecureRandom getSecureRandom() {
 224         return secureRandom;
 225     }
 226 
 227     X509ExtendedKeyManager getX509KeyManager() {
 228         return keyManager;
 229     }
 230 
 231     X509TrustManager getX509TrustManager() {
 232         return trustManager;
 233     }
 234 
 235     EphemeralKeyManager getEphemeralKeyManager() {
 236         return ephemeralKeyManager;
 237     }
 238 
 239     abstract SSLParameters getDefaultServerSSLParams();
 240     abstract SSLParameters getDefaultClientSSLParams();
 241     abstract SSLParameters getSupportedSSLParams();
 242 
 243     // Get supported ProtocolList.
 244     ProtocolList getSuportedProtocolList() {
 245         if (supportedProtocolList == null) {
 246             supportedProtocolList =
 247                 new ProtocolList(getSupportedSSLParams().getProtocols());
 248         }
 249 
 250         return supportedProtocolList;
 251     }
 252 
 253     // Get default ProtocolList.
 254     ProtocolList getDefaultProtocolList(boolean roleIsServer) {
 255         if (roleIsServer) {
 256             if (defaultServerProtocolList == null) {
 257                 defaultServerProtocolList = new ProtocolList(
 258                         getDefaultServerSSLParams().getProtocols());
 259             }
 260 
 261             return defaultServerProtocolList;
 262         } else {
 263             if (defaultClientProtocolList == null) {
 264                 defaultClientProtocolList = new ProtocolList(
 265                         getDefaultClientSSLParams().getProtocols());
 266             }
 267 
 268             return defaultClientProtocolList;
 269         }
 270     }
 271 
 272     // Get supported CipherSuiteList.
 273     CipherSuiteList getSupportedCipherSuiteList() {
 274         // The maintenance of cipher suites needs to be synchronized.
 275         synchronized (this) {
 276             // Clear cache of available ciphersuites.
 277             clearAvailableCache();
 278 
 279             if (supportedCipherSuiteList == null) {
 280                 supportedCipherSuiteList = getApplicableCipherSuiteList(
 281                         getSuportedProtocolList(), false);
 282             }
 283 
 284             return supportedCipherSuiteList;
 285         }
 286     }
 287 
 288     // Get default CipherSuiteList.
 289     CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
 290         // The maintenance of cipher suites needs to be synchronized.
 291         synchronized (this) {
 292             // Clear cache of available ciphersuites.
 293             clearAvailableCache();
 294 
 295             if (roleIsServer) {
 296                 if (defaultServerCipherSuiteList == null) {
 297                     defaultServerCipherSuiteList = getApplicableCipherSuiteList(
 298                         getDefaultProtocolList(true), true);
 299                 }
 300 
 301                 return defaultServerCipherSuiteList;
 302             } else {
 303                 if (defaultClientCipherSuiteList == null) {
 304                     defaultClientCipherSuiteList = getApplicableCipherSuiteList(
 305                         getDefaultProtocolList(false), true);
 306                 }
 307 
 308                 return defaultClientCipherSuiteList;
 309             }
 310         }
 311     }
 312 
 313     /**
 314      * Return whether a protocol list is the original default enabled
 315      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
 316      */
 317     boolean isDefaultProtocolList(ProtocolList protocols) {
 318         return (protocols == defaultServerProtocolList) ||
 319                (protocols == defaultClientProtocolList);
 320     }
 321 
 322 
 323     /*
 324      * Return the list of all available CipherSuites with a priority of
 325      * minPriority or above.
 326      */
 327     private CipherSuiteList getApplicableCipherSuiteList(
 328             ProtocolList protocols, boolean onlyEnabled) {
 329 
 330         int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
 331         if (onlyEnabled) {
 332             minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
 333         }
 334 
 335         Collection<CipherSuite> allowedCipherSuites =
 336                                     CipherSuite.allowedCipherSuites();
 337 
 338         TreeSet<CipherSuite> suites = new TreeSet<>();
 339         if (!(protocols.collection().isEmpty()) &&
 340                 protocols.min.v != ProtocolVersion.NONE.v) {
 341             for (CipherSuite suite : allowedCipherSuites) {
 342                 if (!suite.allowed || suite.priority < minPriority) {
 343                     continue;
 344                 }
 345 
 346                 if (suite.isAvailable() &&
 347                         suite.obsoleted > protocols.min.v &&
 348                         suite.supported <= protocols.max.v) {
 349                     if (SSLAlgorithmConstraints.DEFAULT.permits(
 350                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
 351                             suite.name, null)) {
 352                         suites.add(suite);
 353                     }
 354                 } else if (debug != null &&
 355                         Debug.isOn("sslctx") && Debug.isOn("verbose")) {
 356                     if (suite.obsoleted <= protocols.min.v) {
 357                         System.out.println(
 358                             "Ignoring obsoleted cipher suite: " + suite);
 359                     } else if (suite.supported > protocols.max.v) {
 360                         System.out.println(
 361                             "Ignoring unsupported cipher suite: " + suite);
 362                     } else {
 363                         System.out.println(
 364                             "Ignoring unavailable cipher suite: " + suite);
 365                     }
 366                 }
 367             }
 368         }
 369 
 370         return new CipherSuiteList(suites);
 371     }
 372 
 373     /**
 374      * Clear cache of available ciphersuites. If we support all ciphers
 375      * internally, there is no need to clear the cache and calling this
 376      * method has no effect.
 377      *
 378      * Note that every call to clearAvailableCache() and the maintenance of
 379      * cipher suites need to be synchronized with this instance.
 380      */
 381     private void clearAvailableCache() {
 382         if (CipherSuite.DYNAMIC_AVAILABILITY) {
 383             supportedCipherSuiteList = null;
 384             defaultServerCipherSuiteList = null;
 385             defaultClientCipherSuiteList = null;
 386             CipherSuite.BulkCipher.clearAvailableCache();
 387             JsseJce.clearEcAvailable();
 388         }
 389     }
 390 
 391     /*
 392      * The SSLContext implementation for TLS/SSL algorithm
 393      *
 394      * SSL/TLS protocols specify the forward compatibility and version
 395      * roll-back attack protections, however, a number of SSL/TLS server
 396      * vendors did not implement these aspects properly, and some current
 397      * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
 398      *
 399      * Considering above interoperability issues, SunJSSE will not set
 400      * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
 401      *
 402      * For SSL/TLS servers, there is no such interoperability issues as
 403      * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
 404      * enabled protocols for server by default.
 405      *
 406      * We may change the behavior when popular TLS/SSL vendors support TLS
 407      * forward compatibility properly.
 408      *
 409      * SSLv2Hello is no longer necessary.  This interoperability option was
 410      * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
 411      * and there were a fair number of SSLv2-only servers deployed.  Because
 412      * of the security issues in SSLv2, it is rarely (if ever) used, as
 413      * deployments should now be using SSLv3 and TLSv1.
 414      *
 415      * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
 416      * by default. Applications still can use it by enabling SSLv2Hello with
 417      * the series of setEnabledProtocols APIs.
 418      */
 419 
 420     /*
 421      * The base abstract SSLContext implementation.
 422      *
 423      * This abstract class encapsulates supported and the default server
 424      * SSL parameters.
 425      *
 426      * @see SSLContext
 427      */
 428     private abstract static class AbstractSSLContext extends SSLContextImpl {
 429         // parameters
 430         private static final SSLParameters defaultServerSSLParams;
 431         private static final SSLParameters supportedSSLParams;
 432 
 433         static {
 434             // supported SSL parameters
 435             supportedSSLParams = new SSLParameters();
 436 
 437             // candidates for available protocols
 438             ProtocolVersion[] candidates;
 439 
 440             if (SunJSSE.isFIPS()) {
 441                 supportedSSLParams.setProtocols(new String[] {
 442                     ProtocolVersion.TLS10.name,
 443                     ProtocolVersion.TLS11.name,
 444                     ProtocolVersion.TLS12.name
 445                 });
 446 
 447                 candidates = new ProtocolVersion[] {
 448                     ProtocolVersion.TLS10,
 449                     ProtocolVersion.TLS11,
 450                     ProtocolVersion.TLS12
 451                 };
 452             } else {
 453                 supportedSSLParams.setProtocols(new String[] {
 454                     ProtocolVersion.SSL20Hello.name,
 455                     ProtocolVersion.SSL30.name,
 456                     ProtocolVersion.TLS10.name,
 457                     ProtocolVersion.TLS11.name,
 458                     ProtocolVersion.TLS12.name
 459                 });
 460 
 461                 candidates = new ProtocolVersion[] {
 462                     ProtocolVersion.SSL20Hello,
 463                     ProtocolVersion.SSL30,
 464                     ProtocolVersion.TLS10,
 465                     ProtocolVersion.TLS11,
 466                     ProtocolVersion.TLS12
 467                 };
 468             }
 469 
 470             defaultServerSSLParams = new SSLParameters();
 471             defaultServerSSLParams.setProtocols(
 472                 getAvailableProtocols(candidates).toArray(new String[0]));
 473         }
 474 
 475         @Override
 476         SSLParameters getDefaultServerSSLParams() {
 477             return defaultServerSSLParams;
 478         }
 479 
 480         @Override
 481         SSLParameters getSupportedSSLParams() {
 482             return supportedSSLParams;
 483         }
 484 
 485         static List<String> getAvailableProtocols(
 486                 ProtocolVersion[] protocolCandidates) {
 487 
 488             List<String> availableProtocols = Collections.<String>emptyList();
 489             if (protocolCandidates !=  null && protocolCandidates.length != 0) {
 490                 availableProtocols = new ArrayList<>(protocolCandidates.length);
 491                 for (ProtocolVersion p : protocolCandidates) {
 492                     if (ProtocolVersion.availableProtocols.contains(p)) {
 493                         availableProtocols.add(p.name);
 494                     }
 495                 }
 496             }
 497 
 498             return availableProtocols;
 499         }
 500     }
 501 
 502     /*
 503      * The SSLContext implementation for SSLv3 and TLS10 algorithm
 504      *
 505      * @see SSLContext
 506      */
 507     public static final class TLS10Context extends AbstractSSLContext {
 508         private static final SSLParameters defaultClientSSLParams;
 509 
 510         static {
 511             // candidates for available protocols
 512             ProtocolVersion[] candidates;
 513             if (SunJSSE.isFIPS()) {
 514                 candidates = new ProtocolVersion[] {
 515                     ProtocolVersion.TLS10
 516                 };
 517             } else {
 518                 candidates = new ProtocolVersion[] {
 519                     ProtocolVersion.SSL30,
 520                     ProtocolVersion.TLS10
 521                 };
 522             }
 523 
 524             defaultClientSSLParams = new SSLParameters();
 525             defaultClientSSLParams.setProtocols(
 526                 getAvailableProtocols(candidates).toArray(new String[0]));
 527         }
 528 
 529         @Override
 530         SSLParameters getDefaultClientSSLParams() {
 531             return defaultClientSSLParams;
 532         }
 533     }
 534 
 535     /*
 536      * The SSLContext implementation for TLS11 algorithm
 537      *
 538      * @see SSLContext
 539      */
 540     public static final class TLS11Context extends AbstractSSLContext {
 541         private static final SSLParameters defaultClientSSLParams;
 542 
 543         static {
 544             // candidates for available protocols
 545             ProtocolVersion[] candidates;
 546             if (SunJSSE.isFIPS()) {
 547                 candidates = new ProtocolVersion[] {
 548                     ProtocolVersion.TLS10,
 549                     ProtocolVersion.TLS11
 550                 };
 551             } else {
 552                 candidates = new ProtocolVersion[] {
 553                     ProtocolVersion.SSL30,
 554                     ProtocolVersion.TLS10,
 555                     ProtocolVersion.TLS11
 556                 };
 557             }
 558 
 559             defaultClientSSLParams = new SSLParameters();
 560             defaultClientSSLParams.setProtocols(
 561                 getAvailableProtocols(candidates).toArray(new String[0]));
 562         }
 563 
 564         @Override
 565         SSLParameters getDefaultClientSSLParams() {
 566             return defaultClientSSLParams;
 567         }
 568     }
 569 
 570     /*
 571      * The SSLContext implementation for TLS12 algorithm
 572      *
 573      * @see SSLContext
 574      */
 575     public static final class TLS12Context extends AbstractSSLContext {
 576         private static final SSLParameters defaultClientSSLParams;
 577 
 578         static {
 579             // candidates for available protocols
 580             ProtocolVersion[] candidates;
 581             if (SunJSSE.isFIPS()) {
 582                 candidates = new ProtocolVersion[] {
 583                     ProtocolVersion.TLS10,
 584                     ProtocolVersion.TLS11,
 585                     ProtocolVersion.TLS12
 586                 };
 587             } else {
 588                 candidates = new ProtocolVersion[] {
 589                     ProtocolVersion.SSL30,
 590                     ProtocolVersion.TLS10,
 591                     ProtocolVersion.TLS11,
 592                     ProtocolVersion.TLS12
 593                 };
 594             }
 595 
 596             defaultClientSSLParams = new SSLParameters();
 597             defaultClientSSLParams.setProtocols(
 598                 getAvailableProtocols(candidates).toArray(new String[0]));
 599         }
 600 
 601         @Override
 602         SSLParameters getDefaultClientSSLParams() {
 603             return defaultClientSSLParams;
 604         }
 605     }
 606 
 607     /*
 608      * The SSLContext implementation for customized TLS protocols
 609      *
 610      * @see SSLContext
 611      */
 612     private static class CustomizedSSLContext extends AbstractSSLContext {
 613         private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
 614         private static final SSLParameters defaultClientSSLParams;
 615         private static IllegalArgumentException reservedException = null;
 616 
 617         // Don't want a java.lang.LinkageError for illegal system property.
 618         //
 619         // Please don't throw exception in this static block.  Otherwise,
 620         // java.lang.LinkageError may be thrown during the instantiation of
 621         // the provider service. Instead, let's handle the initialization
 622         // exception in constructor.
 623         static {
 624             // candidates for available protocols
 625             ProtocolVersion[] candidates;
 626 
 627             String property = AccessController.doPrivileged(
 628                     new GetPropertyAction(PROPERTY_NAME));
 629             if (property == null || property.length() == 0) {
 630                 // the default enabled client TLS protocols
 631                 if (SunJSSE.isFIPS()) {
 632                     candidates = new ProtocolVersion[] {
 633                         ProtocolVersion.TLS10,
 634                         ProtocolVersion.TLS11,
 635                         ProtocolVersion.TLS12
 636                     };
 637                 } else {
 638                     candidates = new ProtocolVersion[] {
 639                         ProtocolVersion.SSL30,
 640                         ProtocolVersion.TLS10,
 641                         ProtocolVersion.TLS11,
 642                         ProtocolVersion.TLS12
 643                     };
 644                 }
 645             } else {
 646                 // remove double quote marks from beginning/end of the property
 647                 if (property.length() > 1 && property.charAt(0) == '"' &&
 648                         property.charAt(property.length() - 1) == '"') {
 649                     property = property.substring(1, property.length() - 1);
 650                 }
 651 
 652                 String[] protocols = null;
 653                 if (property != null && property.length() != 0) {
 654                     protocols = property.split(",");
 655                 } else {
 656                     reservedException = new IllegalArgumentException(
 657                         "No protocol specified in " +
 658                         PROPERTY_NAME + " system property");
 659                     protocols = new String[0];
 660                 }
 661 
 662                 candidates = new ProtocolVersion[protocols.length];
 663                 for (int i = 0; i < protocols.length; i++) {
 664                     protocols[i] = protocols[i].trim();
 665                     // Is it a supported protocol name?
 666                     try {
 667                         candidates[i] = ProtocolVersion.valueOf(protocols[i]);
 668                     } catch (IllegalArgumentException iae) {
 669                         reservedException = new IllegalArgumentException(
 670                             PROPERTY_NAME + ": " + protocols[i] +
 671                             " is not a standard SSL/TLS protocol name", iae);
 672                         break;
 673                     }
 674                 }
 675 
 676                 if ((reservedException == null) && SunJSSE.isFIPS()) {
 677                     for (ProtocolVersion protocolVersion : candidates) {
 678                         if (ProtocolVersion.SSL20Hello.v == protocolVersion.v ||
 679                                 ProtocolVersion.SSL30.v == protocolVersion.v) {
 680                             reservedException = new IllegalArgumentException(
 681                                     PROPERTY_NAME + ": " + protocolVersion +
 682                                     " is not FIPS compliant");
 683                         }
 684                     }
 685                 }
 686             }
 687 
 688             defaultClientSSLParams = new SSLParameters();
 689             if (reservedException == null) {
 690                 defaultClientSSLParams.setProtocols(
 691                     getAvailableProtocols(candidates).toArray(new String[0]));
 692             }
 693         }
 694 
 695         protected CustomizedSSLContext() {
 696             if (reservedException != null) {
 697                 throw reservedException;
 698             }
 699         }
 700 
 701         @Override
 702         SSLParameters getDefaultClientSSLParams() {
 703             return defaultClientSSLParams;
 704         }
 705     }
 706 
 707     /*
 708      * The SSLContext implementation for default "TLS" algorithm
 709      *
 710      * @see SSLContext
 711      */
 712     public static final class TLSContext extends CustomizedSSLContext {
 713         // use the default constructor and methods
 714     }
 715 
 716     /*
 717      * The SSLContext implementation for default "Default" algorithm
 718      *
 719      * @see SSLContext
 720      */
 721     public static final class DefaultSSLContext extends CustomizedSSLContext {
 722         private static final String NONE = "NONE";
 723         private static final String P11KEYSTORE = "PKCS11";
 724 
 725         private static volatile SSLContextImpl defaultImpl;
 726 
 727         private static TrustManager[] defaultTrustManagers;
 728         private static KeyManager[] defaultKeyManagers;
 729 
 730         public DefaultSSLContext() throws Exception {
 731             try {
 732                 super.engineInit(getDefaultKeyManager(),
 733                         getDefaultTrustManager(), null);
 734             } catch (Exception e) {
 735                 if (debug != null && Debug.isOn("defaultctx")) {
 736                     System.out.println("default context init failed: " + e);
 737                 }
 738                 throw e;
 739             }
 740 
 741             if (defaultImpl == null) {
 742                 defaultImpl = this;
 743             }
 744         }
 745 
 746         @Override
 747         protected void engineInit(KeyManager[] km, TrustManager[] tm,
 748             SecureRandom sr) throws KeyManagementException {
 749             throw new KeyManagementException
 750                 ("Default SSLContext is initialized automatically");
 751         }
 752 
 753         static synchronized SSLContextImpl getDefaultImpl() throws Exception {
 754             if (defaultImpl == null) {
 755                 new DefaultSSLContext();
 756             }
 757             return defaultImpl;
 758         }
 759 
 760         private static synchronized TrustManager[] getDefaultTrustManager()
 761                 throws Exception {
 762             if (defaultTrustManagers != null) {
 763                 return defaultTrustManagers;
 764             }
 765 
 766             KeyStore ks =
 767                 TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
 768 
 769             TrustManagerFactory tmf = TrustManagerFactory.getInstance(
 770                 TrustManagerFactory.getDefaultAlgorithm());
 771             tmf.init(ks);
 772             defaultTrustManagers = tmf.getTrustManagers();
 773             return defaultTrustManagers;
 774         }
 775 
 776         private static synchronized KeyManager[] getDefaultKeyManager()
 777                 throws Exception {
 778             if (defaultKeyManagers != null) {
 779                 return defaultKeyManagers;
 780             }
 781 
 782             final Map<String,String> props = new HashMap<>();
 783             AccessController.doPrivileged(
 784                         new PrivilegedExceptionAction<Object>() {
 785                 @Override
 786                 public Object run() throws Exception {
 787                     props.put("keyStore",  System.getProperty(
 788                                 "javax.net.ssl.keyStore", ""));
 789                     props.put("keyStoreType", System.getProperty(
 790                                 "javax.net.ssl.keyStoreType",
 791                                 KeyStore.getDefaultType()));
 792                     props.put("keyStoreProvider", System.getProperty(
 793                                 "javax.net.ssl.keyStoreProvider", ""));
 794                     props.put("keyStorePasswd", System.getProperty(
 795                                 "javax.net.ssl.keyStorePassword", ""));
 796                     return null;
 797                 }
 798             });
 799 
 800             final String defaultKeyStore = props.get("keyStore");
 801             String defaultKeyStoreType = props.get("keyStoreType");
 802             String defaultKeyStoreProvider = props.get("keyStoreProvider");
 803             if (debug != null && Debug.isOn("defaultctx")) {
 804                 System.out.println("keyStore is : " + defaultKeyStore);
 805                 System.out.println("keyStore type is : " +
 806                                         defaultKeyStoreType);
 807                 System.out.println("keyStore provider is : " +
 808                                         defaultKeyStoreProvider);
 809             }
 810 
 811             if (P11KEYSTORE.equals(defaultKeyStoreType) &&
 812                     !NONE.equals(defaultKeyStore)) {
 813                 throw new IllegalArgumentException("if keyStoreType is "
 814                     + P11KEYSTORE + ", then keyStore must be " + NONE);
 815             }
 816 
 817             FileInputStream fs = null;
 818             KeyStore ks = null;
 819             char[] passwd = null;
 820             try {
 821                 if (defaultKeyStore.length() != 0 &&
 822                         !NONE.equals(defaultKeyStore)) {
 823                     fs = AccessController.doPrivileged(
 824                             new PrivilegedExceptionAction<FileInputStream>() {
 825                         @Override
 826                         public FileInputStream run() throws Exception {
 827                             return new FileInputStream(defaultKeyStore);
 828                         }
 829                     });
 830                 }
 831 
 832                 String defaultKeyStorePassword = props.get("keyStorePasswd");
 833                 if (defaultKeyStorePassword.length() != 0) {
 834                     passwd = defaultKeyStorePassword.toCharArray();
 835                 }
 836 
 837                 /**
 838                  * Try to initialize key store.
 839                  */
 840                 if ((defaultKeyStoreType.length()) != 0) {
 841                     if (debug != null && Debug.isOn("defaultctx")) {
 842                         System.out.println("init keystore");
 843                     }
 844                     if (defaultKeyStoreProvider.length() == 0) {
 845                         ks = KeyStore.getInstance(defaultKeyStoreType);
 846                     } else {
 847                         ks = KeyStore.getInstance(defaultKeyStoreType,
 848                                             defaultKeyStoreProvider);
 849                     }
 850 
 851                     // if defaultKeyStore is NONE, fs will be null
 852                     ks.load(fs, passwd);
 853                 }
 854             } finally {
 855                 if (fs != null) {
 856                     fs.close();
 857                     fs = null;
 858                 }
 859             }
 860 
 861             /*
 862              * Try to initialize key manager.
 863              */
 864             if (debug != null && Debug.isOn("defaultctx")) {
 865                 System.out.println("init keymanager of type " +
 866                     KeyManagerFactory.getDefaultAlgorithm());
 867             }
 868             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
 869                 KeyManagerFactory.getDefaultAlgorithm());
 870 
 871             if (P11KEYSTORE.equals(defaultKeyStoreType)) {
 872                 kmf.init(ks, null); // do not pass key passwd if using token
 873             } else {
 874                 kmf.init(ks, passwd);
 875             }
 876 
 877             defaultKeyManagers = kmf.getKeyManagers();
 878             return defaultKeyManagers;
 879         }
 880     }
 881 
 882 }
 883 
 884 
 885 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
 886             implements X509TrustManager {
 887 
 888     // the delegated trust manager
 889     private final X509TrustManager tm;
 890 
 891     AbstractTrustManagerWrapper(X509TrustManager tm) {
 892         this.tm = tm;
 893     }
 894 
 895     @Override
 896     public void checkClientTrusted(X509Certificate[] chain, String authType)
 897         throws CertificateException {
 898         tm.checkClientTrusted(chain, authType);
 899     }
 900 
 901     @Override
 902     public void checkServerTrusted(X509Certificate[] chain, String authType)
 903         throws CertificateException {
 904         tm.checkServerTrusted(chain, authType);
 905     }
 906 
 907     @Override
 908     public X509Certificate[] getAcceptedIssuers() {
 909         return tm.getAcceptedIssuers();
 910     }
 911 
 912     @Override
 913     public void checkClientTrusted(X509Certificate[] chain, String authType,
 914                 Socket socket) throws CertificateException {
 915         tm.checkClientTrusted(chain, authType);
 916         checkAdditionalTrust(chain, authType, socket, true);
 917     }
 918 
 919     @Override
 920     public void checkServerTrusted(X509Certificate[] chain, String authType,
 921             Socket socket) throws CertificateException {
 922         tm.checkServerTrusted(chain, authType);
 923         checkAdditionalTrust(chain, authType, socket, false);
 924     }
 925 
 926     @Override
 927     public void checkClientTrusted(X509Certificate[] chain, String authType,
 928             SSLEngine engine) throws CertificateException {
 929         tm.checkClientTrusted(chain, authType);
 930         checkAdditionalTrust(chain, authType, engine, true);
 931     }
 932 
 933     @Override
 934     public void checkServerTrusted(X509Certificate[] chain, String authType,
 935             SSLEngine engine) throws CertificateException {
 936         tm.checkServerTrusted(chain, authType);
 937         checkAdditionalTrust(chain, authType, engine, false);
 938     }
 939 
 940     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
 941                 Socket socket, boolean isClient) throws CertificateException {
 942         if (socket != null && socket.isConnected() &&
 943                                     socket instanceof SSLSocket) {
 944 
 945             SSLSocket sslSocket = (SSLSocket)socket;
 946             SSLSession session = sslSocket.getHandshakeSession();
 947             if (session == null) {
 948                 throw new CertificateException("No handshake session");
 949             }
 950 
 951             // check endpoint identity
 952             String identityAlg = sslSocket.getSSLParameters().
 953                                         getEndpointIdentificationAlgorithm();
 954             if (identityAlg != null && identityAlg.length() != 0) {
 955                 String hostname = session.getPeerHost();
 956                 X509TrustManagerImpl.checkIdentity(
 957                                     hostname, chain[0], identityAlg);
 958             }
 959 
 960             // try the best to check the algorithm constraints
 961             ProtocolVersion protocolVersion =
 962                 ProtocolVersion.valueOf(session.getProtocol());
 963             AlgorithmConstraints constraints = null;
 964             if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
 965                 if (session instanceof ExtendedSSLSession) {
 966                     ExtendedSSLSession extSession =
 967                                     (ExtendedSSLSession)session;
 968                     String[] peerSupportedSignAlgs =
 969                             extSession.getLocalSupportedSignatureAlgorithms();
 970 
 971                     constraints = new SSLAlgorithmConstraints(
 972                                     sslSocket, peerSupportedSignAlgs, true);
 973                 } else {
 974                     constraints =
 975                             new SSLAlgorithmConstraints(sslSocket, true);
 976                 }
 977             } else {
 978                 constraints = new SSLAlgorithmConstraints(sslSocket, true);
 979             }
 980 
 981             checkAlgorithmConstraints(chain, constraints);
 982         }
 983     }
 984 
 985     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
 986             SSLEngine engine, boolean isClient) throws CertificateException {
 987         if (engine != null) {
 988             SSLSession session = engine.getHandshakeSession();
 989             if (session == null) {
 990                 throw new CertificateException("No handshake session");
 991             }
 992 
 993             // check endpoint identity
 994             String identityAlg = engine.getSSLParameters().
 995                                         getEndpointIdentificationAlgorithm();
 996             if (identityAlg != null && identityAlg.length() != 0) {
 997                 String hostname = session.getPeerHost();
 998                 X509TrustManagerImpl.checkIdentity(
 999                                     hostname, chain[0], identityAlg);
1000             }
1001 
1002             // try the best to check the algorithm constraints
1003             ProtocolVersion protocolVersion =
1004                 ProtocolVersion.valueOf(session.getProtocol());
1005             AlgorithmConstraints constraints = null;
1006             if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1007                 if (session instanceof ExtendedSSLSession) {
1008                     ExtendedSSLSession extSession =
1009                                     (ExtendedSSLSession)session;
1010                     String[] peerSupportedSignAlgs =
1011                             extSession.getLocalSupportedSignatureAlgorithms();
1012 
1013                     constraints = new SSLAlgorithmConstraints(
1014                                     engine, peerSupportedSignAlgs, true);
1015                 } else {
1016                     constraints =
1017                             new SSLAlgorithmConstraints(engine, true);
1018                 }
1019             } else {
1020                 constraints = new SSLAlgorithmConstraints(engine, true);
1021             }
1022 
1023             checkAlgorithmConstraints(chain, constraints);
1024         }
1025     }
1026 
1027     private void checkAlgorithmConstraints(X509Certificate[] chain,
1028             AlgorithmConstraints constraints) throws CertificateException {
1029 
1030         try {
1031             // Does the certificate chain end with a trusted certificate?
1032             int checkedLength = chain.length - 1;
1033 
1034             Collection<X509Certificate> trustedCerts = new HashSet<>();
1035             X509Certificate[] certs = tm.getAcceptedIssuers();
1036             if ((certs != null) && (certs.length > 0)){
1037                 Collections.addAll(trustedCerts, certs);
1038             }
1039 
1040             if (trustedCerts.contains(chain[checkedLength])) {
1041                     checkedLength--;
1042             }
1043 
1044             // A forward checker, need to check from trust to target
1045             if (checkedLength >= 0) {
1046                 AlgorithmChecker checker = new AlgorithmChecker(constraints);
1047                 checker.init(false);
1048                 for (int i = checkedLength; i >= 0; i--) {
1049                     Certificate cert = chain[i];
1050                     // We don't care about the unresolved critical extensions.
1051                     checker.check(cert, Collections.<String>emptySet());
1052                 }
1053             }
1054         } catch (CertPathValidatorException cpve) {
1055             throw new CertificateException(
1056                 "Certificates does not conform to algorithm constraints");
1057         }
1058     }
1059 }
1060 
1061 // Dummy X509TrustManager implementation, rejects all peer certificates.
1062 // Used if the application did not specify a proper X509TrustManager.
1063 final class DummyX509TrustManager extends X509ExtendedTrustManager
1064             implements X509TrustManager {
1065 
1066     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
1067 
1068     private DummyX509TrustManager() {
1069         // empty
1070     }
1071 
1072     /*
1073      * Given the partial or complete certificate chain
1074      * provided by the peer, build a certificate path
1075      * to a trusted root and return if it can be
1076      * validated and is trusted for client SSL authentication.
1077      * If not, it throws an exception.
1078      */
1079     @Override
1080     public void checkClientTrusted(X509Certificate[] chain, String authType)
1081         throws CertificateException {
1082         throw new CertificateException(
1083             "No X509TrustManager implementation avaiable");
1084     }
1085 
1086     /*
1087      * Given the partial or complete certificate chain
1088      * provided by the peer, build a certificate path
1089      * to a trusted root and return if it can be
1090      * validated and is trusted for server SSL authentication.
1091      * If not, it throws an exception.
1092      */
1093     @Override
1094     public void checkServerTrusted(X509Certificate[] chain, String authType)
1095         throws CertificateException {
1096         throw new CertificateException(
1097             "No X509TrustManager implementation available");
1098     }
1099 
1100     /*
1101      * Return an array of issuer certificates which are trusted
1102      * for authenticating peers.
1103      */
1104     @Override
1105     public X509Certificate[] getAcceptedIssuers() {
1106         return new X509Certificate[0];
1107     }
1108 
1109     @Override
1110     public void checkClientTrusted(X509Certificate[] chain, String authType,
1111                 Socket socket) throws CertificateException {
1112         throw new CertificateException(
1113             "No X509TrustManager implementation available");
1114     }
1115 
1116     @Override
1117     public void checkServerTrusted(X509Certificate[] chain, String authType,
1118             Socket socket) throws CertificateException {
1119         throw new CertificateException(
1120             "No X509TrustManager implementation available");
1121     }
1122 
1123     @Override
1124     public void checkClientTrusted(X509Certificate[] chain, String authType,
1125             SSLEngine engine) throws CertificateException {
1126         throw new CertificateException(
1127             "No X509TrustManager implementation available");
1128     }
1129 
1130     @Override
1131     public void checkServerTrusted(X509Certificate[] chain, String authType,
1132             SSLEngine engine) throws CertificateException {
1133         throw new CertificateException(
1134             "No X509TrustManager implementation available");
1135     }
1136 }
1137 
1138 /*
1139  * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
1140  */
1141 final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
1142 
1143     private final X509KeyManager km;
1144 
1145     AbstractKeyManagerWrapper(X509KeyManager km) {
1146         this.km = km;
1147     }
1148 
1149     @Override
1150     public String[] getClientAliases(String keyType, Principal[] issuers) {
1151         return km.getClientAliases(keyType, issuers);
1152     }
1153 
1154     @Override
1155     public String chooseClientAlias(String[] keyType, Principal[] issuers,
1156             Socket socket) {
1157         return km.chooseClientAlias(keyType, issuers, socket);
1158     }
1159 
1160     @Override
1161     public String[] getServerAliases(String keyType, Principal[] issuers) {
1162         return km.getServerAliases(keyType, issuers);
1163     }
1164 
1165     @Override
1166     public String chooseServerAlias(String keyType, Principal[] issuers,
1167             Socket socket) {
1168         return km.chooseServerAlias(keyType, issuers, socket);
1169     }
1170 
1171     @Override
1172     public X509Certificate[] getCertificateChain(String alias) {
1173         return km.getCertificateChain(alias);
1174     }
1175 
1176     @Override
1177     public PrivateKey getPrivateKey(String alias) {
1178         return km.getPrivateKey(alias);
1179     }
1180 
1181     // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
1182     // X509ExtendedKeymanager. It defines them to return null;
1183 }
1184 
1185 
1186 // Dummy X509KeyManager implementation, never returns any certificates/keys.
1187 // Used if the application did not specify a proper X509TrustManager.
1188 final class DummyX509KeyManager extends X509ExtendedKeyManager {
1189 
1190     static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
1191 
1192     private DummyX509KeyManager() {
1193         // empty
1194     }
1195 
1196     /*
1197      * Get the matching aliases for authenticating the client side of a secure
1198      * socket given the public key type and the list of
1199      * certificate issuer authorities recognized by the peer (if any).
1200      */
1201     @Override
1202     public String[] getClientAliases(String keyType, Principal[] issuers) {
1203         return null;
1204     }
1205 
1206     /*
1207      * Choose an alias to authenticate the client side of a secure
1208      * socket given the public key type and the list of
1209      * certificate issuer authorities recognized by the peer (if any).
1210      */
1211     @Override
1212     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
1213             Socket socket) {
1214         return null;
1215     }
1216 
1217     /*
1218      * Choose an alias to authenticate the client side of an
1219      * engine given the public key type and the list of
1220      * certificate issuer authorities recognized by the peer (if any).
1221      */
1222     @Override
1223     public String chooseEngineClientAlias(
1224             String[] keyTypes, Principal[] issuers, SSLEngine engine) {
1225         return null;
1226     }
1227 
1228     /*
1229      * Get the matching aliases for authenticating the server side of a secure
1230      * socket given the public key type and the list of
1231      * certificate issuer authorities recognized by the peer (if any).
1232      */
1233     @Override
1234     public String[] getServerAliases(String keyType, Principal[] issuers) {
1235         return null;
1236     }
1237 
1238     /*
1239      * Choose an alias to authenticate the server side of a secure
1240      * socket given the public key type and the list of
1241      * certificate issuer authorities recognized by the peer (if any).
1242      */
1243     @Override
1244     public String chooseServerAlias(String keyType, Principal[] issuers,
1245             Socket socket) {
1246         return null;
1247     }
1248 
1249     /*
1250      * Choose an alias to authenticate the server side of an engine
1251      * given the public key type and the list of
1252      * certificate issuer authorities recognized by the peer (if any).
1253      */
1254     @Override
1255     public String chooseEngineServerAlias(
1256             String keyType, Principal[] issuers, SSLEngine engine) {
1257         return null;
1258     }
1259 
1260     /**
1261      * Returns the certificate chain associated with the given alias.
1262      *
1263      * @param alias the alias name
1264      *
1265      * @return the certificate chain (ordered with the user's certificate first
1266      * and the root certificate authority last)
1267      */
1268     @Override
1269     public X509Certificate[] getCertificateChain(String alias) {
1270         return null;
1271     }
1272 
1273     /*
1274      * Returns the key associated with the given alias, using the given
1275      * password to recover it.
1276      *
1277      * @param alias the alias name
1278      *
1279      * @return the requested key
1280      */
1281     @Override
1282     public PrivateKey getPrivateKey(String alias) {
1283         return null;
1284     }
1285 }