001/* SSLSocketFactory.java -- factory for SSL client sockets.
002   Copyright (C) 2004 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.net.ssl;
040
041import java.io.IOException;
042import java.net.InetAddress;
043import java.net.Socket;
044import java.security.KeyStore;
045import java.security.Security;
046
047import javax.net.SocketFactory;
048
049/**
050 * A socket factory for creating <i>Secure Socket Layer</i> (<b>SSL</b>)
051 * sockets.
052 */
053public 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}