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