Home | History | Annotate | Download | only in ssl
      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 
     78     /**
     79      * Constructs SSLParameters.
     80      * <p>
     81      * The values of cipherSuites, protocols, cryptographic algorithm
     82      * constraints, endpoint identification algorithm, server names and
     83      * server name matchers are set to <code>null</code>, useCipherSuitesOrder,
     84      * wantClientAuth and needClientAuth are set to <code>false</code>.
     85      */
     86     public SSLParameters() {
     87         // empty
     88     }
     89 
     90     /**
     91      * Constructs SSLParameters from the specified array of ciphersuites.
     92      * <p>
     93      * Calling this constructor is equivalent to calling the no-args
     94      * constructor followed by
     95      * <code>setCipherSuites(cipherSuites);</code>.
     96      *
     97      * @param cipherSuites the array of ciphersuites (or null)
     98      */
     99     public SSLParameters(String[] cipherSuites) {
    100         setCipherSuites(cipherSuites);
    101     }
    102 
    103     /**
    104      * Constructs SSLParameters from the specified array of ciphersuites
    105      * and protocols.
    106      * <p>
    107      * Calling this constructor is equivalent to calling the no-args
    108      * constructor followed by
    109      * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
    110      *
    111      * @param cipherSuites the array of ciphersuites (or null)
    112      * @param protocols the array of protocols (or null)
    113      */
    114     public SSLParameters(String[] cipherSuites, String[] protocols) {
    115         setCipherSuites(cipherSuites);
    116         setProtocols(protocols);
    117     }
    118 
    119     private static String[] clone(String[] s) {
    120         return (s == null) ? null : s.clone();
    121     }
    122 
    123     /**
    124      * Returns a copy of the array of ciphersuites or null if none
    125      * have been set.
    126      *
    127      * @return a copy of the array of ciphersuites or null if none
    128      * have been set.
    129      */
    130     public String[] getCipherSuites() {
    131         return clone(cipherSuites);
    132     }
    133 
    134     /**
    135      * Sets the array of ciphersuites.
    136      *
    137      * @param cipherSuites the array of ciphersuites (or null)
    138      */
    139     public void setCipherSuites(String[] cipherSuites) {
    140         this.cipherSuites = clone(cipherSuites);
    141     }
    142 
    143     /**
    144      * Returns a copy of the array of protocols or null if none
    145      * have been set.
    146      *
    147      * @return a copy of the array of protocols or null if none
    148      * have been set.
    149      */
    150     public String[] getProtocols() {
    151         return clone(protocols);
    152     }
    153 
    154     /**
    155      * Sets the array of protocols.
    156      *
    157      * @param protocols the array of protocols (or null)
    158      */
    159     public void setProtocols(String[] protocols) {
    160         this.protocols = clone(protocols);
    161     }
    162 
    163     /**
    164      * Returns whether client authentication should be requested.
    165      *
    166      * @return whether client authentication should be requested.
    167      */
    168     public boolean getWantClientAuth() {
    169         return wantClientAuth;
    170     }
    171 
    172     /**
    173      * Sets whether client authentication should be requested. Calling
    174      * this method clears the <code>needClientAuth</code> flag.
    175      *
    176      * @param wantClientAuth whether client authentication should be requested
    177      */
    178     public void setWantClientAuth(boolean wantClientAuth) {
    179         this.wantClientAuth = wantClientAuth;
    180         this.needClientAuth = false;
    181     }
    182 
    183     /**
    184      * Returns whether client authentication should be required.
    185      *
    186      * @return whether client authentication should be required.
    187      */
    188     public boolean getNeedClientAuth() {
    189         return needClientAuth;
    190     }
    191 
    192     /**
    193      * Sets whether client authentication should be required. Calling
    194      * this method clears the <code>wantClientAuth</code> flag.
    195      *
    196      * @param needClientAuth whether client authentication should be required
    197      */
    198     public void setNeedClientAuth(boolean needClientAuth) {
    199         this.wantClientAuth = false;
    200         this.needClientAuth = needClientAuth;
    201     }
    202 
    203     /**
    204      * Returns the cryptographic algorithm constraints.
    205      *
    206      * @return the cryptographic algorithm constraints, or null if the
    207      *     constraints have not been set
    208      *
    209      * @see #setAlgorithmConstraints(AlgorithmConstraints)
    210      *
    211      * @since 1.7
    212      */
    213     public AlgorithmConstraints getAlgorithmConstraints() {
    214         return algorithmConstraints;
    215     }
    216 
    217     /**
    218      * Sets the cryptographic algorithm constraints, which will be used
    219      * in addition to any configured by the runtime environment.
    220      * <p>
    221      * If the <code>constraints</code> parameter is non-null, every
    222      * cryptographic algorithm, key and algorithm parameters used in the
    223      * SSL/TLS handshake must be permitted by the constraints.
    224      *
    225      * @param constraints the algorithm constraints (or null)
    226      *
    227      * @since 1.7
    228      */
    229     public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
    230         // the constraints object is immutable
    231         this.algorithmConstraints = constraints;
    232     }
    233 
    234     /**
    235      * Gets the endpoint identification algorithm.
    236      *
    237      * @return the endpoint identification algorithm, or null if none
    238      * has been set.
    239      *
    240      * @see X509ExtendedTrustManager
    241      * @see #setEndpointIdentificationAlgorithm(String)
    242      *
    243      * @since 1.7
    244      */
    245     public String getEndpointIdentificationAlgorithm() {
    246         return identificationAlgorithm;
    247     }
    248 
    249     /**
    250      * Sets the endpoint identification algorithm.
    251      * <p>
    252      * If the <code>algorithm</code> parameter is non-null or non-empty, the
    253      * endpoint identification/verification procedures must be handled during
    254      * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
    255      *
    256      * @param algorithm The standard string name of the endpoint
    257      *     identification algorithm (or null).  See Appendix A in the <a href=
    258      *   "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html#AppA">
    259      *     Java Cryptography Architecture API Specification &amp; Reference </a>
    260      *     for information about standard algorithm names.
    261      *
    262      * @see X509ExtendedTrustManager
    263      *
    264      * @since 1.7
    265      */
    266     public void setEndpointIdentificationAlgorithm(String algorithm) {
    267         this.identificationAlgorithm = algorithm;
    268     }
    269 
    270     /**
    271      * Sets the desired {@link SNIServerName}s of the Server Name
    272      * Indication (SNI) parameter.
    273      * <P>
    274      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
    275      * operating in client mode.
    276      * <P>
    277      * Note that the {@code serverNames} list is cloned
    278      * to protect against subsequent modification.
    279      *
    280      * @param  serverNames
    281      *         the list of desired {@link SNIServerName}s (or null)
    282      *
    283      * @throws NullPointerException if the {@code serverNames}
    284      *         contains {@code null} element
    285      * @throws IllegalArgumentException if the {@code serverNames}
    286      *         contains more than one name of the same name type
    287      *
    288      * @see SNIServerName
    289      * @see #getServerNames()
    290      *
    291      * @since 1.8
    292      */
    293     public final void setServerNames(List<SNIServerName> serverNames) {
    294         if (serverNames != null) {
    295             if (!serverNames.isEmpty()) {
    296                 sniNames = new LinkedHashMap<>(serverNames.size());
    297                 for (SNIServerName serverName : serverNames) {
    298                     if (sniNames.put(serverName.getType(),
    299                                                 serverName) != null) {
    300                         throw new IllegalArgumentException(
    301                                     "Duplicated server name of type " +
    302                                     serverName.getType());
    303                     }
    304                 }
    305             } else {
    306                 sniNames = Collections.<Integer, SNIServerName>emptyMap();
    307             }
    308         } else {
    309             sniNames = null;
    310         }
    311     }
    312 
    313     /**
    314      * Returns a {@link List} containing all {@link SNIServerName}s of the
    315      * Server Name Indication (SNI) parameter, or null if none has been set.
    316      * <P>
    317      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
    318      * operating in client mode.
    319      * <P>
    320      * For SSL/TLS connections, the underlying SSL/TLS provider
    321      * may specify a default value for a certain server name type.  In
    322      * client mode, it is recommended that, by default, providers should
    323      * include the server name indication whenever the server can be located
    324      * by a supported server name type.
    325      * <P>
    326      * It is recommended that providers initialize default Server Name
    327      * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
    328      * In the following examples, the server name could be represented by an
    329      * instance of {@link SNIHostName} which has been initialized with the
    330      * hostname "www.example.com" and type
    331      * {@link StandardConstants#SNI_HOST_NAME}.
    332      *
    333      * <pre>
    334      *     Socket socket =
    335      *         sslSocketFactory.createSocket("www.example.com", 443);
    336      * </pre>
    337      * or
    338      * <pre>
    339      *     SSLEngine engine =
    340      *         sslContext.createSSLEngine("www.example.com", 443);
    341      * </pre>
    342      * <P>
    343      *
    344      * @return null or an immutable list of non-null {@link SNIServerName}s
    345      *
    346      * @see List
    347      * @see #setServerNames(List)
    348      *
    349      * @since 1.8
    350      */
    351     public final List<SNIServerName> getServerNames() {
    352         if (sniNames != null) {
    353             if (!sniNames.isEmpty()) {
    354                 return Collections.<SNIServerName>unmodifiableList(
    355                                         new ArrayList<>(sniNames.values()));
    356             } else {
    357                 return Collections.<SNIServerName>emptyList();
    358             }
    359         }
    360 
    361         return null;
    362     }
    363 
    364     /**
    365      * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
    366      * parameter.
    367      * <P>
    368      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
    369      * operating in server mode.
    370      * <P>
    371      * Note that the {@code matchers} collection is cloned to protect
    372      * against subsequent modification.
    373      *
    374      * @param  matchers
    375      *         the collection of {@link SNIMatcher}s (or null)
    376      *
    377      * @throws NullPointerException if the {@code matchers}
    378      *         contains {@code null} element
    379      * @throws IllegalArgumentException if the {@code matchers}
    380      *         contains more than one name of the same name type
    381      *
    382      * @see Collection
    383      * @see SNIMatcher
    384      * @see #getSNIMatchers()
    385      *
    386      * @since 1.8
    387      */
    388     public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
    389         if (matchers != null) {
    390             if (!matchers.isEmpty()) {
    391                 sniMatchers = new HashMap<>(matchers.size());
    392                 for (SNIMatcher matcher : matchers) {
    393                     if (sniMatchers.put(matcher.getType(),
    394                                                 matcher) != null) {
    395                         throw new IllegalArgumentException(
    396                                     "Duplicated server name of type " +
    397                                     matcher.getType());
    398                     }
    399                 }
    400             } else {
    401                 sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
    402             }
    403         } else {
    404             sniMatchers = null;
    405         }
    406     }
    407 
    408     /**
    409      * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
    410      * Server Name Indication (SNI) parameter, or null if none has been set.
    411      * <P>
    412      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
    413      * operating in server mode.
    414      * <P>
    415      * For better interoperability, providers generally will not define
    416      * default matchers so that by default servers will ignore the SNI
    417      * extension and continue the handshake.
    418      *
    419      * @return null or an immutable collection of non-null {@link SNIMatcher}s
    420      *
    421      * @see SNIMatcher
    422      * @see #setSNIMatchers(Collection)
    423      *
    424      * @since 1.8
    425      */
    426     public final Collection<SNIMatcher> getSNIMatchers() {
    427         if (sniMatchers != null) {
    428             if (!sniMatchers.isEmpty()) {
    429                 return Collections.<SNIMatcher>unmodifiableList(
    430                                         new ArrayList<>(sniMatchers.values()));
    431             } else {
    432                 return Collections.<SNIMatcher>emptyList();
    433             }
    434         }
    435 
    436         return null;
    437     }
    438 
    439     /**
    440      * Sets whether the local cipher suites preference should be honored.
    441      *
    442      * @param honorOrder whether local cipher suites order in
    443      *        {@code #getCipherSuites} should be honored during
    444      *        SSL/TLS handshaking.
    445      *
    446      * @see #getUseCipherSuitesOrder()
    447      *
    448      * @since 1.8
    449      */
    450     public final void setUseCipherSuitesOrder(boolean honorOrder) {
    451         this.preferLocalCipherSuites = honorOrder;
    452     }
    453 
    454     /**
    455      * Returns whether the local cipher suites preference should be honored.
    456      *
    457      * @return whether local cipher suites order in {@code #getCipherSuites}
    458      *         should be honored during SSL/TLS handshaking.
    459      *
    460      * @see #setUseCipherSuitesOrder(boolean)
    461      *
    462      * @since 1.8
    463      */
    464     public final boolean getUseCipherSuitesOrder() {
    465         return preferLocalCipherSuites;
    466     }
    467 }
    468