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 = GetPropertyAction.getProperty(PROPERTY_NAME);

 660             if (property != null && property.length() != 0) {
 661                 // remove double quote marks from beginning/end of the property
 662                 if (property.length() > 1 && property.charAt(0) == '"' &&
 663                         property.charAt(property.length() - 1) == '"') {
 664                     property = property.substring(1, property.length() - 1);
 665                 }
 666             }
 667 
 668             if (property != null && property.length() != 0) {
 669                 String[] protocols = property.split(",");
 670                 for (int i = 0; i < protocols.length; i++) {
 671                     protocols[i] = protocols[i].trim();
 672                     // Is it a supported protocol name?
 673                     try {
 674                         ProtocolVersion pro =
 675                                 ProtocolVersion.valueOf(protocols[i]);
 676 
 677                         if (SunJSSE.isFIPS() &&
 678                                 ((pro.v == ProtocolVersion.SSL30.v) ||
 679                                  (pro.v == ProtocolVersion.SSL20Hello.v))) {
 680                             reservedException = new IllegalArgumentException(
 681                                     PROPERTY_NAME + ": " + pro +
 682                                     " is not FIPS compliant");
 683 
 684                             break;
 685                         }
 686 
 687                         // ignore duplicated protocols
 688                         if (!customizedProtocols.contains(pro)) {
 689                             customizedProtocols.add(pro);
 690                         }
 691                     } catch (IllegalArgumentException iae) {
 692                         reservedException = new IllegalArgumentException(
 693                                 PROPERTY_NAME + ": " + protocols[i] +
 694                                 " is not a standard SSL protocol name", iae);
 695                     }
 696                 }
 697             }
 698         }
 699     }
 700 
 701     /*
 702      * The SSLContext implementation for customized TLS protocols
 703      *
 704      * @see SSLContext
 705      */
 706     private static class CustomizedTLSContext extends AbstractTLSContext {
 707 
 708         private static final ProtocolList clientDefaultProtocolList;
 709         private static final CipherSuiteList clientDefaultCipherSuiteList;
 710 
 711         private static IllegalArgumentException reservedException = null;
 712 
 713         // Don't want a java.lang.LinkageError for illegal system property.
 714         //
 715         // Please don't throw exception in this static block.  Otherwise,
 716         // java.lang.LinkageError may be thrown during the instantiation of
 717         // the provider service. Instead, let's handle the initialization
 718         // exception in constructor.
 719         static {
 720             reservedException = CustomizedSSLProtocols.reservedException;
 721             if (reservedException == null) {
 722                 ArrayList<ProtocolVersion>
 723                         customizedTLSProtocols = new ArrayList<>();
 724                 for (ProtocolVersion protocol :
 725                         CustomizedSSLProtocols.customizedProtocols) {
 726                     if (!protocol.isDTLSProtocol()) {
 727                         customizedTLSProtocols.add(protocol);
 728                     }
 729                 }
 730 
 731                 // candidates for available protocols
 732                 ProtocolVersion[] candidates;
 733                 if (customizedTLSProtocols.isEmpty()) {
 734                     // Use the default enabled client protocols if no
 735                     // customized TLS protocols.
 736                     if (SunJSSE.isFIPS()) {
 737                         candidates = new ProtocolVersion[] {
 738                             ProtocolVersion.TLS10,
 739                             ProtocolVersion.TLS11,
 740                             ProtocolVersion.TLS12
 741                         };
 742                     } else {
 743                         candidates = new ProtocolVersion[] {
 744                             ProtocolVersion.SSL30,
 745                             ProtocolVersion.TLS10,
 746                             ProtocolVersion.TLS11,
 747                             ProtocolVersion.TLS12
 748                         };
 749                     }
 750                 } else {
 751                     // Use the customized TLS protocols.
 752                     candidates =
 753                             new ProtocolVersion[customizedTLSProtocols.size()];
 754                     candidates = customizedTLSProtocols.toArray(candidates);
 755                 }
 756 
 757                 clientDefaultProtocolList = new ProtocolList(
 758                         getAvailableProtocols(candidates));
 759                 clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
 760                     clientDefaultProtocolList, true);   // enabled only
 761             } else {
 762                 clientDefaultProtocolList = null;       // unlikely to be used
 763                 clientDefaultCipherSuiteList = null;    // unlikely to be used
 764             }
 765         }
 766 
 767         protected CustomizedTLSContext() {
 768             if (reservedException != null) {
 769                 throw reservedException;
 770             }
 771         }
 772 
 773         @Override
 774         ProtocolList getClientDefaultProtocolList() {
 775             return clientDefaultProtocolList;
 776         }
 777 
 778         @Override
 779         CipherSuiteList getClientDefaultCipherSuiteList() {
 780             return clientDefaultCipherSuiteList;
 781         }
 782     }
 783 
 784     /*
 785      * The SSLContext implementation for default "TLS" algorithm
 786      *
 787      * @see SSLContext
 788      */
 789     public static final class TLSContext extends CustomizedTLSContext {
 790         // use the default constructor and methods
 791     }
 792 
 793     // lazy initialization holder class idiom for static default parameters
 794     //
 795     // See Effective Java Second Edition: Item 71.
 796     private static final class DefaultManagersHolder {
 797         private static final String NONE = "NONE";
 798         private static final String P11KEYSTORE = "PKCS11";
 799 
 800         private static final TrustManager[] trustManagers;
 801         private static final KeyManager[] keyManagers;
 802 
 803         static Exception reservedException = null;
 804 
 805         static {
 806             TrustManager[] tmMediator;
 807             try {
 808                 tmMediator = getTrustManagers();
 809             } catch (Exception e) {
 810                 reservedException = e;
 811                 tmMediator = new TrustManager[0];
 812             }
 813             trustManagers = tmMediator;
 814 
 815             if (reservedException == null) {
 816                 KeyManager[] kmMediator;
 817                 try {
 818                     kmMediator = getKeyManagers();
 819                 } catch (Exception e) {
 820                     reservedException = e;
 821                     kmMediator = new KeyManager[0];
 822                 }
 823                 keyManagers = kmMediator;
 824             } else {
 825                 keyManagers = new KeyManager[0];
 826             }
 827         }
 828 
 829         private static TrustManager[] getTrustManagers() throws Exception {
 830             KeyStore ks =
 831                 TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
 832 
 833             TrustManagerFactory tmf = TrustManagerFactory.getInstance(
 834                 TrustManagerFactory.getDefaultAlgorithm());
 835             tmf.init(ks);
 836             return tmf.getTrustManagers();
 837         }
 838 
 839         private static KeyManager[] getKeyManagers() throws Exception {
 840 
 841             final Map<String,String> props = new HashMap<>();
 842             AccessController.doPrivileged(
 843                         new PrivilegedExceptionAction<Object>() {
 844                 @Override
 845                 public Object run() throws Exception {
 846                     props.put("keyStore",  System.getProperty(
 847                                 "javax.net.ssl.keyStore", ""));
 848                     props.put("keyStoreType", System.getProperty(
 849                                 "javax.net.ssl.keyStoreType",
 850                                 KeyStore.getDefaultType()));
 851                     props.put("keyStoreProvider", System.getProperty(
 852                                 "javax.net.ssl.keyStoreProvider", ""));
 853                     props.put("keyStorePasswd", System.getProperty(
 854                                 "javax.net.ssl.keyStorePassword", ""));
 855                     return null;
 856                 }
 857             });
 858 
 859             final String defaultKeyStore = props.get("keyStore");
 860             String defaultKeyStoreType = props.get("keyStoreType");
 861             String defaultKeyStoreProvider = props.get("keyStoreProvider");
 862             if (debug != null && Debug.isOn("defaultctx")) {
 863                 System.out.println("keyStore is : " + defaultKeyStore);
 864                 System.out.println("keyStore type is : " +
 865                                         defaultKeyStoreType);
 866                 System.out.println("keyStore provider is : " +
 867                                         defaultKeyStoreProvider);
 868             }
 869 
 870             if (P11KEYSTORE.equals(defaultKeyStoreType) &&
 871                     !NONE.equals(defaultKeyStore)) {
 872                 throw new IllegalArgumentException("if keyStoreType is "
 873                     + P11KEYSTORE + ", then keyStore must be " + NONE);
 874             }
 875 
 876             FileInputStream fs = null;
 877             KeyStore ks = null;
 878             char[] passwd = null;
 879             try {
 880                 if (defaultKeyStore.length() != 0 &&
 881                         !NONE.equals(defaultKeyStore)) {
 882                     fs = AccessController.doPrivileged(
 883                             new PrivilegedExceptionAction<FileInputStream>() {
 884                         @Override
 885                         public FileInputStream run() throws Exception {
 886                             return new FileInputStream(defaultKeyStore);
 887                         }
 888                     });
 889                 }
 890 
 891                 String defaultKeyStorePassword = props.get("keyStorePasswd");
 892                 if (defaultKeyStorePassword.length() != 0) {
 893                     passwd = defaultKeyStorePassword.toCharArray();
 894                 }
 895 
 896                 /**
 897                  * Try to initialize key store.
 898                  */
 899                 if ((defaultKeyStoreType.length()) != 0) {
 900                     if (debug != null && Debug.isOn("defaultctx")) {
 901                         System.out.println("init keystore");
 902                     }
 903                     if (defaultKeyStoreProvider.length() == 0) {
 904                         ks = KeyStore.getInstance(defaultKeyStoreType);
 905                     } else {
 906                         ks = KeyStore.getInstance(defaultKeyStoreType,
 907                                             defaultKeyStoreProvider);
 908                     }
 909 
 910                     // if defaultKeyStore is NONE, fs will be null
 911                     ks.load(fs, passwd);
 912                 }
 913             } finally {
 914                 if (fs != null) {
 915                     fs.close();
 916                     fs = null;
 917                 }
 918             }
 919 
 920             /*
 921              * Try to initialize key manager.
 922              */
 923             if (debug != null && Debug.isOn("defaultctx")) {
 924                 System.out.println("init keymanager of type " +
 925                     KeyManagerFactory.getDefaultAlgorithm());
 926             }
 927             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
 928                 KeyManagerFactory.getDefaultAlgorithm());
 929 
 930             if (P11KEYSTORE.equals(defaultKeyStoreType)) {
 931                 kmf.init(ks, null); // do not pass key passwd if using token
 932             } else {
 933                 kmf.init(ks, passwd);
 934             }
 935 
 936             return kmf.getKeyManagers();
 937         }
 938     }
 939 
 940     // lazy initialization holder class idiom for static default parameters
 941     //
 942     // See Effective Java Second Edition: Item 71.
 943     private static final class DefaultSSLContextHolder {
 944 
 945         private static final SSLContextImpl sslContext;
 946         static Exception reservedException = null;
 947 
 948         static {
 949             SSLContextImpl mediator = null;
 950             if (DefaultManagersHolder.reservedException != null) {
 951                 reservedException = DefaultManagersHolder.reservedException;
 952             } else {
 953                 try {
 954                     mediator = new DefaultSSLContext();
 955                 } catch (Exception e) {
 956                     reservedException = e;
 957                 }
 958             }
 959 
 960             sslContext = mediator;
 961         }
 962     }
 963 
 964     /*
 965      * The SSLContext implementation for default "Default" algorithm
 966      *
 967      * @see SSLContext
 968      */
 969     public static final class DefaultSSLContext extends CustomizedTLSContext {
 970 
 971         // public constructor for SSLContext.getInstance("Default")
 972         public DefaultSSLContext() throws Exception {
 973             if (DefaultManagersHolder.reservedException != null) {
 974                 throw DefaultManagersHolder.reservedException;
 975             }
 976 
 977             try {
 978                 super.engineInit(DefaultManagersHolder.keyManagers,
 979                         DefaultManagersHolder.trustManagers, null);
 980             } catch (Exception e) {
 981                 if (debug != null && Debug.isOn("defaultctx")) {
 982                     System.out.println("default context init failed: " + e);
 983                 }
 984                 throw e;
 985             }
 986         }
 987 
 988         @Override
 989         protected void engineInit(KeyManager[] km, TrustManager[] tm,
 990             SecureRandom sr) throws KeyManagementException {
 991             throw new KeyManagementException
 992                 ("Default SSLContext is initialized automatically");
 993         }
 994 
 995         static SSLContextImpl getDefaultImpl() throws Exception {
 996             if (DefaultSSLContextHolder.reservedException != null) {
 997                 throw DefaultSSLContextHolder.reservedException;
 998             }
 999 
1000             return DefaultSSLContextHolder.sslContext;
1001         }
1002     }
1003 
1004     /*
1005      * The base abstract SSLContext implementation for the Datagram Transport
1006      * Layer Security (DTLS) protocols.
1007      *
1008      * This abstract class encapsulates supported and the default server DTLS
1009      * parameters.
1010      *
1011      * @see SSLContext
1012      */
1013     private abstract static class AbstractDTLSContext extends SSLContextImpl {
1014         private static final ProtocolList supportedProtocolList;
1015         private static final ProtocolList serverDefaultProtocolList;
1016 
1017         private static final CipherSuiteList supportedCipherSuiteList;
1018         private static final CipherSuiteList serverDefaultCipherSuiteList;
1019 
1020         static {
1021             // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
1022             supportedProtocolList = new ProtocolList(new String[] {
1023                 ProtocolVersion.DTLS10.name,
1024                 ProtocolVersion.DTLS12.name
1025             });
1026 
1027             // available protocols for server mode
1028             serverDefaultProtocolList = new ProtocolList(
1029                     getAvailableProtocols(new ProtocolVersion[] {
1030                 ProtocolVersion.DTLS10,
1031                 ProtocolVersion.DTLS12
1032             }));
1033 
1034             supportedCipherSuiteList = getApplicableCipherSuiteList(
1035                     supportedProtocolList, false);          // all supported
1036             serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
1037                     serverDefaultProtocolList, true);       // enabled only
1038         }
1039 
1040         @Override
1041         ProtocolList getSuportedProtocolList() {
1042             return supportedProtocolList;
1043         }
1044 
1045         @Override
1046         CipherSuiteList getSupportedCipherSuiteList() {
1047             return supportedCipherSuiteList;
1048         }
1049 
1050         @Override
1051         ProtocolList getServerDefaultProtocolList() {
1052             return serverDefaultProtocolList;
1053         }
1054 
1055         @Override
1056         CipherSuiteList getServerDefaultCipherSuiteList() {
1057             return serverDefaultCipherSuiteList;
1058         }
1059 
1060         @Override
1061         SSLEngine createSSLEngineImpl() {
1062             return new SSLEngineImpl(this, true);
1063         }
1064 
1065         @Override
1066         SSLEngine createSSLEngineImpl(String host, int port) {
1067             return new SSLEngineImpl(this, host, port, true);
1068         }
1069 
1070         @Override
1071         HelloCookieManager getHelloCookieManager(SecureRandom secureRandom) {
1072             return new HelloCookieManager(secureRandom);
1073         }
1074     }
1075 
1076     /*
1077      * The SSLContext implementation for DTLSv1.0 algorithm.
1078      *
1079      * @see SSLContext
1080      */
1081     public static final class DTLS10Context extends AbstractDTLSContext {
1082         private static final ProtocolList clientDefaultProtocolList;
1083         private static final CipherSuiteList clientDefaultCipherSuiteList;
1084 
1085         static {
1086             // available protocols for client mode
1087             clientDefaultProtocolList = new ProtocolList(
1088                     getAvailableProtocols(new ProtocolVersion[] {
1089                 ProtocolVersion.DTLS10
1090             }));
1091 
1092             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1093                     clientDefaultProtocolList, true);       // enabled only
1094         }
1095 
1096         @Override
1097         ProtocolList getClientDefaultProtocolList() {
1098             return clientDefaultProtocolList;
1099         }
1100 
1101         @Override
1102         CipherSuiteList getClientDefaultCipherSuiteList() {
1103             return clientDefaultCipherSuiteList;
1104         }
1105     }
1106 
1107     /*
1108      * The SSLContext implementation for DTLSv1.2 algorithm.
1109      *
1110      * @see SSLContext
1111      */
1112     public static final class DTLS12Context extends AbstractDTLSContext {
1113         private static final ProtocolList clientDefaultProtocolList;
1114         private static final CipherSuiteList clientDefaultCipherSuiteList;
1115 
1116         static {
1117             // available protocols for client mode
1118             clientDefaultProtocolList = new ProtocolList(
1119                     getAvailableProtocols(new ProtocolVersion[] {
1120                 ProtocolVersion.DTLS10,
1121                 ProtocolVersion.DTLS12
1122             }));
1123 
1124             clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1125                     clientDefaultProtocolList, true);       // enabled only
1126         }
1127 
1128         @Override
1129         ProtocolList getClientDefaultProtocolList() {
1130             return clientDefaultProtocolList;
1131         }
1132 
1133         @Override
1134         CipherSuiteList getClientDefaultCipherSuiteList() {
1135             return clientDefaultCipherSuiteList;
1136         }
1137     }
1138 
1139     /*
1140      * The SSLContext implementation for customized TLS protocols
1141      *
1142      * @see SSLContext
1143      */
1144     private static class CustomizedDTLSContext extends AbstractDTLSContext {
1145         private static final ProtocolList clientDefaultProtocolList;
1146         private static final CipherSuiteList clientDefaultCipherSuiteList;
1147 
1148         private static IllegalArgumentException reservedException = null;
1149 
1150         // Don't want a java.lang.LinkageError for illegal system property.
1151         //
1152         // Please don't throw exception in this static block.  Otherwise,
1153         // java.lang.LinkageError may be thrown during the instantiation of
1154         // the provider service. Instead, let's handle the initialization
1155         // exception in constructor.
1156         static {
1157             reservedException = CustomizedSSLProtocols.reservedException;
1158             if (reservedException == null) {
1159                 ArrayList<ProtocolVersion>
1160                         customizedDTLSProtocols = new ArrayList<>();
1161                 for (ProtocolVersion protocol :
1162                         CustomizedSSLProtocols.customizedProtocols) {
1163                     if (protocol.isDTLSProtocol()) {
1164                         customizedDTLSProtocols.add(protocol);
1165                     }
1166                 }
1167 
1168                 // candidates for available protocols
1169                 ProtocolVersion[] candidates;
1170                 if (customizedDTLSProtocols.isEmpty()) {
1171                     // Use the default enabled client protocols if no
1172                     // customized TLS protocols.
1173                     //
1174                     // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
1175                     candidates = new ProtocolVersion[] {
1176                         ProtocolVersion.DTLS10,
1177                         ProtocolVersion.DTLS12
1178                     };
1179 
1180                 } else {
1181                     // Use the customized TLS protocols.
1182                     candidates =
1183                             new ProtocolVersion[customizedDTLSProtocols.size()];
1184                     candidates = customizedDTLSProtocols.toArray(candidates);
1185                 }
1186 
1187                 clientDefaultProtocolList = new ProtocolList(
1188                         getAvailableProtocols(candidates));
1189                 clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
1190                     clientDefaultProtocolList, true);   // enabled only
1191             } else {
1192                 clientDefaultProtocolList = null;       // unlikely to be used
1193                 clientDefaultCipherSuiteList = null;    // unlikely to be used
1194             }
1195         }
1196 
1197         protected CustomizedDTLSContext() {
1198             if (reservedException != null) {
1199                 throw reservedException;
1200             }
1201         }
1202 
1203         @Override
1204         ProtocolList getClientDefaultProtocolList() {
1205             return clientDefaultProtocolList;
1206         }
1207 
1208         @Override
1209         CipherSuiteList getClientDefaultCipherSuiteList() {
1210             return clientDefaultCipherSuiteList;
1211         }
1212     }
1213 
1214     /*
1215      * The SSLContext implementation for default "DTLS" algorithm
1216      *
1217      * @see SSLContext
1218      */
1219     public static final class DTLSContext extends CustomizedDTLSContext {
1220         // use the default constructor and methods
1221     }
1222 
1223 }
1224 
1225 
1226 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
1227             implements X509TrustManager {
1228 
1229     // the delegated trust manager
1230     private final X509TrustManager tm;
1231 
1232     AbstractTrustManagerWrapper(X509TrustManager tm) {
1233         this.tm = tm;
1234     }
1235 
1236     @Override
1237     public void checkClientTrusted(X509Certificate[] chain, String authType)
1238         throws CertificateException {
1239         tm.checkClientTrusted(chain, authType);
1240     }
1241 
1242     @Override
1243     public void checkServerTrusted(X509Certificate[] chain, String authType)
1244         throws CertificateException {
1245         tm.checkServerTrusted(chain, authType);
1246     }
1247 
1248     @Override
1249     public X509Certificate[] getAcceptedIssuers() {
1250         return tm.getAcceptedIssuers();
1251     }
1252 
1253     @Override
1254     public void checkClientTrusted(X509Certificate[] chain, String authType,
1255                 Socket socket) throws CertificateException {
1256         tm.checkClientTrusted(chain, authType);
1257         checkAdditionalTrust(chain, authType, socket, true);
1258     }
1259 
1260     @Override
1261     public void checkServerTrusted(X509Certificate[] chain, String authType,
1262             Socket socket) throws CertificateException {
1263         tm.checkServerTrusted(chain, authType);
1264         checkAdditionalTrust(chain, authType, socket, false);
1265     }
1266 
1267     @Override
1268     public void checkClientTrusted(X509Certificate[] chain, String authType,
1269             SSLEngine engine) throws CertificateException {
1270         tm.checkClientTrusted(chain, authType);
1271         checkAdditionalTrust(chain, authType, engine, true);
1272     }
1273 
1274     @Override
1275     public void checkServerTrusted(X509Certificate[] chain, String authType,
1276             SSLEngine engine) throws CertificateException {
1277         tm.checkServerTrusted(chain, authType);
1278         checkAdditionalTrust(chain, authType, engine, false);
1279     }
1280 
1281     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1282                 Socket socket, boolean isClient) throws CertificateException {
1283         if (socket != null && socket.isConnected() &&
1284                                     socket instanceof SSLSocket) {
1285 
1286             SSLSocket sslSocket = (SSLSocket)socket;
1287             SSLSession session = sslSocket.getHandshakeSession();
1288             if (session == null) {
1289                 throw new CertificateException("No handshake session");
1290             }
1291 
1292             // check endpoint identity
1293             String identityAlg = sslSocket.getSSLParameters().
1294                                         getEndpointIdentificationAlgorithm();
1295             if (identityAlg != null && identityAlg.length() != 0) {
1296                 String hostname = session.getPeerHost();
1297                 X509TrustManagerImpl.checkIdentity(
1298                                     hostname, chain[0], identityAlg);
1299             }
1300 
1301             // try the best to check the algorithm constraints
1302             ProtocolVersion protocolVersion =
1303                 ProtocolVersion.valueOf(session.getProtocol());
1304             AlgorithmConstraints constraints = null;
1305             if (protocolVersion.useTLS12PlusSpec()) {
1306                 if (session instanceof ExtendedSSLSession) {
1307                     ExtendedSSLSession extSession =
1308                                     (ExtendedSSLSession)session;
1309                     String[] peerSupportedSignAlgs =
1310                             extSession.getLocalSupportedSignatureAlgorithms();
1311 
1312                     constraints = new SSLAlgorithmConstraints(
1313                                     sslSocket, peerSupportedSignAlgs, true);
1314                 } else {
1315                     constraints =
1316                             new SSLAlgorithmConstraints(sslSocket, true);
1317                 }
1318             } else {
1319                 constraints = new SSLAlgorithmConstraints(sslSocket, true);
1320             }
1321 
1322             checkAlgorithmConstraints(chain, constraints);
1323         }
1324     }
1325 
1326     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1327             SSLEngine engine, boolean isClient) throws CertificateException {
1328         if (engine != null) {
1329             SSLSession session = engine.getHandshakeSession();
1330             if (session == null) {
1331                 throw new CertificateException("No handshake session");
1332             }
1333 
1334             // check endpoint identity
1335             String identityAlg = engine.getSSLParameters().
1336                                         getEndpointIdentificationAlgorithm();
1337             if (identityAlg != null && identityAlg.length() != 0) {
1338                 String hostname = session.getPeerHost();
1339                 X509TrustManagerImpl.checkIdentity(
1340                                     hostname, chain[0], identityAlg);
1341             }
1342 
1343             // try the best to check the algorithm constraints
1344             ProtocolVersion protocolVersion =
1345                 ProtocolVersion.valueOf(session.getProtocol());
1346             AlgorithmConstraints constraints = null;
1347             if (protocolVersion.useTLS12PlusSpec()) {
1348                 if (session instanceof ExtendedSSLSession) {
1349                     ExtendedSSLSession extSession =
1350                                     (ExtendedSSLSession)session;
1351                     String[] peerSupportedSignAlgs =
1352                             extSession.getLocalSupportedSignatureAlgorithms();
1353 
1354                     constraints = new SSLAlgorithmConstraints(
1355                                     engine, peerSupportedSignAlgs, true);
1356                 } else {
1357                     constraints =
1358                             new SSLAlgorithmConstraints(engine, true);
1359                 }
1360             } else {
1361                 constraints = new SSLAlgorithmConstraints(engine, true);
1362             }
1363 
1364             checkAlgorithmConstraints(chain, constraints);
1365         }
1366     }
1367 
1368     private void checkAlgorithmConstraints(X509Certificate[] chain,
1369             AlgorithmConstraints constraints) throws CertificateException {
1370 
1371         try {
1372             // Does the certificate chain end with a trusted certificate?
1373             int checkedLength = chain.length - 1;
1374 
1375             Collection<X509Certificate> trustedCerts = new HashSet<>();
1376             X509Certificate[] certs = tm.getAcceptedIssuers();
1377             if ((certs != null) && (certs.length > 0)){
1378                 Collections.addAll(trustedCerts, certs);
1379             }
1380 
1381             if (trustedCerts.contains(chain[checkedLength])) {
1382                     checkedLength--;
1383             }
1384 
1385             // A forward checker, need to check from trust to target
1386             if (checkedLength >= 0) {
1387                 AlgorithmChecker checker = new AlgorithmChecker(constraints);
1388                 checker.init(false);
1389                 for (int i = checkedLength; i >= 0; i--) {
1390                     Certificate cert = chain[i];
1391                     // We don't care about the unresolved critical extensions.
1392                     checker.check(cert, Collections.<String>emptySet());
1393                 }
1394             }
1395         } catch (CertPathValidatorException cpve) {
1396             throw new CertificateException(
1397                 "Certificates does not conform to algorithm constraints");
1398         }
1399     }
1400 }
1401 
1402 // Dummy X509TrustManager implementation, rejects all peer certificates.
1403 // Used if the application did not specify a proper X509TrustManager.
1404 final class DummyX509TrustManager extends X509ExtendedTrustManager
1405             implements X509TrustManager {
1406 
1407     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
1408 
1409     private DummyX509TrustManager() {
1410         // empty
1411     }
1412 
1413     /*
1414      * Given the partial or complete certificate chain
1415      * provided by the peer, build a certificate path
1416      * to a trusted root and return if it can be
1417      * validated and is trusted for client SSL authentication.
1418      * If not, it throws an exception.
1419      */
1420     @Override
1421     public void checkClientTrusted(X509Certificate[] chain, String authType)
1422         throws CertificateException {
1423         throw new CertificateException(
1424             "No X509TrustManager implementation avaiable");
1425     }
1426 
1427     /*
1428      * Given the partial or complete certificate chain
1429      * provided by the peer, build a certificate path
1430      * to a trusted root and return if it can be
1431      * validated and is trusted for server SSL authentication.
1432      * If not, it throws an exception.
1433      */
1434     @Override
1435     public void checkServerTrusted(X509Certificate[] chain, String authType)
1436         throws CertificateException {
1437         throw new CertificateException(
1438             "No X509TrustManager implementation available");
1439     }
1440 
1441     /*
1442      * Return an array of issuer certificates which are trusted
1443      * for authenticating peers.
1444      */
1445     @Override
1446     public X509Certificate[] getAcceptedIssuers() {
1447         return new X509Certificate[0];
1448     }
1449 
1450     @Override
1451     public void checkClientTrusted(X509Certificate[] chain, String authType,
1452                 Socket socket) throws CertificateException {
1453         throw new CertificateException(
1454             "No X509TrustManager implementation available");
1455     }
1456 
1457     @Override
1458     public void checkServerTrusted(X509Certificate[] chain, String authType,
1459             Socket socket) throws CertificateException {
1460         throw new CertificateException(
1461             "No X509TrustManager implementation available");
1462     }
1463 
1464     @Override
1465     public void checkClientTrusted(X509Certificate[] chain, String authType,
1466             SSLEngine engine) throws CertificateException {
1467         throw new CertificateException(
1468             "No X509TrustManager implementation available");
1469     }
1470 
1471     @Override
1472     public void checkServerTrusted(X509Certificate[] chain, String authType,
1473             SSLEngine engine) throws CertificateException {
1474         throw new CertificateException(
1475             "No X509TrustManager implementation available");
1476     }
1477 }
1478 
1479 /*
1480  * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
1481  */
1482 final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
1483 
1484     private final X509KeyManager km;
1485 
1486     AbstractKeyManagerWrapper(X509KeyManager km) {
1487         this.km = km;
1488     }
1489 
1490     @Override
1491     public String[] getClientAliases(String keyType, Principal[] issuers) {
1492         return km.getClientAliases(keyType, issuers);
1493     }
1494 
1495     @Override
1496     public String chooseClientAlias(String[] keyType, Principal[] issuers,
1497             Socket socket) {
1498         return km.chooseClientAlias(keyType, issuers, socket);
1499     }
1500 
1501     @Override
1502     public String[] getServerAliases(String keyType, Principal[] issuers) {
1503         return km.getServerAliases(keyType, issuers);
1504     }
1505 
1506     @Override
1507     public String chooseServerAlias(String keyType, Principal[] issuers,
1508             Socket socket) {
1509         return km.chooseServerAlias(keyType, issuers, socket);
1510     }
1511 
1512     @Override
1513     public X509Certificate[] getCertificateChain(String alias) {
1514         return km.getCertificateChain(alias);
1515     }
1516 
1517     @Override
1518     public PrivateKey getPrivateKey(String alias) {
1519         return km.getPrivateKey(alias);
1520     }
1521 
1522     // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
1523     // X509ExtendedKeymanager. It defines them to return null;
1524 }
1525 
1526 
1527 // Dummy X509KeyManager implementation, never returns any certificates/keys.
1528 // Used if the application did not specify a proper X509TrustManager.
1529 final class DummyX509KeyManager extends X509ExtendedKeyManager {
1530 
1531     static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
1532 
1533     private DummyX509KeyManager() {
1534         // empty
1535     }
1536 
1537     /*
1538      * Get the matching aliases for authenticating the client side of a secure
1539      * socket given the public key type and the list of
1540      * certificate issuer authorities recognized by the peer (if any).
1541      */
1542     @Override
1543     public String[] getClientAliases(String keyType, Principal[] issuers) {
1544         return null;
1545     }
1546 
1547     /*
1548      * Choose an alias to authenticate the client side of a secure
1549      * socket given the public key type and the list of
1550      * certificate issuer authorities recognized by the peer (if any).
1551      */
1552     @Override
1553     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
1554             Socket socket) {
1555         return null;
1556     }
1557 
1558     /*
1559      * Choose an alias to authenticate the client side of an
1560      * engine given the public key type and the list of
1561      * certificate issuer authorities recognized by the peer (if any).
1562      */
1563     @Override
1564     public String chooseEngineClientAlias(
1565             String[] keyTypes, Principal[] issuers, SSLEngine engine) {
1566         return null;
1567     }
1568 
1569     /*
1570      * Get the matching aliases for authenticating the server side of a secure
1571      * socket given the public key type and the list of
1572      * certificate issuer authorities recognized by the peer (if any).
1573      */
1574     @Override
1575     public String[] getServerAliases(String keyType, Principal[] issuers) {
1576         return null;
1577     }
1578 
1579     /*
1580      * Choose an alias to authenticate the server side of a secure
1581      * socket given the public key type and the list of
1582      * certificate issuer authorities recognized by the peer (if any).
1583      */
1584     @Override
1585     public String chooseServerAlias(String keyType, Principal[] issuers,
1586             Socket socket) {
1587         return null;
1588     }
1589 
1590     /*
1591      * Choose an alias to authenticate the server side of an engine
1592      * given the public key type and the list of
1593      * certificate issuer authorities recognized by the peer (if any).
1594      */
1595     @Override
1596     public String chooseEngineServerAlias(
1597             String keyType, Principal[] issuers, SSLEngine engine) {
1598         return null;
1599     }
1600 
1601     /**
1602      * Returns the certificate chain associated with the given alias.
1603      *
1604      * @param alias the alias name
1605      *
1606      * @return the certificate chain (ordered with the user's certificate first
1607      * and the root certificate authority last)
1608      */
1609     @Override
1610     public X509Certificate[] getCertificateChain(String alias) {
1611         return null;
1612     }
1613 
1614     /*
1615      * Returns the key associated with the given alias, using the given
1616      * password to recover it.
1617      *
1618      * @param alias the alias name
1619      *
1620      * @return the requested key
1621      */
1622     @Override
1623     public PrivateKey getPrivateKey(String alias) {
1624         return null;
1625     }
1626 }
--- EOF ---