1 /*
   2  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.net.ssl;
  27 
  28 import java.security.AlgorithmConstraints;
  29 import java.util.Map;
  30 import java.util.List;
  31 import java.util.HashMap;
  32 import java.util.ArrayList;
  33 import java.util.Collection;
  34 import java.util.Collections;
  35 import java.util.LinkedHashMap;
  36 
  37 /**
  38  * Encapsulates parameters for an SSL/TLS connection. The parameters
  39  * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
  40  * the list of protocols to be allowed, the endpoint identification
  41  * algorithm during SSL/TLS handshaking, the Server Name Indication (SNI),
  42  * the algorithm constraints and whether SSL/TLS servers should request
  43  * or require client authentication, etc.
  44  * <p>
  45  * SSLParameters can be created via the constructors in this class.
  46  * Objects can also be obtained using the <code>getSSLParameters()</code>
  47  * methods in
  48  * {@link SSLSocket#getSSLParameters SSLSocket} and
  49  * {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
  50  * {@link SSLEngine#getSSLParameters SSLEngine} or the
  51  * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
  52  * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
  53  * methods in <code>SSLContext</code>.
  54  * <p>
  55  * SSLParameters can be applied to a connection via the methods
  56  * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
  57  * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
  58  * and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.
  59  *
  60  * @see SSLSocket
  61  * @see SSLEngine
  62  * @see SSLContext
  63  *
  64  * @since 1.6
  65  */
  66 public class SSLParameters {
  67 
  68     private String[] cipherSuites;
  69     private String[] protocols;
  70     private boolean wantClientAuth;
  71     private boolean needClientAuth;
  72     private String identificationAlgorithm;
  73     private AlgorithmConstraints algorithmConstraints;
  74     private Map<Integer, SNIServerName> sniNames = null;
  75     private Map<Integer, SNIMatcher> sniMatchers = null;
  76     private boolean preferLocalCipherSuites;
  77     private boolean sendFallbackSCSV;
  78 
  79     /**
  80      * Constructs SSLParameters.
  81      * <p>
  82      * The values of cipherSuites, protocols, cryptographic algorithm
  83      * constraints, endpoint identification algorithm, server names and
  84      * server name matchers are set to <code>null</code>, useCipherSuitesOrder,
  85      * wantClientAuth and needClientAuth are set to <code>false</code>.
  86      */
  87     public SSLParameters() {
  88         // empty
  89     }
  90 
  91     /**
  92      * Constructs SSLParameters from the specified array of ciphersuites.
  93      * <p>
  94      * Calling this constructor is equivalent to calling the no-args
  95      * constructor followed by
  96      * <code>setCipherSuites(cipherSuites);</code>.
  97      *
  98      * @param cipherSuites the array of ciphersuites (or null)
  99      */
 100     public SSLParameters(String[] cipherSuites) {
 101         setCipherSuites(cipherSuites);
 102     }
 103 
 104     /**
 105      * Constructs SSLParameters from the specified array of ciphersuites
 106      * and protocols.
 107      * <p>
 108      * Calling this constructor is equivalent to calling the no-args
 109      * constructor followed by
 110      * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
 111      *
 112      * @param cipherSuites the array of ciphersuites (or null)
 113      * @param protocols the array of protocols (or null)
 114      */
 115     public SSLParameters(String[] cipherSuites, String[] protocols) {
 116         setCipherSuites(cipherSuites);
 117         setProtocols(protocols);
 118     }
 119 
 120     private static String[] clone(String[] s) {
 121         return (s == null) ? null : s.clone();
 122     }
 123 
 124     /**
 125      * Returns a copy of the array of ciphersuites or null if none
 126      * have been set.
 127      *
 128      * @return a copy of the array of ciphersuites or null if none
 129      * have been set.
 130      */
 131     public String[] getCipherSuites() {
 132         return clone(cipherSuites);
 133     }
 134 
 135     /**
 136      * Sets the array of ciphersuites.
 137      *
 138      * @param cipherSuites the array of ciphersuites (or null)
 139      */
 140     public void setCipherSuites(String[] cipherSuites) {
 141         this.cipherSuites = clone(cipherSuites);
 142     }
 143 
 144     /**
 145      * Returns a copy of the array of protocols or null if none
 146      * have been set.
 147      *
 148      * @return a copy of the array of protocols or null if none
 149      * have been set.
 150      */
 151     public String[] getProtocols() {
 152         return clone(protocols);
 153     }
 154 
 155     /**
 156      * Sets the array of protocols.
 157      *
 158      * @param protocols the array of protocols (or null)
 159      */
 160     public void setProtocols(String[] protocols) {
 161         this.protocols = clone(protocols);
 162     }
 163 
 164     /**
 165      * Returns whether client authentication should be requested.
 166      *
 167      * @return whether client authentication should be requested.
 168      */
 169     public boolean getWantClientAuth() {
 170         return wantClientAuth;
 171     }
 172 
 173     /**
 174      * Sets whether client authentication should be requested. Calling
 175      * this method clears the <code>needClientAuth</code> flag.
 176      *
 177      * @param wantClientAuth whether client authentication should be requested
 178      */
 179     public void setWantClientAuth(boolean wantClientAuth) {
 180         this.wantClientAuth = wantClientAuth;
 181         this.needClientAuth = false;
 182     }
 183 
 184     /**
 185      * Returns whether client authentication should be required.
 186      *
 187      * @return whether client authentication should be required.
 188      */
 189     public boolean getNeedClientAuth() {
 190         return needClientAuth;
 191     }
 192 
 193     /**
 194      * Sets whether client authentication should be required. Calling
 195      * this method clears the <code>wantClientAuth</code> flag.
 196      *
 197      * @param needClientAuth whether client authentication should be required
 198      */
 199     public void setNeedClientAuth(boolean needClientAuth) {
 200         this.wantClientAuth = false;
 201         this.needClientAuth = needClientAuth;
 202     }
 203 
 204     /**
 205      * Returns the cryptographic algorithm constraints.
 206      *
 207      * @return the cryptographic algorithm constraints, or null if the
 208      *     constraints have not been set
 209      *
 210      * @see #setAlgorithmConstraints(AlgorithmConstraints)
 211      *
 212      * @since 1.7
 213      */
 214     public AlgorithmConstraints getAlgorithmConstraints() {
 215         return algorithmConstraints;
 216     }
 217 
 218     /**
 219      * Sets the cryptographic algorithm constraints, which will be used
 220      * in addition to any configured by the runtime environment.
 221      * <p>
 222      * If the <code>constraints</code> parameter is non-null, every
 223      * cryptographic algorithm, key and algorithm parameters used in the
 224      * SSL/TLS handshake must be permitted by the constraints.
 225      *
 226      * @param constraints the algorithm constraints (or null)
 227      *
 228      * @since 1.7
 229      */
 230     public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
 231         // the constraints object is immutable
 232         this.algorithmConstraints = constraints;
 233     }
 234 
 235     /**
 236      * Gets the endpoint identification algorithm.
 237      *
 238      * @return the endpoint identification algorithm, or null if none
 239      * has been set.
 240      *
 241      * @see X509ExtendedTrustManager
 242      * @see #setEndpointIdentificationAlgorithm(String)
 243      *
 244      * @since 1.7
 245      */
 246     public String getEndpointIdentificationAlgorithm() {
 247         return identificationAlgorithm;
 248     }
 249 
 250     /**
 251      * Sets the endpoint identification algorithm.
 252      * <p>
 253      * If the <code>algorithm</code> parameter is non-null or non-empty, the
 254      * endpoint identification/verification procedures must be handled during
 255      * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
 256      *
 257      * @param algorithm The standard string name of the endpoint
 258      *     identification algorithm (or null).  See Appendix A in the <a href=
 259      *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
 260      *     Java Cryptography Architecture API Specification &amp; Reference </a>
 261      *     for information about standard algorithm names.
 262      *
 263      * @see X509ExtendedTrustManager
 264      *
 265      * @since 1.7
 266      */
 267     public void setEndpointIdentificationAlgorithm(String algorithm) {
 268         this.identificationAlgorithm = algorithm;
 269     }
 270 
 271     /**
 272      * Sets the desired {@link SNIServerName}s of the Server Name
 273      * Indication (SNI) parameter.
 274      * <P>
 275      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
 276      * operating in client mode.
 277      * <P>
 278      * Note that the {@code serverNames} list is cloned
 279      * to protect against subsequent modification.
 280      *
 281      * @param  serverNames
 282      *         the list of desired {@link SNIServerName}s (or null)
 283      *
 284      * @throws NullPointerException if the {@code serverNames}
 285      *         contains {@code null} element
 286      * @throws IllegalArgumentException if the {@code serverNames}
 287      *         contains more than one name of the same name type
 288      *
 289      * @see SNIServerName
 290      * @see #getServerNames()
 291      *
 292      * @since 1.8
 293      */
 294     public final void setServerNames(List<SNIServerName> serverNames) {
 295         if (serverNames != null) {
 296             if (!serverNames.isEmpty()) {
 297                 sniNames = new LinkedHashMap<>(serverNames.size());
 298                 for (SNIServerName serverName : serverNames) {
 299                     if (sniNames.put(serverName.getType(),
 300                                                 serverName) != null) {
 301                         throw new IllegalArgumentException(
 302                                     "Duplicated server name of type " +
 303                                     serverName.getType());
 304                     }
 305                 }
 306             } else {
 307                 sniNames = Collections.<Integer, SNIServerName>emptyMap();
 308             }
 309         } else {
 310             sniNames = null;
 311         }
 312     }
 313 
 314     /**
 315      * Returns a {@link List} containing all {@link SNIServerName}s of the
 316      * Server Name Indication (SNI) parameter, or null if none has been set.
 317      * <P>
 318      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
 319      * operating in client mode.
 320      * <P>
 321      * For SSL/TLS connections, the underlying SSL/TLS provider
 322      * may specify a default value for a certain server name type.  In
 323      * client mode, it is recommended that, by default, providers should
 324      * include the server name indication whenever the server can be located
 325      * by a supported server name type.
 326      * <P>
 327      * It is recommended that providers initialize default Server Name
 328      * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
 329      * In the following examples, the server name could be represented by an
 330      * instance of {@link SNIHostName} which has been initialized with the
 331      * hostname "www.example.com" and type
 332      * {@link StandardConstants#SNI_HOST_NAME}.
 333      *
 334      * <pre>
 335      *     Socket socket =
 336      *         sslSocketFactory.createSocket("www.example.com", 443);
 337      * </pre>
 338      * or
 339      * <pre>
 340      *     SSLEngine engine =
 341      *         sslContext.createSSLEngine("www.example.com", 443);
 342      * </pre>
 343      * <P>
 344      *
 345      * @return null or an immutable list of non-null {@link SNIServerName}s
 346      *
 347      * @see List
 348      * @see #setServerNames(List)
 349      *
 350      * @since 1.8
 351      */
 352     public final List<SNIServerName> getServerNames() {
 353         if (sniNames != null) {
 354             if (!sniNames.isEmpty()) {
 355                 return Collections.<SNIServerName>unmodifiableList(
 356                                         new ArrayList<>(sniNames.values()));
 357             } else {
 358                 return Collections.<SNIServerName>emptyList();
 359             }
 360         }
 361 
 362         return null;
 363     }
 364 
 365     /**
 366      * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
 367      * parameter.
 368      * <P>
 369      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
 370      * operating in server mode.
 371      * <P>
 372      * Note that the {@code matchers} collection is cloned to protect
 373      * against subsequent modification.
 374      *
 375      * @param  matchers
 376      *         the collection of {@link SNIMatcher}s (or null)
 377      *
 378      * @throws NullPointerException if the {@code matchers}
 379      *         contains {@code null} element
 380      * @throws IllegalArgumentException if the {@code matchers}
 381      *         contains more than one name of the same name type
 382      *
 383      * @see Collection
 384      * @see SNIMatcher
 385      * @see #getSNIMatchers()
 386      *
 387      * @since 1.8
 388      */
 389     public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
 390         if (matchers != null) {
 391             if (!matchers.isEmpty()) {
 392                 sniMatchers = new HashMap<>(matchers.size());
 393                 for (SNIMatcher matcher : matchers) {
 394                     if (sniMatchers.put(matcher.getType(),
 395                                                 matcher) != null) {
 396                         throw new IllegalArgumentException(
 397                                     "Duplicated server name of type " +
 398                                     matcher.getType());
 399                     }
 400                 }
 401             } else {
 402                 sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
 403             }
 404         } else {
 405             sniMatchers = null;
 406         }
 407     }
 408 
 409     /**
 410      * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
 411      * Server Name Indication (SNI) parameter, or null if none has been set.
 412      * <P>
 413      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
 414      * operating in server mode.
 415      * <P>
 416      * For better interoperability, providers generally will not define
 417      * default matchers so that by default servers will ignore the SNI
 418      * extension and continue the handshake.
 419      *
 420      * @return null or an immutable collection of non-null {@link SNIMatcher}s
 421      *
 422      * @see SNIMatcher
 423      * @see #setSNIMatchers(Collection)
 424      *
 425      * @since 1.8
 426      */
 427     public final Collection<SNIMatcher> getSNIMatchers() {
 428         if (sniMatchers != null) {
 429             if (!sniMatchers.isEmpty()) {
 430                 return Collections.<SNIMatcher>unmodifiableList(
 431                                         new ArrayList<>(sniMatchers.values()));
 432             } else {
 433                 return Collections.<SNIMatcher>emptyList();
 434             }
 435         }
 436 
 437         return null;
 438     }
 439 
 440     /**
 441      * Sets whether the local cipher suites preference should be honored.
 442      *
 443      * @param honorOrder whether local cipher suites order in
 444      *        {@code #getCipherSuites} should be honored during
 445      *        SSL/TLS handshaking.
 446      *
 447      * @see #getUseCipherSuitesOrder()
 448      *
 449      * @since 1.8
 450      */
 451     public final void setUseCipherSuitesOrder(boolean honorOrder) {
 452         this.preferLocalCipherSuites = honorOrder;
 453     }
 454 
 455     /**
 456      * Returns whether the local cipher suites preference should be honored.
 457      *
 458      * @return whether local cipher suites order in {@code #getCipherSuites}
 459      *         should be honored during SSL/TLS handshaking.
 460      *
 461      * @see #setUseCipherSuitesOrder(boolean)
 462      *
 463      * @since 1.8
 464      */
 465     public final boolean getUseCipherSuitesOrder() {
 466         return preferLocalCipherSuites;
 467     }
 468 
 469     /**
 470      * Sets whether the TLS client should tell the TLS server that it
 471      * has performed a protocol downgrade.
 472      * <p>
 473      * <em>Note: Performing protocol downgrades outside the TLS
 474      * protocol can introduce security vulnerabilities.  The
 475      * built-in version negotiation mechanism of the TLS protocol
 476      * should be used instead of explicit protocol downgrades.</em>
 477      *
 478      * @param sendSCSV whether to send @{code TLS_FALLBACK_SCSV}
 479      *        as part of the TLS handshake.
 480      *
 481      * @see #getSendFallbackSCSV()
 482      *
 483      * @since 1.9
 484      */
 485     public final void setSendFallbackSCSV(boolean sendSCSV) {
 486         sendFallbackSCSV = sendSCSV;
 487     }
 488 
 489     /**
 490      * Returns whether the TLS client should tell the TLS server that it
 491      * has performed a protocol downgrade.
 492      *
 493      * @return whether to send @{code TLS_FALLBACK_SCSV}
 494      *         as part of the TLS handshake.
 495      *
 496      * @see #setSendFallbackSCSV(boolean)
 497      *
 498      * @since 1.9
 499      */
 500     public final boolean getSendFallbackSCSV() {
 501         return sendFallbackSCSV;
 502     }
 503 }
 504