1 /*
   2  * Copyright (c) 1997, 2018, 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 = GetPropertyAction.privilegedGetProperty("javax.net.debug", "")
  55                 .toLowerCase(Locale.ENGLISH);
  56 
  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                     @SuppressWarnings("deprecation")
 110                     SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
 111                     log("instantiated an instance of class " + clsName);
 112                     theFactory = fac;
 113                     return fac;
 114                 } catch (Exception e) {
 115                     log("SSLSocketFactory instantiation failed: " + e.toString());
 116                     theFactory = new DefaultSSLSocketFactory(e);
 117                     return theFactory;
 118                 }
 119             }
 120         }
 121 
 122         try {
 123             return SSLContext.getDefault().getSocketFactory();
 124         } catch (NoSuchAlgorithmException | UnsupportedOperationException e) {
 125             return new DefaultSSLSocketFactory(e);
 126         }
 127     }
 128 
 129     static String getSecurityProperty(final String name) {
 130         return AccessController.doPrivileged(new PrivilegedAction<>() {
 131             @Override
 132             public String run() {
 133                 String s = java.security.Security.getProperty(name);
 134                 if (s != null) {
 135                     s = s.trim();
 136                     if (s.length() == 0) {
 137                         s = null;
 138                     }
 139                 }
 140                 return s;
 141             }
 142         });
 143     }
 144 
 145     /**
 146      * Returns the list of cipher suites which are enabled by default.
 147      * Unless a different list is enabled, handshaking on an SSL connection
 148      * will use one of these cipher suites.  The minimum quality of service
 149      * for these defaults requires confidentiality protection and server
 150      * authentication (that is, no anonymous cipher suites).
 151      * <P>
 152      * The returned array includes cipher suites from the list of standard
 153      * cipher suite names in the <a href=
 154      * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
 155      * JSSE Cipher Suite Names</a> section of the Java Cryptography
 156      * Architecture Standard Algorithm Name Documentation, and may also
 157      * include other cipher suites that the provider supports.
 158      *
 159      * @see #getSupportedCipherSuites()
 160      * @return array of the cipher suites enabled by default
 161      */
 162     public abstract String [] getDefaultCipherSuites();
 163 
 164     /**
 165      * Returns the names of the cipher suites which could be enabled for use
 166      * on an SSL connection.  Normally, only a subset of these will actually
 167      * be enabled by default, since this list may include cipher suites which
 168      * do not meet quality of service requirements for those defaults.  Such
 169      * cipher suites are useful in specialized applications.
 170      * <P>
 171      * The returned array includes cipher suites from the list of standard
 172      * cipher suite names in the <a href=
 173      * "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
 174      * JSSE Cipher Suite Names</a> section of the Java Cryptography
 175      * Architecture Standard Algorithm Name Documentation, and may also
 176      * include other cipher suites that the provider supports.
 177      *
 178      * @see #getDefaultCipherSuites()
 179      * @return an array of cipher suite names
 180      */
 181     public abstract String [] getSupportedCipherSuites();
 182 
 183     /**
 184      * Returns a socket layered over an existing socket connected to the named
 185      * host, at the given port.  This constructor can be used when tunneling SSL
 186      * through a proxy or when negotiating the use of SSL over an existing
 187      * socket. The host and port refer to the logical peer destination.
 188      * This socket is configured using the socket options established for
 189      * this factory.
 190      *
 191      * @param s the existing socket
 192      * @param host the server host
 193      * @param port the server port
 194      * @param autoClose close the underlying socket when this socket is closed
 195      * @return a socket connected to the specified host and port
 196      * @throws IOException if an I/O error occurs when creating the socket
 197      * @throws NullPointerException if the parameter s is null
 198      */
 199     public abstract Socket createSocket(Socket s, String host,
 200             int port, boolean autoClose) throws IOException;
 201 
 202     /**
 203      * Creates a server mode {@link Socket} layered over an
 204      * existing connected socket, and is able to read data which has
 205      * already been consumed/removed from the {@link Socket}'s
 206      * underlying {@link InputStream}.
 207      * <p>
 208      * This method can be used by a server application that needs to
 209      * observe the inbound data but still create valid SSL/TLS
 210      * connections: for example, inspection of Server Name Indication
 211      * (SNI) extensions (See section 3 of <A
 212      * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions
 213      * (RFC6066)</A>).  Data that has been already removed from the
 214      * underlying {@link InputStream} should be loaded into the
 215      * {@code consumed} stream before this method is called, perhaps
 216      * using a {@link java.io.ByteArrayInputStream}.  When this
 217      * {@link Socket} begins handshaking, it will read all of the data in
 218      * {@code consumed} until it reaches {@code EOF}, then all further
 219      * data is read from the underlying {@link InputStream} as
 220      * usual.
 221      * <p>
 222      * The returned socket is configured using the socket options
 223      * established for this factory, and is set to use server mode when
 224      * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}).
 225      *
 226      * @param  s
 227      *         the existing socket
 228      * @param  consumed
 229      *         the consumed inbound network data that has already been
 230      *         removed from the existing {@link Socket}
 231      *         {@link InputStream}.  This parameter may be
 232      *         {@code null} if no data has been removed.
 233      * @param  autoClose close the underlying socket when this socket is closed.
 234      *
 235      * @return the {@link Socket} compliant with the socket options
 236      *         established for this factory
 237      *
 238      * @throws IOException if an I/O error occurs when creating the socket
 239      * @throws UnsupportedOperationException if the underlying provider
 240      *         does not implement the operation
 241      * @throws NullPointerException if {@code s} is {@code null}
 242      *
 243      * @since 1.8
 244      */
 245     public Socket createSocket(Socket s, InputStream consumed,
 246             boolean autoClose) throws IOException {
 247         throw new UnsupportedOperationException();
 248     }
 249 }
 250 
 251 
 252 // file private
 253 class DefaultSSLSocketFactory extends SSLSocketFactory
 254 {
 255     private Exception reason;
 256 
 257     DefaultSSLSocketFactory(Exception reason) {
 258         this.reason = reason;
 259     }
 260 
 261     private Socket throwException() throws SocketException {
 262         throw (SocketException)
 263             new SocketException(reason.toString()).initCause(reason);
 264     }
 265 
 266     @Override
 267     public Socket createSocket()
 268     throws IOException
 269     {
 270         return throwException();
 271     }
 272 
 273     @Override
 274     public Socket createSocket(String host, int port)
 275     throws IOException
 276     {
 277         return throwException();
 278     }
 279 
 280     @Override
 281     public Socket createSocket(Socket s, String host,
 282                                 int port, boolean autoClose)
 283     throws IOException
 284     {
 285         return throwException();
 286     }
 287 
 288     @Override
 289     public Socket createSocket(InetAddress address, int port)
 290     throws IOException
 291     {
 292         return throwException();
 293     }
 294 
 295     @Override
 296     public Socket createSocket(String host, int port,
 297         InetAddress clientAddress, int clientPort)
 298     throws IOException
 299     {
 300         return throwException();
 301     }
 302 
 303     @Override
 304     public Socket createSocket(InetAddress address, int port,
 305         InetAddress clientAddress, int clientPort)
 306     throws IOException
 307     {
 308         return throwException();
 309     }
 310 
 311     @Override
 312     public String [] getDefaultCipherSuites() {
 313         return new String[0];
 314     }
 315 
 316     @Override
 317     public String [] getSupportedCipherSuites() {
 318         return new String[0];
 319     }
 320 }