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