1 /* 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 17 package android.net; 18 19 import android.annotation.UnsupportedAppUsage; 20 import android.os.Build; 21 import android.os.SystemProperties; 22 import android.util.Log; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.internal.os.RoSystemProperties; 26 import com.android.org.conscrypt.ClientSessionContext; 27 import com.android.org.conscrypt.OpenSSLSocketImpl; 28 import com.android.org.conscrypt.SSLClientSessionCache; 29 30 import java.io.IOException; 31 import java.net.InetAddress; 32 import java.net.Socket; 33 import java.net.SocketException; 34 import java.security.KeyManagementException; 35 import java.security.NoSuchAlgorithmException; 36 import java.security.NoSuchProviderException; 37 import java.security.PrivateKey; 38 import java.security.cert.X509Certificate; 39 40 import javax.net.SocketFactory; 41 import javax.net.ssl.HostnameVerifier; 42 import javax.net.ssl.HttpsURLConnection; 43 import javax.net.ssl.KeyManager; 44 import javax.net.ssl.SSLContext; 45 import javax.net.ssl.SSLException; 46 import javax.net.ssl.SSLPeerUnverifiedException; 47 import javax.net.ssl.SSLSession; 48 import javax.net.ssl.SSLSocket; 49 import javax.net.ssl.SSLSocketFactory; 50 import javax.net.ssl.TrustManager; 51 import javax.net.ssl.X509TrustManager; 52 53 /** 54 * SSLSocketFactory implementation with several extra features: 55 * 56 * <ul> 57 * <li>Timeout specification for SSL handshake operations 58 * <li>Hostname verification in most cases (see WARNINGs below) 59 * <li>Optional SSL session caching with {@link SSLSessionCache} 60 * <li>Optionally bypass all SSL certificate checks 61 * </ul> 62 * 63 * The handshake timeout does not apply to actual TCP socket connection. 64 * If you want a connection timeout as well, use {@link #createSocket()} 65 * and {@link Socket#connect(java.net.SocketAddress, int)}, after which you 66 * must verify the identity of the server you are connected to. 67 * 68 * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not 69 * verify the server's identity, allowing man-in-the-middle attacks.</b> 70 * This implementation does check the server's certificate hostname, but only 71 * for createSocket variants that specify a hostname. When using methods that 72 * use {@link InetAddress} or which return an unconnected socket, you MUST 73 * verify the server's identity yourself to ensure a secure connection. 74 * 75 * Refer to 76 * <a href="https://developer.android.com/training/articles/security-gms-provider.html"> 77 * Updating Your Security Provider to Protect Against SSL Exploits</a> 78 * for further information.</p> 79 * 80 * <p>The recommended way to verify the server's identity is to use 81 * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a 82 * {@link HostnameVerifier} to verify the certificate hostname. 83 * 84 * <p><b>Warning</b>: Some methods on this class return connected sockets and some return 85 * unconnected sockets. For the methods that return connected sockets, setting 86 * connection- or handshake-related properties on those sockets will have no effect. 87 * 88 * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all 89 * SSL certificate and hostname checks for testing purposes. This setting 90 * requires root access. 91 * 92 * @deprecated This class has less error-prone replacements using standard APIs. To create an 93 * {@code SSLSocket}, obtain an {@link SSLSocketFactory} from {@link SSLSocketFactory#getDefault()} 94 * or {@link javax.net.ssl.SSLContext#getSocketFactory()}. To verify hostnames, pass 95 * {@code "HTTPS"} to 96 * {@link javax.net.ssl.SSLParameters#setEndpointIdentificationAlgorithm(String)}. To enable ALPN, 97 * use {@link javax.net.ssl.SSLParameters#setApplicationProtocols(String[])}. To enable SNI, 98 * use {@link javax.net.ssl.SSLParameters#setServerNames(java.util.List)}. 99 */ 100 @Deprecated 101 public class SSLCertificateSocketFactory extends SSLSocketFactory { 102 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 103 private static final String TAG = "SSLCertificateSocketFactory"; 104 105 @UnsupportedAppUsage 106 private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] { 107 new X509TrustManager() { 108 public X509Certificate[] getAcceptedIssuers() { return null; } 109 public void checkClientTrusted(X509Certificate[] certs, String authType) { } 110 public void checkServerTrusted(X509Certificate[] certs, String authType) { } 111 } 112 }; 113 114 @UnsupportedAppUsage 115 private SSLSocketFactory mInsecureFactory = null; 116 @UnsupportedAppUsage 117 private SSLSocketFactory mSecureFactory = null; 118 @UnsupportedAppUsage 119 private TrustManager[] mTrustManagers = null; 120 @UnsupportedAppUsage 121 private KeyManager[] mKeyManagers = null; 122 @UnsupportedAppUsage 123 private byte[] mNpnProtocols = null; 124 @UnsupportedAppUsage 125 private byte[] mAlpnProtocols = null; 126 @UnsupportedAppUsage 127 private PrivateKey mChannelIdPrivateKey = null; 128 129 @UnsupportedAppUsage 130 private final int mHandshakeTimeoutMillis; 131 @UnsupportedAppUsage 132 private final SSLClientSessionCache mSessionCache; 133 @UnsupportedAppUsage 134 private final boolean mSecure; 135 136 /** @deprecated Use {@link #getDefault(int)} instead. */ 137 @Deprecated SSLCertificateSocketFactory(int handshakeTimeoutMillis)138 public SSLCertificateSocketFactory(int handshakeTimeoutMillis) { 139 this(handshakeTimeoutMillis, null, true); 140 } 141 142 @UnsupportedAppUsage SSLCertificateSocketFactory( int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure)143 private SSLCertificateSocketFactory( 144 int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure) { 145 mHandshakeTimeoutMillis = handshakeTimeoutMillis; 146 mSessionCache = cache == null ? null : cache.mSessionCache; 147 mSecure = secure; 148 } 149 150 /** 151 * Returns a new socket factory instance with an optional handshake timeout. 152 * 153 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 154 * for none. The socket timeout is reset to 0 after the handshake. 155 * @return a new SSLSocketFactory with the specified parameters 156 */ getDefault(int handshakeTimeoutMillis)157 public static SocketFactory getDefault(int handshakeTimeoutMillis) { 158 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, null, true); 159 } 160 161 /** 162 * Returns a new socket factory instance with an optional handshake timeout 163 * and SSL session cache. 164 * 165 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 166 * for none. The socket timeout is reset to 0 after the handshake. 167 * @param cache The {@link SSLSessionCache} to use, or null for no cache. 168 * @return a new SSLSocketFactory with the specified parameters 169 */ getDefault(int handshakeTimeoutMillis, SSLSessionCache cache)170 public static SSLSocketFactory getDefault(int handshakeTimeoutMillis, SSLSessionCache cache) { 171 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true); 172 } 173 174 /** 175 * Returns a new instance of a socket factory with all SSL security checks 176 * disabled, using an optional handshake timeout and SSL session cache. 177 * 178 * <p class="caution"><b>Warning:</b> Sockets created using this factory 179 * are vulnerable to man-in-the-middle attacks!</p> 180 * 181 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 182 * for none. The socket timeout is reset to 0 after the handshake. 183 * @param cache The {@link SSLSessionCache} to use, or null for no cache. 184 * @return an insecure SSLSocketFactory with the specified parameters 185 */ getInsecure(int handshakeTimeoutMillis, SSLSessionCache cache)186 public static SSLSocketFactory getInsecure(int handshakeTimeoutMillis, SSLSessionCache cache) { 187 return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, false); 188 } 189 190 /** 191 * Returns a socket factory (also named SSLSocketFactory, but in a different 192 * namespace) for use with the Apache HTTP stack. 193 * 194 * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 195 * for none. The socket timeout is reset to 0 after the handshake. 196 * @param cache The {@link SSLSessionCache} to use, or null for no cache. 197 * @return a new SocketFactory with the specified parameters 198 * 199 * @deprecated Use {@link #getDefault()} along with a {@link javax.net.ssl.HttpsURLConnection} 200 * instead. The Apache HTTP client is no longer maintained and may be removed in a future 201 * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 202 * for further details. 203 * 204 * @removed 205 */ 206 @Deprecated getHttpSocketFactory( int handshakeTimeoutMillis, SSLSessionCache cache)207 public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory( 208 int handshakeTimeoutMillis, SSLSessionCache cache) { 209 return new org.apache.http.conn.ssl.SSLSocketFactory( 210 new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true)); 211 } 212 213 /** 214 * Verify the hostname of the certificate used by the other end of a connected socket using the 215 * {@link HostnameVerifier} obtained from {@code 216 * HttpsURLConnection.getDefaultHostnameVerifier()}. You MUST call this if you did not supply a 217 * hostname to {@link #createSocket()}. It is harmless to call this method redundantly if the 218 * hostname has already been verified. 219 * 220 * <p>Wildcard certificates are allowed to verify any matching hostname, so 221 * "foo.bar.example.com" is verified if the peer has a certificate for "*.example.com". 222 * 223 * @param socket An SSL socket which has been connected to a server 224 * @param hostname The expected hostname of the remote server 225 * @throws IOException if something goes wrong handshaking with the server 226 * @throws SSLPeerUnverifiedException if the server cannot prove its identity 227 * 228 * @hide 229 */ 230 @UnsupportedAppUsage verifyHostname(Socket socket, String hostname)231 public static void verifyHostname(Socket socket, String hostname) throws IOException { 232 if (!(socket instanceof SSLSocket)) { 233 throw new IllegalArgumentException("Attempt to verify non-SSL socket"); 234 } 235 236 if (!isSslCheckRelaxed()) { 237 // The code at the start of OpenSSLSocketImpl.startHandshake() 238 // ensures that the call is idempotent, so we can safely call it. 239 SSLSocket ssl = (SSLSocket) socket; 240 ssl.startHandshake(); 241 242 SSLSession session = ssl.getSession(); 243 if (session == null) { 244 throw new SSLException("Cannot verify SSL socket without session"); 245 } 246 if (!HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session)) { 247 throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname); 248 } 249 } 250 } 251 252 @UnsupportedAppUsage makeSocketFactory( KeyManager[] keyManagers, TrustManager[] trustManagers)253 private SSLSocketFactory makeSocketFactory( 254 KeyManager[] keyManagers, TrustManager[] trustManagers) { 255 try { 256 SSLContext sslContext = SSLContext.getInstance("TLS", "AndroidOpenSSL"); 257 sslContext.init(keyManagers, trustManagers, null); 258 ((ClientSessionContext) sslContext.getClientSessionContext()) 259 .setPersistentCache(mSessionCache); 260 return sslContext.getSocketFactory(); 261 } catch (KeyManagementException | NoSuchAlgorithmException | NoSuchProviderException e) { 262 Log.wtf(TAG, e); 263 return (SSLSocketFactory) SSLSocketFactory.getDefault(); // Fallback 264 } 265 } 266 267 @UnsupportedAppUsage isSslCheckRelaxed()268 private static boolean isSslCheckRelaxed() { 269 return RoSystemProperties.DEBUGGABLE && 270 SystemProperties.getBoolean("socket.relaxsslcheck", false); 271 } 272 273 @UnsupportedAppUsage getDelegate()274 private synchronized SSLSocketFactory getDelegate() { 275 // Relax the SSL check if instructed (for this factory, or systemwide) 276 if (!mSecure || isSslCheckRelaxed()) { 277 if (mInsecureFactory == null) { 278 if (mSecure) { 279 Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***"); 280 } else { 281 Log.w(TAG, "Bypassing SSL security checks at caller's request"); 282 } 283 mInsecureFactory = makeSocketFactory(mKeyManagers, INSECURE_TRUST_MANAGER); 284 } 285 return mInsecureFactory; 286 } else { 287 if (mSecureFactory == null) { 288 mSecureFactory = makeSocketFactory(mKeyManagers, mTrustManagers); 289 } 290 return mSecureFactory; 291 } 292 } 293 294 /** 295 * Sets the {@link TrustManager}s to be used for connections made by this factory. 296 */ setTrustManagers(TrustManager[] trustManager)297 public void setTrustManagers(TrustManager[] trustManager) { 298 mTrustManagers = trustManager; 299 300 // Clear out all cached secure factories since configurations have changed. 301 mSecureFactory = null; 302 // Note - insecure factories only ever use the INSECURE_TRUST_MANAGER so they need not 303 // be cleared out here. 304 } 305 306 /** 307 * Sets the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next 308 * Protocol Negotiation (NPN)</a> protocols that this peer is interested in. 309 * 310 * <p>For servers this is the sequence of protocols to advertise as 311 * supported, in order of preference. This list is sent unencrypted to 312 * all clients that support NPN. 313 * 314 * <p>For clients this is a list of supported protocols to match against the 315 * server's list. If there is no protocol supported by both client and 316 * server then the first protocol in the client's list will be selected. 317 * The order of the client's protocols is otherwise insignificant. 318 * 319 * @param npnProtocols a non-empty list of protocol byte arrays. All arrays 320 * must be non-empty and of length less than 256. 321 */ setNpnProtocols(byte[][] npnProtocols)322 public void setNpnProtocols(byte[][] npnProtocols) { 323 this.mNpnProtocols = toLengthPrefixedList(npnProtocols); 324 } 325 326 /** 327 * Sets the 328 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01"> 329 * Application Layer Protocol Negotiation (ALPN)</a> protocols that this peer 330 * is interested in. 331 * 332 * <p>For servers this is the sequence of protocols to advertise as 333 * supported, in order of preference. This list is sent unencrypted to 334 * all clients that support ALPN. 335 * 336 * <p>For clients this is a list of supported protocols to match against the 337 * server's list. If there is no protocol supported by both client and 338 * server then the first protocol in the client's list will be selected. 339 * The order of the client's protocols is otherwise insignificant. 340 * 341 * @param protocols a non-empty list of protocol byte arrays. All arrays 342 * must be non-empty and of length less than 256. 343 * @hide 344 */ 345 @UnsupportedAppUsage setAlpnProtocols(byte[][] protocols)346 public void setAlpnProtocols(byte[][] protocols) { 347 this.mAlpnProtocols = toLengthPrefixedList(protocols); 348 } 349 350 /** 351 * Returns an array containing the concatenation of length-prefixed byte 352 * strings. 353 * @hide 354 */ 355 @VisibleForTesting toLengthPrefixedList(byte[]... items)356 public static byte[] toLengthPrefixedList(byte[]... items) { 357 if (items.length == 0) { 358 throw new IllegalArgumentException("items.length == 0"); 359 } 360 int totalLength = 0; 361 for (byte[] s : items) { 362 if (s.length == 0 || s.length > 255) { 363 throw new IllegalArgumentException("s.length == 0 || s.length > 255: " + s.length); 364 } 365 totalLength += 1 + s.length; 366 } 367 byte[] result = new byte[totalLength]; 368 int pos = 0; 369 for (byte[] s : items) { 370 result[pos++] = (byte) s.length; 371 for (byte b : s) { 372 result[pos++] = b; 373 } 374 } 375 return result; 376 } 377 378 /** 379 * Returns the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next 380 * Protocol Negotiation (NPN)</a> protocol selected by client and server, or 381 * null if no protocol was negotiated. 382 * 383 * @param socket a socket created by this factory. 384 * @throws IllegalArgumentException if the socket was not created by this factory. 385 */ getNpnSelectedProtocol(Socket socket)386 public byte[] getNpnSelectedProtocol(Socket socket) { 387 return castToOpenSSLSocket(socket).getNpnSelectedProtocol(); 388 } 389 390 /** 391 * Returns the 392 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">Application 393 * Layer Protocol Negotiation (ALPN)</a> protocol selected by client and server, or null 394 * if no protocol was negotiated. 395 * 396 * @param socket a socket created by this factory. 397 * @throws IllegalArgumentException if the socket was not created by this factory. 398 * @hide 399 */ 400 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) getAlpnSelectedProtocol(Socket socket)401 public byte[] getAlpnSelectedProtocol(Socket socket) { 402 return castToOpenSSLSocket(socket).getAlpnSelectedProtocol(); 403 } 404 405 /** 406 * Sets the {@link KeyManager}s to be used for connections made by this factory. 407 */ setKeyManagers(KeyManager[] keyManagers)408 public void setKeyManagers(KeyManager[] keyManagers) { 409 mKeyManagers = keyManagers; 410 411 // Clear out any existing cached factories since configurations have changed. 412 mSecureFactory = null; 413 mInsecureFactory = null; 414 } 415 416 /** 417 * Sets the private key to be used for TLS Channel ID by connections made by this 418 * factory. 419 * 420 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 421 * TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the 422 * NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 423 * 424 * @hide 425 */ 426 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) setChannelIdPrivateKey(PrivateKey privateKey)427 public void setChannelIdPrivateKey(PrivateKey privateKey) { 428 mChannelIdPrivateKey = privateKey; 429 } 430 431 /** 432 * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a> 433 * support on the given socket. 434 * 435 * @param socket a socket created by this factory 436 * @param useSessionTickets {@code true} to enable session ticket support on this socket. 437 * @throws IllegalArgumentException if the socket was not created by this factory. 438 */ setUseSessionTickets(Socket socket, boolean useSessionTickets)439 public void setUseSessionTickets(Socket socket, boolean useSessionTickets) { 440 castToOpenSSLSocket(socket).setUseSessionTickets(useSessionTickets); 441 } 442 443 /** 444 * Turns on <a href="http://tools.ietf.org/html/rfc6066#section-3">Server 445 * Name Indication (SNI)</a> on a given socket. 446 * 447 * @param socket a socket created by this factory. 448 * @param hostName the desired SNI hostname, null to disable. 449 * @throws IllegalArgumentException if the socket was not created by this factory. 450 */ setHostname(Socket socket, String hostName)451 public void setHostname(Socket socket, String hostName) { 452 castToOpenSSLSocket(socket).setHostname(hostName); 453 } 454 455 /** 456 * Sets this socket's SO_SNDTIMEO write timeout in milliseconds. 457 * Use 0 for no timeout. 458 * To take effect, this option must be set before the blocking method was called. 459 * 460 * @param socket a socket created by this factory. 461 * @param timeout the desired write timeout in milliseconds. 462 * @throws IllegalArgumentException if the socket was not created by this factory. 463 * 464 * @hide 465 */ 466 @UnsupportedAppUsage setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)467 public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds) 468 throws SocketException { 469 castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds); 470 } 471 472 @UnsupportedAppUsage castToOpenSSLSocket(Socket socket)473 private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) { 474 if (!(socket instanceof OpenSSLSocketImpl)) { 475 throw new IllegalArgumentException("Socket not created by this factory: " 476 + socket); 477 } 478 479 return (OpenSSLSocketImpl) socket; 480 } 481 482 /** 483 * {@inheritDoc} 484 * 485 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 486 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 487 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 488 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 489 * instead. 490 */ 491 @Override createSocket(Socket k, String host, int port, boolean close)492 public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException { 493 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close); 494 s.setNpnProtocols(mNpnProtocols); 495 s.setAlpnProtocols(mAlpnProtocols); 496 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 497 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 498 if (mSecure) { 499 verifyHostname(s, host); 500 } 501 return s; 502 } 503 504 /** 505 * Creates a new socket which is <i>not connected</i> to any remote host. 506 * You must use {@link Socket#connect} to connect the socket. 507 * 508 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 509 * with this method. You MUST verify the server's identity after connecting 510 * the socket to avoid man-in-the-middle attacks.</p> 511 */ 512 @Override createSocket()513 public Socket createSocket() throws IOException { 514 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(); 515 s.setNpnProtocols(mNpnProtocols); 516 s.setAlpnProtocols(mAlpnProtocols); 517 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 518 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 519 return s; 520 } 521 522 /** 523 * {@inheritDoc} 524 * 525 * <p>This method returns a socket that is <i>not connected</i>. 526 * 527 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 528 * with this method. You MUST verify the server's identity after connecting 529 * the socket to avoid man-in-the-middle attacks.</p> 530 */ 531 @Override createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)532 public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort) 533 throws IOException { 534 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 535 addr, port, localAddr, localPort); 536 s.setNpnProtocols(mNpnProtocols); 537 s.setAlpnProtocols(mAlpnProtocols); 538 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 539 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 540 return s; 541 } 542 543 /** 544 * {@inheritDoc} 545 * 546 * <p>This method returns a socket that is <i>not connected</i>. 547 * 548 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 549 * with this method. You MUST verify the server's identity after connecting 550 * the socket to avoid man-in-the-middle attacks.</p> 551 */ 552 @Override createSocket(InetAddress addr, int port)553 public Socket createSocket(InetAddress addr, int port) throws IOException { 554 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port); 555 s.setNpnProtocols(mNpnProtocols); 556 s.setAlpnProtocols(mAlpnProtocols); 557 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 558 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 559 return s; 560 } 561 562 /** 563 * {@inheritDoc} 564 * 565 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 566 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 567 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 568 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 569 * instead. 570 */ 571 @Override createSocket(String host, int port, InetAddress localAddr, int localPort)572 public Socket createSocket(String host, int port, InetAddress localAddr, int localPort) 573 throws IOException { 574 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 575 host, port, localAddr, localPort); 576 s.setNpnProtocols(mNpnProtocols); 577 s.setAlpnProtocols(mAlpnProtocols); 578 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 579 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 580 if (mSecure) { 581 verifyHostname(s, host); 582 } 583 return s; 584 } 585 586 /** 587 * {@inheritDoc} 588 * 589 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 590 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 591 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 592 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 593 * instead. 594 */ 595 @Override createSocket(String host, int port)596 public Socket createSocket(String host, int port) throws IOException { 597 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port); 598 s.setNpnProtocols(mNpnProtocols); 599 s.setAlpnProtocols(mAlpnProtocols); 600 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 601 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 602 if (mSecure) { 603 verifyHostname(s, host); 604 } 605 return s; 606 } 607 608 @Override getDefaultCipherSuites()609 public String[] getDefaultCipherSuites() { 610 return getDelegate().getDefaultCipherSuites(); 611 } 612 613 @Override getSupportedCipherSuites()614 public String[] getSupportedCipherSuites() { 615 return getDelegate().getSupportedCipherSuites(); 616 } 617 } 618