rev 14210 : 8154231: Simplify access to System properties from JDK code
Reviewed-by: rriggs

   1 /*
   2  * Copyright (c) 1999, 2016, 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     // DTLS cookie exchange manager
  56     private volatile HelloCookieManager helloCookieManager;
  57 
  58     private final boolean clientEnableStapling = Debug.getBooleanProperty(
  59             "jdk.tls.client.enableStatusRequestExtension", true);
  60     private final boolean serverEnableStapling = Debug.getBooleanProperty(
  61             "jdk.tls.server.enableStatusRequestExtension", false);
  62     private volatile StatusResponseManager statusResponseManager;
  63 
  64     SSLContextImpl() {
  65         ephemeralKeyManager = new EphemeralKeyManager();
  66         clientCache = new SSLSessionContextImpl();
  67         serverCache = new SSLSessionContextImpl();
  68     }
  69 
  70     @Override
  71     protected void engineInit(KeyManager[] km, TrustManager[] tm,
  72                                 SecureRandom sr) throws KeyManagementException {
  73         isInitialized = false;
  74         keyManager = chooseKeyManager(km);
  75 
  76         if (tm == null) {
  77             try {
  78                 TrustManagerFactory tmf = TrustManagerFactory.getInstance(
  79                         TrustManagerFactory.getDefaultAlgorithm());
  80                 tmf.init((KeyStore)null);
  81                 tm = tmf.getTrustManagers();
  82             } catch (Exception e) {
  83                 // eat
  84             }
  85         }
  86         trustManager = chooseTrustManager(tm);
  87 
  88         if (sr == null) {
  89             secureRandom = JsseJce.getSecureRandom();
  90         } else {
  91             if (SunJSSE.isFIPS() &&
  92                         (sr.getProvider() != SunJSSE.cryptoProvider)) {
  93                 throw new KeyManagementException
  94                     ("FIPS mode: SecureRandom must be from provider "
  95                     + SunJSSE.cryptoProvider.getName());
  96             }
  97             secureRandom = sr;
  98         }
  99 
 100         /*
 101          * The initial delay of seeding the random number generator
 102          * could be long enough to cause the initial handshake on our
 103          * first connection to timeout and fail. Make sure it is
 104          * primed and ready by getting some initial output from it.
 105          */
 106         if (debug != null && Debug.isOn("sslctx")) {
 107             System.out.println("trigger seeding of SecureRandom");
 108         }
 109         secureRandom.nextInt();
 110         if (debug != null && Debug.isOn("sslctx")) {
 111             System.out.println("done seeding SecureRandom");
 112         }
 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     abstract SSLEngine createSSLEngineImpl();
 179     abstract SSLEngine createSSLEngineImpl(String host, int port);
 180 
 181     @Override
 182     protected SSLEngine engineCreateSSLEngine() {
 183         if (!isInitialized) {
 184             throw new IllegalStateException("SSLContext is not initialized");
 185         }
 186         return createSSLEngineImpl();
 187     }
 188 
 189     @Override
 190     protected SSLEngine engineCreateSSLEngine(String host, int port) {
 191         if (!isInitialized) {
 192             throw new IllegalStateException("SSLContext is not initialized");
 193         }
 194         return createSSLEngineImpl(host, port);
 195     }
 196 
 197     @Override
 198     protected SSLSocketFactory engineGetSocketFactory() {
 199         if (!isInitialized) {
 200             throw new IllegalStateException("SSLContext is not initialized");
 201         }
 202        return new SSLSocketFactoryImpl(this);
 203     }
 204 
 205     @Override
 206     protected SSLServerSocketFactory engineGetServerSocketFactory() {
 207         if (!isInitialized) {
 208             throw new IllegalStateException("SSLContext is not initialized");
 209         }
 210         return new SSLServerSocketFactoryImpl(this);
 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     // Used for DTLS in server mode only, see ServerHandshaker.
 240     HelloCookieManager getHelloCookieManager() {
 241         if (!isInitialized) {
 242             throw new IllegalStateException("SSLContext is not initialized");
 243         }
 244 
 245         if (helloCookieManager != null) {
 246             return helloCookieManager;
 247         }
 248 
 249         synchronized (this) {
 250             if (helloCookieManager == null) {
 251                 helloCookieManager = getHelloCookieManager(secureRandom);
 252             }
 253         }
 254 
 255         return helloCookieManager;
 256     }
 257 
 258     HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) {
 259         throw new UnsupportedOperationException(
 260                 "Cookie exchange applies to DTLS only");
 261     }
 262 
 263     StatusResponseManager getStatusResponseManager() {
 264         if (serverEnableStapling && statusResponseManager == null) {
 265             synchronized (this) {
 266                 if (statusResponseManager == null) {
 267                     if (debug != null && Debug.isOn("sslctx")) {
 268                         System.out.println(
 269                                 "Initializing StatusResponseManager");
 270                     }
 271                     statusResponseManager = new StatusResponseManager();
 272                 }
 273             }
 274         }
 275 
 276         return statusResponseManager;
 277     }
 278 
 279     // Get supported ProtocolList.
 280     abstract ProtocolList getSuportedProtocolList();
 281 
 282     // Get default ProtocolList for server mode.
 283     abstract ProtocolList getServerDefaultProtocolList();
 284 
 285     // Get default ProtocolList for client mode.
 286     abstract ProtocolList getClientDefaultProtocolList();
 287 
 288     // Get supported CipherSuiteList.
 289     abstract CipherSuiteList getSupportedCipherSuiteList();
 290 
 291     // Get default CipherSuiteList for server mode.
 292     abstract CipherSuiteList getServerDefaultCipherSuiteList();
 293 
 294     // Get default CipherSuiteList for client mode.
 295     abstract CipherSuiteList getClientDefaultCipherSuiteList();
 296 
 297     // Get default ProtocolList.
 298     ProtocolList getDefaultProtocolList(boolean roleIsServer) {
 299         return roleIsServer ? getServerDefaultProtocolList()
 300                             : getClientDefaultProtocolList();
 301     }
 302 
 303     // Get default CipherSuiteList.
 304     CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
 305         return roleIsServer ? getServerDefaultCipherSuiteList()
 306                             : getClientDefaultCipherSuiteList();
 307     }
 308 
 309     /**
 310      * Return whether a protocol list is the original default enabled
 311      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
 312      */
 313     boolean isDefaultProtocolList(ProtocolList protocols) {
 314         return (protocols == getServerDefaultProtocolList()) ||
 315                (protocols == getClientDefaultProtocolList());
 316     }
 317 
 318     /**
 319      * Return whether a protocol list is the original default enabled
 320      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
 321      */
 322     boolean isDefaultCipherSuiteList(CipherSuiteList cipherSuites) {
 323         return (cipherSuites == getServerDefaultCipherSuiteList()) ||
 324                (cipherSuites == getClientDefaultCipherSuiteList());
 325     }
 326 
 327     /**
 328      * Return whether client or server side stapling has been enabled
 329      * for this SSLContextImpl
 330      * @param isClient true if the caller is operating in a client side role,
 331      * false if acting as a server.
 332      * @return true if stapling has been enabled for the specified role, false
 333      * otherwise.
 334      */
 335     boolean isStaplingEnabled(boolean isClient) {
 336         return isClient ? clientEnableStapling : serverEnableStapling;
 337     }
 338 
 339     /*
 340      * Return the list of all available CipherSuites with a priority of
 341      * minPriority or above.
 342      */
 343     private static CipherSuiteList getApplicableCipherSuiteList(
 344             ProtocolList protocols, boolean onlyEnabled) {
 345 
 346         int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
 347         if (onlyEnabled) {
 348             minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
 349         }
 350 
 351         Collection<CipherSuite> allowedCipherSuites =
 352                                     CipherSuite.allowedCipherSuites();
 353 
 354         TreeSet<CipherSuite> suites = new TreeSet<>();
 355         if (!(protocols.collection().isEmpty()) &&
 356                 protocols.min.v != ProtocolVersion.NONE.v) {
 357             for (CipherSuite suite : allowedCipherSuites) {
 358                 if (!suite.allowed || suite.priority < minPriority) {
 359                     continue;
 360                 }
 361 
 362                 if (suite.isAvailable() &&
 363                         !protocols.min.obsoletes(suite) &&
 364                         protocols.max.supports(suite)) {
 365                     if (SSLAlgorithmConstraints.DEFAULT.permits(
 366                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
 367                             suite.name, null)) {
 368                         suites.add(suite);
 369                     }
 370                 } else if (debug != null &&
 371                         Debug.isOn("sslctx") && Debug.isOn("verbose")) {
 372                     if (protocols.min.obsoletes(suite)) {
 373                         System.out.println(
 374                             "Ignoring obsoleted cipher suite: " + suite);
 375                     } else if (!protocols.max.supports(suite)) {
 376                         System.out.println(
 377                             "Ignoring unsupported cipher suite: " + suite);
 378                     } else {
 379                         System.out.println(
 380                             "Ignoring unavailable cipher suite: " + suite);
 381                     }
 382                 }
 383             }
 384         }
 385 
 386         return new CipherSuiteList(suites);
 387     }
 388 
 389     private static String[] getAvailableProtocols(
 390             ProtocolVersion[] protocolCandidates) {
 391 
 392         List<String> availableProtocols = Collections.<String>emptyList();
 393         if (protocolCandidates !=  null && protocolCandidates.length != 0) {
 394             availableProtocols = new ArrayList<>(protocolCandidates.length);
 395             for (ProtocolVersion p : protocolCandidates) {
 396                 if (ProtocolVersion.availableProtocols.contains(p)) {
 397                     availableProtocols.add(p.name);
 398                 }
 399             }
 400         }
 401 
 402         return availableProtocols.toArray(new String[0]);
 403     }
 404 
 405 
 406     /*
 407      * The SSLContext implementation for SSL/(D)TLS algorithm
 408      *
 409      * SSL/TLS protocols specify the forward compatibility and version
 410      * roll-back attack protections, however, a number of SSL/TLS server
 411      * vendors did not implement these aspects properly, and some current
 412      * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
 413      *
 414      * Considering above interoperability issues, SunJSSE will not set
 415      * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
 416      *
 417      * For SSL/TLS servers, there is no such interoperability issues as
 418      * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
 419      * enabled protocols for server by default.
 420      *
 421      * We may change the behavior when popular TLS/SSL vendors support TLS
 422      * forward compatibility properly.
 423      *
 424      * SSLv2Hello is no longer necessary.  This interoperability option was
 425      * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
 426      * and there were a fair number of SSLv2-only servers deployed.  Because
 427      * of the security issues in SSLv2, it is rarely (if ever) used, as
 428      * deployments should now be using SSLv3 and TLSv1.
 429      *
 430      * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
 431      * by default. Applications still can use it by enabling SSLv2Hello with
 432      * the series of setEnabledProtocols APIs.
 433      */
 434 
 435     /*
 436      * The base abstract SSLContext implementation for the Transport Layer
 437      * Security (TLS) protocols.
 438      *
 439      * This abstract class encapsulates supported and the default server
 440      * SSL/TLS parameters.
 441      *
 442      * @see SSLContext
 443      */
 444     private abstract static class AbstractTLSContext extends SSLContextImpl {
 445         private static final ProtocolList supportedProtocolList;
 446         private static final ProtocolList serverDefaultProtocolList;
 447 
 448         private static final CipherSuiteList supportedCipherSuiteList;
 449         private static final CipherSuiteList serverDefaultCipherSuiteList;
 450 
 451         static {
 452             if (SunJSSE.isFIPS()) {
 453                 supportedProtocolList = new ProtocolList(new String[] {
 454                     ProtocolVersion.TLS10.name,
 455                     ProtocolVersion.TLS11.name,
 456                     ProtocolVersion.TLS12.name
 457                 });
 458 
 459                 serverDefaultProtocolList = new ProtocolList(
 460                         getAvailableProtocols(new ProtocolVersion[] {
 461                     ProtocolVersion.TLS10,
 462                     ProtocolVersion.TLS11,
 463                     ProtocolVersion.TLS12
 464                 }));
 465             } else {
 466                 supportedProtocolList = new ProtocolList(new String[] {
 467                     ProtocolVersion.SSL20Hello.name,
 468                     ProtocolVersion.SSL30.name,
 469                     ProtocolVersion.TLS10.name,
 470                     ProtocolVersion.TLS11.name,
 471                     ProtocolVersion.TLS12.name
 472                 });
 473 
 474                 serverDefaultProtocolList = new ProtocolList(
 475                         getAvailableProtocols(new ProtocolVersion[] {
 476                     ProtocolVersion.SSL20Hello,
 477                     ProtocolVersion.SSL30,
 478                     ProtocolVersion.TLS10,
 479                     ProtocolVersion.TLS11,
 480                     ProtocolVersion.TLS12
 481                 }));
 482             }
 483 
 484             supportedCipherSuiteList = getApplicableCipherSuiteList(
 485                     supportedProtocolList, false);          // all supported
 486             serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
 487                     serverDefaultProtocolList, true);       // enabled only
 488         }
 489 
 490         @Override
 491         ProtocolList getSuportedProtocolList() {
 492             return supportedProtocolList;
 493         }
 494 
 495         @Override
 496         CipherSuiteList getSupportedCipherSuiteList() {
 497             return supportedCipherSuiteList;
 498         }
 499 
 500         @Override
 501         ProtocolList getServerDefaultProtocolList() {
 502             return serverDefaultProtocolList;
 503         }
 504 
 505         @Override
 506         CipherSuiteList getServerDefaultCipherSuiteList() {
 507             return serverDefaultCipherSuiteList;
 508         }
 509 
 510         @Override
 511         SSLEngine createSSLEngineImpl() {
 512             return new SSLEngineImpl(this, false);
 513         }
 514 
 515         @Override
 516         SSLEngine createSSLEngineImpl(String host, int port) {
 517             return new SSLEngineImpl(this, host, port, false);
 518         }
 519     }
 520 
 521     /*
 522      * The SSLContext implementation for SSLv3 and TLS10 algorithm
 523      *
 524      * @see SSLContext
 525      */
 526     public static final class TLS10Context extends AbstractTLSContext {
 527         private static final ProtocolList clientDefaultProtocolList;
 528         private static final CipherSuiteList clientDefaultCipherSuiteList;
 529 
 530         static {
 531             if (SunJSSE.isFIPS()) {
 532                 clientDefaultProtocolList = new ProtocolList(
 533                         getAvailableProtocols(new ProtocolVersion[] {
 534                     ProtocolVersion.TLS10
 535                 }));
 536             } else {
 537                 clientDefaultProtocolList = new ProtocolList(
 538                         getAvailableProtocols(new ProtocolVersion[] {
 539                     ProtocolVersion.SSL30,
 540                     ProtocolVersion.TLS10
 541                 }));
 542             }
 543 
 544             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
 545                     clientDefaultProtocolList, true);       // enabled only
 546         }
 547 
 548         @Override
 549         ProtocolList getClientDefaultProtocolList() {
 550             return clientDefaultProtocolList;
 551         }
 552 
 553         @Override
 554         CipherSuiteList getClientDefaultCipherSuiteList() {
 555             return clientDefaultCipherSuiteList;
 556         }
 557     }
 558 
 559     /*
 560      * The SSLContext implementation for TLS11 algorithm
 561      *
 562      * @see SSLContext
 563      */
 564     public static final class TLS11Context extends AbstractTLSContext {
 565         private static final ProtocolList clientDefaultProtocolList;
 566         private static final CipherSuiteList clientDefaultCipherSuiteList;
 567 
 568         static {
 569             if (SunJSSE.isFIPS()) {
 570                 clientDefaultProtocolList = new ProtocolList(
 571                         getAvailableProtocols(new ProtocolVersion[] {
 572                     ProtocolVersion.TLS10,
 573                     ProtocolVersion.TLS11
 574                 }));
 575             } else {
 576                 clientDefaultProtocolList = new ProtocolList(
 577                         getAvailableProtocols(new ProtocolVersion[] {
 578                     ProtocolVersion.SSL30,
 579                     ProtocolVersion.TLS10,
 580                     ProtocolVersion.TLS11
 581                 }));
 582             }
 583 
 584             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
 585                     clientDefaultProtocolList, true);       // enabled only
 586         }
 587 
 588         @Override
 589         ProtocolList getClientDefaultProtocolList() {
 590             return clientDefaultProtocolList;
 591         }
 592 
 593         @Override
 594         CipherSuiteList getClientDefaultCipherSuiteList() {
 595             return clientDefaultCipherSuiteList;
 596         }
 597     }
 598 
 599     /*
 600      * The SSLContext implementation for TLS12 algorithm
 601      *
 602      * @see SSLContext
 603      */
 604     public static final class TLS12Context extends AbstractTLSContext {
 605         private static final ProtocolList clientDefaultProtocolList;
 606         private static final CipherSuiteList clientDefaultCipherSuiteList;
 607 
 608         static {
 609             if (SunJSSE.isFIPS()) {
 610                 clientDefaultProtocolList = new ProtocolList(
 611                         getAvailableProtocols(new ProtocolVersion[] {
 612                     ProtocolVersion.TLS10,
 613                     ProtocolVersion.TLS11,
 614                     ProtocolVersion.TLS12
 615                 }));
 616             } else {
 617                 clientDefaultProtocolList = new ProtocolList(
 618                         getAvailableProtocols(new ProtocolVersion[] {
 619                     ProtocolVersion.SSL30,
 620                     ProtocolVersion.TLS10,
 621                     ProtocolVersion.TLS11,
 622                     ProtocolVersion.TLS12
 623                 }));
 624             }
 625 
 626             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
 627                     clientDefaultProtocolList, true);       // enabled only
 628         }
 629 
 630         @Override
 631         ProtocolList getClientDefaultProtocolList() {
 632             return clientDefaultProtocolList;
 633         }
 634 
 635         @Override
 636         CipherSuiteList getClientDefaultCipherSuiteList() {
 637             return clientDefaultCipherSuiteList;
 638         }
 639     }
 640 
 641     /*
 642      * The interface for the customized SSL/(D)TLS SSLContext.
 643      *
 644      * @see SSLContext
 645      */
 646     private static class CustomizedSSLProtocols {
 647         private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
 648         static IllegalArgumentException reservedException = null;
 649         static ArrayList<ProtocolVersion>
 650                                 customizedProtocols = new ArrayList<>();
 651 
 652         // Don't want a java.lang.LinkageError for illegal system property.
 653         //
 654         // Please don't throw exception in this static block.  Otherwise,
 655         // java.lang.LinkageError may be thrown during the instantiation of
 656         // the provider service. Instead, please handle the initialization
 657         // exception in the caller's constructor.
 658         static {
 659             String property = AccessController.doPrivileged(
 660                     new GetPropertyAction(PROPERTY_NAME));
 661             if (property != null && property.length() != 0) {
 662                 // remove double quote marks from beginning/end of the property
 663                 if (property.length() > 1 && property.charAt(0) == '"' &&
 664                         property.charAt(property.length() - 1) == '"') {
 665                     property = property.substring(1, property.length() - 1);
 666                 }
 667             }
 668 
 669             if (property != null && property.length() != 0) {
 670                 String[] protocols = property.split(",");
 671                 for (int i = 0; i < protocols.length; i++) {
 672                     protocols[i] = protocols[i].trim();
 673                     // Is it a supported protocol name?
 674                     try {
 675                         ProtocolVersion pro =
 676                                 ProtocolVersion.valueOf(protocols[i]);
 677 
 678                         if (SunJSSE.isFIPS() &&
 679                                 ((pro.v == ProtocolVersion.SSL30.v) ||
 680                                  (pro.v == ProtocolVersion.SSL20Hello.v))) {
 681                             reservedException = new IllegalArgumentException(
 682                                     PROPERTY_NAME + ": " + pro +
 683                                     " is not FIPS compliant");
 684 
 685                             break;
 686                         }
 687 
 688                         // ignore duplicated protocols
 689                         if (!customizedProtocols.contains(pro)) {
 690                             customizedProtocols.add(pro);
 691                         }
 692                     } catch (IllegalArgumentException iae) {
 693                         reservedException = new IllegalArgumentException(
 694                                 PROPERTY_NAME + ": " + protocols[i] +
 695                                 " is not a standard SSL protocol name", iae);
 696                     }
 697                 }
 698             }
 699         }
 700     }
 701 
 702     /*
 703      * The SSLContext implementation for customized TLS protocols
 704      *
 705      * @see SSLContext
 706      */
 707     private static class CustomizedTLSContext extends AbstractTLSContext {
 708 
 709         private static final ProtocolList clientDefaultProtocolList;
 710         private static final CipherSuiteList clientDefaultCipherSuiteList;
 711 
 712         private static IllegalArgumentException reservedException = null;
 713 
 714         // Don't want a java.lang.LinkageError for illegal system property.
 715         //
 716         // Please don't throw exception in this static block.  Otherwise,
 717         // java.lang.LinkageError may be thrown during the instantiation of
 718         // the provider service. Instead, let's handle the initialization
 719         // exception in constructor.
 720         static {
 721             reservedException = CustomizedSSLProtocols.reservedException;
 722             if (reservedException == null) {
 723                 ArrayList<ProtocolVersion>
 724                         customizedTLSProtocols = new ArrayList<>();
 725                 for (ProtocolVersion protocol :
 726                         CustomizedSSLProtocols.customizedProtocols) {
 727                     if (!protocol.isDTLSProtocol()) {
 728                         customizedTLSProtocols.add(protocol);
 729                     }
 730                 }
 731 
 732                 // candidates for available protocols
 733                 ProtocolVersion[] candidates;
 734                 if (customizedTLSProtocols.isEmpty()) {
 735                     // Use the default enabled client protocols if no
 736                     // customized TLS protocols.
 737                     if (SunJSSE.isFIPS()) {
 738                         candidates = new ProtocolVersion[] {
 739                             ProtocolVersion.TLS10,
 740                             ProtocolVersion.TLS11,
 741                             ProtocolVersion.TLS12
 742                         };
 743                     } else {
 744                         candidates = new ProtocolVersion[] {
 745                             ProtocolVersion.SSL30,
 746                             ProtocolVersion.TLS10,
 747                             ProtocolVersion.TLS11,
 748                             ProtocolVersion.TLS12
 749                         };
 750                     }
 751                 } else {
 752                     // Use the customized TLS protocols.
 753                     candidates =
 754                             new ProtocolVersion[customizedTLSProtocols.size()];
 755                     candidates = customizedTLSProtocols.toArray(candidates);
 756                 }
 757 
 758                 clientDefaultProtocolList = new ProtocolList(
 759                         getAvailableProtocols(candidates));
 760                 clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
 761                     clientDefaultProtocolList, true);   // enabled only
 762             } else {
 763                 clientDefaultProtocolList = null;       // unlikely to be used
 764                 clientDefaultCipherSuiteList = null;    // unlikely to be used
 765             }
 766         }
 767 
 768         protected CustomizedTLSContext() {
 769             if (reservedException != null) {
 770                 throw reservedException;
 771             }
 772         }
 773 
 774         @Override
 775         ProtocolList getClientDefaultProtocolList() {
 776             return clientDefaultProtocolList;
 777         }
 778 
 779         @Override
 780         CipherSuiteList getClientDefaultCipherSuiteList() {
 781             return clientDefaultCipherSuiteList;
 782         }
 783     }
 784 
 785     /*
 786      * The SSLContext implementation for default "TLS" algorithm
 787      *
 788      * @see SSLContext
 789      */
 790     public static final class TLSContext extends CustomizedTLSContext {
 791         // use the default constructor and methods
 792     }
 793 
 794     // lazy initialization holder class idiom for static default parameters
 795     //
 796     // See Effective Java Second Edition: Item 71.
 797     private static final class DefaultManagersHolder {
 798         private static final String NONE = "NONE";
 799         private static final String P11KEYSTORE = "PKCS11";
 800 
 801         private static final TrustManager[] trustManagers;
 802         private static final KeyManager[] keyManagers;
 803 
 804         static Exception reservedException = null;
 805 
 806         static {
 807             TrustManager[] tmMediator;
 808             try {
 809                 tmMediator = getTrustManagers();
 810             } catch (Exception e) {
 811                 reservedException = e;
 812                 tmMediator = new TrustManager[0];
 813             }
 814             trustManagers = tmMediator;
 815 
 816             if (reservedException == null) {
 817                 KeyManager[] kmMediator;
 818                 try {
 819                     kmMediator = getKeyManagers();
 820                 } catch (Exception e) {
 821                     reservedException = e;
 822                     kmMediator = new KeyManager[0];
 823                 }
 824                 keyManagers = kmMediator;
 825             } else {
 826                 keyManagers = new KeyManager[0];
 827             }
 828         }
 829 
 830         private static TrustManager[] getTrustManagers() throws Exception {
 831             KeyStore ks =
 832                 TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
 833 
 834             TrustManagerFactory tmf = TrustManagerFactory.getInstance(
 835                 TrustManagerFactory.getDefaultAlgorithm());
 836             tmf.init(ks);
 837             return tmf.getTrustManagers();
 838         }
 839 
 840         private static KeyManager[] getKeyManagers() throws Exception {
 841 
 842             final Map<String,String> props = new HashMap<>();
 843             AccessController.doPrivileged(
 844                         new PrivilegedExceptionAction<Object>() {
 845                 @Override
 846                 public Object run() throws Exception {
 847                     props.put("keyStore",  System.getProperty(
 848                                 "javax.net.ssl.keyStore", ""));
 849                     props.put("keyStoreType", System.getProperty(
 850                                 "javax.net.ssl.keyStoreType",
 851                                 KeyStore.getDefaultType()));
 852                     props.put("keyStoreProvider", System.getProperty(
 853                                 "javax.net.ssl.keyStoreProvider", ""));
 854                     props.put("keyStorePasswd", System.getProperty(
 855                                 "javax.net.ssl.keyStorePassword", ""));
 856                     return null;
 857                 }
 858             });
 859 
 860             final String defaultKeyStore = props.get("keyStore");
 861             String defaultKeyStoreType = props.get("keyStoreType");
 862             String defaultKeyStoreProvider = props.get("keyStoreProvider");
 863             if (debug != null && Debug.isOn("defaultctx")) {
 864                 System.out.println("keyStore is : " + defaultKeyStore);
 865                 System.out.println("keyStore type is : " +
 866                                         defaultKeyStoreType);
 867                 System.out.println("keyStore provider is : " +
 868                                         defaultKeyStoreProvider);
 869             }
 870 
 871             if (P11KEYSTORE.equals(defaultKeyStoreType) &&
 872                     !NONE.equals(defaultKeyStore)) {
 873                 throw new IllegalArgumentException("if keyStoreType is "
 874                     + P11KEYSTORE + ", then keyStore must be " + NONE);
 875             }
 876 
 877             FileInputStream fs = null;
 878             KeyStore ks = null;
 879             char[] passwd = null;
 880             try {
 881                 if (defaultKeyStore.length() != 0 &&
 882                         !NONE.equals(defaultKeyStore)) {
 883                     fs = AccessController.doPrivileged(
 884                             new PrivilegedExceptionAction<FileInputStream>() {
 885                         @Override
 886                         public FileInputStream run() throws Exception {
 887                             return new FileInputStream(defaultKeyStore);
 888                         }
 889                     });
 890                 }
 891 
 892                 String defaultKeyStorePassword = props.get("keyStorePasswd");
 893                 if (defaultKeyStorePassword.length() != 0) {
 894                     passwd = defaultKeyStorePassword.toCharArray();
 895                 }
 896 
 897                 /**
 898                  * Try to initialize key store.
 899                  */
 900                 if ((defaultKeyStoreType.length()) != 0) {
 901                     if (debug != null && Debug.isOn("defaultctx")) {
 902                         System.out.println("init keystore");
 903                     }
 904                     if (defaultKeyStoreProvider.length() == 0) {
 905                         ks = KeyStore.getInstance(defaultKeyStoreType);
 906                     } else {
 907                         ks = KeyStore.getInstance(defaultKeyStoreType,
 908                                             defaultKeyStoreProvider);
 909                     }
 910 
 911                     // if defaultKeyStore is NONE, fs will be null
 912                     ks.load(fs, passwd);
 913                 }
 914             } finally {
 915                 if (fs != null) {
 916                     fs.close();
 917                     fs = null;
 918                 }
 919             }
 920 
 921             /*
 922              * Try to initialize key manager.
 923              */
 924             if (debug != null && Debug.isOn("defaultctx")) {
 925                 System.out.println("init keymanager of type " +
 926                     KeyManagerFactory.getDefaultAlgorithm());
 927             }
 928             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
 929                 KeyManagerFactory.getDefaultAlgorithm());
 930 
 931             if (P11KEYSTORE.equals(defaultKeyStoreType)) {
 932                 kmf.init(ks, null); // do not pass key passwd if using token
 933             } else {
 934                 kmf.init(ks, passwd);
 935             }
 936 
 937             return kmf.getKeyManagers();
 938         }
 939     }
 940 
 941     // lazy initialization holder class idiom for static default parameters
 942     //
 943     // See Effective Java Second Edition: Item 71.
 944     private static final class DefaultSSLContextHolder {
 945 
 946         private static final SSLContextImpl sslContext;
 947         static Exception reservedException = null;
 948 
 949         static {
 950             SSLContextImpl mediator = null;
 951             if (DefaultManagersHolder.reservedException != null) {
 952                 reservedException = DefaultManagersHolder.reservedException;
 953             } else {
 954                 try {
 955                     mediator = new DefaultSSLContext();
 956                 } catch (Exception e) {
 957                     reservedException = e;
 958                 }
 959             }
 960 
 961             sslContext = mediator;
 962         }
 963     }
 964 
 965     /*
 966      * The SSLContext implementation for default "Default" algorithm
 967      *
 968      * @see SSLContext
 969      */
 970     public static final class DefaultSSLContext extends CustomizedTLSContext {
 971 
 972         // public constructor for SSLContext.getInstance("Default")
 973         public DefaultSSLContext() throws Exception {
 974             if (DefaultManagersHolder.reservedException != null) {
 975                 throw DefaultManagersHolder.reservedException;
 976             }
 977 
 978             try {
 979                 super.engineInit(DefaultManagersHolder.keyManagers,
 980                         DefaultManagersHolder.trustManagers, null);
 981             } catch (Exception e) {
 982                 if (debug != null && Debug.isOn("defaultctx")) {
 983                     System.out.println("default context init failed: " + e);
 984                 }
 985                 throw e;
 986             }
 987         }
 988 
 989         @Override
 990         protected void engineInit(KeyManager[] km, TrustManager[] tm,
 991             SecureRandom sr) throws KeyManagementException {
 992             throw new KeyManagementException
 993                 ("Default SSLContext is initialized automatically");
 994         }
 995 
 996         static SSLContextImpl getDefaultImpl() throws Exception {
 997             if (DefaultSSLContextHolder.reservedException != null) {
 998                 throw DefaultSSLContextHolder.reservedException;
 999             }
1000 
1001             return DefaultSSLContextHolder.sslContext;
1002         }
1003     }
1004 
1005     /*
1006      * The base abstract SSLContext implementation for the Datagram Transport
1007      * Layer Security (DTLS) protocols.
1008      *
1009      * This abstract class encapsulates supported and the default server DTLS
1010      * parameters.
1011      *
1012      * @see SSLContext
1013      */
1014     private abstract static class AbstractDTLSContext extends SSLContextImpl {
1015         private static final ProtocolList supportedProtocolList;
1016         private static final ProtocolList serverDefaultProtocolList;
1017 
1018         private static final CipherSuiteList supportedCipherSuiteList;
1019         private static final CipherSuiteList serverDefaultCipherSuiteList;
1020 
1021         static {
1022             // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
1023             supportedProtocolList = new ProtocolList(new String[] {
1024                 ProtocolVersion.DTLS10.name,
1025                 ProtocolVersion.DTLS12.name
1026             });
1027 
1028             // available protocols for server mode
1029             serverDefaultProtocolList = new ProtocolList(
1030                     getAvailableProtocols(new ProtocolVersion[] {
1031                 ProtocolVersion.DTLS10,
1032                 ProtocolVersion.DTLS12
1033             }));
1034 
1035             supportedCipherSuiteList = getApplicableCipherSuiteList(
1036                     supportedProtocolList, false);          // all supported
1037             serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
1038                     serverDefaultProtocolList, true);       // enabled only
1039         }
1040 
1041         @Override
1042         ProtocolList getSuportedProtocolList() {
1043             return supportedProtocolList;
1044         }
1045 
1046         @Override
1047         CipherSuiteList getSupportedCipherSuiteList() {
1048             return supportedCipherSuiteList;
1049         }
1050 
1051         @Override
1052         ProtocolList getServerDefaultProtocolList() {
1053             return serverDefaultProtocolList;
1054         }
1055 
1056         @Override
1057         CipherSuiteList getServerDefaultCipherSuiteList() {
1058             return serverDefaultCipherSuiteList;
1059         }
1060 
1061         @Override
1062         SSLEngine createSSLEngineImpl() {
1063             return new SSLEngineImpl(this, true);
1064         }
1065 
1066         @Override
1067         SSLEngine createSSLEngineImpl(String host, int port) {
1068             return new SSLEngineImpl(this, host, port, true);
1069         }
1070 
1071         @Override
1072         HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) {
1073             return new HelloCookieManager(secureRandom);
1074         }
1075     }
1076 
1077     /*
1078      * The SSLContext implementation for DTLSv1.0 algorithm.
1079      *
1080      * @see SSLContext
1081      */
1082     public static final class DTLS10Context extends AbstractDTLSContext {
1083         private static final ProtocolList clientDefaultProtocolList;
1084         private static final CipherSuiteList clientDefaultCipherSuiteList;
1085 
1086         static {
1087             // available protocols for client mode
1088             clientDefaultProtocolList = new ProtocolList(
1089                     getAvailableProtocols(new ProtocolVersion[] {
1090                 ProtocolVersion.DTLS10
1091             }));
1092 
1093             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1094                     clientDefaultProtocolList, true);       // enabled only
1095         }
1096 
1097         @Override
1098         ProtocolList getClientDefaultProtocolList() {
1099             return clientDefaultProtocolList;
1100         }
1101 
1102         @Override
1103         CipherSuiteList getClientDefaultCipherSuiteList() {
1104             return clientDefaultCipherSuiteList;
1105         }
1106     }
1107 
1108     /*
1109      * The SSLContext implementation for DTLSv1.2 algorithm.
1110      *
1111      * @see SSLContext
1112      */
1113     public static final class DTLS12Context extends AbstractDTLSContext {
1114         private static final ProtocolList clientDefaultProtocolList;
1115         private static final CipherSuiteList clientDefaultCipherSuiteList;
1116 
1117         static {
1118             // available protocols for client mode
1119             clientDefaultProtocolList = new ProtocolList(
1120                     getAvailableProtocols(new ProtocolVersion[] {
1121                 ProtocolVersion.DTLS10,
1122                 ProtocolVersion.DTLS12
1123             }));
1124 
1125             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1126                     clientDefaultProtocolList, true);       // enabled only
1127         }
1128 
1129         @Override
1130         ProtocolList getClientDefaultProtocolList() {
1131             return clientDefaultProtocolList;
1132         }
1133 
1134         @Override
1135         CipherSuiteList getClientDefaultCipherSuiteList() {
1136             return clientDefaultCipherSuiteList;
1137         }
1138     }
1139 
1140     /*
1141      * The SSLContext implementation for customized TLS protocols
1142      *
1143      * @see SSLContext
1144      */
1145     private static class CustomizedDTLSContext extends AbstractDTLSContext {
1146         private static final ProtocolList clientDefaultProtocolList;
1147         private static final CipherSuiteList clientDefaultCipherSuiteList;
1148 
1149         private static IllegalArgumentException reservedException = null;
1150 
1151         // Don't want a java.lang.LinkageError for illegal system property.
1152         //
1153         // Please don't throw exception in this static block.  Otherwise,
1154         // java.lang.LinkageError may be thrown during the instantiation of
1155         // the provider service. Instead, let's handle the initialization
1156         // exception in constructor.
1157         static {
1158             reservedException = CustomizedSSLProtocols.reservedException;
1159             if (reservedException == null) {
1160                 ArrayList<ProtocolVersion>
1161                         customizedDTLSProtocols = new ArrayList<>();
1162                 for (ProtocolVersion protocol :
1163                         CustomizedSSLProtocols.customizedProtocols) {
1164                     if (protocol.isDTLSProtocol()) {
1165                         customizedDTLSProtocols.add(protocol);
1166                     }
1167                 }
1168 
1169                 // candidates for available protocols
1170                 ProtocolVersion[] candidates;
1171                 if (customizedDTLSProtocols.isEmpty()) {
1172                     // Use the default enabled client protocols if no
1173                     // customized TLS protocols.
1174                     //
1175                     // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
1176                     candidates = new ProtocolVersion[] {
1177                         ProtocolVersion.DTLS10,
1178                         ProtocolVersion.DTLS12
1179                     };
1180 
1181                 } else {
1182                     // Use the customized TLS protocols.
1183                     candidates =
1184                             new ProtocolVersion[customizedDTLSProtocols.size()];
1185                     candidates = customizedDTLSProtocols.toArray(candidates);
1186                 }
1187 
1188                 clientDefaultProtocolList = new ProtocolList(
1189                         getAvailableProtocols(candidates));
1190                 clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1191                     clientDefaultProtocolList, true);   // enabled only
1192             } else {
1193                 clientDefaultProtocolList = null;       // unlikely to be used
1194                 clientDefaultCipherSuiteList = null;    // unlikely to be used
1195             }
1196         }
1197 
1198         protected CustomizedDTLSContext() {
1199             if (reservedException != null) {
1200                 throw reservedException;
1201             }
1202         }
1203 
1204         @Override
1205         ProtocolList getClientDefaultProtocolList() {
1206             return clientDefaultProtocolList;
1207         }
1208 
1209         @Override
1210         CipherSuiteList getClientDefaultCipherSuiteList() {
1211             return clientDefaultCipherSuiteList;
1212         }
1213     }
1214 
1215     /*
1216      * The SSLContext implementation for default "DTLS" algorithm
1217      *
1218      * @see SSLContext
1219      */
1220     public static final class DTLSContext extends CustomizedDTLSContext {
1221         // use the default constructor and methods
1222     }
1223 
1224 }
1225 
1226 
1227 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
1228             implements X509TrustManager {
1229 
1230     // the delegated trust manager
1231     private final X509TrustManager tm;
1232 
1233     AbstractTrustManagerWrapper(X509TrustManager tm) {
1234         this.tm = tm;
1235     }
1236 
1237     @Override
1238     public void checkClientTrusted(X509Certificate[] chain, String authType)
1239         throws CertificateException {
1240         tm.checkClientTrusted(chain, authType);
1241     }
1242 
1243     @Override
1244     public void checkServerTrusted(X509Certificate[] chain, String authType)
1245         throws CertificateException {
1246         tm.checkServerTrusted(chain, authType);
1247     }
1248 
1249     @Override
1250     public X509Certificate[] getAcceptedIssuers() {
1251         return tm.getAcceptedIssuers();
1252     }
1253 
1254     @Override
1255     public void checkClientTrusted(X509Certificate[] chain, String authType,
1256                 Socket socket) throws CertificateException {
1257         tm.checkClientTrusted(chain, authType);
1258         checkAdditionalTrust(chain, authType, socket, true);
1259     }
1260 
1261     @Override
1262     public void checkServerTrusted(X509Certificate[] chain, String authType,
1263             Socket socket) throws CertificateException {
1264         tm.checkServerTrusted(chain, authType);
1265         checkAdditionalTrust(chain, authType, socket, false);
1266     }
1267 
1268     @Override
1269     public void checkClientTrusted(X509Certificate[] chain, String authType,
1270             SSLEngine engine) throws CertificateException {
1271         tm.checkClientTrusted(chain, authType);
1272         checkAdditionalTrust(chain, authType, engine, true);
1273     }
1274 
1275     @Override
1276     public void checkServerTrusted(X509Certificate[] chain, String authType,
1277             SSLEngine engine) throws CertificateException {
1278         tm.checkServerTrusted(chain, authType);
1279         checkAdditionalTrust(chain, authType, engine, false);
1280     }
1281 
1282     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1283                 Socket socket, boolean isClient) throws CertificateException {
1284         if (socket != null && socket.isConnected() &&
1285                                     socket instanceof SSLSocket) {
1286 
1287             SSLSocket sslSocket = (SSLSocket)socket;
1288             SSLSession session = sslSocket.getHandshakeSession();
1289             if (session == null) {
1290                 throw new CertificateException("No handshake session");
1291             }
1292 
1293             // check endpoint identity
1294             String identityAlg = sslSocket.getSSLParameters().
1295                                         getEndpointIdentificationAlgorithm();
1296             if (identityAlg != null && identityAlg.length() != 0) {
1297                 String hostname = session.getPeerHost();
1298                 X509TrustManagerImpl.checkIdentity(
1299                                     hostname, chain[0], identityAlg);
1300             }
1301 
1302             // try the best to check the algorithm constraints
1303             ProtocolVersion protocolVersion =
1304                 ProtocolVersion.valueOf(session.getProtocol());
1305             AlgorithmConstraints constraints = null;
1306             if (protocolVersion.useTLS12PlusSpec()) {
1307                 if (session instanceof ExtendedSSLSession) {
1308                     ExtendedSSLSession extSession =
1309                                     (ExtendedSSLSession)session;
1310                     String[] peerSupportedSignAlgs =
1311                             extSession.getLocalSupportedSignatureAlgorithms();
1312 
1313                     constraints = new SSLAlgorithmConstraints(
1314                                     sslSocket, peerSupportedSignAlgs, true);
1315                 } else {
1316                     constraints =
1317                             new SSLAlgorithmConstraints(sslSocket, true);
1318                 }
1319             } else {
1320                 constraints = new SSLAlgorithmConstraints(sslSocket, true);
1321             }
1322 
1323             checkAlgorithmConstraints(chain, constraints);
1324         }
1325     }
1326 
1327     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1328             SSLEngine engine, boolean isClient) throws CertificateException {
1329         if (engine != null) {
1330             SSLSession session = engine.getHandshakeSession();
1331             if (session == null) {
1332                 throw new CertificateException("No handshake session");
1333             }
1334 
1335             // check endpoint identity
1336             String identityAlg = engine.getSSLParameters().
1337                                         getEndpointIdentificationAlgorithm();
1338             if (identityAlg != null && identityAlg.length() != 0) {
1339                 String hostname = session.getPeerHost();
1340                 X509TrustManagerImpl.checkIdentity(
1341                                     hostname, chain[0], identityAlg);
1342             }
1343 
1344             // try the best to check the algorithm constraints
1345             ProtocolVersion protocolVersion =
1346                 ProtocolVersion.valueOf(session.getProtocol());
1347             AlgorithmConstraints constraints = null;
1348             if (protocolVersion.useTLS12PlusSpec()) {
1349                 if (session instanceof ExtendedSSLSession) {
1350                     ExtendedSSLSession extSession =
1351                                     (ExtendedSSLSession)session;
1352                     String[] peerSupportedSignAlgs =
1353                             extSession.getLocalSupportedSignatureAlgorithms();
1354 
1355                     constraints = new SSLAlgorithmConstraints(
1356                                     engine, peerSupportedSignAlgs, true);
1357                 } else {
1358                     constraints =
1359                             new SSLAlgorithmConstraints(engine, true);
1360                 }
1361             } else {
1362                 constraints = new SSLAlgorithmConstraints(engine, true);
1363             }
1364 
1365             checkAlgorithmConstraints(chain, constraints);
1366         }
1367     }
1368 
1369     private void checkAlgorithmConstraints(X509Certificate[] chain,
1370             AlgorithmConstraints constraints) throws CertificateException {
1371 
1372         try {
1373             // Does the certificate chain end with a trusted certificate?
1374             int checkedLength = chain.length - 1;
1375 
1376             Collection<X509Certificate> trustedCerts = new HashSet<>();
1377             X509Certificate[] certs = tm.getAcceptedIssuers();
1378             if ((certs != null) && (certs.length > 0)){
1379                 Collections.addAll(trustedCerts, certs);
1380             }
1381 
1382             if (trustedCerts.contains(chain[checkedLength])) {
1383                     checkedLength--;
1384             }
1385 
1386             // A forward checker, need to check from trust to target
1387             if (checkedLength >= 0) {
1388                 AlgorithmChecker checker = new AlgorithmChecker(constraints);
1389                 checker.init(false);
1390                 for (int i = checkedLength; i >= 0; i--) {
1391                     Certificate cert = chain[i];
1392                     // We don't care about the unresolved critical extensions.
1393                     checker.check(cert, Collections.<String>emptySet());
1394                 }
1395             }
1396         } catch (CertPathValidatorException cpve) {
1397             throw new CertificateException(
1398                 "Certificates does not conform to algorithm constraints");
1399         }
1400     }
1401 }
1402 
1403 // Dummy X509TrustManager implementation, rejects all peer certificates.
1404 // Used if the application did not specify a proper X509TrustManager.
1405 final class DummyX509TrustManager extends X509ExtendedTrustManager
1406             implements X509TrustManager {
1407 
1408     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
1409 
1410     private DummyX509TrustManager() {
1411         // empty
1412     }
1413 
1414     /*
1415      * Given the partial or complete certificate chain
1416      * provided by the peer, build a certificate path
1417      * to a trusted root and return if it can be
1418      * validated and is trusted for client SSL authentication.
1419      * If not, it throws an exception.
1420      */
1421     @Override
1422     public void checkClientTrusted(X509Certificate[] chain, String authType)
1423         throws CertificateException {
1424         throw new CertificateException(
1425             "No X509TrustManager implementation avaiable");
1426     }
1427 
1428     /*
1429      * Given the partial or complete certificate chain
1430      * provided by the peer, build a certificate path
1431      * to a trusted root and return if it can be
1432      * validated and is trusted for server SSL authentication.
1433      * If not, it throws an exception.
1434      */
1435     @Override
1436     public void checkServerTrusted(X509Certificate[] chain, String authType)
1437         throws CertificateException {
1438         throw new CertificateException(
1439             "No X509TrustManager implementation available");
1440     }
1441 
1442     /*
1443      * Return an array of issuer certificates which are trusted
1444      * for authenticating peers.
1445      */
1446     @Override
1447     public X509Certificate[] getAcceptedIssuers() {
1448         return new X509Certificate[0];
1449     }
1450 
1451     @Override
1452     public void checkClientTrusted(X509Certificate[] chain, String authType,
1453                 Socket socket) throws CertificateException {
1454         throw new CertificateException(
1455             "No X509TrustManager implementation available");
1456     }
1457 
1458     @Override
1459     public void checkServerTrusted(X509Certificate[] chain, String authType,
1460             Socket socket) throws CertificateException {
1461         throw new CertificateException(
1462             "No X509TrustManager implementation available");
1463     }
1464 
1465     @Override
1466     public void checkClientTrusted(X509Certificate[] chain, String authType,
1467             SSLEngine engine) throws CertificateException {
1468         throw new CertificateException(
1469             "No X509TrustManager implementation available");
1470     }
1471 
1472     @Override
1473     public void checkServerTrusted(X509Certificate[] chain, String authType,
1474             SSLEngine engine) throws CertificateException {
1475         throw new CertificateException(
1476             "No X509TrustManager implementation available");
1477     }
1478 }
1479 
1480 /*
1481  * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
1482  */
1483 final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
1484 
1485     private final X509KeyManager km;
1486 
1487     AbstractKeyManagerWrapper(X509KeyManager km) {
1488         this.km = km;
1489     }
1490 
1491     @Override
1492     public String[] getClientAliases(String keyType, Principal[] issuers) {
1493         return km.getClientAliases(keyType, issuers);
1494     }
1495 
1496     @Override
1497     public String chooseClientAlias(String[] keyType, Principal[] issuers,
1498             Socket socket) {
1499         return km.chooseClientAlias(keyType, issuers, socket);
1500     }
1501 
1502     @Override
1503     public String[] getServerAliases(String keyType, Principal[] issuers) {
1504         return km.getServerAliases(keyType, issuers);
1505     }
1506 
1507     @Override
1508     public String chooseServerAlias(String keyType, Principal[] issuers,
1509             Socket socket) {
1510         return km.chooseServerAlias(keyType, issuers, socket);
1511     }
1512 
1513     @Override
1514     public X509Certificate[] getCertificateChain(String alias) {
1515         return km.getCertificateChain(alias);
1516     }
1517 
1518     @Override
1519     public PrivateKey getPrivateKey(String alias) {
1520         return km.getPrivateKey(alias);
1521     }
1522 
1523     // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
1524     // X509ExtendedKeymanager. It defines them to return null;
1525 }
1526 
1527 
1528 // Dummy X509KeyManager implementation, never returns any certificates/keys.
1529 // Used if the application did not specify a proper X509TrustManager.
1530 final class DummyX509KeyManager extends X509ExtendedKeyManager {
1531 
1532     static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
1533 
1534     private DummyX509KeyManager() {
1535         // empty
1536     }
1537 
1538     /*
1539      * Get the matching aliases for authenticating the client side of a secure
1540      * socket given the public key type and the list of
1541      * certificate issuer authorities recognized by the peer (if any).
1542      */
1543     @Override
1544     public String[] getClientAliases(String keyType, Principal[] issuers) {
1545         return null;
1546     }
1547 
1548     /*
1549      * Choose an alias to authenticate the client side of a secure
1550      * socket given the public key type and the list of
1551      * certificate issuer authorities recognized by the peer (if any).
1552      */
1553     @Override
1554     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
1555             Socket socket) {
1556         return null;
1557     }
1558 
1559     /*
1560      * Choose an alias to authenticate the client side of an
1561      * engine given the public key type and the list of
1562      * certificate issuer authorities recognized by the peer (if any).
1563      */
1564     @Override
1565     public String chooseEngineClientAlias(
1566             String[] keyTypes, Principal[] issuers, SSLEngine engine) {
1567         return null;
1568     }
1569 
1570     /*
1571      * Get the matching aliases for authenticating the server side of a secure
1572      * socket given the public key type and the list of
1573      * certificate issuer authorities recognized by the peer (if any).
1574      */
1575     @Override
1576     public String[] getServerAliases(String keyType, Principal[] issuers) {
1577         return null;
1578     }
1579 
1580     /*
1581      * Choose an alias to authenticate the server side of a secure
1582      * socket given the public key type and the list of
1583      * certificate issuer authorities recognized by the peer (if any).
1584      */
1585     @Override
1586     public String chooseServerAlias(String keyType, Principal[] issuers,
1587             Socket socket) {
1588         return null;
1589     }
1590 
1591     /*
1592      * Choose an alias to authenticate the server side of an engine
1593      * given the public key type and the list of
1594      * certificate issuer authorities recognized by the peer (if any).
1595      */
1596     @Override
1597     public String chooseEngineServerAlias(
1598             String keyType, Principal[] issuers, SSLEngine engine) {
1599         return null;
1600     }
1601 
1602     /**
1603      * Returns the certificate chain associated with the given alias.
1604      *
1605      * @param alias the alias name
1606      *
1607      * @return the certificate chain (ordered with the user's certificate first
1608      * and the root certificate authority last)
1609      */
1610     @Override
1611     public X509Certificate[] getCertificateChain(String alias) {
1612         return null;
1613     }
1614 
1615     /*
1616      * Returns the key associated with the given alias, using the given
1617      * password to recover it.
1618      *
1619      * @param alias the alias name
1620      *
1621      * @return the requested key
1622      */
1623     @Override
1624     public PrivateKey getPrivateKey(String alias) {
1625         return null;
1626     }
1627 }
--- EOF ---