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 // Android-changed: Use "on-path" to comply with Android's inclusive language guidance. 252 /** 253 * Sets the endpoint identification algorithm. 254 * <p> 255 * If the <code>algorithm</code> parameter is non-null or non-empty, the 256 * endpoint identification/verification procedures must be handled during 257 * SSL/TLS handshaking. This is to prevent on-path attacks. 258 * 259 * @param algorithm The standard string name of the endpoint 260 * identification algorithm (or null). See Appendix A in the <a href= 261 * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> 262 * Java Cryptography Architecture API Specification & Reference </a> 263 * for information about standard algorithm names. 264 * 265 * @see X509ExtendedTrustManager 266 * 267 * @since 1.7 268 */ setEndpointIdentificationAlgorithm(String algorithm)269 public void setEndpointIdentificationAlgorithm(String algorithm) { 270 this.identificationAlgorithm = algorithm; 271 } 272 273 /** 274 * Sets the desired {@link SNIServerName}s of the Server Name 275 * Indication (SNI) parameter. 276 * <P> 277 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 278 * operating in client mode. 279 * <P> 280 * Note that the {@code serverNames} list is cloned 281 * to protect against subsequent modification. 282 * 283 * @param serverNames 284 * the list of desired {@link SNIServerName}s (or null) 285 * 286 * @throws NullPointerException if the {@code serverNames} 287 * contains {@code null} element 288 * @throws IllegalArgumentException if the {@code serverNames} 289 * contains more than one name of the same name type 290 * 291 * @see SNIServerName 292 * @see #getServerNames() 293 * 294 * @since 1.8 295 */ setServerNames(List<SNIServerName> serverNames)296 public final void setServerNames(List<SNIServerName> serverNames) { 297 if (serverNames != null) { 298 if (!serverNames.isEmpty()) { 299 sniNames = new LinkedHashMap<>(serverNames.size()); 300 for (SNIServerName serverName : serverNames) { 301 if (sniNames.put(serverName.getType(), 302 serverName) != null) { 303 throw new IllegalArgumentException( 304 "Duplicated server name of type " + 305 serverName.getType()); 306 } 307 } 308 } else { 309 sniNames = Collections.<Integer, SNIServerName>emptyMap(); 310 } 311 } else { 312 sniNames = null; 313 } 314 } 315 316 /** 317 * Returns a {@link List} containing all {@link SNIServerName}s of the 318 * Server Name Indication (SNI) parameter, or null if none has been set. 319 * <P> 320 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 321 * operating in client mode. 322 * <P> 323 * For SSL/TLS connections, the underlying SSL/TLS provider 324 * may specify a default value for a certain server name type. In 325 * client mode, it is recommended that, by default, providers should 326 * include the server name indication whenever the server can be located 327 * by a supported server name type. 328 * <P> 329 * It is recommended that providers initialize default Server Name 330 * Indications when creating {@code SSLSocket}/{@code SSLEngine}s. 331 * In the following examples, the server name could be represented by an 332 * instance of {@link SNIHostName} which has been initialized with the 333 * hostname "www.example.com" and type 334 * {@link StandardConstants#SNI_HOST_NAME}. 335 * 336 * <pre> 337 * Socket socket = 338 * sslSocketFactory.createSocket("www.example.com", 443); 339 * </pre> 340 * or 341 * <pre> 342 * SSLEngine engine = 343 * sslContext.createSSLEngine("www.example.com", 443); 344 * </pre> 345 * <P> 346 * 347 * @return null or an immutable list of non-null {@link SNIServerName}s 348 * 349 * @see List 350 * @see #setServerNames(List) 351 * 352 * @since 1.8 353 */ getServerNames()354 public final List<SNIServerName> getServerNames() { 355 if (sniNames != null) { 356 if (!sniNames.isEmpty()) { 357 return Collections.<SNIServerName>unmodifiableList( 358 new ArrayList<>(sniNames.values())); 359 } else { 360 return Collections.<SNIServerName>emptyList(); 361 } 362 } 363 364 return null; 365 } 366 367 /** 368 * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI) 369 * parameter. 370 * <P> 371 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 372 * operating in server mode. 373 * <P> 374 * Note that the {@code matchers} collection is cloned to protect 375 * against subsequent modification. 376 * 377 * @param matchers 378 * the collection of {@link SNIMatcher}s (or null) 379 * 380 * @throws NullPointerException if the {@code matchers} 381 * contains {@code null} element 382 * @throws IllegalArgumentException if the {@code matchers} 383 * contains more than one name of the same name type 384 * 385 * @see Collection 386 * @see SNIMatcher 387 * @see #getSNIMatchers() 388 * 389 * @since 1.8 390 */ setSNIMatchers(Collection<SNIMatcher> matchers)391 public final void setSNIMatchers(Collection<SNIMatcher> matchers) { 392 if (matchers != null) { 393 if (!matchers.isEmpty()) { 394 sniMatchers = new HashMap<>(matchers.size()); 395 for (SNIMatcher matcher : matchers) { 396 if (sniMatchers.put(matcher.getType(), 397 matcher) != null) { 398 throw new IllegalArgumentException( 399 "Duplicated server name of type " + 400 matcher.getType()); 401 } 402 } 403 } else { 404 sniMatchers = Collections.<Integer, SNIMatcher>emptyMap(); 405 } 406 } else { 407 sniMatchers = null; 408 } 409 } 410 411 /** 412 * Returns a {@link Collection} containing all {@link SNIMatcher}s of the 413 * Server Name Indication (SNI) parameter, or null if none has been set. 414 * <P> 415 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 416 * operating in server mode. 417 * <P> 418 * For better interoperability, providers generally will not define 419 * default matchers so that by default servers will ignore the SNI 420 * extension and continue the handshake. 421 * 422 * @return null or an immutable collection of non-null {@link SNIMatcher}s 423 * 424 * @see SNIMatcher 425 * @see #setSNIMatchers(Collection) 426 * 427 * @since 1.8 428 */ getSNIMatchers()429 public final Collection<SNIMatcher> getSNIMatchers() { 430 if (sniMatchers != null) { 431 if (!sniMatchers.isEmpty()) { 432 return Collections.<SNIMatcher>unmodifiableList( 433 new ArrayList<>(sniMatchers.values())); 434 } else { 435 return Collections.<SNIMatcher>emptyList(); 436 } 437 } 438 439 return null; 440 } 441 442 /** 443 * Sets whether the local cipher suites preference should be honored. 444 * 445 * @param honorOrder whether local cipher suites order in 446 * {@code #getCipherSuites} should be honored during 447 * SSL/TLS handshaking. 448 * 449 * @see #getUseCipherSuitesOrder() 450 * 451 * @since 1.8 452 */ setUseCipherSuitesOrder(boolean honorOrder)453 public final void setUseCipherSuitesOrder(boolean honorOrder) { 454 this.preferLocalCipherSuites = honorOrder; 455 } 456 457 /** 458 * Returns whether the local cipher suites preference should be honored. 459 * 460 * @return whether local cipher suites order in {@code #getCipherSuites} 461 * should be honored during SSL/TLS handshaking. 462 * 463 * @see #setUseCipherSuitesOrder(boolean) 464 * 465 * @since 1.8 466 */ getUseCipherSuitesOrder()467 public final boolean getUseCipherSuitesOrder() { 468 return preferLocalCipherSuites; 469 } 470 471 // BEGIN Android-added: Integrate ALPN-related methods from OpenJDK 9+181 472 // Also removed references to DTLS in documentation; Android doesn't support DTLS. 473 /** 474 * Returns a prioritized array of application-layer protocol names that 475 * can be negotiated over the SSL/TLS protocols. 476 * <p> 477 * The array could be empty (zero-length), in which case protocol 478 * indications will not be used. 479 * <p> 480 * This method will return a new array each time it is invoked. 481 * 482 * @return a non-null, possibly zero-length array of application protocol 483 * {@code String}s. The array is ordered based on protocol 484 * preference, with {@code protocols[0]} being the most preferred. 485 * @see #setApplicationProtocols 486 * @since 9 487 */ getApplicationProtocols()488 public String[] getApplicationProtocols() { 489 return applicationProtocols.clone(); 490 } 491 492 /** 493 * Sets the prioritized array of application-layer protocol names that 494 * can be negotiated over the SSL/TLS protocols. 495 * <p> 496 * If application-layer protocols are supported by the underlying 497 * SSL/TLS implementation, this method configures which values can 498 * be negotiated by protocols such as <a 499 * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the 500 * Application Layer Protocol Negotiation (ALPN). 501 * <p> 502 * If this end of the connection is expected to offer application protocol 503 * values, all protocols configured by this method will be sent to the 504 * peer. 505 * <p> 506 * If this end of the connection is expected to select the application 507 * protocol value, the {@code protocols} configured by this method are 508 * compared with those sent by the peer. The first matched value becomes 509 * the negotiated value. If none of the {@code protocols} were actually 510 * requested by the peer, the underlying protocol will determine what 511 * action to take. (For example, ALPN will send a 512 * {@code "no_application_protocol"} alert and terminate the connection.) 513 * <p> 514 * @implSpec 515 * This method will make a copy of the {@code protocols} array. 516 * 517 * @param protocols an ordered array of application protocols, 518 * with {@code protocols[0]} being the most preferred. 519 * If the array is empty (zero-length), protocol 520 * indications will not be used. 521 * @throws IllegalArgumentException if protocols is null, or if 522 * any element in a non-empty array is null or an 523 * empty (zero-length) string 524 * @see #getApplicationProtocols 525 * @since 9 526 */ setApplicationProtocols(String[] protocols)527 public void setApplicationProtocols(String[] protocols) { 528 if (protocols == null) { 529 throw new IllegalArgumentException("protocols was null"); 530 } 531 532 String[] tempProtocols = protocols.clone(); 533 534 for (String p : tempProtocols) { 535 if (p == null || p.equals("")) { 536 throw new IllegalArgumentException( 537 "An element of protocols was null/empty"); 538 } 539 } 540 applicationProtocols = tempProtocols; 541 } 542 // END Android-added: Integrate ALPN-related methods from OpenJDK 9+181 543 } 544