1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 28 package javax.net.ssl; 29 30 import java.net.*; 31 import javax.net.SocketFactory; 32 import java.io.IOException; 33 import java.io.InputStream; 34 import java.security.*; 35 import java.util.Locale; 36 37 import sun.security.action.GetPropertyAction; 38 39 /** 40 * <code>SSLSocketFactory</code>s create <code>SSLSocket</code>s. 41 * 42 * @since 1.4 43 * @see SSLSocket 44 * @author David Brownell 45 */ 46 public abstract class SSLSocketFactory extends SocketFactory 47 { 48 // Android-changed: Renamed field. 49 // Some apps rely on changing this field via reflection, so we can't change the name 50 // without introducing app compatibility problems. See http://b/62248930. 51 private static SSLSocketFactory defaultSocketFactory; 52 53 // Android-changed: Check Security.getVersion() on each update. 54 // If the set of providers or other such things changes, it may change the default 55 // factory, so we track the version returned from Security.getVersion() instead of 56 // only having a flag that says if we've ever initialized the default. 57 // private static boolean propertyChecked; 58 private static int lastVersion = -1; 59 60 static final boolean DEBUG; 61 62 static { 63 String s = java.security.AccessController.doPrivileged( 64 new GetPropertyAction("javax.net.debug", "")).toLowerCase( 65 Locale.ENGLISH); 66 DEBUG = s.contains("all") || s.contains("ssl"); 67 } 68 log(String msg)69 private static void log(String msg) { 70 if (DEBUG) { 71 System.out.println(msg); 72 } 73 } 74 75 /** 76 * Constructor is used only by subclasses. 77 */ SSLSocketFactory()78 public SSLSocketFactory() { 79 } 80 81 /** 82 * Returns the default SSL socket factory. 83 * 84 * <p>The first time this method is called, the security property 85 * "ssl.SocketFactory.provider" is examined. If it is non-null, a class by 86 * that name is loaded and instantiated. If that is successful and the 87 * object is an instance of SSLSocketFactory, it is made the default SSL 88 * socket factory. 89 * 90 * <p>Otherwise, this method returns 91 * <code>SSLContext.getDefault().getSocketFactory()</code>. If that 92 * call fails, an inoperative factory is returned. 93 * 94 * @return the default <code>SocketFactory</code> 95 * @see SSLContext#getDefault 96 */ getDefault()97 public static synchronized SocketFactory getDefault() { 98 // Android-changed: Check Security.getVersion() on each update. 99 if (defaultSocketFactory != null && lastVersion == Security.getVersion()) { 100 return defaultSocketFactory; 101 } 102 103 lastVersion = Security.getVersion(); 104 SSLSocketFactory previousDefaultSocketFactory = defaultSocketFactory; 105 defaultSocketFactory = null; 106 107 String clsName = getSecurityProperty("ssl.SocketFactory.provider"); 108 109 if (clsName != null) { 110 // Android-changed: Check if we already have an instance of the default factory class. 111 // The instance for the default socket factory is checked for updates quite 112 // often (for instance, every time a security provider is added). Which leads 113 // to unnecessary overload and excessive error messages in case of class-loading 114 // errors. Avoid creating a new object if the class name is the same as before. 115 if (previousDefaultSocketFactory != null 116 && clsName.equals(previousDefaultSocketFactory.getClass().getName())) { 117 defaultSocketFactory = previousDefaultSocketFactory; 118 return defaultSocketFactory; 119 } 120 log("setting up default SSLSocketFactory"); 121 try { 122 Class<?> cls = null; 123 try { 124 cls = Class.forName(clsName); 125 } catch (ClassNotFoundException e) { 126 // Android-changed: Try the contextClassLoader first. 127 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 128 if (cl == null) { 129 cl = ClassLoader.getSystemClassLoader(); 130 } 131 132 if (cl != null) { 133 // Android-changed: Use Class.forName() so the class gets initialized. 134 cls = Class.forName(clsName, true, cl); 135 } 136 } 137 log("class " + clsName + " is loaded"); 138 SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance(); 139 log("instantiated an instance of class " + clsName); 140 defaultSocketFactory = fac; 141 return fac; 142 } catch (Exception e) { 143 log("SSLSocketFactory instantiation failed: " + e.toString()); 144 // Android-changed: Fallback to the default SSLContext on exception. 145 } 146 } 147 148 try { 149 // Android-changed: Allow for {@code null} SSLContext.getDefault. 150 SSLContext context = SSLContext.getDefault(); 151 if (context != null) { 152 defaultSocketFactory = context.getSocketFactory(); 153 } else { 154 defaultSocketFactory = new DefaultSSLSocketFactory(new IllegalStateException("No factory found.")); 155 } 156 return defaultSocketFactory; 157 } catch (NoSuchAlgorithmException e) { 158 return new DefaultSSLSocketFactory(e); 159 } 160 } 161 getSecurityProperty(final String name)162 static String getSecurityProperty(final String name) { 163 return AccessController.doPrivileged(new PrivilegedAction<String>() { 164 @Override 165 public String run() { 166 String s = java.security.Security.getProperty(name); 167 if (s != null) { 168 s = s.trim(); 169 if (s.length() == 0) { 170 s = null; 171 } 172 } 173 return s; 174 } 175 }); 176 } 177 178 /** 179 * Returns the list of cipher suites which are enabled by default. 180 * Unless a different list is enabled, handshaking on an SSL connection 181 * will use one of these cipher suites. The minimum quality of service 182 * for these defaults requires confidentiality protection and server 183 * authentication (that is, no anonymous cipher suites). 184 * 185 * @see #getSupportedCipherSuites() 186 * @return array of the cipher suites enabled by default 187 */ 188 public abstract String [] getDefaultCipherSuites(); 189 190 // Android-changed: Added warnings about misuse 191 /** 192 * Returns the names of the cipher suites which could be enabled for use 193 * on an SSL connection. Normally, only a subset of these will actually 194 * be enabled by default, since this list may include cipher suites which 195 * do not meet quality of service requirements for those defaults. Such 196 * cipher suites are useful in specialized applications. 197 * 198 * <p class="caution">Applications should not blindly enable all supported 199 * cipher suites. The supported cipher suites can include signaling cipher suite 200 * values that can cause connection problems if enabled inappropriately. 201 * 202 * <p>The proper way to use this method is to either check if a specific cipher 203 * suite is supported via {@code Arrays.asList(getSupportedCipherSuites()).contains(...)} 204 * or to filter a desired list of cipher suites to only the supported ones via 205 * {@code desiredSuiteSet.retainAll(Arrays.asList(getSupportedCipherSuites()))}. 206 * 207 * @see #getDefaultCipherSuites() 208 * @return an array of cipher suite names 209 */ 210 public abstract String [] getSupportedCipherSuites(); 211 212 /** 213 * Returns a socket layered over an existing socket connected to the named 214 * host, at the given port. This constructor can be used when tunneling SSL 215 * through a proxy or when negotiating the use of SSL over an existing 216 * socket. The host and port refer to the logical peer destination. 217 * This socket is configured using the socket options established for 218 * this factory. 219 * 220 * @param s the existing socket 221 * @param host the server host 222 * @param port the server port 223 * @param autoClose close the underlying socket when this socket is closed 224 * @return a socket connected to the specified host and port 225 * @throws IOException if an I/O error occurs when creating the socket 226 * @throws NullPointerException if the parameter s is null 227 */ 228 public abstract Socket createSocket(Socket s, String host, 229 int port, boolean autoClose) throws IOException; 230 231 /** 232 * Creates a server mode {@link Socket} layered over an 233 * existing connected socket, and is able to read data which has 234 * already been consumed/removed from the {@link Socket}'s 235 * underlying {@link InputStream}. 236 * <p> 237 * This method can be used by a server application that needs to 238 * observe the inbound data but still create valid SSL/TLS 239 * connections: for example, inspection of Server Name Indication 240 * (SNI) extensions (See section 3 of <A 241 * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions 242 * (RFC6066)</A>). Data that has been already removed from the 243 * underlying {@link InputStream} should be loaded into the 244 * {@code consumed} stream before this method is called, perhaps 245 * using a {@link java.io.ByteArrayInputStream}. When this 246 * {@link Socket} begins handshaking, it will read all of the data in 247 * {@code consumed} until it reaches {@code EOF}, then all further 248 * data is read from the underlying {@link InputStream} as 249 * usual. 250 * <p> 251 * The returned socket is configured using the socket options 252 * established for this factory, and is set to use server mode when 253 * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}). 254 * 255 * @param s 256 * the existing socket 257 * @param consumed 258 * the consumed inbound network data that has already been 259 * removed from the existing {@link Socket} 260 * {@link InputStream}. This parameter may be 261 * {@code null} if no data has been removed. 262 * @param autoClose close the underlying socket when this socket is closed. 263 * 264 * @return the {@link Socket} compliant with the socket options 265 * established for this factory 266 * 267 * @throws IOException if an I/O error occurs when creating the socket 268 * @throws UnsupportedOperationException if the underlying provider 269 * does not implement the operation 270 * @throws NullPointerException if {@code s} is {@code null} 271 * 272 * @since 1.8 273 * 274 * @hide 275 */ 276 public Socket createSocket(Socket s, InputStream consumed, 277 boolean autoClose) throws IOException { 278 throw new UnsupportedOperationException(); 279 } 280 } 281 282 283 // file private 284 class DefaultSSLSocketFactory extends SSLSocketFactory 285 { 286 private Exception reason; 287 288 DefaultSSLSocketFactory(Exception reason) { 289 this.reason = reason; 290 } 291 292 private Socket throwException() throws SocketException { 293 throw (SocketException) 294 new SocketException(reason.toString()).initCause(reason); 295 } 296 297 @Override 298 public Socket createSocket() 299 throws IOException 300 { 301 return throwException(); 302 } 303 304 @Override 305 public Socket createSocket(String host, int port) 306 throws IOException 307 { 308 return throwException(); 309 } 310 311 @Override 312 public Socket createSocket(Socket s, String host, 313 int port, boolean autoClose) 314 throws IOException 315 { 316 return throwException(); 317 } 318 319 @Override 320 public Socket createSocket(InetAddress address, int port) 321 throws IOException 322 { 323 return throwException(); 324 } 325 326 @Override 327 public Socket createSocket(String host, int port, 328 InetAddress clientAddress, int clientPort) 329 throws IOException 330 { 331 return throwException(); 332 } 333 334 @Override 335 public Socket createSocket(InetAddress address, int port, 336 InetAddress clientAddress, int clientPort) 337 throws IOException 338 { 339 return throwException(); 340 } 341 342 @Override 343 public String [] getDefaultCipherSuites() { 344 return new String[0]; 345 } 346 347 @Override 348 public String [] getSupportedCipherSuites() { 349 return new String[0]; 350 } 351 } 352