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