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    }