1 /*
2  * Copyright (c) 2005, 2017, 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     // Android-added: Integrate ALPN-related methods from OpenJDK 9+181
78     private String[] applicationProtocols = new String[0];
79 
80     /**
81      * Constructs SSLParameters.
82      * <p>
83      * The values of cipherSuites, protocols, cryptographic algorithm
84      * constraints, endpoint identification algorithm, server names and
85      * server name matchers are set to <code>null</code>, useCipherSuitesOrder,
86      * wantClientAuth and needClientAuth are set to <code>false</code>.
87      */
SSLParameters()88     public SSLParameters() {
89         // empty
90     }
91 
92     /**
93      * Constructs SSLParameters from the specified array of ciphersuites.
94      * <p>
95      * Calling this constructor is equivalent to calling the no-args
96      * constructor followed by
97      * <code>setCipherSuites(cipherSuites);</code>.
98      *
99      * @param cipherSuites the array of ciphersuites (or null)
100      */
SSLParameters(String[] cipherSuites)101     public SSLParameters(String[] cipherSuites) {
102         setCipherSuites(cipherSuites);
103     }
104 
105     /**
106      * Constructs SSLParameters from the specified array of ciphersuites
107      * and protocols.
108      * <p>
109      * Calling this constructor is equivalent to calling the no-args
110      * constructor followed by
111      * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
112      *
113      * @param cipherSuites the array of ciphersuites (or null)
114      * @param protocols the array of protocols (or null)
115      */
SSLParameters(String[] cipherSuites, String[] protocols)116     public SSLParameters(String[] cipherSuites, String[] protocols) {
117         setCipherSuites(cipherSuites);
118         setProtocols(protocols);
119     }
120 
clone(String[] s)121     private static String[] clone(String[] s) {
122         return (s == null) ? null : s.clone();
123     }
124 
125     /**
126      * Returns a copy of the array of ciphersuites or null if none
127      * have been set.
128      *
129      * @return a copy of the array of ciphersuites or null if none
130      * have been set.
131      */
getCipherSuites()132     public String[] getCipherSuites() {
133         return clone(cipherSuites);
134     }
135 
136     /**
137      * Sets the array of ciphersuites.
138      *
139      * @param cipherSuites the array of ciphersuites (or null)
140      */
setCipherSuites(String[] cipherSuites)141     public void setCipherSuites(String[] cipherSuites) {
142         this.cipherSuites = clone(cipherSuites);
143     }
144 
145     /**
146      * Returns a copy of the array of protocols or null if none
147      * have been set.
148      *
149      * @return a copy of the array of protocols or null if none
150      * have been set.
151      */
getProtocols()152     public String[] getProtocols() {
153         return clone(protocols);
154     }
155 
156     /**
157      * Sets the array of protocols.
158      *
159      * @param protocols the array of protocols (or null)
160      */
setProtocols(String[] protocols)161     public void setProtocols(String[] protocols) {
162         this.protocols = clone(protocols);
163     }
164 
165     /**
166      * Returns whether client authentication should be requested.
167      *
168      * @return whether client authentication should be requested.
169      */
getWantClientAuth()170     public boolean getWantClientAuth() {
171         return wantClientAuth;
172     }
173 
174     /**
175      * Sets whether client authentication should be requested. Calling
176      * this method clears the <code>needClientAuth</code> flag.
177      *
178      * @param wantClientAuth whether client authentication should be requested
179      */
setWantClientAuth(boolean wantClientAuth)180     public void setWantClientAuth(boolean wantClientAuth) {
181         this.wantClientAuth = wantClientAuth;
182         this.needClientAuth = false;
183     }
184 
185     /**
186      * Returns whether client authentication should be required.
187      *
188      * @return whether client authentication should be required.
189      */
getNeedClientAuth()190     public boolean getNeedClientAuth() {
191         return needClientAuth;
192     }
193 
194     /**
195      * Sets whether client authentication should be required. Calling
196      * this method clears the <code>wantClientAuth</code> flag.
197      *
198      * @param needClientAuth whether client authentication should be required
199      */
setNeedClientAuth(boolean needClientAuth)200     public void setNeedClientAuth(boolean needClientAuth) {
201         this.wantClientAuth = false;
202         this.needClientAuth = needClientAuth;
203     }
204 
205     /**
206      * Returns the cryptographic algorithm constraints.
207      *
208      * @return the cryptographic algorithm constraints, or null if the
209      *     constraints have not been set
210      *
211      * @see #setAlgorithmConstraints(AlgorithmConstraints)
212      *
213      * @since 1.7
214      */
getAlgorithmConstraints()215     public AlgorithmConstraints getAlgorithmConstraints() {
216         return algorithmConstraints;
217     }
218 
219     /**
220      * Sets the cryptographic algorithm constraints, which will be used
221      * in addition to any configured by the runtime environment.
222      * <p>
223      * If the <code>constraints</code> parameter is non-null, every
224      * cryptographic algorithm, key and algorithm parameters used in the
225      * SSL/TLS handshake must be permitted by the constraints.
226      *
227      * @param constraints the algorithm constraints (or null)
228      *
229      * @since 1.7
230      */
setAlgorithmConstraints(AlgorithmConstraints constraints)231     public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
232         // the constraints object is immutable
233         this.algorithmConstraints = constraints;
234     }
235 
236     /**
237      * Gets the endpoint identification algorithm.
238      *
239      * @return the endpoint identification algorithm, or null if none
240      * has been set.
241      *
242      * @see X509ExtendedTrustManager
243      * @see #setEndpointIdentificationAlgorithm(String)
244      *
245      * @since 1.7
246      */
getEndpointIdentificationAlgorithm()247     public String getEndpointIdentificationAlgorithm() {
248         return identificationAlgorithm;
249     }
250 
251     /**
252      * Sets the endpoint identification algorithm.
253      * <p>
254      * If the <code>algorithm</code> parameter is non-null or non-empty, the
255      * endpoint identification/verification procedures must be handled during
256      * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
257      *
258      * @param algorithm The standard string name of the endpoint
259      *     identification algorithm (or null).  See Appendix A in the <a href=
260      *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
261      *     Java Cryptography Architecture API Specification &amp; Reference </a>
262      *     for information about standard algorithm names.
263      *
264      * @see X509ExtendedTrustManager
265      *
266      * @since 1.7
267      */
setEndpointIdentificationAlgorithm(String algorithm)268     public void setEndpointIdentificationAlgorithm(String algorithm) {
269         this.identificationAlgorithm = algorithm;
270     }
271 
272     /**
273      * Sets the desired {@link SNIServerName}s of the Server Name
274      * Indication (SNI) parameter.
275      * <P>
276      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
277      * operating in client mode.
278      * <P>
279      * Note that the {@code serverNames} list is cloned
280      * to protect against subsequent modification.
281      *
282      * @param  serverNames
283      *         the list of desired {@link SNIServerName}s (or null)
284      *
285      * @throws NullPointerException if the {@code serverNames}
286      *         contains {@code null} element
287      * @throws IllegalArgumentException if the {@code serverNames}
288      *         contains more than one name of the same name type
289      *
290      * @see SNIServerName
291      * @see #getServerNames()
292      *
293      * @since 1.8
294      */
setServerNames(List<SNIServerName> serverNames)295     public final void setServerNames(List<SNIServerName> serverNames) {
296         if (serverNames != null) {
297             if (!serverNames.isEmpty()) {
298                 sniNames = new LinkedHashMap<>(serverNames.size());
299                 for (SNIServerName serverName : serverNames) {
300                     if (sniNames.put(serverName.getType(),
301                                                 serverName) != null) {
302                         throw new IllegalArgumentException(
303                                     "Duplicated server name of type " +
304                                     serverName.getType());
305                     }
306                 }
307             } else {
308                 sniNames = Collections.<Integer, SNIServerName>emptyMap();
309             }
310         } else {
311             sniNames = null;
312         }
313     }
314 
315     /**
316      * Returns a {@link List} containing all {@link SNIServerName}s of the
317      * Server Name Indication (SNI) parameter, or null if none has been set.
318      * <P>
319      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
320      * operating in client mode.
321      * <P>
322      * For SSL/TLS connections, the underlying SSL/TLS provider
323      * may specify a default value for a certain server name type.  In
324      * client mode, it is recommended that, by default, providers should
325      * include the server name indication whenever the server can be located
326      * by a supported server name type.
327      * <P>
328      * It is recommended that providers initialize default Server Name
329      * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
330      * In the following examples, the server name could be represented by an
331      * instance of {@link SNIHostName} which has been initialized with the
332      * hostname "www.example.com" and type
333      * {@link StandardConstants#SNI_HOST_NAME}.
334      *
335      * <pre>
336      *     Socket socket =
337      *         sslSocketFactory.createSocket("www.example.com", 443);
338      * </pre>
339      * or
340      * <pre>
341      *     SSLEngine engine =
342      *         sslContext.createSSLEngine("www.example.com", 443);
343      * </pre>
344      * <P>
345      *
346      * @return null or an immutable list of non-null {@link SNIServerName}s
347      *
348      * @see List
349      * @see #setServerNames(List)
350      *
351      * @since 1.8
352      */
getServerNames()353     public final List<SNIServerName> getServerNames() {
354         if (sniNames != null) {
355             if (!sniNames.isEmpty()) {
356                 return Collections.<SNIServerName>unmodifiableList(
357                                         new ArrayList<>(sniNames.values()));
358             } else {
359                 return Collections.<SNIServerName>emptyList();
360             }
361         }
362 
363         return null;
364     }
365 
366     /**
367      * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
368      * parameter.
369      * <P>
370      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
371      * operating in server mode.
372      * <P>
373      * Note that the {@code matchers} collection is cloned to protect
374      * against subsequent modification.
375      *
376      * @param  matchers
377      *         the collection of {@link SNIMatcher}s (or null)
378      *
379      * @throws NullPointerException if the {@code matchers}
380      *         contains {@code null} element
381      * @throws IllegalArgumentException if the {@code matchers}
382      *         contains more than one name of the same name type
383      *
384      * @see Collection
385      * @see SNIMatcher
386      * @see #getSNIMatchers()
387      *
388      * @since 1.8
389      */
setSNIMatchers(Collection<SNIMatcher> matchers)390     public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
391         if (matchers != null) {
392             if (!matchers.isEmpty()) {
393                 sniMatchers = new HashMap<>(matchers.size());
394                 for (SNIMatcher matcher : matchers) {
395                     if (sniMatchers.put(matcher.getType(),
396                                                 matcher) != null) {
397                         throw new IllegalArgumentException(
398                                     "Duplicated server name of type " +
399                                     matcher.getType());
400                     }
401                 }
402             } else {
403                 sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
404             }
405         } else {
406             sniMatchers = null;
407         }
408     }
409 
410     /**
411      * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
412      * Server Name Indication (SNI) parameter, or null if none has been set.
413      * <P>
414      * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
415      * operating in server mode.
416      * <P>
417      * For better interoperability, providers generally will not define
418      * default matchers so that by default servers will ignore the SNI
419      * extension and continue the handshake.
420      *
421      * @return null or an immutable collection of non-null {@link SNIMatcher}s
422      *
423      * @see SNIMatcher
424      * @see #setSNIMatchers(Collection)
425      *
426      * @since 1.8
427      */
getSNIMatchers()428     public final Collection<SNIMatcher> getSNIMatchers() {
429         if (sniMatchers != null) {
430             if (!sniMatchers.isEmpty()) {
431                 return Collections.<SNIMatcher>unmodifiableList(
432                                         new ArrayList<>(sniMatchers.values()));
433             } else {
434                 return Collections.<SNIMatcher>emptyList();
435             }
436         }
437 
438         return null;
439     }
440 
441     /**
442      * Sets whether the local cipher suites preference should be honored.
443      *
444      * @param honorOrder whether local cipher suites order in
445      *        {@code #getCipherSuites} should be honored during
446      *        SSL/TLS handshaking.
447      *
448      * @see #getUseCipherSuitesOrder()
449      *
450      * @since 1.8
451      */
setUseCipherSuitesOrder(boolean honorOrder)452     public final void setUseCipherSuitesOrder(boolean honorOrder) {
453         this.preferLocalCipherSuites = honorOrder;
454     }
455 
456     /**
457      * Returns whether the local cipher suites preference should be honored.
458      *
459      * @return whether local cipher suites order in {@code #getCipherSuites}
460      *         should be honored during SSL/TLS handshaking.
461      *
462      * @see #setUseCipherSuitesOrder(boolean)
463      *
464      * @since 1.8
465      */
getUseCipherSuitesOrder()466     public final boolean getUseCipherSuitesOrder() {
467         return preferLocalCipherSuites;
468     }
469 
470     // BEGIN Android-added: Integrate ALPN-related methods from OpenJDK 9+181
471     // Also removed references to DTLS in documentation; Android doesn't support DTLS.
472     /**
473      * Returns a prioritized array of application-layer protocol names that
474      * can be negotiated over the SSL/TLS protocols.
475      * <p>
476      * The array could be empty (zero-length), in which case protocol
477      * indications will not be used.
478      * <p>
479      * This method will return a new array each time it is invoked.
480      *
481      * @return a non-null, possibly zero-length array of application protocol
482      *         {@code String}s.  The array is ordered based on protocol
483      *         preference, with {@code protocols[0]} being the most preferred.
484      * @see #setApplicationProtocols
485      * @since 9
486      */
getApplicationProtocols()487     public String[] getApplicationProtocols() {
488         return applicationProtocols.clone();
489     }
490 
491     /**
492      * Sets the prioritized array of application-layer protocol names that
493      * can be negotiated over the SSL/TLS protocols.
494      * <p>
495      * If application-layer protocols are supported by the underlying
496      * SSL/TLS implementation, this method configures which values can
497      * be negotiated by protocols such as <a
498      * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
499      * Application Layer Protocol Negotiation (ALPN).
500      * <p>
501      * If this end of the connection is expected to offer application protocol
502      * values, all protocols configured by this method will be sent to the
503      * peer.
504      * <p>
505      * If this end of the connection is expected to select the application
506      * protocol value, the {@code protocols} configured by this method are
507      * compared with those sent by the peer.  The first matched value becomes
508      * the negotiated value.  If none of the {@code protocols} were actually
509      * requested by the peer, the underlying protocol will determine what
510      * action to take.  (For example, ALPN will send a
511      * {@code "no_application_protocol"} alert and terminate the connection.)
512      * <p>
513      * @implSpec
514      * This method will make a copy of the {@code protocols} array.
515      *
516      * @param protocols   an ordered array of application protocols,
517      *                    with {@code protocols[0]} being the most preferred.
518      *                    If the array is empty (zero-length), protocol
519      *                    indications will not be used.
520      * @throws IllegalArgumentException if protocols is null, or if
521      *                    any element in a non-empty array is null or an
522      *                    empty (zero-length) string
523      * @see #getApplicationProtocols
524      * @since 9
525      */
setApplicationProtocols(String[] protocols)526     public void setApplicationProtocols(String[] protocols) {
527         if (protocols == null) {
528             throw new IllegalArgumentException("protocols was null");
529         }
530 
531         String[] tempProtocols = protocols.clone();
532 
533         for (String p : tempProtocols) {
534             if (p == null || p.equals("")) {
535                 throw new IllegalArgumentException(
536                     "An element of protocols was null/empty");
537             }
538         }
539         applicationProtocols = tempProtocols;
540     }
541     // END Android-added: Integrate ALPN-related methods from OpenJDK 9+181
542 }
543