1 /*
   2  * Copyright (c) 1997, 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 
  26 
  27 package javax.net.ssl;
  28 
  29 import java.net.*;
  30 import javax.net.SocketFactory;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.security.*;
  34 import java.util.Locale;
  35 
  36 import sun.security.action.GetPropertyAction;
  37 
  38 /**
  39  * <code>SSLSocketFactory</code>s create <code>SSLSocket</code>s.
  40  *
  41  * @since 1.4
  42  * @see SSLSocket
  43  * @author David Brownell
  44  */
  45 public abstract class SSLSocketFactory extends SocketFactory
  46 {
  47     private static SSLSocketFactory theFactory;
  48 
  49     private static boolean propertyChecked;
  50 
  51     static final boolean DEBUG;
  52 
  53     static {
  54         String s = java.security.AccessController.doPrivileged(
  55             new GetPropertyAction("javax.net.debug", "")).toLowerCase(
  56                                                             Locale.ENGLISH);
  57         DEBUG = s.contains("all") || s.contains("ssl");
  58     }
  59 
  60     private static void log(String msg) {
  61         if (DEBUG) {
  62             System.out.println(msg);
  63         }
  64     }
  65 
  66     /**
  67      * Constructor is used only by subclasses.
  68      */
  69     public SSLSocketFactory() {
  70     }
  71 
  72     /**
  73      * Returns the default SSL socket factory.
  74      *
  75      * <p>The first time this method is called, the security property
  76      * "ssl.SocketFactory.provider" is examined. If it is non-null, a class by
  77      * that name is loaded and instantiated. If that is successful and the
  78      * object is an instance of SSLSocketFactory, it is made the default SSL
  79      * socket factory.
  80      *
  81      * <p>Otherwise, this method returns
  82      * <code>SSLContext.getDefault().getSocketFactory()</code>. If that
  83      * call fails, an inoperative factory is returned.
  84      *
  85      * @return the default <code>SocketFactory</code>
  86      * @see SSLContext#getDefault
  87      */
  88     public static synchronized SocketFactory getDefault() {
  89         if (theFactory != null) {
  90             return theFactory;
  91         }
  92 
  93         if (propertyChecked == false) {
  94             propertyChecked = true;
  95             String clsName = getSecurityProperty("ssl.SocketFactory.provider");
  96             if (clsName != null) {
  97                 log("setting up default SSLSocketFactory");
  98                 try {
  99                     Class<?> cls = null;
 100                     try {
 101                         cls = Class.forName(clsName);
 102                     } catch (ClassNotFoundException e) {
 103                         ClassLoader cl = ClassLoader.getSystemClassLoader();
 104                         if (cl != null) {
 105                             cls = cl.loadClass(clsName);
 106                         }
 107                     }
 108                     log("class " + clsName + " is loaded");
 109                     SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
 110                     log("instantiated an instance of class " + clsName);
 111                     theFactory = fac;
 112                     return fac;
 113                 } catch (Exception e) {
 114                     log("SSLSocketFactory instantiation failed: " + e.toString());
 115                     theFactory = new DefaultSSLSocketFactory(e);
 116                     return theFactory;
 117                 }
 118             }
 119         }
 120 
 121         try {
 122             return SSLContext.getDefault().getSocketFactory();
 123         } catch (NoSuchAlgorithmException e) {
 124             return new DefaultSSLSocketFactory(e);
 125         }
 126     }
 127 
 128     static String getSecurityProperty(final String name) {
 129         return AccessController.doPrivileged(new PrivilegedAction<String>() {
 130             @Override
 131             public String run() {
 132                 String s = java.security.Security.getProperty(name);
 133                 if (s != null) {
 134                     s = s.trim();
 135                     if (s.length() == 0) {
 136                         s = null;
 137                     }
 138                 }
 139                 return s;
 140             }
 141         });
 142     }
 143 
 144     /**
 145      * Returns the list of cipher suites which are enabled by default.
 146      * Unless a different list is enabled, handshaking on an SSL connection
 147      * will use one of these cipher suites.  The minimum quality of service
 148      * for these defaults requires confidentiality protection and server
 149      * authentication (that is, no anonymous cipher suites).
 150      *
 151      * @see #getSupportedCipherSuites()
 152      * @return array of the cipher suites enabled by default
 153      */
 154     public abstract String [] getDefaultCipherSuites();
 155 
 156     /**
 157      * Returns the names of the cipher suites which could be enabled for use
 158      * on an SSL connection.  Normally, only a subset of these will actually
 159      * be enabled by default, since this list may include cipher suites which
 160      * do not meet quality of service requirements for those defaults.  Such
 161      * cipher suites are useful in specialized applications.
 162      *
 163      * @see #getDefaultCipherSuites()
 164      * @return an array of cipher suite names
 165      */
 166     public abstract String [] getSupportedCipherSuites();
 167 
 168     /**
 169      * Returns a socket layered over an existing socket connected to the named
 170      * host, at the given port.  This constructor can be used when tunneling SSL
 171      * through a proxy or when negotiating the use of SSL over an existing
 172      * socket. The host and port refer to the logical peer destination.
 173      * This socket is configured using the socket options established for
 174      * this factory.
 175      *
 176      * @param s the existing socket
 177      * @param host the server host
 178      * @param port the server port
 179      * @param autoClose close the underlying socket when this socket is closed
 180      * @return a socket connected to the specified host and port
 181      * @throws IOException if an I/O error occurs when creating the socket
 182      * @throws NullPointerException if the parameter s is null
 183      */
 184     public abstract Socket createSocket(Socket s, String host,
 185             int port, boolean autoClose) throws IOException;
 186 
 187     /**
 188      * Creates a server mode {@link Socket} layered over an
 189      * existing connected socket, and is able to read data which has
 190      * already been consumed/removed from the {@link Socket}'s
 191      * underlying {@link InputStream}.
 192      * <p>
 193      * This method can be used by a server application that needs to
 194      * observe the inbound data but still create valid SSL/TLS
 195      * connections: for example, inspection of Server Name Indication
 196      * (SNI) extensions (See section 3 of <A
 197      * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions
 198      * (RFC6066)</A>).  Data that has been already removed from the
 199      * underlying {@link InputStream} should be loaded into the
 200      * {@code consumed} stream before this method is called, perhaps
 201      * using a {@link java.io.ByteArrayInputStream}.  When this
 202      * {@link Socket} begins handshaking, it will read all of the data in
 203      * {@code consumed} until it reaches {@code EOF}, then all further
 204      * data is read from the underlying {@link InputStream} as
 205      * usual.
 206      * <p>
 207      * The returned socket is configured using the socket options
 208      * established for this factory, and is set to use server mode when
 209      * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}).
 210      *
 211      * @param  s
 212      *         the existing socket
 213      * @param  consumed
 214      *         the consumed inbound network data that has already been
 215      *         removed from the existing {@link Socket}
 216      *         {@link InputStream}.  This parameter may be
 217      *         {@code null} if no data has been removed.
 218      * @param  autoClose close the underlying socket when this socket is closed.
 219      *
 220      * @return the {@link Socket} compliant with the socket options
 221      *         established for this factory
 222      *
 223      * @throws IOException if an I/O error occurs when creating the socket
 224      * @throws UnsupportedOperationException if the underlying provider
 225      *         does not implement the operation
 226      * @throws NullPointerException if {@code s} is {@code null}
 227      *
 228      * @since 1.8
 229      */
 230     public Socket createSocket(Socket s, InputStream consumed,
 231             boolean autoClose) throws IOException {
 232         throw new UnsupportedOperationException();
 233     }
 234 }
 235 
 236 
 237 // file private
 238 class DefaultSSLSocketFactory extends SSLSocketFactory
 239 {
 240     private Exception reason;
 241 
 242     DefaultSSLSocketFactory(Exception reason) {
 243         this.reason = reason;
 244     }
 245 
 246     private Socket throwException() throws SocketException {
 247         throw (SocketException)
 248             new SocketException(reason.toString()).initCause(reason);
 249     }
 250 
 251     @Override
 252     public Socket createSocket()
 253     throws IOException
 254     {
 255         return throwException();
 256     }
 257 
 258     @Override
 259     public Socket createSocket(String host, int port)
 260     throws IOException
 261     {
 262         return throwException();
 263     }
 264 
 265     @Override
 266     public Socket createSocket(Socket s, String host,
 267                                 int port, boolean autoClose)
 268     throws IOException
 269     {
 270         return throwException();
 271     }
 272 
 273     @Override
 274     public Socket createSocket(InetAddress address, int port)
 275     throws IOException
 276     {
 277         return throwException();
 278     }
 279 
 280     @Override
 281     public Socket createSocket(String host, int port,
 282         InetAddress clientAddress, int clientPort)
 283     throws IOException
 284     {
 285         return throwException();
 286     }
 287 
 288     @Override
 289     public Socket createSocket(InetAddress address, int port,
 290         InetAddress clientAddress, int clientPort)
 291     throws IOException
 292     {
 293         return throwException();
 294     }
 295 
 296     @Override
 297     public String [] getDefaultCipherSuites() {
 298         return new String[0];
 299     }
 300 
 301     @Override
 302     public String [] getSupportedCipherSuites() {
 303         return new String[0];
 304     }
 305 }