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.isEmpty()) { 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 }