001 /* SSLSocketFactory.java -- factory for SSL client sockets.
002 Copyright (C) 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.net.ssl;
040
041 import java.io.IOException;
042 import java.net.InetAddress;
043 import java.net.Socket;
044 import java.security.KeyStore;
045 import java.security.Security;
046
047 import javax.net.SocketFactory;
048
049 /**
050 * A socket factory for creating <i>Secure Socket Layer</i> (<b>SSL</b>)
051 * sockets.
052 */
053 public abstract class SSLSocketFactory extends SocketFactory
054 {
055 // Constants.
056 // -------------------------------------------------------------------------
057
058 private static SSLContext context;
059
060 // Constructor.
061 // -------------------------------------------------------------------------
062
063 public SSLSocketFactory()
064 {
065 super();
066 }
067
068 // Class methods.
069 // -------------------------------------------------------------------------
070
071 /**
072 * Returns a default implementation of a SSL socket factory.
073 *
074 * <p>To control the class that gets returned by this method, set the
075 * security property "ssl.SocketFactory.provider" to the class
076 * name of a concrete implementation of this class. If not set, a
077 * system-dependent implementation will be used.</p>
078 *
079 * <p>The implementation returned is created by the first implementation
080 * of the {@link SSLContext} class found, which is initialized with
081 * default parameters. To control the key and trust manager factory
082 * algorithms used as defaults, set the security properties
083 * "ssl.keyManagerFactory.algorithm" and "ssl.trustManagerFactory.algorithm"
084 * to the appropriate names.</p>
085 *
086 * <p>Using this method is not recommended. Instead, use the methods of
087 * {@link SSLContext}, which provide much better control over the
088 * creation of socket factories.</p>
089 *
090 * @return The default socket factory.
091 * @throws RuntimeException If no default can be created.
092 */
093 public static synchronized SocketFactory getDefault()
094 {
095 try
096 {
097 String s = Security.getProperty("ssl.SocketFactory.provider");
098 ClassLoader cl = ClassLoader.getSystemClassLoader();
099 if (s != null && cl != null)
100 {
101 return (SocketFactory) cl.loadClass(s).newInstance();
102 }
103 }
104 catch (Exception e)
105 {
106 }
107 if (context == null)
108 {
109 KeyManager[] km = null;
110 TrustManager[] tm = null;
111
112 // 1. Determine which algorithms to use for the key and trust
113 // manager factories.
114 String kmAlg = KeyManagerFactory.getDefaultAlgorithm();
115 String tmAlg = TrustManagerFactory.getDefaultAlgorithm();
116
117 // 2. Try to initialize the factories with default parameters.
118 try
119 {
120 KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmAlg);
121 kmf.init(null, null);
122 km = kmf.getKeyManagers();
123 }
124 catch (Exception ex)
125 {
126 }
127 try
128 {
129 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlg);
130 tmf.init((KeyStore) null);
131 tm = tmf.getTrustManagers();
132 }
133 catch (Exception ex)
134 {
135 }
136
137 // 3. Create and initialize a context.
138 try
139 {
140 context = SSLContext.getInstance("SSLv3");
141 context.init(km, tm, null);
142 }
143 catch (Exception ex)
144 {
145 return new ErrorSocketFactory(new RuntimeException(
146 "error instantiating default socket factory: " + ex.toString(),
147 ex));
148 }
149 }
150 try
151 {
152 return context.getSocketFactory();
153 }
154 catch (Exception e)
155 {
156 }
157 return new ErrorSocketFactory(new RuntimeException(
158 "no SSLSocketFactory implementation available"));
159 }
160
161 private static final class ErrorSocketFactory extends SSLSocketFactory
162 {
163 private RuntimeException x;
164
165 ErrorSocketFactory(RuntimeException x)
166 {
167 this.x = x;
168 }
169
170 public Socket createSocket() throws IOException
171 {
172 throw (IOException) new IOException().initCause(x);
173 }
174
175 public Socket createSocket(String host, int port)
176 throws IOException
177 {
178 throw (IOException) new IOException().initCause(x);
179 }
180
181 public Socket createSocket(String host, int port, InetAddress localHost,
182 int localPort)
183 throws IOException
184 {
185 throw (IOException) new IOException().initCause(x);
186 }
187
188 public Socket createSocket(InetAddress host, int port) throws IOException
189 {
190 throw (IOException) new IOException().initCause(x);
191 }
192
193 public Socket createSocket(InetAddress hast, int port, InetAddress localHost,
194 int localPort)
195 throws IOException
196 {
197 throw (IOException) new IOException().initCause(x);
198 }
199
200 public String[] getDefaultCipherSuites()
201 {
202 throw new RuntimeException(x);
203 }
204
205 public String[] getSupportedCipherSuites()
206 {
207 throw new RuntimeException(x);
208 }
209
210 public Socket createSocket(Socket s, String host, int port,
211 boolean autoClose)
212 throws IOException
213 {
214 throw new RuntimeException(x);
215 }
216 }
217
218 // Abstract methods.
219 // -------------------------------------------------------------------------
220
221 /**
222 * Creates a SSL socket wrapped around an existing socket.
223 *
224 * @param socket The socket to wrap.
225 * @param host The host the socket is connected to.
226 * @param port The port the socket is connected to.
227 * @param autoClose Whether or not the wrapped socket should be closed
228 * automatically.
229 * @return The new SSL socket.
230 * @throws IOException If the socket could not be created.
231 */
232 public abstract Socket createSocket(Socket socket, String host,
233 int port, boolean autoClose)
234 throws IOException;
235
236 /**
237 * Returns the list of cipher suites that will be enabled in sockets
238 * created by this factory.
239 *
240 * @return The default cipher suites.
241 */
242 public abstract String[] getDefaultCipherSuites();
243
244 /**
245 * Returns the list of all cipher suites supported by this factory.
246 *
247 * @return The list of supported cipher suites.
248 */
249 public abstract String[] getSupportedCipherSuites();
250 }