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 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 */ SSLParameters()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 */ SSLParameters(String[] cipherSuites)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 */ SSLParameters(String[] cipherSuites, String[] protocols)114 public SSLParameters(String[] cipherSuites, String[] protocols) { 115 setCipherSuites(cipherSuites); 116 setProtocols(protocols); 117 } 118 clone(String[] s)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 */ getCipherSuites()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 */ setCipherSuites(String[] cipherSuites)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 */ getProtocols()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 */ setProtocols(String[] protocols)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 */ getWantClientAuth()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 */ setWantClientAuth(boolean wantClientAuth)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 */ getNeedClientAuth()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 */ setNeedClientAuth(boolean needClientAuth)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 */ getAlgorithmConstraints()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 */ setAlgorithmConstraints(AlgorithmConstraints constraints)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 */ getEndpointIdentificationAlgorithm()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}openjdk-redirect.html?v=8&path=/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 */ setEndpointIdentificationAlgorithm(String algorithm)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 */ setServerNames(List<SNIServerName> serverNames)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 * <P> 343 * 344 * @return null or an immutable list of non-null {@link SNIServerName}s 345 * 346 * @see List 347 * @see #setServerNames(List) 348 * 349 * @since 1.8 350 */ getServerNames()351 public final List<SNIServerName> getServerNames() { 352 if (sniNames != null) { 353 if (!sniNames.isEmpty()) { 354 return Collections.<SNIServerName>unmodifiableList( 355 new ArrayList<>(sniNames.values())); 356 } else { 357 return Collections.<SNIServerName>emptyList(); 358 } 359 } 360 361 return null; 362 } 363 364 /** 365 * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI) 366 * parameter. 367 * <P> 368 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 369 * operating in server mode. 370 * <P> 371 * Note that the {@code matchers} collection is cloned to protect 372 * against subsequent modification. 373 * 374 * @param matchers 375 * the collection of {@link SNIMatcher}s (or null) 376 * 377 * @throws NullPointerException if the {@code matchers} 378 * contains {@code null} element 379 * @throws IllegalArgumentException if the {@code matchers} 380 * contains more than one name of the same name type 381 * 382 * @see Collection 383 * @see SNIMatcher 384 * @see #getSNIMatchers() 385 * 386 * @since 1.8 387 */ setSNIMatchers(Collection<SNIMatcher> matchers)388 public final void setSNIMatchers(Collection<SNIMatcher> matchers) { 389 if (matchers != null) { 390 if (!matchers.isEmpty()) { 391 sniMatchers = new HashMap<>(matchers.size()); 392 for (SNIMatcher matcher : matchers) { 393 if (sniMatchers.put(matcher.getType(), 394 matcher) != null) { 395 throw new IllegalArgumentException( 396 "Duplicated server name of type " + 397 matcher.getType()); 398 } 399 } 400 } else { 401 sniMatchers = Collections.<Integer, SNIMatcher>emptyMap(); 402 } 403 } else { 404 sniMatchers = null; 405 } 406 } 407 408 /** 409 * Returns a {@link Collection} containing all {@link SNIMatcher}s of the 410 * Server Name Indication (SNI) parameter, or null if none has been set. 411 * <P> 412 * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s 413 * operating in server mode. 414 * <P> 415 * For better interoperability, providers generally will not define 416 * default matchers so that by default servers will ignore the SNI 417 * extension and continue the handshake. 418 * 419 * @return null or an immutable collection of non-null {@link SNIMatcher}s 420 * 421 * @see SNIMatcher 422 * @see #setSNIMatchers(Collection) 423 * 424 * @since 1.8 425 */ getSNIMatchers()426 public final Collection<SNIMatcher> getSNIMatchers() { 427 if (sniMatchers != null) { 428 if (!sniMatchers.isEmpty()) { 429 return Collections.<SNIMatcher>unmodifiableList( 430 new ArrayList<>(sniMatchers.values())); 431 } else { 432 return Collections.<SNIMatcher>emptyList(); 433 } 434 } 435 436 return null; 437 } 438 439 /** 440 * Sets whether the local cipher suites preference should be honored. 441 * 442 * @param honorOrder whether local cipher suites order in 443 * {@code #getCipherSuites} should be honored during 444 * SSL/TLS handshaking. 445 * 446 * @see #getUseCipherSuitesOrder() 447 * 448 * @since 1.8 449 */ setUseCipherSuitesOrder(boolean honorOrder)450 public final void setUseCipherSuitesOrder(boolean honorOrder) { 451 this.preferLocalCipherSuites = honorOrder; 452 } 453 454 /** 455 * Returns whether the local cipher suites preference should be honored. 456 * 457 * @return whether local cipher suites order in {@code #getCipherSuites} 458 * should be honored during SSL/TLS handshaking. 459 * 460 * @see #setUseCipherSuitesOrder(boolean) 461 * 462 * @since 1.8 463 */ getUseCipherSuitesOrder()464 public final boolean getUseCipherSuitesOrder() { 465 return preferLocalCipherSuites; 466 } 467 } 468