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