1 /*
   2  * Copyright (c) 1999, 2019, 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.*;
  29 import java.lang.invoke.MethodHandles;
  30 import java.lang.invoke.VarHandle;
  31 import java.util.Objects;
  32 import sun.security.jca.GetInstance;
  33 
  34 /**
  35  * Instances of this class represent a secure socket protocol
  36  * implementation which acts as a factory for secure socket
  37  * factories or {@code SSLEngine}s. This class is initialized
  38  * with an optional set of key and trust managers and source of
  39  * secure random bytes.
  40  *
  41  * <p> Every implementation of the Java platform is required to support the
  42  * following standard {@code SSLContext} protocol:
  43  * <ul>
  44  * <li>{@code TLSv1.2}</li>
  45  * </ul>
  46  * This protocol is described in the <a href=
  47  * "{@docRoot}/../specs/security/standard-names.html#sslcontext-algorithms">
  48  * SSLContext section</a> of the
  49  * Java Security Standard Algorithm Names Specification.
  50  * Consult the release documentation for your implementation to see if any
  51  * other protocols are supported.
  52  *
  53  * @since 1.4
  54  */
  55 public class SSLContext {
  56     private final Provider provider;
  57 
  58     private final SSLContextSpi contextSpi;
  59 
  60     private final String protocol;
  61 
  62     private static volatile SSLContext defaultContext;
  63 
  64     private static final VarHandle VH_DEFAULT_CONTEXT;
  65 
  66     static {
  67         try {
  68             VH_DEFAULT_CONTEXT = MethodHandles.lookup()
  69                 .findStaticVarHandle(
  70                     SSLContext.class, "defaultContext", SSLContext.class);
  71         } catch (Exception e) {
  72             throw new ExceptionInInitializerError(e);
  73         }
  74     }
  75 
  76     /**
  77      * Creates an SSLContext object.
  78      *
  79      * @param contextSpi the delegate
  80      * @param provider the provider
  81      * @param protocol the protocol
  82      */
  83     protected SSLContext(SSLContextSpi contextSpi, Provider provider,
  84             String protocol) {
  85         this.contextSpi = contextSpi;
  86         this.provider = provider;
  87         this.protocol = protocol;
  88     }
  89 
  90     /**
  91      * Returns the default SSL context.
  92      *
  93      * <p>If a default context was set using the {@link #setDefault
  94      * SSLContext.setDefault()} method, it is returned. Otherwise, the first
  95      * call of this method triggers the call
  96      * {@code SSLContext.getInstance("Default")}.
  97      * If successful, that object is made the default SSL context and returned.
  98      *
  99      * <p>The default context is immediately
 100      * usable and does not require {@linkplain #init initialization}.
 101      *
 102      * @return the default SSL context
 103      * @throws NoSuchAlgorithmException if the
 104      *   {@link SSLContext#getInstance SSLContext.getInstance()} call fails
 105      * @since 1.6
 106      */
 107     public static SSLContext getDefault() throws NoSuchAlgorithmException {
 108         SSLContext temporaryContext = defaultContext;
 109         if (temporaryContext == null) {
 110             temporaryContext = SSLContext.getInstance("Default");
 111             if (!VH_DEFAULT_CONTEXT.compareAndSet(null, temporaryContext)) {
 112                 temporaryContext = defaultContext;
 113             }
 114         }
 115 
 116         return temporaryContext;
 117     }
 118 
 119     /**
 120      * Sets the default SSL context. It will be returned by subsequent calls
 121      * to {@link #getDefault}. The default context must be immediately usable
 122      * and not require {@linkplain #init initialization}.
 123      *
 124      * @param context the SSLContext
 125      * @throws  NullPointerException if context is null
 126      * @throws  SecurityException if a security manager exists and its
 127      *          {@code checkPermission} method does not allow
 128      *          {@code SSLPermission("setDefaultSSLContext")}
 129      * @since 1.6
 130      */
 131     public static void setDefault(SSLContext context) {
 132         if (context == null) {
 133             throw new NullPointerException();
 134         }
 135         SecurityManager sm = System.getSecurityManager();
 136         if (sm != null) {
 137             sm.checkPermission(new SSLPermission("setDefaultSSLContext"));
 138         }
 139 
 140         defaultContext = context;
 141     }
 142 
 143     /**
 144      * Returns a {@code SSLContext} object that implements the
 145      * specified secure socket protocol.
 146      *
 147      * <p> This method traverses the list of registered security Providers,
 148      * starting with the most preferred Provider.
 149      * A new SSLContext object encapsulating the
 150      * SSLContextSpi implementation from the first
 151      * Provider that supports the specified protocol is returned.
 152      *
 153      * <p> Note that the list of registered providers may be retrieved via
 154      * the {@link Security#getProviders() Security.getProviders()} method.
 155      *
 156      * @implNote
 157      * The JDK Reference Implementation additionally uses the
 158      * {@code jdk.security.provider.preferred}
 159      * {@link Security#getProperty(String) Security} property to determine
 160      * the preferred provider order for the specified algorithm. This
 161      * may be different than the order of providers returned by
 162      * {@link Security#getProviders() Security.getProviders()}.
 163      *
 164      * @param protocol the standard name of the requested protocol.
 165      *          See the SSLContext section in the <a href=
 166      * "{@docRoot}/../specs/security/standard-names.html#sslcontext-algorithms">
 167      *          Java Security Standard Algorithm Names Specification</a>
 168      *          for information about standard protocol names.
 169      *
 170      * @return the new {@code SSLContext} object
 171      *
 172      * @throws NoSuchAlgorithmException if no {@code Provider} supports a
 173      *         {@code SSLContextSpi} implementation for the
 174      *         specified protocol
 175      *
 176      * @throws NullPointerException if {@code protocol} is {@code null}
 177      *
 178      * @see java.security.Provider
 179      */
 180     public static SSLContext getInstance(String protocol)
 181             throws NoSuchAlgorithmException {
 182         Objects.requireNonNull(protocol, "null protocol name");
 183         GetInstance.Instance instance = GetInstance.getInstance
 184                 ("SSLContext", SSLContextSpi.class, protocol);
 185         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
 186                 protocol);
 187     }
 188 
 189     /**
 190      * Returns a {@code SSLContext} object that implements the
 191      * specified secure socket protocol.
 192      *
 193      * <p> A new SSLContext object encapsulating the
 194      * SSLContextSpi implementation from the specified provider
 195      * is returned.  The specified provider must be registered
 196      * in the security provider list.
 197      *
 198      * <p> Note that the list of registered providers may be retrieved via
 199      * the {@link Security#getProviders() Security.getProviders()} method.
 200      *
 201      * @param protocol the standard name of the requested protocol.
 202      *          See the SSLContext section in the <a href=
 203      * "{@docRoot}/../specs/security/standard-names.html#sslcontext-algorithms">
 204      *          Java Security Standard Algorithm Names Specification</a>
 205      *          for information about standard protocol names.
 206      *
 207      * @param provider the name of the provider.
 208      *
 209      * @return the new {@code SSLContext} object
 210      *
 211      * @throws IllegalArgumentException if the provider name is
 212      *         {@code null} or empty
 213      *
 214      * @throws NoSuchAlgorithmException if a {@code SSLContextSpi}
 215      *         implementation for the specified protocol is not
 216      *         available from the specified provider
 217      *
 218      * @throws NoSuchProviderException if the specified provider is not
 219      *         registered in the security provider list
 220      *
 221      * @throws NullPointerException if {@code protocol} is {@code null}
 222      *
 223      * @see java.security.Provider
 224      */
 225     public static SSLContext getInstance(String protocol, String provider)
 226             throws NoSuchAlgorithmException, NoSuchProviderException {
 227         Objects.requireNonNull(protocol, "null protocol name");
 228         GetInstance.Instance instance = GetInstance.getInstance
 229                 ("SSLContext", SSLContextSpi.class, protocol, provider);
 230         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
 231                 protocol);
 232     }
 233 
 234     /**
 235      * Returns a {@code SSLContext} object that implements the
 236      * specified secure socket protocol.
 237      *
 238      * <p> A new SSLContext object encapsulating the
 239      * SSLContextSpi implementation from the specified Provider
 240      * object is returned.  Note that the specified Provider object
 241      * does not have to be registered in the provider list.
 242      *
 243      * @param protocol the standard name of the requested protocol.
 244      *          See the SSLContext section in the <a href=
 245      * "{@docRoot}/../specs/security/standard-names.html#sslcontext-algorithms">
 246      *          Java Security Standard Algorithm Names Specification</a>
 247      *          for information about standard protocol names.
 248      *
 249      * @param provider an instance of the provider.
 250      *
 251      * @return the new {@code SSLContext} object
 252      *
 253      * @throws IllegalArgumentException if the provider is {@code null}
 254      *
 255      * @throws NoSuchAlgorithmException if a {@code SSLContextSpi}
 256      *         implementation for the specified protocol is not available
 257      *         from the specified {@code Provider} object
 258      *
 259      * @throws NullPointerException if {@code protocol} is {@code null}
 260      *
 261      * @see java.security.Provider
 262      */
 263     public static SSLContext getInstance(String protocol, Provider provider)
 264             throws NoSuchAlgorithmException {
 265         Objects.requireNonNull(protocol, "null protocol name");
 266         GetInstance.Instance instance = GetInstance.getInstance
 267                 ("SSLContext", SSLContextSpi.class, protocol, provider);
 268         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
 269                 protocol);
 270     }
 271 
 272     /**
 273      * Returns the protocol name of this {@code SSLContext} object.
 274      *
 275      * <p>This is the same name that was specified in one of the
 276      * {@code getInstance} calls that created this
 277      * {@code SSLContext} object.
 278      *
 279      * @return the protocol name of this {@code SSLContext} object.
 280      */
 281     public final String getProtocol() {
 282         return this.protocol;
 283     }
 284 
 285     /**
 286      * Returns the provider of this {@code SSLContext} object.
 287      *
 288      * @return the provider of this {@code SSLContext} object
 289      */
 290     public final Provider getProvider() {
 291         return this.provider;
 292     }
 293 
 294     /**
 295      * Initializes this context. Either of the first two parameters
 296      * may be null in which case the installed security providers will
 297      * be searched for the highest priority implementation of the
 298      * appropriate factory. Likewise, the secure random parameter may
 299      * be null in which case the default implementation will be used.
 300      * <P>
 301      * Only the first instance of a particular key and/or trust manager
 302      * implementation type in the array is used.  (For example, only
 303      * the first javax.net.ssl.X509KeyManager in the array will be used.)
 304      *
 305      * @param km the sources of authentication keys or null
 306      * @param tm the sources of peer authentication trust decisions or null
 307      * @param random the source of randomness for this generator or null
 308      * @throws KeyManagementException if this operation fails
 309      */
 310     public final void init(KeyManager[] km, TrustManager[] tm,
 311                                 SecureRandom random)
 312         throws KeyManagementException {
 313         contextSpi.engineInit(km, tm, random);
 314     }
 315 
 316     /**
 317      * Returns a {@code SocketFactory} object for this
 318      * context.
 319      *
 320      * @return the {@code SocketFactory} object
 321      * @throws UnsupportedOperationException if the underlying provider
 322      *         does not implement the operation.
 323      * @throws IllegalStateException if the SSLContextImpl requires
 324      *         initialization and the {@code init()} has not been called
 325      */
 326     public final SSLSocketFactory getSocketFactory() {
 327         return contextSpi.engineGetSocketFactory();
 328     }
 329 
 330     /**
 331      * Returns a {@code ServerSocketFactory} object for
 332      * this context.
 333      *
 334      * @return the {@code ServerSocketFactory} object
 335      * @throws UnsupportedOperationException if the underlying provider
 336      *         does not implement the operation.
 337      * @throws IllegalStateException if the SSLContextImpl requires
 338      *         initialization and the {@code init()} has not been called
 339      */
 340     public final SSLServerSocketFactory getServerSocketFactory() {
 341         return contextSpi.engineGetServerSocketFactory();
 342     }
 343 
 344     /**
 345      * Creates a new {@code SSLEngine} using this context.
 346      * <P>
 347      * Applications using this factory method are providing no hints
 348      * for an internal session reuse strategy. If hints are desired,
 349      * {@link #createSSLEngine(String, int)} should be used
 350      * instead.
 351      * <P>
 352      * Some cipher suites (such as Kerberos) require remote hostname
 353      * information, in which case this factory method should not be used.
 354      *
 355      * @return  the {@code SSLEngine} object
 356      * @throws  UnsupportedOperationException if the underlying provider
 357      *          does not implement the operation.
 358      * @throws  IllegalStateException if the SSLContextImpl requires
 359      *          initialization and the {@code init()} has not been called
 360      * @since   1.5
 361      */
 362     public final SSLEngine createSSLEngine() {
 363         try {
 364             return contextSpi.engineCreateSSLEngine();
 365         } catch (AbstractMethodError e) {
 366             UnsupportedOperationException unsup =
 367                 new UnsupportedOperationException(
 368                     "Provider: " + getProvider() +
 369                     " doesn't support this operation");
 370             unsup.initCause(e);
 371             throw unsup;
 372         }
 373     }
 374 
 375     /**
 376      * Creates a new {@code SSLEngine} using this context using
 377      * advisory peer information.
 378      * <P>
 379      * Applications using this factory method are providing hints
 380      * for an internal session reuse strategy.
 381      * <P>
 382      * Some cipher suites (such as Kerberos) require remote hostname
 383      * information, in which case peerHost needs to be specified.
 384      *
 385      * @param   peerHost the non-authoritative name of the host
 386      * @param   peerPort the non-authoritative port
 387      * @return  the new {@code SSLEngine} object
 388      * @throws  UnsupportedOperationException if the underlying provider
 389      *          does not implement the operation.
 390      * @throws  IllegalStateException if the SSLContextImpl requires
 391      *          initialization and the {@code init()} has not been called
 392      * @since   1.5
 393      */
 394     public final SSLEngine createSSLEngine(String peerHost, int peerPort) {
 395         try {
 396             return contextSpi.engineCreateSSLEngine(peerHost, peerPort);
 397         } catch (AbstractMethodError e) {
 398             UnsupportedOperationException unsup =
 399                 new UnsupportedOperationException(
 400                     "Provider: " + getProvider() +
 401                     " does not support this operation");
 402             unsup.initCause(e);
 403             throw unsup;
 404         }
 405     }
 406 
 407     /**
 408      * Returns the server session context, which represents the set of
 409      * SSL sessions available for use during the handshake phase of
 410      * server-side SSL sockets.
 411      * <P>
 412      * This context may be unavailable in some environments, in which
 413      * case this method returns null. For example, when the underlying
 414      * SSL provider does not provide an implementation of SSLSessionContext
 415      * interface, this method returns null. A non-null session context
 416      * is returned otherwise.
 417      *
 418      * @return server session context bound to this SSL context
 419      */
 420     public final SSLSessionContext getServerSessionContext() {
 421         return contextSpi.engineGetServerSessionContext();
 422     }
 423 
 424     /**
 425      * Returns the client session context, which represents the set of
 426      * SSL sessions available for use during the handshake phase of
 427      * client-side SSL sockets.
 428      * <P>
 429      * This context may be unavailable in some environments, in which
 430      * case this method returns null. For example, when the underlying
 431      * SSL provider does not provide an implementation of SSLSessionContext
 432      * interface, this method returns null. A non-null session context
 433      * is returned otherwise.
 434      *
 435      * @return client session context bound to this SSL context
 436      */
 437     public final SSLSessionContext getClientSessionContext() {
 438         return contextSpi.engineGetClientSessionContext();
 439     }
 440 
 441     /**
 442      * Returns a copy of the SSLParameters indicating the default
 443      * settings for this SSL context.
 444      *
 445      * <p>The parameters will always have the ciphersuites and protocols
 446      * arrays set to non-null values.
 447      *
 448      * @return a copy of the SSLParameters object with the default settings
 449      * @throws UnsupportedOperationException if the default SSL parameters
 450      *   could not be obtained.
 451      * @since 1.6
 452      */
 453     public final SSLParameters getDefaultSSLParameters() {
 454         return contextSpi.engineGetDefaultSSLParameters();
 455     }
 456 
 457     /**
 458      * Returns a copy of the SSLParameters indicating the supported
 459      * settings for this SSL context.
 460      *
 461      * <p>The parameters will always have the ciphersuites and protocols
 462      * arrays set to non-null values.
 463      *
 464      * @return a copy of the SSLParameters object with the supported
 465      *   settings
 466      * @throws UnsupportedOperationException if the supported SSL parameters
 467      *   could not be obtained.
 468      * @since 1.6
 469      */
 470     public final SSLParameters getSupportedSSLParameters() {
 471         return contextSpi.engineGetSupportedSSLParameters();
 472     }
 473 
 474 }