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