Path: blob/master/src/java.base/share/classes/javax/net/ssl/SSLParameters.java
41159 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.net.ssl;2627import java.security.AlgorithmConstraints;28import java.util.Map;29import java.util.List;30import java.util.HashMap;31import java.util.ArrayList;32import java.util.Collection;33import java.util.Collections;34import java.util.LinkedHashMap;3536/**37* Encapsulates parameters for an SSL/TLS/DTLS connection. The parameters38* are the list of ciphersuites to be accepted in an SSL/TLS/DTLS handshake,39* the list of protocols to be allowed, the endpoint identification40* algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),41* the maximum network packet size, the algorithm constraints and whether42* SSL/TLS/DTLS servers should request or require client authentication, etc.43* <p>44* SSLParameters can be created via the constructors in this class.45* Objects can also be obtained using the {@code getSSLParameters()}46* methods in47* {@link SSLSocket#getSSLParameters SSLSocket} and48* {@link SSLServerSocket#getSSLParameters SSLServerSocket} and49* {@link SSLEngine#getSSLParameters SSLEngine} or the50* {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and51* {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}52* methods in {@code SSLContext}.53* <p>54* SSLParameters can be applied to a connection via the methods55* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and56* {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}57* and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.58* <p>59* For example:60*61* <blockquote><pre>62* SSLParameters p = sslSocket.getSSLParameters();63* p.setProtocols(new String[] { "TLSv1.2" });64* p.setCipherSuites(65* new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ... });66* p.setApplicationProtocols(new String[] {"h2", "http/1.1"});67* sslSocket.setSSLParameters(p);68* </pre></blockquote>69*70* @see SSLSocket71* @see SSLEngine72* @see SSLContext73*74* @since 1.675*/76public class SSLParameters {7778private String[] cipherSuites;79private String[] protocols;80private boolean wantClientAuth;81private boolean needClientAuth;82private String identificationAlgorithm;83private AlgorithmConstraints algorithmConstraints;84private Map<Integer, SNIServerName> sniNames = null;85private Map<Integer, SNIMatcher> sniMatchers = null;86private boolean preferLocalCipherSuites;87private boolean enableRetransmissions = true;88private int maximumPacketSize = 0;89private String[] applicationProtocols = new String[0];9091/**92* Constructs SSLParameters.93* <p>94* The values of cipherSuites, protocols, cryptographic algorithm95* constraints, endpoint identification algorithm, server names and96* server name matchers are set to {@code null}; useCipherSuitesOrder,97* wantClientAuth and needClientAuth are set to {@code false};98* enableRetransmissions is set to {@code true}; maximum network packet99* size is set to {@code 0}.100*/101public SSLParameters() {102// empty103}104105/**106* Constructs SSLParameters from the specified array of ciphersuites.107* <p>108* Calling this constructor is equivalent to calling the no-args109* constructor followed by110* {@code setCipherSuites(cipherSuites);}. Note that the111* standard list of cipher suite names may be found in the <a href=112* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">113* JSSE Cipher Suite Names</a> section of the Java Cryptography114* Architecture Standard Algorithm Name Documentation. Providers115* may support cipher suite names not found in this list.116*117* @param cipherSuites the array of ciphersuites (or null)118*/119public SSLParameters(String[] cipherSuites) {120setCipherSuites(cipherSuites);121}122123/**124* Constructs SSLParameters from the specified array of ciphersuites125* and protocols.126* <p>127* Calling this constructor is equivalent to calling the no-args128* constructor followed by129* {@code setCipherSuites(cipherSuites); setProtocols(protocols);}.130* Note that the standard list of cipher suite names may be found in the131* <a href=132* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">133* JSSE Cipher Suite Names</a> section of the Java Cryptography134* Architecture Standard Algorithm Name Documentation. Providers135* may support cipher suite names not found in this list.136*137* @param cipherSuites the array of ciphersuites (or null)138* @param protocols the array of protocols (or null)139*/140public SSLParameters(String[] cipherSuites, String[] protocols) {141setCipherSuites(cipherSuites);142setProtocols(protocols);143}144145private static String[] clone(String[] s) {146return (s == null) ? null : s.clone();147}148149/**150* Returns a copy of the array of ciphersuites or null if none151* have been set.152* <P>153* The returned array includes cipher suites from the list of standard154* cipher suite names in the <a href=155* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">156* JSSE Cipher Suite Names</a> section of the Java Cryptography157* Architecture Standard Algorithm Name Documentation, and may also158* include other cipher suites that the provider supports.159*160* @return a copy of the array of ciphersuites or null if none161* have been set.162*/163public String[] getCipherSuites() {164return clone(cipherSuites);165}166167/**168* Sets the array of ciphersuites.169*170* @param cipherSuites the array of ciphersuites (or null). Note that the171* standard list of cipher suite names may be found in the <a href=172* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">173* JSSE Cipher Suite Names</a> section of the Java Cryptography174* Architecture Standard Algorithm Name Documentation. Providers175* may support cipher suite names not found in this list or might not176* use the recommended name for a certain cipher suite.177*/178public void setCipherSuites(String[] cipherSuites) {179this.cipherSuites = clone(cipherSuites);180}181182/**183* Returns a copy of the array of protocols or null if none184* have been set.185*186* @return a copy of the array of protocols or null if none187* have been set.188*/189public String[] getProtocols() {190return clone(protocols);191}192193/**194* Sets the array of protocols.195*196* @param protocols the array of protocols (or null)197*/198public void setProtocols(String[] protocols) {199this.protocols = clone(protocols);200}201202/**203* Returns whether client authentication should be requested.204*205* @return whether client authentication should be requested.206*/207public boolean getWantClientAuth() {208return wantClientAuth;209}210211/**212* Sets whether client authentication should be requested. Calling213* this method clears the {@code needClientAuth} flag.214*215* @param wantClientAuth whether client authentication should be requested216*/217public void setWantClientAuth(boolean wantClientAuth) {218this.wantClientAuth = wantClientAuth;219this.needClientAuth = false;220}221222/**223* Returns whether client authentication should be required.224*225* @return whether client authentication should be required.226*/227public boolean getNeedClientAuth() {228return needClientAuth;229}230231/**232* Sets whether client authentication should be required. Calling233* this method clears the {@code wantClientAuth} flag.234*235* @param needClientAuth whether client authentication should be required236*/237public void setNeedClientAuth(boolean needClientAuth) {238this.wantClientAuth = false;239this.needClientAuth = needClientAuth;240}241242/**243* Returns the cryptographic algorithm constraints.244*245* @return the cryptographic algorithm constraints, or null if the246* constraints have not been set247*248* @see #setAlgorithmConstraints(AlgorithmConstraints)249*250* @since 1.7251*/252public AlgorithmConstraints getAlgorithmConstraints() {253return algorithmConstraints;254}255256/**257* Sets the cryptographic algorithm constraints, which will be used258* in addition to any configured by the runtime environment.259* <p>260* If the {@code constraints} parameter is non-null, every261* cryptographic algorithm, key and algorithm parameters used in the262* SSL/TLS/DTLS handshake must be permitted by the constraints.263*264* @param constraints the algorithm constraints (or null)265*266* @since 1.7267*/268public void setAlgorithmConstraints(AlgorithmConstraints constraints) {269// the constraints object is immutable270this.algorithmConstraints = constraints;271}272273/**274* Gets the endpoint identification algorithm.275*276* @return the endpoint identification algorithm, or null if none277* has been set.278*279* @see X509ExtendedTrustManager280* @see #setEndpointIdentificationAlgorithm(String)281*282* @since 1.7283*/284public String getEndpointIdentificationAlgorithm() {285return identificationAlgorithm;286}287288/**289* Sets the endpoint identification algorithm.290* <p>291* If the {@code algorithm} parameter is non-null or non-empty, the292* endpoint identification/verification procedures must be handled during293* SSL/TLS/DTLS handshaking. This is to prevent man-in-the-middle attacks.294*295* @param algorithm The standard string name of the endpoint296* identification algorithm (or null).297* See the <a href=298* "{@docRoot}/../specs/security/standard-names.html">299* Java Security Standard Algorithm Names</a> document300* for information about standard algorithm names.301*302* @see X509ExtendedTrustManager303*304* @since 1.7305*/306public void setEndpointIdentificationAlgorithm(String algorithm) {307this.identificationAlgorithm = algorithm;308}309310/**311* Sets the desired {@link SNIServerName}s of the Server Name312* Indication (SNI) parameter.313* <P>314* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s315* operating in client mode.316* <P>317* Note that the {@code serverNames} list is cloned318* to protect against subsequent modification.319*320* @param serverNames321* the list of desired {@link SNIServerName}s (or null)322*323* @throws NullPointerException if the {@code serverNames}324* contains {@code null} element325* @throws IllegalArgumentException if the {@code serverNames}326* contains more than one name of the same name type327*328* @see SNIServerName329* @see #getServerNames()330*331* @since 1.8332*/333public final void setServerNames(List<SNIServerName> serverNames) {334if (serverNames != null) {335if (!serverNames.isEmpty()) {336sniNames = new LinkedHashMap<>(serverNames.size());337for (SNIServerName serverName : serverNames) {338if (sniNames.put(serverName.getType(),339serverName) != null) {340throw new IllegalArgumentException(341"Duplicated server name of type " +342serverName.getType());343}344}345} else {346sniNames = Collections.<Integer, SNIServerName>emptyMap();347}348} else {349sniNames = null;350}351}352353/**354* Returns a {@link List} containing all {@link SNIServerName}s of the355* Server Name Indication (SNI) parameter, or null if none has been set.356* <P>357* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s358* operating in client mode.359* <P>360* For SSL/TLS/DTLS connections, the underlying SSL/TLS/DTLS provider361* may specify a default value for a certain server name type. In362* client mode, it is recommended that, by default, providers should363* include the server name indication whenever the server can be located364* by a supported server name type.365* <P>366* It is recommended that providers initialize default Server Name367* Indications when creating {@code SSLSocket}/{@code SSLEngine}s.368* In the following examples, the server name could be represented by an369* instance of {@link SNIHostName} which has been initialized with the370* hostname "www.example.com" and type371* {@link StandardConstants#SNI_HOST_NAME}.372*373* <pre>374* Socket socket =375* sslSocketFactory.createSocket("www.example.com", 443);376* </pre>377* or378* <pre>379* SSLEngine engine =380* sslContext.createSSLEngine("www.example.com", 443);381* </pre>382*383* @return null or an immutable list of non-null {@link SNIServerName}s384*385* @see List386* @see #setServerNames(List)387*388* @since 1.8389*/390public final List<SNIServerName> getServerNames() {391if (sniNames != null) {392if (!sniNames.isEmpty()) {393return Collections.<SNIServerName>unmodifiableList(394new ArrayList<>(sniNames.values()));395} else {396return Collections.<SNIServerName>emptyList();397}398}399400return null;401}402403/**404* Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)405* parameter.406* <P>407* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s408* operating in server mode.409* <P>410* Note that the {@code matchers} collection is cloned to protect411* against subsequent modification.412*413* @param matchers414* the collection of {@link SNIMatcher}s (or null)415*416* @throws NullPointerException if the {@code matchers}417* contains {@code null} element418* @throws IllegalArgumentException if the {@code matchers}419* contains more than one name of the same name type420*421* @see Collection422* @see SNIMatcher423* @see #getSNIMatchers()424*425* @since 1.8426*/427public final void setSNIMatchers(Collection<SNIMatcher> matchers) {428if (matchers != null) {429if (!matchers.isEmpty()) {430sniMatchers = new HashMap<>(matchers.size());431for (SNIMatcher matcher : matchers) {432if (sniMatchers.put(matcher.getType(),433matcher) != null) {434throw new IllegalArgumentException(435"Duplicated server name of type " +436matcher.getType());437}438}439} else {440sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();441}442} else {443sniMatchers = null;444}445}446447/**448* Returns a {@link Collection} containing all {@link SNIMatcher}s of the449* Server Name Indication (SNI) parameter, or null if none has been set.450* <P>451* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s452* operating in server mode.453* <P>454* For better interoperability, providers generally will not define455* default matchers so that by default servers will ignore the SNI456* extension and continue the handshake.457*458* @return null or an immutable collection of non-null {@link SNIMatcher}s459*460* @see SNIMatcher461* @see #setSNIMatchers(Collection)462*463* @since 1.8464*/465public final Collection<SNIMatcher> getSNIMatchers() {466if (sniMatchers != null) {467if (!sniMatchers.isEmpty()) {468return Collections.<SNIMatcher>unmodifiableList(469new ArrayList<>(sniMatchers.values()));470} else {471return Collections.<SNIMatcher>emptyList();472}473}474475return null;476}477478/**479* Sets whether the local cipher suites preference should be honored.480*481* @param honorOrder whether local cipher suites order in482* {@code #getCipherSuites} should be honored during483* SSL/TLS/DTLS handshaking.484*485* @see #getUseCipherSuitesOrder()486*487* @since 1.8488*/489public final void setUseCipherSuitesOrder(boolean honorOrder) {490this.preferLocalCipherSuites = honorOrder;491}492493/**494* Returns whether the local cipher suites preference should be honored.495*496* @return whether local cipher suites order in {@code #getCipherSuites}497* should be honored during SSL/TLS/DTLS handshaking.498*499* @see #setUseCipherSuitesOrder(boolean)500*501* @since 1.8502*/503public final boolean getUseCipherSuitesOrder() {504return preferLocalCipherSuites;505}506507/**508* Sets whether DTLS handshake retransmissions should be enabled.509*510* This method only applies to DTLS.511*512* @param enableRetransmissions513* {@code true} indicates that DTLS handshake retransmissions514* should be enabled; {@code false} indicates that DTLS handshake515* retransmissions should be disabled516*517* @see #getEnableRetransmissions()518*519* @since 9520*/521public void setEnableRetransmissions(boolean enableRetransmissions) {522this.enableRetransmissions = enableRetransmissions;523}524525/**526* Returns whether DTLS handshake retransmissions should be enabled.527*528* This method only applies to DTLS.529*530* @return true, if DTLS handshake retransmissions should be enabled531*532* @see #setEnableRetransmissions(boolean)533*534* @since 9535*/536public boolean getEnableRetransmissions() {537return enableRetransmissions;538}539540/**541* Sets the maximum expected network packet size in bytes for542* SSL/TLS/DTLS records.543*544* @apiNote It is recommended that if possible, the maximum packet size545* should not be less than 256 bytes so that small handshake546* messages, such as HelloVerifyRequests, are not fragmented.547*548* @implNote If the maximum packet size is too small to hold a minimal549* record, an implementation may attempt to generate as minimal550* records as possible. However, this may cause a generated551* packet to be larger than the maximum packet size.552*553* @param maximumPacketSize554* the maximum expected network packet size in bytes, or555* {@code 0} to use the implicit size that is automatically556* specified by the underlying implementation.557* @throws IllegalArgumentException558* if {@code maximumPacketSize} is negative.559*560* @see #getMaximumPacketSize()561*562* @since 9563*/564public void setMaximumPacketSize(int maximumPacketSize) {565if (maximumPacketSize < 0) {566throw new IllegalArgumentException(567"The maximum packet size cannot be negative");568}569570this.maximumPacketSize = maximumPacketSize;571}572573/**574* Returns the maximum expected network packet size in bytes for575* SSL/TLS/DTLS records.576*577* @apiNote The implicit size may not be a fixed value, especially578* for a DTLS protocols implementation.579*580* @implNote For SSL/TLS/DTLS connections, the underlying provider581* should calculate and specify the implicit value of the582* maximum expected network packet size if it is not583* configured explicitly. For any connection populated584* object, this method should never return {@code 0} so585* that applications can retrieve the actual implicit size586* of the underlying implementation.587* <P>588* An implementation should attempt to comply with the maximum589* packet size configuration. However, if the maximum packet590* size is too small to hold a minimal record, an implementation591* may try to generate as minimal records as possible. This592* may cause a generated packet to be larger than the maximum593* packet size.594*595* @return the maximum expected network packet size, or {@code 0} if596* use the implicit size that is automatically specified by597* the underlying implementation and this object has not been598* populated by any connection.599*600* @see #setMaximumPacketSize(int)601*602* @since 9603*/604public int getMaximumPacketSize() {605return maximumPacketSize;606}607608/**609* Returns a prioritized array of application-layer protocol names that610* can be negotiated over the SSL/TLS/DTLS protocols.611* <p>612* The array could be empty (zero-length), in which case protocol613* indications will not be used.614* <p>615* This method will return a new array each time it is invoked.616*617* @return a non-null, possibly zero-length array of application protocol618* {@code String}s. The array is ordered based on protocol619* preference, with {@code protocols[0]} being the most preferred.620* @see #setApplicationProtocols621* @since 9622*/623public String[] getApplicationProtocols() {624return applicationProtocols.clone();625}626627/**628* Sets the prioritized array of application-layer protocol names that629* can be negotiated over the SSL/TLS/DTLS protocols.630* <p>631* If application-layer protocols are supported by the underlying632* SSL/TLS implementation, this method configures which values can633* be negotiated by protocols such as <a634* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the635* Application Layer Protocol Negotiation (ALPN).636* <p>637* If this end of the connection is expected to offer application protocol638* values, all protocols configured by this method will be sent to the639* peer.640* <p>641* If this end of the connection is expected to select the application642* protocol value, the {@code protocols} configured by this method are643* compared with those sent by the peer. The first matched value becomes644* the negotiated value. If none of the {@code protocols} were actually645* requested by the peer, the underlying protocol will determine what646* action to take. (For example, ALPN will send a647* {@code "no_application_protocol"} alert and terminate the connection.)648* <p>649* The {@code String} values must be presented using the network650* byte representation expected by the peer. For example, if an ALPN651* {@code String} should be exchanged using {@code UTF-8}, the652* {@code String} should be converted to its {@code byte[]} representation653* and stored as a byte-oriented {@code String} before calling this method.654*655* <blockquote><pre>656* // MEETEI MAYEK LETTERS HUK UN I (Unicode 0xabcd->0xabcf): 2 bytes657* byte[] bytes = "\u005cuabcd\u005cuabce\u005cuabcf"658* .getBytes(StandardCharsets.UTF_8);659* String HUK_UN_I = new String(bytes, StandardCharsets.ISO_8859_1);660*661* // 0x00-0xFF: 1 byte662* String rfc7301Grease8A = "\u005cu008A\u005cu008A";663*664* SSLParameters p = sslSocket.getSSLParameters();665* p.setApplicationProtocols(new String[] {666* "h2", "http/1.1", rfc7301Grease8A, HUK_UN_I});667* sslSocket.setSSLParameters(p);668* </pre></blockquote>669*670* @implSpec671* This method will make a copy of the {@code protocols} array.672*673* @param protocols an ordered array of application protocols,674* with {@code protocols[0]} being the most preferred.675* If the array is empty (zero-length), protocol676* indications will not be used.677* @throws IllegalArgumentException if protocols is null, or if678* any element in a non-empty array is null or an679* empty (zero-length) string680* @see #getApplicationProtocols681* @since 9682*/683public void setApplicationProtocols(String[] protocols) {684if (protocols == null) {685throw new IllegalArgumentException("protocols was null");686}687688String[] tempProtocols = protocols.clone();689690for (String p : tempProtocols) {691if (p == null || p.isEmpty()) {692throw new IllegalArgumentException(693"An element of protocols was null/empty");694}695}696applicationProtocols = tempProtocols;697}698}699700701