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.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 defaultSocketFactory; 48 49 private static int lastVersion = -1; 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 log(String msg)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 */ SSLSocketFactory()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 */ getDefault()88 public static synchronized SocketFactory getDefault() { 89 // Android-changed: Use security version instead of propertyChecked. 90 if (defaultSocketFactory != null && lastVersion == Security.getVersion()) { 91 return defaultSocketFactory; 92 } 93 94 lastVersion = Security.getVersion(); 95 SSLSocketFactory previousDefaultSocketFactory = defaultSocketFactory; 96 defaultSocketFactory = null; 97 98 String clsName = getSecurityProperty("ssl.SocketFactory.provider"); 99 100 if (clsName != null) { 101 // The instance for the default socket factory is checked for updates quite 102 // often (for instance, every time a security provider is added). Which leads 103 // to unnecessary overload and excessive error messages in case of class-loading 104 // errors. Avoid creating a new object if the class name is the same as before. 105 if (previousDefaultSocketFactory != null 106 && clsName.equals(previousDefaultSocketFactory.getClass().getName())) { 107 defaultSocketFactory = previousDefaultSocketFactory; 108 return defaultSocketFactory; 109 } 110 log("setting up default SSLSocketFactory"); 111 try { 112 Class cls = null; 113 try { 114 cls = Class.forName(clsName); 115 } catch (ClassNotFoundException e) { 116 // Android-changed; Try the contextClassLoader first. 117 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 118 if (cl == null) { 119 cl = ClassLoader.getSystemClassLoader(); 120 } 121 122 if (cl != null) { 123 cls = Class.forName(clsName, true, cl); 124 } 125 } 126 log("class " + clsName + " is loaded"); 127 defaultSocketFactory = (SSLSocketFactory)cls.newInstance(); 128 log("instantiated an instance of class " + clsName); 129 if (defaultSocketFactory != null) { 130 return defaultSocketFactory; 131 } 132 } catch (Exception e) { 133 log("SSLSocketFactory instantiation failed: " + e.toString()); 134 } 135 } 136 137 // Android-changed: Allow for {@code null} SSLContext.getDefault. 138 try { 139 SSLContext context = SSLContext.getDefault(); 140 if (context != null) { 141 defaultSocketFactory = context.getSocketFactory(); 142 } 143 } catch (NoSuchAlgorithmException e) { 144 } 145 146 if (defaultSocketFactory == null) { 147 defaultSocketFactory = new DefaultSSLSocketFactory(new IllegalStateException("No factory found.")); 148 } 149 150 return defaultSocketFactory; 151 } 152 getSecurityProperty(final String name)153 static String getSecurityProperty(final String name) { 154 return AccessController.doPrivileged(new PrivilegedAction<String>() { 155 public String run() { 156 String s = java.security.Security.getProperty(name); 157 if (s != null) { 158 s = s.trim(); 159 if (s.length() == 0) { 160 s = null; 161 } 162 } 163 return s; 164 } 165 }); 166 } 167 168 /** 169 * Returns the list of cipher suites which are enabled by default. 170 * Unless a different list is enabled, handshaking on an SSL connection 171 * will use one of these cipher suites. The minimum quality of service 172 * for these defaults requires confidentiality protection and server 173 * authentication (that is, no anonymous cipher suites). 174 * 175 * @see #getSupportedCipherSuites() 176 * @return array of the cipher suites enabled by default 177 */ 178 public abstract String [] getDefaultCipherSuites(); 179 180 /** 181 * Returns the names of the cipher suites which could be enabled for use 182 * on an SSL connection. Normally, only a subset of these will actually 183 * be enabled by default, since this list may include cipher suites which 184 * do not meet quality of service requirements for those defaults. Such 185 * cipher suites are useful in specialized applications. 186 * 187 * @see #getDefaultCipherSuites() 188 * @return an array of cipher suite names 189 */ 190 public abstract String [] getSupportedCipherSuites(); 191 192 /** 193 * Returns a socket layered over an existing socket connected to the named 194 * host, at the given port. This constructor can be used when tunneling SSL 195 * through a proxy or when negotiating the use of SSL over an existing 196 * socket. The host and port refer to the logical peer destination. 197 * This socket is configured using the socket options established for 198 * this factory. 199 * 200 * @param s the existing socket 201 * @param host the server host 202 * @param port the server port 203 * @param autoClose close the underlying socket when this socket is closed 204 * @return a socket connected to the specified host and port 205 * @throws IOException if an I/O error occurs when creating the socket 206 * @throws NullPointerException if the parameter s is null 207 */ 208 public abstract Socket createSocket(Socket s, String host, 209 int port, boolean autoClose) throws IOException; 210 } 211 212 213 // file private 214 class DefaultSSLSocketFactory extends SSLSocketFactory 215 { 216 private Exception reason; 217 218 DefaultSSLSocketFactory(Exception reason) { 219 this.reason = reason; 220 } 221 222 private Socket throwException() throws SocketException { 223 throw (SocketException) 224 new SocketException(reason.toString()).initCause(reason); 225 } 226 227 @Override 228 public Socket createSocket() 229 throws IOException 230 { 231 return throwException(); 232 } 233 234 @Override 235 public Socket createSocket(String host, int port) 236 throws IOException 237 { 238 return throwException(); 239 } 240 241 @Override 242 public Socket createSocket(Socket s, String host, 243 int port, boolean autoClose) 244 throws IOException 245 { 246 return throwException(); 247 } 248 249 @Override 250 public Socket createSocket(InetAddress address, int port) 251 throws IOException 252 { 253 return throwException(); 254 } 255 256 @Override 257 public Socket createSocket(String host, int port, 258 InetAddress clientAddress, int clientPort) 259 throws IOException 260 { 261 return throwException(); 262 } 263 264 @Override 265 public Socket createSocket(InetAddress address, int port, 266 InetAddress clientAddress, int clientPort) 267 throws IOException 268 { 269 return throwException(); 270 } 271 272 @Override 273 public String [] getDefaultCipherSuites() { 274 return new String[0]; 275 } 276 277 @Override 278 public String [] getSupportedCipherSuites() { 279 return new String[0]; 280 } 281 } 282