blob: 0b1569ca4ff585049ea6a385912bbd817d67738b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.util.Log;
John Recked065022016-09-20 14:24:21 -070021
22import com.android.internal.os.RoSystemProperties;
Kenny Root7fdce762017-03-28 10:02:23 -070023import com.android.org.conscrypt.Conscrypt;
Kenny Root12e75222013-04-23 22:34:24 -070024import com.android.org.conscrypt.OpenSSLContextImpl;
25import com.android.org.conscrypt.OpenSSLSocketImpl;
26import com.android.org.conscrypt.SSLClientSessionCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import java.io.IOException;
28import java.net.InetAddress;
29import java.net.Socket;
Brian Carlstrom7ab7a8b2012-09-21 16:33:50 -070030import java.net.SocketException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import java.security.KeyManagementException;
Alex Klyubinac5eb032013-03-12 10:30:59 -070032import java.security.PrivateKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import java.security.cert.X509Certificate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import javax.net.SocketFactory;
Dan Egnor7fc93c32010-06-29 17:51:28 -070035import javax.net.ssl.HostnameVerifier;
36import javax.net.ssl.HttpsURLConnection;
Ben Komalo1b528062011-05-03 09:40:15 -070037import javax.net.ssl.KeyManager;
Dan Egnor7fc93c32010-06-29 17:51:28 -070038import javax.net.ssl.SSLException;
39import javax.net.ssl.SSLPeerUnverifiedException;
40import javax.net.ssl.SSLSession;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import javax.net.ssl.SSLSocket;
42import javax.net.ssl.SSLSocketFactory;
43import javax.net.ssl.TrustManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import javax.net.ssl.X509TrustManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045
46/**
Dan Egnor60586f22010-02-08 21:56:38 -080047 * SSLSocketFactory implementation with several extra features:
Dan Egnor7fc93c32010-06-29 17:51:28 -070048 *
Dan Egnor60586f22010-02-08 21:56:38 -080049 * <ul>
50 * <li>Timeout specification for SSL handshake operations
Dan Egnor7fc93c32010-06-29 17:51:28 -070051 * <li>Hostname verification in most cases (see WARNINGs below)
Dan Egnor60586f22010-02-08 21:56:38 -080052 * <li>Optional SSL session caching with {@link SSLSessionCache}
Dan Egnor9d4b5752010-02-13 20:34:51 -080053 * <li>Optionally bypass all SSL certificate checks
Dan Egnor60586f22010-02-08 21:56:38 -080054 * </ul>
Dan Egnor7fc93c32010-06-29 17:51:28 -070055 *
56 * The handshake timeout does not apply to actual TCP socket connection.
57 * If you want a connection timeout as well, use {@link #createSocket()}
58 * and {@link Socket#connect(SocketAddress, int)}, after which you
59 * must verify the identity of the server you are connected to.
60 *
61 * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not
62 * verify the server's identity, allowing man-in-the-middle attacks.</b>
63 * This implementation does check the server's certificate hostname, but only
64 * for createSocket variants that specify a hostname. When using methods that
65 * use {@link InetAddress} or which return an unconnected socket, you MUST
66 * verify the server's identity yourself to ensure a secure connection.</p>
67 *
68 * <p>One way to verify the server's identity is to use
69 * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
70 * {@link HostnameVerifier} to verify the certificate hostname.
71 *
72 * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
73 * SSL certificate and hostname checks for testing purposes. This setting
74 * requires root access.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 */
76public class SSLCertificateSocketFactory extends SSLSocketFactory {
Dan Egnor60586f22010-02-08 21:56:38 -080077 private static final String TAG = "SSLCertificateSocketFactory";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078
Dan Egnor60586f22010-02-08 21:56:38 -080079 private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 new X509TrustManager() {
Dan Egnor60586f22010-02-08 21:56:38 -080081 public X509Certificate[] getAcceptedIssuers() { return null; }
82 public void checkClientTrusted(X509Certificate[] certs, String authType) { }
83 public void checkServerTrusted(X509Certificate[] certs, String authType) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 }
85 };
86
Dan Egnor60586f22010-02-08 21:56:38 -080087 private SSLSocketFactory mInsecureFactory = null;
88 private SSLSocketFactory mSecureFactory = null;
Ben Komalo1b528062011-05-03 09:40:15 -070089 private TrustManager[] mTrustManagers = null;
90 private KeyManager[] mKeyManagers = null;
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -040091 private byte[] mNpnProtocols = null;
Kenny Root100d7292013-06-25 12:00:34 -070092 private byte[] mAlpnProtocols = null;
Alex Klyubinac5eb032013-03-12 10:30:59 -070093 private PrivateKey mChannelIdPrivateKey = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
Dan Egnor60586f22010-02-08 21:56:38 -080095 private final int mHandshakeTimeoutMillis;
96 private final SSLClientSessionCache mSessionCache;
Dan Egnor9d4b5752010-02-13 20:34:51 -080097 private final boolean mSecure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
Dan Egnor60586f22010-02-08 21:56:38 -080099 /** @deprecated Use {@link #getDefault(int)} instead. */
Jesse Wilson28c74252010-11-04 14:09:18 -0700100 @Deprecated
Dan Egnor60586f22010-02-08 21:56:38 -0800101 public SSLCertificateSocketFactory(int handshakeTimeoutMillis) {
Dan Egnor9d4b5752010-02-13 20:34:51 -0800102 this(handshakeTimeoutMillis, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 }
104
Dan Egnor9d4b5752010-02-13 20:34:51 -0800105 private SSLCertificateSocketFactory(
Brian Carlstrom992f2382012-09-26 14:33:47 -0700106 int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure) {
Dan Egnor60586f22010-02-08 21:56:38 -0800107 mHandshakeTimeoutMillis = handshakeTimeoutMillis;
108 mSessionCache = cache == null ? null : cache.mSessionCache;
Dan Egnor9d4b5752010-02-13 20:34:51 -0800109 mSecure = secure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 }
111
112 /**
Dan Egnor9d4b5752010-02-13 20:34:51 -0800113 * Returns a new socket factory instance with an optional handshake timeout.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 *
Dan Egnor60586f22010-02-08 21:56:38 -0800115 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
116 * for none. The socket timeout is reset to 0 after the handshake.
Dan Egnor7fc93c32010-06-29 17:51:28 -0700117 * @return a new SSLSocketFactory with the specified parameters
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 */
Dan Egnor60586f22010-02-08 21:56:38 -0800119 public static SocketFactory getDefault(int handshakeTimeoutMillis) {
Dan Egnor9d4b5752010-02-13 20:34:51 -0800120 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 }
122
123 /**
Dan Egnor9d4b5752010-02-13 20:34:51 -0800124 * Returns a new socket factory instance with an optional handshake timeout
125 * and SSL session cache.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 *
Dan Egnor60586f22010-02-08 21:56:38 -0800127 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
128 * for none. The socket timeout is reset to 0 after the handshake.
Jesse Wilsonff556992011-03-23 16:43:39 -0700129 * @param cache The {@link SSLSessionCache} to use, or null for no cache.
Dan Egnor7fc93c32010-06-29 17:51:28 -0700130 * @return a new SSLSocketFactory with the specified parameters
Dan Egnor60586f22010-02-08 21:56:38 -0800131 */
Dan Egnor9d4b5752010-02-13 20:34:51 -0800132 public static SSLSocketFactory getDefault(int handshakeTimeoutMillis, SSLSessionCache cache) {
133 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true);
134 }
135
136 /**
137 * Returns a new instance of a socket factory with all SSL security checks
138 * disabled, using an optional handshake timeout and SSL session cache.
Dan Egnor7fc93c32010-06-29 17:51:28 -0700139 *
140 * <p class="caution"><b>Warning:</b> Sockets created using this factory
Kenny Roote19ca072014-08-13 12:08:48 -0700141 * are vulnerable to man-in-the-middle attacks!</p>
Dan Egnor9d4b5752010-02-13 20:34:51 -0800142 *
143 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
144 * for none. The socket timeout is reset to 0 after the handshake.
Jesse Wilsonff556992011-03-23 16:43:39 -0700145 * @param cache The {@link SSLSessionCache} to use, or null for no cache.
Dan Egnor7fc93c32010-06-29 17:51:28 -0700146 * @return an insecure SSLSocketFactory with the specified parameters
Dan Egnor9d4b5752010-02-13 20:34:51 -0800147 */
148 public static SSLSocketFactory getInsecure(int handshakeTimeoutMillis, SSLSessionCache cache) {
149 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, false);
Dan Egnor60586f22010-02-08 21:56:38 -0800150 }
151
152 /**
153 * Returns a socket factory (also named SSLSocketFactory, but in a different
154 * namespace) for use with the Apache HTTP stack.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 *
Dan Egnor60586f22010-02-08 21:56:38 -0800156 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
157 * for none. The socket timeout is reset to 0 after the handshake.
Jesse Wilsonff556992011-03-23 16:43:39 -0700158 * @param cache The {@link SSLSessionCache} to use, or null for no cache.
Dan Egnor60586f22010-02-08 21:56:38 -0800159 * @return a new SocketFactory with the specified parameters
Narayan Kamath823675fd2014-10-23 17:35:01 +0100160 *
161 * @deprecated Use {@link #getDefault()} along with a {@link javax.net.ssl.HttpsURLConnection}
162 * instead. The Apache HTTP client is no longer maintained and may be removed in a future
163 * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
164 * for further details.
Narayan Kamath406e1ed2014-12-10 18:55:12 +0000165 *
166 * @removed
Dan Egnor60586f22010-02-08 21:56:38 -0800167 */
Narayan Kamath823675fd2014-10-23 17:35:01 +0100168 @Deprecated
Dan Egnor60586f22010-02-08 21:56:38 -0800169 public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
Jesse Wilsonff556992011-03-23 16:43:39 -0700170 int handshakeTimeoutMillis, SSLSessionCache cache) {
Dan Egnor60586f22010-02-08 21:56:38 -0800171 return new org.apache.http.conn.ssl.SSLSocketFactory(
Dan Egnor9d4b5752010-02-13 20:34:51 -0800172 new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true));
Dan Egnor60586f22010-02-08 21:56:38 -0800173 }
174
Dan Egnor7fc93c32010-06-29 17:51:28 -0700175 /**
176 * Verify the hostname of the certificate used by the other end of a
177 * connected socket. You MUST call this if you did not supply a hostname
178 * to {@link #createSocket()}. It is harmless to call this method
179 * redundantly if the hostname has already been verified.
180 *
181 * <p>Wildcard certificates are allowed to verify any matching hostname,
182 * so "foo.bar.example.com" is verified if the peer has a certificate
183 * for "*.example.com".
184 *
185 * @param socket An SSL socket which has been connected to a server
186 * @param hostname The expected hostname of the remote server
187 * @throws IOException if something goes wrong handshaking with the server
188 * @throws SSLPeerUnverifiedException if the server cannot prove its identity
189 *
190 * @hide
191 */
192 public static void verifyHostname(Socket socket, String hostname) throws IOException {
193 if (!(socket instanceof SSLSocket)) {
194 throw new IllegalArgumentException("Attempt to verify non-SSL socket");
195 }
196
197 if (!isSslCheckRelaxed()) {
198 // The code at the start of OpenSSLSocketImpl.startHandshake()
199 // ensures that the call is idempotent, so we can safely call it.
200 SSLSocket ssl = (SSLSocket) socket;
201 ssl.startHandshake();
202
203 SSLSession session = ssl.getSession();
204 if (session == null) {
205 throw new SSLException("Cannot verify SSL socket without session");
206 }
Kenny Root928ee1e2013-07-23 20:36:03 -0700207 if (!HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session)) {
Dan Egnor7fc93c32010-06-29 17:51:28 -0700208 throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
209 }
210 }
211 }
212
Ben Komalo1b528062011-05-03 09:40:15 -0700213 private SSLSocketFactory makeSocketFactory(
214 KeyManager[] keyManagers, TrustManager[] trustManagers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 try {
Kenny Root7fdce762017-03-28 10:02:23 -0700216 OpenSSLContextImpl sslContext = (OpenSSLContextImpl) Conscrypt.newPreferredSSLContextSpi();
Ben Komalo1b528062011-05-03 09:40:15 -0700217 sslContext.engineInit(keyManagers, trustManagers, null);
Brian Carlstrom2c42c8f2010-09-14 00:11:14 -0700218 sslContext.engineGetClientSessionContext().setPersistentCache(mSessionCache);
Dan Egnor60586f22010-02-08 21:56:38 -0800219 return sslContext.engineGetSocketFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 } catch (KeyManagementException e) {
Dan Egnor60586f22010-02-08 21:56:38 -0800221 Log.wtf(TAG, e);
222 return (SSLSocketFactory) SSLSocketFactory.getDefault(); // Fallback
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 }
224 }
225
Dan Egnor7fc93c32010-06-29 17:51:28 -0700226 private static boolean isSslCheckRelaxed() {
John Recked065022016-09-20 14:24:21 -0700227 return RoSystemProperties.DEBUGGABLE &&
228 SystemProperties.getBoolean("socket.relaxsslcheck", false);
Dan Egnor7fc93c32010-06-29 17:51:28 -0700229 }
230
Dan Egnor60586f22010-02-08 21:56:38 -0800231 private synchronized SSLSocketFactory getDelegate() {
Dan Egnor9d4b5752010-02-13 20:34:51 -0800232 // Relax the SSL check if instructed (for this factory, or systemwide)
Dan Egnor7fc93c32010-06-29 17:51:28 -0700233 if (!mSecure || isSslCheckRelaxed()) {
Dan Egnor60586f22010-02-08 21:56:38 -0800234 if (mInsecureFactory == null) {
Dan Egnor9d4b5752010-02-13 20:34:51 -0800235 if (mSecure) {
236 Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***");
Kenny Roote19ca072014-08-13 12:08:48 -0700237 } else {
238 Log.w(TAG, "Bypassing SSL security checks at caller's request");
Dan Egnor9d4b5752010-02-13 20:34:51 -0800239 }
Ben Komalo1b528062011-05-03 09:40:15 -0700240 mInsecureFactory = makeSocketFactory(mKeyManagers, INSECURE_TRUST_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 }
Dan Egnor60586f22010-02-08 21:56:38 -0800242 return mInsecureFactory;
243 } else {
244 if (mSecureFactory == null) {
Ben Komalo1b528062011-05-03 09:40:15 -0700245 mSecureFactory = makeSocketFactory(mKeyManagers, mTrustManagers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 }
Dan Egnor60586f22010-02-08 21:56:38 -0800247 return mSecureFactory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
249 }
250
Dan Egnor7fc93c32010-06-29 17:51:28 -0700251 /**
Ben Komalo1b528062011-05-03 09:40:15 -0700252 * Sets the {@link TrustManager}s to be used for connections made by this factory.
Ben Komalo1b528062011-05-03 09:40:15 -0700253 */
254 public void setTrustManagers(TrustManager[] trustManager) {
255 mTrustManagers = trustManager;
256
257 // Clear out all cached secure factories since configurations have changed.
258 mSecureFactory = null;
259 // Note - insecure factories only ever use the INSECURE_TRUST_MANAGER so they need not
260 // be cleared out here.
261 }
262
263 /**
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400264 * Sets the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next
265 * Protocol Negotiation (NPN)</a> protocols that this peer is interested in.
266 *
267 * <p>For servers this is the sequence of protocols to advertise as
268 * supported, in order of preference. This list is sent unencrypted to
269 * all clients that support NPN.
270 *
271 * <p>For clients this is a list of supported protocols to match against the
272 * server's list. If there is no protocol supported by both client and
273 * server then the first protocol in the client's list will be selected.
274 * The order of the client's protocols is otherwise insignificant.
275 *
Jesse Wilson2108ead2012-05-17 13:46:17 -0400276 * @param npnProtocols a non-empty list of protocol byte arrays. All arrays
277 * must be non-empty and of length less than 256.
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400278 */
279 public void setNpnProtocols(byte[][] npnProtocols) {
Kenny Root100d7292013-06-25 12:00:34 -0700280 this.mNpnProtocols = toLengthPrefixedList(npnProtocols);
281 }
282
283 /**
284 * Sets the
285 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">
286 * Application Layer Protocol Negotiation (ALPN)</a> protocols that this peer
287 * is interested in.
288 *
289 * <p>For servers this is the sequence of protocols to advertise as
290 * supported, in order of preference. This list is sent unencrypted to
291 * all clients that support ALPN.
292 *
293 * <p>For clients this is a list of supported protocols to match against the
294 * server's list. If there is no protocol supported by both client and
295 * server then the first protocol in the client's list will be selected.
296 * The order of the client's protocols is otherwise insignificant.
297 *
298 * @param protocols a non-empty list of protocol byte arrays. All arrays
299 * must be non-empty and of length less than 256.
300 * @hide
301 */
302 public void setAlpnProtocols(byte[][] protocols) {
303 this.mAlpnProtocols = toLengthPrefixedList(protocols);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400304 }
305
306 /**
307 * Returns an array containing the concatenation of length-prefixed byte
308 * strings.
309 */
Kenny Root100d7292013-06-25 12:00:34 -0700310 static byte[] toLengthPrefixedList(byte[]... items) {
311 if (items.length == 0) {
312 throw new IllegalArgumentException("items.length == 0");
Jesse Wilson2108ead2012-05-17 13:46:17 -0400313 }
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400314 int totalLength = 0;
Kenny Root100d7292013-06-25 12:00:34 -0700315 for (byte[] s : items) {
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400316 if (s.length == 0 || s.length > 255) {
317 throw new IllegalArgumentException("s.length == 0 || s.length > 255: " + s.length);
318 }
319 totalLength += 1 + s.length;
320 }
321 byte[] result = new byte[totalLength];
322 int pos = 0;
Kenny Root100d7292013-06-25 12:00:34 -0700323 for (byte[] s : items) {
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400324 result[pos++] = (byte) s.length;
325 for (byte b : s) {
326 result[pos++] = b;
327 }
328 }
329 return result;
330 }
331
332 /**
333 * Returns the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next
334 * Protocol Negotiation (NPN)</a> protocol selected by client and server, or
335 * null if no protocol was negotiated.
336 *
337 * @param socket a socket created by this factory.
Narayan Kamathb4db9622012-09-17 17:59:00 +0100338 * @throws IllegalArgumentException if the socket was not created by this factory.
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400339 */
340 public byte[] getNpnSelectedProtocol(Socket socket) {
Narayan Kamathb4db9622012-09-17 17:59:00 +0100341 return castToOpenSSLSocket(socket).getNpnSelectedProtocol();
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400342 }
343
344 /**
Kenny Root100d7292013-06-25 12:00:34 -0700345 * Returns the
346 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">Application
347 * Layer Protocol Negotiation (ALPN)</a> protocol selected by client and server, or null
348 * if no protocol was negotiated.
349 *
350 * @param socket a socket created by this factory.
351 * @throws IllegalArgumentException if the socket was not created by this factory.
352 * @hide
353 */
354 public byte[] getAlpnSelectedProtocol(Socket socket) {
355 return castToOpenSSLSocket(socket).getAlpnSelectedProtocol();
356 }
357
358 /**
Ben Komalo1b528062011-05-03 09:40:15 -0700359 * Sets the {@link KeyManager}s to be used for connections made by this factory.
Ben Komalo1b528062011-05-03 09:40:15 -0700360 */
361 public void setKeyManagers(KeyManager[] keyManagers) {
362 mKeyManagers = keyManagers;
363
364 // Clear out any existing cached factories since configurations have changed.
365 mSecureFactory = null;
366 mInsecureFactory = null;
367 }
368
Narayan Kamathb4db9622012-09-17 17:59:00 +0100369 /**
Alex Klyubinac5eb032013-03-12 10:30:59 -0700370 * Sets the private key to be used for TLS Channel ID by connections made by this
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800371 * factory.
372 *
373 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
374 * TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the
375 * NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
376 *
377 * @hide
378 */
Alex Klyubinac5eb032013-03-12 10:30:59 -0700379 public void setChannelIdPrivateKey(PrivateKey privateKey) {
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800380 mChannelIdPrivateKey = privateKey;
381 }
382
383 /**
Narayan Kamathb4db9622012-09-17 17:59:00 +0100384 * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a>
385 * support on the given socket.
386 *
387 * @param socket a socket created by this factory
388 * @param useSessionTickets {@code true} to enable session ticket support on this socket.
389 * @throws IllegalArgumentException if the socket was not created by this factory.
390 */
391 public void setUseSessionTickets(Socket socket, boolean useSessionTickets) {
392 castToOpenSSLSocket(socket).setUseSessionTickets(useSessionTickets);
393 }
394
395 /**
396 * Turns on <a href="http://tools.ietf.org/html/rfc6066#section-3">Server
397 * Name Indication (SNI)</a> on a given socket.
398 *
399 * @param socket a socket created by this factory.
400 * @param hostName the desired SNI hostname, null to disable.
401 * @throws IllegalArgumentException if the socket was not created by this factory.
402 */
403 public void setHostname(Socket socket, String hostName) {
404 castToOpenSSLSocket(socket).setHostname(hostName);
405 }
406
Brian Carlstrom7ab7a8b2012-09-21 16:33:50 -0700407 /**
408 * Sets this socket's SO_SNDTIMEO write timeout in milliseconds.
409 * Use 0 for no timeout.
410 * To take effect, this option must be set before the blocking method was called.
411 *
412 * @param socket a socket created by this factory.
Brian Carlstrom992f2382012-09-26 14:33:47 -0700413 * @param timeout the desired write timeout in milliseconds.
Brian Carlstrom7ab7a8b2012-09-21 16:33:50 -0700414 * @throws IllegalArgumentException if the socket was not created by this factory.
Brian Carlstrom992f2382012-09-26 14:33:47 -0700415 *
416 * @hide
Brian Carlstrom7ab7a8b2012-09-21 16:33:50 -0700417 */
418 public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)
419 throws SocketException {
420 castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds);
421 }
422
Narayan Kamathb4db9622012-09-17 17:59:00 +0100423 private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) {
424 if (!(socket instanceof OpenSSLSocketImpl)) {
425 throw new IllegalArgumentException("Socket not created by this factory: "
426 + socket);
427 }
428
429 return (OpenSSLSocketImpl) socket;
430 }
Ben Komalo1b528062011-05-03 09:40:15 -0700431
432 /**
Dan Egnor7fc93c32010-06-29 17:51:28 -0700433 * {@inheritDoc}
434 *
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700435 * <p>This method verifies the peer's certificate hostname after connecting
436 * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
Dan Egnor7fc93c32010-06-29 17:51:28 -0700437 */
Dan Egnor60586f22010-02-08 21:56:38 -0800438 @Override
439 public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
440 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400441 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700442 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800443 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800444 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700445 if (mSecure) {
446 verifyHostname(s, host);
447 }
Dan Egnor60586f22010-02-08 21:56:38 -0800448 return s;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
450
Dan Egnor7fc93c32010-06-29 17:51:28 -0700451 /**
452 * Creates a new socket which is not connected to any remote host.
453 * You must use {@link Socket#connect} to connect the socket.
454 *
455 * <p class="caution"><b>Warning:</b> Hostname verification is not performed
456 * with this method. You MUST verify the server's identity after connecting
457 * the socket to avoid man-in-the-middle attacks.</p>
458 */
Dan Egnor60586f22010-02-08 21:56:38 -0800459 @Override
460 public Socket createSocket() throws IOException {
461 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400462 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700463 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800464 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800465 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Dan Egnor60586f22010-02-08 21:56:38 -0800466 return s;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 }
468
Dan Egnor7fc93c32010-06-29 17:51:28 -0700469 /**
470 * {@inheritDoc}
471 *
472 * <p class="caution"><b>Warning:</b> Hostname verification is not performed
473 * with this method. You MUST verify the server's identity after connecting
474 * the socket to avoid man-in-the-middle attacks.</p>
475 */
Dan Egnor60586f22010-02-08 21:56:38 -0800476 @Override
477 public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)
478 throws IOException {
479 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
480 addr, port, localAddr, localPort);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400481 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700482 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800483 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800484 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Dan Egnor60586f22010-02-08 21:56:38 -0800485 return s;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487
Dan Egnor7fc93c32010-06-29 17:51:28 -0700488 /**
489 * {@inheritDoc}
490 *
491 * <p class="caution"><b>Warning:</b> Hostname verification is not performed
492 * with this method. You MUST verify the server's identity after connecting
493 * the socket to avoid man-in-the-middle attacks.</p>
494 */
Dan Egnor60586f22010-02-08 21:56:38 -0800495 @Override
496 public Socket createSocket(InetAddress addr, int port) throws IOException {
497 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400498 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700499 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800500 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800501 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Dan Egnor60586f22010-02-08 21:56:38 -0800502 return s;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 }
504
Dan Egnor7fc93c32010-06-29 17:51:28 -0700505 /**
506 * {@inheritDoc}
507 *
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700508 * <p>This method verifies the peer's certificate hostname after connecting
509 * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
Dan Egnor7fc93c32010-06-29 17:51:28 -0700510 */
Dan Egnor60586f22010-02-08 21:56:38 -0800511 @Override
512 public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
513 throws IOException {
514 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
515 host, port, localAddr, localPort);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400516 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700517 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800518 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800519 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700520 if (mSecure) {
521 verifyHostname(s, host);
522 }
Dan Egnor60586f22010-02-08 21:56:38 -0800523 return s;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
525
Dan Egnor7fc93c32010-06-29 17:51:28 -0700526 /**
527 * {@inheritDoc}
528 *
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700529 * <p>This method verifies the peer's certificate hostname after connecting
530 * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
Dan Egnor7fc93c32010-06-29 17:51:28 -0700531 */
Dan Egnor60586f22010-02-08 21:56:38 -0800532 @Override
533 public Socket createSocket(String host, int port) throws IOException {
534 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
Jesse Wilsonf5fb5e82012-03-23 15:55:03 -0400535 s.setNpnProtocols(mNpnProtocols);
Kenny Root100d7292013-06-25 12:00:34 -0700536 s.setAlpnProtocols(mAlpnProtocols);
Dan Egnor60586f22010-02-08 21:56:38 -0800537 s.setHandshakeTimeout(mHandshakeTimeoutMillis);
Alex Klyubin4ef6c9b2013-01-18 12:50:39 -0800538 s.setChannelIdPrivateKey(mChannelIdPrivateKey);
Andrew Stadlerdf27c0c2010-07-12 15:31:40 -0700539 if (mSecure) {
540 verifyHostname(s, host);
541 }
Dan Egnor60586f22010-02-08 21:56:38 -0800542 return s;
543 }
544
545 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 public String[] getDefaultCipherSuites() {
Alex Klyubin019118a2013-10-28 16:16:38 -0700547 return getDelegate().getDefaultCipherSuites();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 }
549
Dan Egnor60586f22010-02-08 21:56:38 -0800550 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 public String[] getSupportedCipherSuites() {
Dan Egnor60586f22010-02-08 21:56:38 -0800552 return getDelegate().getSupportedCipherSuites();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 }
554}