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