src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java
changeset 50768 68fa3d4026ea
child 51407 910f7b56592f
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.ssl;
       
    27 
       
    28 import java.security.AccessControlContext;
       
    29 import java.security.AccessController;
       
    30 import java.security.AlgorithmConstraints;
       
    31 import java.security.NoSuchAlgorithmException;
       
    32 import java.security.PrivilegedActionException;
       
    33 import java.security.PrivilegedExceptionAction;
       
    34 import java.util.ArrayList;
       
    35 import java.util.Arrays;
       
    36 import java.util.Collection;
       
    37 import java.util.Collections;
       
    38 import java.util.HashMap;
       
    39 import java.util.List;
       
    40 import java.util.function.BiFunction;
       
    41 import javax.net.ssl.HandshakeCompletedListener;
       
    42 import javax.net.ssl.SNIMatcher;
       
    43 import javax.net.ssl.SNIServerName;
       
    44 import javax.net.ssl.SSLEngine;
       
    45 import javax.net.ssl.SSLParameters;
       
    46 import javax.net.ssl.SSLSocket;
       
    47 import sun.security.ssl.SSLExtension.ClientExtensions;
       
    48 import sun.security.ssl.SSLExtension.ServerExtensions;
       
    49 
       
    50 /**
       
    51  * SSL/(D)TLS configuration.
       
    52  */
       
    53 final class SSLConfiguration implements Cloneable {
       
    54     // configurations with SSLParameters
       
    55     AlgorithmConstraints        algorithmConstraints;
       
    56     List<ProtocolVersion>       enabledProtocols;
       
    57     List<CipherSuite>           enabledCipherSuites;
       
    58     ClientAuthType              clientAuthType;
       
    59     String                      identificationProtocol;
       
    60     List<SNIServerName>         serverNames;
       
    61     Collection<SNIMatcher>      sniMatchers;
       
    62     String[]                    applicationProtocols;
       
    63     boolean                     preferLocalCipherSuites;
       
    64     boolean                     enableRetransmissions;
       
    65     int                         maximumPacketSize;
       
    66 
       
    67     // the maximum protocol version of enabled protocols
       
    68     ProtocolVersion             maximumProtocolVersion;
       
    69 
       
    70     // Configurations per SSLSocket or SSLEngine instance.
       
    71     boolean                     isClientMode;
       
    72     boolean                     enableSessionCreation;
       
    73 
       
    74     // the application layer protocol negotiation configuration
       
    75     BiFunction<SSLSocket, List<String>, String> socketAPSelector;
       
    76     BiFunction<SSLEngine, List<String>, String> engineAPSelector;
       
    77 
       
    78     HashMap<HandshakeCompletedListener, AccessControlContext>
       
    79                                 handshakeListeners;
       
    80 
       
    81     boolean                     noSniExtension;
       
    82     boolean                     noSniMatcher;
       
    83 
       
    84     // To switch off the extended_master_secret extension.
       
    85     static final boolean useExtendedMasterSecret;
       
    86 
       
    87     // Allow session resumption without Extended Master Secret extension.
       
    88     static final boolean allowLegacyResumption =
       
    89         Utilities.getBooleanProperty("jdk.tls.allowLegacyResumption", true);
       
    90 
       
    91     // Allow full handshake without Extended Master Secret extension.
       
    92     static final boolean allowLegacyMasterSecret =
       
    93         Utilities.getBooleanProperty("jdk.tls.allowLegacyMasterSecret", true);
       
    94 
       
    95     // Allow full handshake without Extended Master Secret extension.
       
    96     static final boolean useCompatibilityMode = Utilities.getBooleanProperty(
       
    97             "jdk.tls.client.useCompatibilityMode", true);
       
    98 
       
    99 // TODO: Please remove after TLS 1.3 draft interop testing
       
   100 // delete me
       
   101 static int tls13VN;
       
   102 
       
   103     // Is the extended_master_secret extension supported?
       
   104     static {
       
   105         boolean supportExtendedMasterSecret = Utilities.getBooleanProperty(
       
   106                     "jdk.tls.useExtendedMasterSecret", true);
       
   107         if (supportExtendedMasterSecret) {
       
   108             try {
       
   109                 JsseJce.getKeyGenerator("SunTlsExtendedMasterSecret");
       
   110             } catch (NoSuchAlgorithmException nae) {
       
   111                 supportExtendedMasterSecret = false;
       
   112             }
       
   113         }
       
   114         useExtendedMasterSecret = supportExtendedMasterSecret;
       
   115 
       
   116 // delete me
       
   117 try {
       
   118     tls13VN =
       
   119         AccessController.doPrivileged(
       
   120             new PrivilegedExceptionAction<Integer>() {
       
   121                 @Override
       
   122                 public Integer run() throws Exception {
       
   123                     return Integer.parseInt(
       
   124                         System.getProperty("jdk.tls13.version", "0304"), 16);
       
   125                 }
       
   126             });
       
   127 } catch (PrivilegedActionException ex) {
       
   128     // blank
       
   129 }
       
   130     }
       
   131 
       
   132     SSLConfiguration(SSLContextImpl sslContext, boolean isClientMode) {
       
   133 
       
   134         // Configurations with SSLParameters, default values.
       
   135         this.algorithmConstraints = SSLAlgorithmConstraints.DEFAULT;
       
   136         this.enabledProtocols =
       
   137                 sslContext.getDefaultProtocolVersions(!isClientMode);
       
   138         this.enabledCipherSuites =
       
   139                 sslContext.getDefaultCipherSuites(!isClientMode);
       
   140         this.clientAuthType = ClientAuthType.CLIENT_AUTH_NONE;
       
   141 
       
   142         this.identificationProtocol = null;
       
   143         this.serverNames = Collections.<SNIServerName>emptyList();
       
   144         this.sniMatchers = Collections.<SNIMatcher>emptyList();
       
   145         this.preferLocalCipherSuites = false;
       
   146 
       
   147         this.applicationProtocols = new String[0];
       
   148         this.enableRetransmissions = sslContext.isDTLS();
       
   149         this.maximumPacketSize = 0;         // please reset it explicitly later
       
   150 
       
   151         this.maximumProtocolVersion = ProtocolVersion.NONE;
       
   152         for (ProtocolVersion pv : enabledProtocols) {
       
   153             if (pv.compareTo(maximumProtocolVersion) > 0) {
       
   154                 this.maximumProtocolVersion = pv;
       
   155             }
       
   156         }
       
   157 
       
   158         // Configurations per SSLSocket or SSLEngine instance.
       
   159         this.isClientMode = isClientMode;
       
   160         this.enableSessionCreation = true;
       
   161         this.socketAPSelector = null;
       
   162         this.engineAPSelector = null;
       
   163 
       
   164         this.handshakeListeners = null;
       
   165         this.noSniExtension = false;
       
   166         this.noSniMatcher = false;
       
   167     }
       
   168 
       
   169     SSLParameters getSSLParameters() {
       
   170         SSLParameters params = new SSLParameters();
       
   171 
       
   172         params.setAlgorithmConstraints(this.algorithmConstraints);
       
   173         params.setProtocols(ProtocolVersion.toStringArray(enabledProtocols));
       
   174         params.setCipherSuites(CipherSuite.namesOf(enabledCipherSuites));
       
   175         switch (this.clientAuthType) {
       
   176             case CLIENT_AUTH_REQUIRED:
       
   177                 params.setNeedClientAuth(true);
       
   178                 break;
       
   179             case CLIENT_AUTH_REQUESTED:
       
   180                 params.setWantClientAuth(true);
       
   181                 break;
       
   182             default:
       
   183                 params.setWantClientAuth(false);
       
   184         }
       
   185         params.setEndpointIdentificationAlgorithm(this.identificationProtocol);
       
   186 
       
   187         if (serverNames.isEmpty() && !noSniExtension) {
       
   188             // 'null' indicates none has been set
       
   189             params.setServerNames(null);
       
   190         } else {
       
   191             params.setServerNames(this.serverNames);
       
   192         }
       
   193 
       
   194         if (sniMatchers.isEmpty() && !noSniMatcher) {
       
   195             // 'null' indicates none has been set
       
   196             params.setSNIMatchers(null);
       
   197         } else {
       
   198             params.setSNIMatchers(this.sniMatchers);
       
   199         }
       
   200 
       
   201         params.setApplicationProtocols(this.applicationProtocols);
       
   202         params.setUseCipherSuitesOrder(this.preferLocalCipherSuites);
       
   203         params.setEnableRetransmissions(this.enableRetransmissions);
       
   204         params.setMaximumPacketSize(this.maximumPacketSize);
       
   205 
       
   206         return params;
       
   207     }
       
   208 
       
   209     void setSSLParameters(SSLParameters params) {
       
   210         AlgorithmConstraints ac = params.getAlgorithmConstraints();
       
   211         if (ac != null) {
       
   212             this.algorithmConstraints = ac;
       
   213         }   // otherwise, use the default value
       
   214 
       
   215         String[] sa = params.getCipherSuites();
       
   216         if (sa != null) {
       
   217             this.enabledCipherSuites = CipherSuite.validValuesOf(sa);
       
   218         }   // otherwise, use the default values
       
   219 
       
   220         sa = params.getProtocols();
       
   221         if (sa != null) {
       
   222             this.enabledProtocols = ProtocolVersion.namesOf(sa);
       
   223 
       
   224             this.maximumProtocolVersion = ProtocolVersion.NONE;
       
   225             for (ProtocolVersion pv : enabledProtocols) {
       
   226                 if (pv.compareTo(maximumProtocolVersion) > 0) {
       
   227                     this.maximumProtocolVersion = pv;
       
   228                 }
       
   229             }
       
   230         }   // otherwise, use the default values
       
   231 
       
   232         if (params.getNeedClientAuth()) {
       
   233             this.clientAuthType = ClientAuthType.CLIENT_AUTH_REQUIRED;
       
   234         } else if (params.getWantClientAuth()) {
       
   235             this.clientAuthType = ClientAuthType.CLIENT_AUTH_REQUESTED;
       
   236         } else {
       
   237             this.clientAuthType = ClientAuthType.CLIENT_AUTH_NONE;
       
   238         }
       
   239 
       
   240         String s = params.getEndpointIdentificationAlgorithm();
       
   241         if (s != null) {
       
   242             this.identificationProtocol = s;
       
   243         }   // otherwise, use the default value
       
   244 
       
   245         List<SNIServerName> sniNames = params.getServerNames();
       
   246         if (sniNames != null) {
       
   247             this.noSniExtension = sniNames.isEmpty();
       
   248             this.serverNames = sniNames;
       
   249         }   // null if none has been set
       
   250 
       
   251         Collection<SNIMatcher> matchers = params.getSNIMatchers();
       
   252         if (matchers != null) {
       
   253             this.noSniMatcher = matchers.isEmpty();
       
   254             this.sniMatchers = matchers;
       
   255         }   // null if none has been set
       
   256 
       
   257         sa = params.getApplicationProtocols();
       
   258         if (sa != null) {
       
   259             this.applicationProtocols = sa;
       
   260         }   // otherwise, use the default values
       
   261 
       
   262         this.preferLocalCipherSuites = params.getUseCipherSuitesOrder();
       
   263         this.enableRetransmissions = params.getEnableRetransmissions();
       
   264         this.maximumPacketSize = params.getMaximumPacketSize();
       
   265     }
       
   266 
       
   267     // SSLSocket only
       
   268     void addHandshakeCompletedListener(
       
   269             HandshakeCompletedListener listener) {
       
   270 
       
   271         if (handshakeListeners == null) {
       
   272             handshakeListeners = new HashMap<>(4);
       
   273         }
       
   274 
       
   275         handshakeListeners.put(listener, AccessController.getContext());
       
   276     }
       
   277 
       
   278     // SSLSocket only
       
   279     void removeHandshakeCompletedListener(
       
   280             HandshakeCompletedListener listener) {
       
   281 
       
   282         if (handshakeListeners == null) {
       
   283             throw new IllegalArgumentException("no listeners");
       
   284         }
       
   285 
       
   286         if (handshakeListeners.remove(listener) == null) {
       
   287             throw new IllegalArgumentException("listener not registered");
       
   288         }
       
   289 
       
   290         if (handshakeListeners.isEmpty()) {
       
   291             handshakeListeners = null;
       
   292         }
       
   293     }
       
   294 
       
   295     /**
       
   296      * Return true if the extension is available.
       
   297      */
       
   298     boolean isAvailable(SSLExtension extension) {
       
   299         for (ProtocolVersion protocolVersion : enabledProtocols) {
       
   300             if (extension.isAvailable(protocolVersion)) {
       
   301                 if (isClientMode ?
       
   302                         ClientExtensions.defaults.contains(extension) :
       
   303                         ServerExtensions.defaults.contains(extension)) {
       
   304                     return true;
       
   305                 }
       
   306             }
       
   307         }
       
   308 
       
   309         return false;
       
   310     }
       
   311 
       
   312     /**
       
   313      * Return true if the extension is available for the specific protocol.
       
   314      */
       
   315     boolean isAvailable(SSLExtension extension,
       
   316             ProtocolVersion protocolVersion) {
       
   317         return extension.isAvailable(protocolVersion) &&
       
   318                 (isClientMode ? ClientExtensions.defaults.contains(extension) :
       
   319                                 ServerExtensions.defaults.contains(extension));
       
   320     }
       
   321 
       
   322     /**
       
   323      * Get the enabled extensions for the specific handshake message.
       
   324      *
       
   325      * Used to consume handshake extensions.
       
   326      */
       
   327     SSLExtension[] getEnabledExtensions(SSLHandshake handshakeType) {
       
   328         List<SSLExtension> extensions = new ArrayList<>();
       
   329         for (SSLExtension extension : SSLExtension.values()) {
       
   330             if (extension.handshakeType == handshakeType) {
       
   331                 if (isAvailable(extension)) {
       
   332                     extensions.add(extension);
       
   333                 }
       
   334             }
       
   335         }
       
   336 
       
   337         return extensions.toArray(new SSLExtension[0]);
       
   338     }
       
   339 
       
   340     /**
       
   341      * Get the enabled extensions for the specific handshake message, excluding
       
   342      * the specified extensions.
       
   343      *
       
   344      * Used to consume handshake extensions.
       
   345      */
       
   346     SSLExtension[] getExclusiveExtensions(SSLHandshake handshakeType,
       
   347             List<SSLExtension> excluded) {
       
   348         List<SSLExtension> extensions = new ArrayList<>();
       
   349         for (SSLExtension extension : SSLExtension.values()) {
       
   350             if (extension.handshakeType == handshakeType) {
       
   351                 if (isAvailable(extension) && !excluded.contains(extension)) {
       
   352                     extensions.add(extension);
       
   353                 }
       
   354             }
       
   355         }
       
   356 
       
   357         return extensions.toArray(new SSLExtension[0]);
       
   358     }
       
   359 
       
   360     /**
       
   361      * Get the enabled extensions for the specific handshake message
       
   362      * and the specific protocol version.
       
   363      *
       
   364      * Used to produce handshake extensions after handshake protocol
       
   365      * version negotiation.
       
   366      */
       
   367     SSLExtension[] getEnabledExtensions(
       
   368             SSLHandshake handshakeType, ProtocolVersion protocolVersion) {
       
   369         return getEnabledExtensions(
       
   370             handshakeType, Arrays.asList(protocolVersion));
       
   371     }
       
   372 
       
   373     /**
       
   374      * Get the enabled extensions for the specific handshake message
       
   375      * and the specific protocol versions.
       
   376      *
       
   377      * Used to produce ClientHello extensions before handshake protocol
       
   378      * version negotiation.
       
   379      */
       
   380     SSLExtension[] getEnabledExtensions(
       
   381             SSLHandshake handshakeType, List<ProtocolVersion> activeProtocols) {
       
   382         List<SSLExtension> extensions = new ArrayList<>();
       
   383         for (SSLExtension extension : SSLExtension.values()) {
       
   384             if (extension.handshakeType == handshakeType) {
       
   385                 if (!isAvailable(extension)) {
       
   386                     continue;
       
   387                 }
       
   388 
       
   389                 for (ProtocolVersion protocolVersion : activeProtocols) {
       
   390                     if (extension.isAvailable(protocolVersion)) {
       
   391                         extensions.add(extension);
       
   392                         break;
       
   393                     }
       
   394                 }
       
   395             }
       
   396         }
       
   397 
       
   398         return extensions.toArray(new SSLExtension[0]);
       
   399     }
       
   400 
       
   401     @Override
       
   402     @SuppressWarnings({"unchecked", "CloneDeclaresCloneNotSupported"})
       
   403     public Object clone() {
       
   404         // Note that only references to the configurations are copied.
       
   405         try {
       
   406             SSLConfiguration config = (SSLConfiguration)super.clone();
       
   407             if (handshakeListeners != null) {
       
   408                 config.handshakeListeners =
       
   409                     (HashMap<HandshakeCompletedListener, AccessControlContext>)
       
   410                             handshakeListeners.clone();
       
   411             }
       
   412 
       
   413             return config;
       
   414         } catch (CloneNotSupportedException cnse) {
       
   415             // unlikely
       
   416         }
       
   417 
       
   418         return null;    // unlikely
       
   419     }
       
   420 }