1 /* 2 * Copyright (c) 1997, 2012, 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.getProperty("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 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 * 152 * @see #getSupportedCipherSuites() 153 * @return array of the cipher suites enabled by default 154 */ 155 public abstract String [] getDefaultCipherSuites(); 156 157 /** 158 * Returns the names of the cipher suites which could be enabled for use 159 * on an SSL connection. Normally, only a subset of these will actually 160 * be enabled by default, since this list may include cipher suites which 161 * do not meet quality of service requirements for those defaults. Such 162 * cipher suites are useful in specialized applications. 163 * 164 * @see #getDefaultCipherSuites() 165 * @return an array of cipher suite names 166 */ 167 public abstract String [] getSupportedCipherSuites(); 168 169 /** 170 * Returns a socket layered over an existing socket connected to the named 171 * host, at the given port. This constructor can be used when tunneling SSL 172 * through a proxy or when negotiating the use of SSL over an existing 173 * socket. The host and port refer to the logical peer destination. 174 * This socket is configured using the socket options established for 175 * this factory. 176 * 177 * @param s the existing socket 178 * @param host the server host 179 * @param port the server port 180 * @param autoClose close the underlying socket when this socket is closed 181 * @return a socket connected to the specified host and port 182 * @throws IOException if an I/O error occurs when creating the socket 183 * @throws NullPointerException if the parameter s is null 184 */ 185 public abstract Socket createSocket(Socket s, String host, 186 int port, boolean autoClose) throws IOException; 187 188 /** 189 * Creates a server mode {@link Socket} layered over an 190 * existing connected socket, and is able to read data which has 191 * already been consumed/removed from the {@link Socket}'s 192 * underlying {@link InputStream}. 193 * <p> 194 * This method can be used by a server application that needs to 195 * observe the inbound data but still create valid SSL/TLS 196 * connections: for example, inspection of Server Name Indication 197 * (SNI) extensions (See section 3 of <A 198 * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions 199 * (RFC6066)</A>). Data that has been already removed from the 200 * underlying {@link InputStream} should be loaded into the 201 * {@code consumed} stream before this method is called, perhaps 202 * using a {@link java.io.ByteArrayInputStream}. When this 203 * {@link Socket} begins handshaking, it will read all of the data in 204 * {@code consumed} until it reaches {@code EOF}, then all further 205 * data is read from the underlying {@link InputStream} as 206 * usual. 207 * <p> 208 * The returned socket is configured using the socket options 209 * established for this factory, and is set to use server mode when 210 * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}). 211 * 212 * @param s 213 * the existing socket 214 * @param consumed 215 * the consumed inbound network data that has already been 216 * removed from the existing {@link Socket} 217 * {@link InputStream}. This parameter may be 218 * {@code null} if no data has been removed. 219 * @param autoClose close the underlying socket when this socket is closed. 220 * 221 * @return the {@link Socket} compliant with the socket options 222 * established for this factory 223 * 224 * @throws IOException if an I/O error occurs when creating the socket 225 * @throws UnsupportedOperationException if the underlying provider 226 * does not implement the operation 227 * @throws NullPointerException if {@code s} is {@code null} 228 * 229 * @since 1.8 230 */ 231 public Socket createSocket(Socket s, InputStream consumed, 232 boolean autoClose) throws IOException { 233 throw new UnsupportedOperationException(); 234 } 235 } 236 237 238 // file private 239 class DefaultSSLSocketFactory extends SSLSocketFactory 240 { 241 private Exception reason; 242 243 DefaultSSLSocketFactory(Exception reason) { 244 this.reason = reason; 245 } 246 247 private Socket throwException() throws SocketException { 248 throw (SocketException) 249 new SocketException(reason.toString()).initCause(reason); 250 } 251 252 @Override 253 public Socket createSocket() 254 throws IOException 255 { 256 return throwException(); 257 } 258 259 @Override 260 public Socket createSocket(String host, int port) 261 throws IOException 262 { 263 return throwException(); 264 } 265 266 @Override 267 public Socket createSocket(Socket s, String host, 268 int port, boolean autoClose) 269 throws IOException 270 { 271 return throwException(); 272 } 273 274 @Override 275 public Socket createSocket(InetAddress address, int port) 276 throws IOException 277 { 278 return throwException(); 279 } 280 281 @Override 282 public Socket createSocket(String host, int port, 283 InetAddress clientAddress, int clientPort) 284 throws IOException 285 { 286 return throwException(); 287 } 288 289 @Override 290 public Socket createSocket(InetAddress address, int port, 291 InetAddress clientAddress, int clientPort) 292 throws IOException 293 { 294 return throwException(); 295 } 296 297 @Override 298 public String [] getDefaultCipherSuites() { 299 return new String[0]; 300 } 301 302 @Override 303 public String [] getSupportedCipherSuites() { 304 return new String[0]; 305 } 306 }