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
26package javax.net.ssl;
27
28import java.security.AlgorithmConstraints;
29import java.util.Map;
30import java.util.List;
31import java.util.HashMap;
32import java.util.ArrayList;
33import java.util.Collection;
34import java.util.Collections;
35import java.util.LinkedHashMap;
36
37/**
38 * Encapsulates parameters for an SSL/TLS/DTLS connection. The parameters
39 * are the list of ciphersuites to be accepted in an SSL/TLS/DTLS handshake,
40 * the list of protocols to be allowed, the endpoint identification
41 * algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
42 * the maximum network packet size, the algorithm constraints and whether
43 * SSL/TLS/DTLS servers should request 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()}
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}.
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 * <p>
60 * For example:
61 *
62 * <blockquote><pre>
63 *     SSLParameters p = sslSocket.getSSLParameters();
64 *     p.setProtocols(new String[] { "TLSv1.2" });
65 *     p.setCipherSuites(
66 *         new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ... });
67 *     p.setApplicationProtocols(new String[] {"h2", "http/1.1"});
68 *     sslSocket.setSSLParameters(p);
69 * </pre></blockquote>
70 *
71 * @see SSLSocket
72 * @see SSLEngine
73 * @see SSLContext
74 *
75 * @since 1.6
76 */
77public class SSLParameters {
78
79    private String[] cipherSuites;
80    private String[] protocols;
81    private boolean wantClientAuth;
82    private boolean needClientAuth;
83    private String identificationAlgorithm;
84    private AlgorithmConstraints algorithmConstraints;
85    private Map<Integer, SNIServerName> sniNames = null;
86    private Map<Integer, SNIMatcher> sniMatchers = null;
87    private boolean preferLocalCipherSuites;
88    private boolean enableRetransmissions = true;
89    private int maximumPacketSize = 0;
90    private String[] applicationProtocols = new String[0];
91
92    /**
93     * Constructs SSLParameters.
94     * <p>
95     * The values of cipherSuites, protocols, cryptographic algorithm
96     * constraints, endpoint identification algorithm, server names and
97     * server name matchers are set to {@code null}; useCipherSuitesOrder,
98     * wantClientAuth and needClientAuth are set to {@code false};
99     * enableRetransmissions is set to {@code true}; maximum network packet
100     * size is set to {@code 0}.
101     */
102    public SSLParameters() {
103        // empty
104    }
105
106    /**
107     * Constructs SSLParameters from the specified array of ciphersuites.
108     * <p>
109     * Calling this constructor is equivalent to calling the no-args
110     * constructor followed by
111     * {@code setCipherSuites(cipherSuites);}.  Note that the
112     * standard list of cipher suite names may be found in the <a href=
113     * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
114     * JSSE Cipher Suite Names</a> section of the Java Cryptography
115     * Architecture Standard Algorithm Name Documentation.  Providers
116     * may support cipher suite names not found in this list.
117     *
118     * @param cipherSuites the array of ciphersuites (or null)
119     */
120    public SSLParameters(String[] cipherSuites) {
121        setCipherSuites(cipherSuites);
122    }
123
124    /**
125     * Constructs SSLParameters from the specified array of ciphersuites
126     * and protocols.
127     * <p>
128     * Calling this constructor is equivalent to calling the no-args
129     * constructor followed by
130     * {@code setCipherSuites(cipherSuites); setProtocols(protocols);}.
131     * Note that the standard list of cipher suite names may be found in the
132     * <a href=
133     * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
134     * JSSE Cipher Suite Names</a> section of the Java Cryptography
135     * Architecture Standard Algorithm Name Documentation.  Providers
136     * may support cipher suite names not found in this list.
137     *
138     * @param cipherSuites the array of ciphersuites (or null)
139     * @param protocols the array of protocols (or null)
140     */
141    public SSLParameters(String[] cipherSuites, String[] protocols) {
142        setCipherSuites(cipherSuites);
143        setProtocols(protocols);
144    }
145
146    private static String[] clone(String[] s) {
147        return (s == null) ? null : s.clone();
148    }
149
150    /**
151     * Returns a copy of the array of ciphersuites or null if none
152     * have been set.
153     * <P>
154     * The returned array includes cipher suites from the list of standard
155     * cipher suite names in the <a href=
156     * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
157     * JSSE Cipher Suite Names</a> section of the Java Cryptography
158     * Architecture Standard Algorithm Name Documentation, and may also
159     * include other cipher suites that the provider supports.
160     *
161     * @return a copy of the array of ciphersuites or null if none
162     * have been set.
163     */
164    public String[] getCipherSuites() {
165        return clone(cipherSuites);
166    }
167
168    /**
169     * Sets the array of ciphersuites.
170     *
171     * @param cipherSuites the array of ciphersuites (or null).  Note that the
172     * standard list of cipher suite names may be found in the <a href=
173     * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
174     * JSSE Cipher Suite Names</a> section of the Java Cryptography
175     * Architecture Standard Algorithm Name Documentation.  Providers
176     * may support cipher suite names not found in this list or might not
177     * use the recommended name for a certain cipher suite.
178     */
179    public void setCipherSuites(String[] cipherSuites) {
180        this.cipherSuites = clone(cipherSuites);
181    }
182
183    /**
184     * Returns a copy of the array of protocols or null if none
185     * have been set.
186     *
187     * @return a copy of the array of protocols or null if none
188     * have been set.
189     */
190    public String[] getProtocols() {
191        return clone(protocols);
192    }
193
194    /**
195     * Sets the array of protocols.
196     *
197     * @param protocols the array of protocols (or null)
198     */
199    public void setProtocols(String[] protocols) {
200        this.protocols = clone(protocols);
201    }
202
203    /**
204     * Returns whether client authentication should be requested.
205     *
206     * @return whether client authentication should be requested.
207     */
208    public boolean getWantClientAuth() {
209        return wantClientAuth;
210    }
211
212    /**
213     * Sets whether client authentication should be requested. Calling
214     * this method clears the {@code needClientAuth} flag.
215     *
216     * @param wantClientAuth whether client authentication should be requested
217     */
218    public void setWantClientAuth(boolean wantClientAuth) {
219        this.wantClientAuth = wantClientAuth;
220        this.needClientAuth = false;
221    }
222
223    /**
224     * Returns whether client authentication should be required.
225     *
226     * @return whether client authentication should be required.
227     */
228    public boolean getNeedClientAuth() {
229        return needClientAuth;
230    }
231
232    /**
233     * Sets whether client authentication should be required. Calling
234     * this method clears the {@code wantClientAuth} flag.
235     *
236     * @param needClientAuth whether client authentication should be required
237     */
238    public void setNeedClientAuth(boolean needClientAuth) {
239        this.wantClientAuth = false;
240        this.needClientAuth = needClientAuth;
241    }
242
243    /**
244     * Returns the cryptographic algorithm constraints.
245     *
246     * @return the cryptographic algorithm constraints, or null if the
247     *     constraints have not been set
248     *
249     * @see #setAlgorithmConstraints(AlgorithmConstraints)
250     *
251     * @since 1.7
252     */
253    public AlgorithmConstraints getAlgorithmConstraints() {
254        return algorithmConstraints;
255    }
256
257    /**
258     * Sets the cryptographic algorithm constraints, which will be used
259     * in addition to any configured by the runtime environment.
260     * <p>
261     * If the {@code constraints} parameter is non-null, every
262     * cryptographic algorithm, key and algorithm parameters used in the
263     * SSL/TLS/DTLS handshake must be permitted by the constraints.
264     *
265     * @param constraints the algorithm constraints (or null)
266     *
267     * @since 1.7
268     */
269    public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
270        // the constraints object is immutable
271        this.algorithmConstraints = constraints;
272    }
273
274    /**
275     * Gets the endpoint identification algorithm.
276     *
277     * @return the endpoint identification algorithm, or null if none
278     * has been set.
279     *
280     * @see X509ExtendedTrustManager
281     * @see #setEndpointIdentificationAlgorithm(String)
282     *
283     * @since 1.7
284     */
285    public String getEndpointIdentificationAlgorithm() {
286        return identificationAlgorithm;
287    }
288
289    /**
290     * Sets the endpoint identification algorithm.
291     * <p>
292     * If the {@code algorithm} parameter is non-null or non-empty, the
293     * endpoint identification/verification procedures must be handled during
294     * SSL/TLS/DTLS handshaking.  This is to prevent man-in-the-middle attacks.
295     *
296     * @param algorithm The standard string name of the endpoint
297     *     identification algorithm (or null).
298     *     See the <a href=
299     *     "{@docRoot}/../specs/security/standard-names.html">
300     *     Java Security Standard Algorithm Names</a> document
301     *     for information about standard algorithm names.
302     *
303     * @see X509ExtendedTrustManager
304     *
305     * @since 1.7
306     */
307    public void setEndpointIdentificationAlgorithm(String algorithm) {
308        this.identificationAlgorithm = algorithm;
309    }
310
311    /**
312     * Sets the desired {@link SNIServerName}s of the Server Name
313     * Indication (SNI) parameter.
314     * <P>
315     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
316     * operating in client mode.
317     * <P>
318     * Note that the {@code serverNames} list is cloned
319     * to protect against subsequent modification.
320     *
321     * @param  serverNames
322     *         the list of desired {@link SNIServerName}s (or null)
323     *
324     * @throws NullPointerException if the {@code serverNames}
325     *         contains {@code null} element
326     * @throws IllegalArgumentException if the {@code serverNames}
327     *         contains more than one name of the same name type
328     *
329     * @see SNIServerName
330     * @see #getServerNames()
331     *
332     * @since 1.8
333     */
334    public final void setServerNames(List<SNIServerName> serverNames) {
335        if (serverNames != null) {
336            if (!serverNames.isEmpty()) {
337                sniNames = new LinkedHashMap<>(serverNames.size());
338                for (SNIServerName serverName : serverNames) {
339                    if (sniNames.put(serverName.getType(),
340                                                serverName) != null) {
341                        throw new IllegalArgumentException(
342                                    "Duplicated server name of type " +
343                                    serverName.getType());
344                    }
345                }
346            } else {
347                sniNames = Collections.<Integer, SNIServerName>emptyMap();
348            }
349        } else {
350            sniNames = null;
351        }
352    }
353
354    /**
355     * Returns a {@link List} containing all {@link SNIServerName}s of the
356     * Server Name Indication (SNI) parameter, or null if none has been set.
357     * <P>
358     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
359     * operating in client mode.
360     * <P>
361     * For SSL/TLS/DTLS connections, the underlying SSL/TLS/DTLS provider
362     * may specify a default value for a certain server name type.  In
363     * client mode, it is recommended that, by default, providers should
364     * include the server name indication whenever the server can be located
365     * by a supported server name type.
366     * <P>
367     * It is recommended that providers initialize default Server Name
368     * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
369     * In the following examples, the server name could be represented by an
370     * instance of {@link SNIHostName} which has been initialized with the
371     * hostname "www.example.com" and type
372     * {@link StandardConstants#SNI_HOST_NAME}.
373     *
374     * <pre>
375     *     Socket socket =
376     *         sslSocketFactory.createSocket("www.example.com", 443);
377     * </pre>
378     * or
379     * <pre>
380     *     SSLEngine engine =
381     *         sslContext.createSSLEngine("www.example.com", 443);
382     * </pre>
383     *
384     * @return null or an immutable list of non-null {@link SNIServerName}s
385     *
386     * @see List
387     * @see #setServerNames(List)
388     *
389     * @since 1.8
390     */
391    public final List<SNIServerName> getServerNames() {
392        if (sniNames != null) {
393            if (!sniNames.isEmpty()) {
394                return Collections.<SNIServerName>unmodifiableList(
395                                        new ArrayList<>(sniNames.values()));
396            } else {
397                return Collections.<SNIServerName>emptyList();
398            }
399        }
400
401        return null;
402    }
403
404    /**
405     * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
406     * parameter.
407     * <P>
408     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
409     * operating in server mode.
410     * <P>
411     * Note that the {@code matchers} collection is cloned to protect
412     * against subsequent modification.
413     *
414     * @param  matchers
415     *         the collection of {@link SNIMatcher}s (or null)
416     *
417     * @throws NullPointerException if the {@code matchers}
418     *         contains {@code null} element
419     * @throws IllegalArgumentException if the {@code matchers}
420     *         contains more than one name of the same name type
421     *
422     * @see Collection
423     * @see SNIMatcher
424     * @see #getSNIMatchers()
425     *
426     * @since 1.8
427     */
428    public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
429        if (matchers != null) {
430            if (!matchers.isEmpty()) {
431                sniMatchers = new HashMap<>(matchers.size());
432                for (SNIMatcher matcher : matchers) {
433                    if (sniMatchers.put(matcher.getType(),
434                                                matcher) != null) {
435                        throw new IllegalArgumentException(
436                                    "Duplicated server name of type " +
437                                    matcher.getType());
438                    }
439                }
440            } else {
441                sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
442            }
443        } else {
444            sniMatchers = null;
445        }
446    }
447
448    /**
449     * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
450     * Server Name Indication (SNI) parameter, or null if none has been set.
451     * <P>
452     * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
453     * operating in server mode.
454     * <P>
455     * For better interoperability, providers generally will not define
456     * default matchers so that by default servers will ignore the SNI
457     * extension and continue the handshake.
458     *
459     * @return null or an immutable collection of non-null {@link SNIMatcher}s
460     *
461     * @see SNIMatcher
462     * @see #setSNIMatchers(Collection)
463     *
464     * @since 1.8
465     */
466    public final Collection<SNIMatcher> getSNIMatchers() {
467        if (sniMatchers != null) {
468            if (!sniMatchers.isEmpty()) {
469                return Collections.<SNIMatcher>unmodifiableList(
470                                        new ArrayList<>(sniMatchers.values()));
471            } else {
472                return Collections.<SNIMatcher>emptyList();
473            }
474        }
475
476        return null;
477    }
478
479    /**
480     * Sets whether the local cipher suites preference should be honored.
481     *
482     * @param honorOrder whether local cipher suites order in
483     *        {@code #getCipherSuites} should be honored during
484     *        SSL/TLS/DTLS handshaking.
485     *
486     * @see #getUseCipherSuitesOrder()
487     *
488     * @since 1.8
489     */
490    public final void setUseCipherSuitesOrder(boolean honorOrder) {
491        this.preferLocalCipherSuites = honorOrder;
492    }
493
494    /**
495     * Returns whether the local cipher suites preference should be honored.
496     *
497     * @return whether local cipher suites order in {@code #getCipherSuites}
498     *         should be honored during SSL/TLS/DTLS handshaking.
499     *
500     * @see #setUseCipherSuitesOrder(boolean)
501     *
502     * @since 1.8
503     */
504    public final boolean getUseCipherSuitesOrder() {
505        return preferLocalCipherSuites;
506    }
507
508    /**
509     * Sets whether DTLS handshake retransmissions should be enabled.
510     *
511     * This method only applies to DTLS.
512     *
513     * @param   enableRetransmissions
514     *          {@code true} indicates that DTLS handshake retransmissions
515     *          should be enabled; {@code false} indicates that DTLS handshake
516     *          retransmissions should be disabled
517     *
518     * @see     #getEnableRetransmissions()
519     *
520     * @since 9
521     */
522    public void setEnableRetransmissions(boolean enableRetransmissions) {
523        this.enableRetransmissions = enableRetransmissions;
524    }
525
526    /**
527     * Returns whether DTLS handshake retransmissions should be enabled.
528     *
529     * This method only applies to DTLS.
530     *
531     * @return  true, if DTLS handshake retransmissions should be enabled
532     *
533     * @see     #setEnableRetransmissions(boolean)
534     *
535     * @since 9
536     */
537    public boolean getEnableRetransmissions() {
538        return enableRetransmissions;
539    }
540
541    /**
542     * Sets the maximum expected network packet size in bytes for
543     * SSL/TLS/DTLS records.
544     *
545     * @apiNote  It is recommended that if possible, the maximum packet size
546     *           should not be less than 256 bytes so that small handshake
547     *           messages, such as HelloVerifyRequests, are not fragmented.
548     *
549     * @implNote If the maximum packet size is too small to hold a minimal
550     *           record, an implementation may attempt to generate as minimal
551     *           records as possible.  However, this may cause a generated
552     *           packet to be larger than the maximum packet size.
553     *
554     * @param   maximumPacketSize
555     *          the maximum expected network packet size in bytes, or
556     *          {@code 0} to use the implicit size that is automatically
557     *          specified by the underlying implementation.
558     * @throws  IllegalArgumentException
559     *          if {@code maximumPacketSize} is negative.
560     *
561     * @see     #getMaximumPacketSize()
562     *
563     * @since 9
564     */
565    public void setMaximumPacketSize(int maximumPacketSize) {
566        if (maximumPacketSize < 0) {
567            throw new IllegalArgumentException(
568                "The maximum packet size cannot be negative");
569        }
570
571        this.maximumPacketSize = maximumPacketSize;
572    }
573
574    /**
575     * Returns the maximum expected network packet size in bytes for
576     * SSL/TLS/DTLS records.
577     *
578     * @apiNote  The implicit size may not be a fixed value, especially
579     *           for a DTLS protocols implementation.
580     *
581     * @implNote For SSL/TLS/DTLS connections, the underlying provider
582     *           should calculate and specify the implicit value of the
583     *           maximum expected network packet size if it is not
584     *           configured explicitly.  For any connection populated
585     *           object, this method should never return {@code 0} so
586     *           that applications can retrieve the actual implicit size
587     *           of the underlying implementation.
588     *           <P>
589     *           An implementation should attempt to comply with the maximum
590     *           packet size configuration.  However, if the maximum packet
591     *           size is too small to hold a minimal record, an implementation
592     *           may try to generate as minimal records as possible.  This
593     *           may cause a generated packet to be larger than the maximum
594     *           packet size.
595     *
596     * @return   the maximum expected network packet size, or {@code 0} if
597     *           use the implicit size that is automatically specified by
598     *           the underlying implementation and this object has not been
599     *           populated by any connection.
600     *
601     * @see      #setMaximumPacketSize(int)
602     *
603     * @since 9
604     */
605    public int getMaximumPacketSize() {
606        return maximumPacketSize;
607    }
608
609    /**
610     * Returns a prioritized array of application-layer protocol names that
611     * can be negotiated over the SSL/TLS/DTLS protocols.
612     * <p>
613     * The array could be empty (zero-length), in which case protocol
614     * indications will not be used.
615     * <p>
616     * This method will return a new array each time it is invoked.
617     *
618     * @return a non-null, possibly zero-length array of application protocol
619     *         {@code String}s.  The array is ordered based on protocol
620     *         preference, with {@code protocols[0]} being the most preferred.
621     * @see #setApplicationProtocols
622     * @since 9
623     */
624    public String[] getApplicationProtocols() {
625        return applicationProtocols.clone();
626    }
627
628    /**
629     * Sets the prioritized array of application-layer protocol names that
630     * can be negotiated over the SSL/TLS/DTLS protocols.
631     * <p>
632     * If application-layer protocols are supported by the underlying
633     * SSL/TLS implementation, this method configures which values can
634     * be negotiated by protocols such as <a
635     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
636     * Application Layer Protocol Negotiation (ALPN).
637     * <p>
638     * If this end of the connection is expected to offer application protocol
639     * values, all protocols configured by this method will be sent to the
640     * peer.
641     * <p>
642     * If this end of the connection is expected to select the application
643     * protocol value, the {@code protocols} configured by this method are
644     * compared with those sent by the peer.  The first matched value becomes
645     * the negotiated value.  If none of the {@code protocols} were actually
646     * requested by the peer, the underlying protocol will determine what
647     * action to take.  (For example, ALPN will send a
648     * {@code "no_application_protocol"} alert and terminate the connection.)
649     *
650     * @implSpec
651     * This method will make a copy of the {@code protocols} array.
652     *
653     * @param protocols   an ordered array of application protocols,
654     *                    with {@code protocols[0]} being the most preferred.
655     *                    If the array is empty (zero-length), protocol
656     *                    indications will not be used.
657     * @throws IllegalArgumentException if protocols is null, or if
658     *                    any element in a non-empty array is null or an
659     *                    empty (zero-length) string
660     * @see #getApplicationProtocols
661     * @since 9
662     */
663    public void setApplicationProtocols(String[] protocols) {
664        if (protocols == null) {
665            throw new IllegalArgumentException("protocols was null");
666        }
667
668        String[] tempProtocols = protocols.clone();
669
670        for (String p : tempProtocols) {
671            if (p == null || p.equals("")) {
672                throw new IllegalArgumentException(
673                    "An element of protocols was null/empty");
674            }
675        }
676        applicationProtocols = tempProtocols;
677    }
678}
679