1 /* SSLContext.java -- an SSL protocol context.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package javax.net.ssl;
40 
41 import gnu.java.security.Engine;
42 
43 import java.lang.reflect.InvocationTargetException;
44 import java.security.KeyManagementException;
45 import java.security.NoSuchAlgorithmException;
46 import java.security.NoSuchProviderException;
47 import java.security.Provider;
48 import java.security.SecureRandom;
49 import java.security.Security;
50 
51 /**
52  * A "meta-factory" for protocol-specific socket and server socket
53  * factories. This class serves as a clearinghouse for socket
54  * factories and cached session contexts for a particular protocol,
55  * such as SSLv3.
56  *
57  * @author Casey Marshall (rsdio@metastatic.org)
58  */
59 public class SSLContext
60 {
61   // Constants and fields.
62   // ------------------------------------------------------------------
63 
64   /** Service name for SSL contexts. */
65   private static final String SSL_CONTEXT = "SSLContext";
66 
67   /** The underlying engine. */
68   private final SSLContextSpi ctxSpi;
69 
70   /** The provider of the engine class. */
71   private final Provider provider;
72 
73   /** The protocal name. */
74   private final String protocol;
75 
76   // Constructor.
77   // ------------------------------------------------------------------
78 
79   /**
80    * Create a new SSL context.
81    *
82    * @param ctxSpi The context engine.
83    * @param provider The provider of the implementation.
84    * @param protocol The name of the SSL protocol.
85    */
SSLContext(SSLContextSpi ctxSpi, Provider provider, String protocol)86   protected SSLContext(SSLContextSpi ctxSpi, Provider provider,
87                        String protocol)
88   {
89     this.ctxSpi = ctxSpi;
90     this.provider = provider;
91     this.protocol = protocol;
92   }
93 
94   /**
95    * Get an instance of a context for the specified protocol from the first
96    * provider that implements it.
97    *
98    * @param protocol The name of the protocol to get a context for.
99    * @return The new context.
100    * @throws NoSuchAlgorithmException If no provider implements the given
101    *           protocol.
102    * @throws IllegalArgumentException if <code>protocol</code> is
103    *           <code>null</code> or is an empty string.
104    */
getInstance(String protocol)105   public static final SSLContext getInstance(String protocol)
106       throws NoSuchAlgorithmException
107   {
108     Provider[] p = Security.getProviders();
109     NoSuchAlgorithmException lastException = null;
110     for (int i = 0; i < p.length; i++)
111       try
112         {
113           return getInstance(protocol, p[i]);
114         }
115       catch (NoSuchAlgorithmException x)
116         {
117           lastException = x;
118         }
119     if (lastException != null)
120       throw lastException;
121     throw new NoSuchAlgorithmException(protocol);
122   }
123 
124   /**
125    * Get an instance of a context for the specified protocol from the named
126    * provider.
127    *
128    * @param protocol The name of the protocol to get a context for.
129    * @param provider The name of the provider to get the implementation from.
130    * @return The new context.
131    * @throws NoSuchAlgorithmException If the provider does not implement the
132    *           given protocol.
133    * @throws NoSuchProviderException If the named provider does not exist.
134    * @throws IllegalArgumentException if either <code>protocol</code> or
135    *           <code>provider</code> is <code>null</code>, or if
136    *           <code>protocol</code> is an empty string.
137    */
getInstance(String protocol, String provider)138   public static final SSLContext getInstance(String protocol, String provider)
139       throws NoSuchAlgorithmException, NoSuchProviderException
140   {
141     if (provider == null)
142       throw new IllegalArgumentException("provider MUST NOT be null");
143     Provider p = Security.getProvider(provider);
144     if (p == null)
145       throw new NoSuchProviderException(provider);
146     return getInstance(protocol, p);
147   }
148 
149   /**
150    * Get an instance of a context for the specified protocol from the specified
151    * provider.
152    *
153    * @param protocol The name of the protocol to get a context for.
154    * @param provider The name of the provider to get the implementation from.
155    * @return The new context.
156    * @throws NoSuchAlgorithmException If the provider does not implement the
157    *           given protocol.
158    * @throws IllegalArgumentException if either <code>protocol</code> or
159    *           <code>provider</code> is <code>null</code>, or if
160    *           <code>protocol</code> is an empty string.
161    */
getInstance(String protocol, Provider provider)162   public static final SSLContext getInstance(String protocol, Provider provider)
163       throws NoSuchAlgorithmException
164   {
165     StringBuilder sb = new StringBuilder("SSLContext for protocol [")
166         .append(protocol).append("] from provider[")
167         .append(provider).append("] could not be created");
168     Throwable cause;
169     try
170       {
171         Object spi = Engine.getInstance(SSL_CONTEXT, protocol, provider);
172         return new SSLContext((SSLContextSpi) spi, provider, protocol);
173       }
174     catch (InvocationTargetException x)
175       {
176         cause = x.getCause();
177         if (cause instanceof NoSuchAlgorithmException)
178           throw (NoSuchAlgorithmException) cause;
179         if (cause == null)
180           cause = x;
181       }
182     catch (ClassCastException x)
183       {
184         cause = x;
185       }
186     NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
187     x.initCause(cause);
188     throw x;
189   }
190 
191   /**
192    * Creates a new {@link SSLEngine} for this context.
193    *
194    * @return The new SSLEngine.
195    * @since 1.5
196    */
createSSLEngine()197   public final SSLEngine createSSLEngine ()
198   {
199     return ctxSpi.engineCreateSSLEngine ();
200   }
201 
202   /**
203    * Creates a new {@link SSLEngine} for this context, with a given
204    * host name and port number.
205    *
206    * @param host The local host name.
207    * @param port The local port number.
208    * @return The new SSLEngine.
209    * @since 1.5
210    */
createSSLEngine(final String host, final int port)211   public final SSLEngine createSSLEngine (final String host, final int port)
212   {
213     return ctxSpi.engineCreateSSLEngine (host, port);
214   }
215 
216   /**
217    * Returns the set of SSL contexts available for client connections.
218    *
219    * @return The set of SSL contexts available for client connections.
220    */
getClientSessionContext()221   public final SSLSessionContext getClientSessionContext()
222   {
223     return ctxSpi.engineGetClientSessionContext();
224   }
225 
226   /**
227    * Returns the protocol name of this context.
228    *
229    * @return The protocol name of this context.
230    */
getProtocol()231   public final String getProtocol()
232   {
233     return protocol;
234   }
235 
236   /**
237    * Returns the provider of this implementation.
238    *
239    * @return The provider of this implementation.
240    */
getProvider()241   public final Provider getProvider()
242   {
243     return provider;
244   }
245 
246   /**
247    * Returns the set of SSL contexts available for server connections.
248    *
249    * @return The set of SSL contexts available for server connections.
250    */
getServerSessionContext()251   public final SSLSessionContext getServerSessionContext()
252   {
253     return ctxSpi.engineGetServerSessionContext();
254   }
255 
256   /**
257    * Returns the factory for server SSL sockets.
258    *
259    * @return The factory for server SSL sockets.
260    */
getServerSocketFactory()261   public final SSLServerSocketFactory getServerSocketFactory()
262   {
263     return ctxSpi.engineGetServerSocketFactory();
264   }
265 
266   /**
267    * Returns the factory for client SSL sockets.
268    *
269    * @return The factory for client SSL sockets.
270    */
getSocketFactory()271   public final SSLSocketFactory getSocketFactory()
272   {
273     return ctxSpi.engineGetSocketFactory();
274   }
275 
276   /**
277    * Initializes this context and prepares it for producing socket
278    * factories. All of the parameters are optional; default values are
279    * used if left unspecified.
280    *
281    * @param keyManagers The set of key managers to use.
282    * @param trustManagers The set of trust managers to use.
283    * @param random A source of random bits to use.
284    * @throws KeyManagementException If initialization fails.
285    */
init(KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom random)286   public final void init(KeyManager[] keyManagers,
287                          TrustManager[] trustManagers,
288                          SecureRandom random)
289     throws KeyManagementException
290   {
291     ctxSpi.engineInit(keyManagers, trustManagers, random);
292   }
293 }
294