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 & 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