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.compat.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 308 * <a class="external" href="https://tools.ietf.org/id/draft-agl-tls-nextprotoneg-03.html">Next 309 * Protocol Negotiation (NPN)</a> protocols that this peer is interested in. 310 * 311 * <p>For servers this is the sequence of protocols to advertise as 312 * supported, in order of preference. This list is sent unencrypted to 313 * all clients that support NPN. 314 * 315 * <p>For clients this is a list of supported protocols to match against the 316 * server's list. If there is no protocol supported by both client and 317 * server then the first protocol in the client's list will be selected. 318 * The order of the client's protocols is otherwise insignificant. 319 * 320 * @param npnProtocols a non-empty list of protocol byte arrays. All arrays 321 * must be non-empty and of length less than 256. 322 */ setNpnProtocols(byte[][] npnProtocols)323 public void setNpnProtocols(byte[][] npnProtocols) { 324 this.mNpnProtocols = toLengthPrefixedList(npnProtocols); 325 } 326 327 /** 328 * Sets the 329 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01"> 330 * Application Layer Protocol Negotiation (ALPN)</a> protocols that this peer 331 * is interested in. 332 * 333 * <p>For servers this is the sequence of protocols to advertise as 334 * supported, in order of preference. This list is sent unencrypted to 335 * all clients that support ALPN. 336 * 337 * <p>For clients this is a list of supported protocols to match against the 338 * server's list. If there is no protocol supported by both client and 339 * server then the first protocol in the client's list will be selected. 340 * The order of the client's protocols is otherwise insignificant. 341 * 342 * @param protocols a non-empty list of protocol byte arrays. All arrays 343 * must be non-empty and of length less than 256. 344 * @hide 345 */ 346 @UnsupportedAppUsage setAlpnProtocols(byte[][] protocols)347 public void setAlpnProtocols(byte[][] protocols) { 348 this.mAlpnProtocols = toLengthPrefixedList(protocols); 349 } 350 351 /** 352 * Returns an array containing the concatenation of length-prefixed byte 353 * strings. 354 * @hide 355 */ 356 @VisibleForTesting toLengthPrefixedList(byte[]... items)357 public static byte[] toLengthPrefixedList(byte[]... items) { 358 if (items.length == 0) { 359 throw new IllegalArgumentException("items.length == 0"); 360 } 361 int totalLength = 0; 362 for (byte[] s : items) { 363 if (s.length == 0 || s.length > 255) { 364 throw new IllegalArgumentException("s.length == 0 || s.length > 255: " + s.length); 365 } 366 totalLength += 1 + s.length; 367 } 368 byte[] result = new byte[totalLength]; 369 int pos = 0; 370 for (byte[] s : items) { 371 result[pos++] = (byte) s.length; 372 for (byte b : s) { 373 result[pos++] = b; 374 } 375 } 376 return result; 377 } 378 379 /** 380 * Returns the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next 381 * Protocol Negotiation (NPN)</a> protocol selected by client and server, or 382 * null if no protocol was negotiated. 383 * 384 * @param socket a socket created by this factory. 385 * @throws IllegalArgumentException if the socket was not created by this factory. 386 */ getNpnSelectedProtocol(Socket socket)387 public byte[] getNpnSelectedProtocol(Socket socket) { 388 return castToOpenSSLSocket(socket).getNpnSelectedProtocol(); 389 } 390 391 /** 392 * Returns the 393 * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">Application 394 * Layer Protocol Negotiation (ALPN)</a> protocol selected by client and server, or null 395 * if no protocol was negotiated. 396 * 397 * @param socket a socket created by this factory. 398 * @throws IllegalArgumentException if the socket was not created by this factory. 399 * @hide 400 */ 401 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) getAlpnSelectedProtocol(Socket socket)402 public byte[] getAlpnSelectedProtocol(Socket socket) { 403 return castToOpenSSLSocket(socket).getAlpnSelectedProtocol(); 404 } 405 406 /** 407 * Sets the {@link KeyManager}s to be used for connections made by this factory. 408 */ setKeyManagers(KeyManager[] keyManagers)409 public void setKeyManagers(KeyManager[] keyManagers) { 410 mKeyManagers = keyManagers; 411 412 // Clear out any existing cached factories since configurations have changed. 413 mSecureFactory = null; 414 mInsecureFactory = null; 415 } 416 417 /** 418 * Sets the private key to be used for TLS Channel ID by connections made by this 419 * factory. 420 * 421 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 422 * TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the 423 * NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 424 * 425 * @hide 426 */ 427 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) setChannelIdPrivateKey(PrivateKey privateKey)428 public void setChannelIdPrivateKey(PrivateKey privateKey) { 429 mChannelIdPrivateKey = privateKey; 430 } 431 432 /** 433 * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a> 434 * support on the given socket. 435 * 436 * @param socket a socket created by this factory 437 * @param useSessionTickets {@code true} to enable session ticket support on this socket. 438 * @throws IllegalArgumentException if the socket was not created by this factory. 439 */ setUseSessionTickets(Socket socket, boolean useSessionTickets)440 public void setUseSessionTickets(Socket socket, boolean useSessionTickets) { 441 castToOpenSSLSocket(socket).setUseSessionTickets(useSessionTickets); 442 } 443 444 /** 445 * Turns on <a href="http://tools.ietf.org/html/rfc6066#section-3">Server 446 * Name Indication (SNI)</a> on a given socket. 447 * 448 * @param socket a socket created by this factory. 449 * @param hostName the desired SNI hostname, null to disable. 450 * @throws IllegalArgumentException if the socket was not created by this factory. 451 */ setHostname(Socket socket, String hostName)452 public void setHostname(Socket socket, String hostName) { 453 castToOpenSSLSocket(socket).setHostname(hostName); 454 } 455 456 /** 457 * Sets this socket's SO_SNDTIMEO write timeout in milliseconds. 458 * Use 0 for no timeout. 459 * To take effect, this option must be set before the blocking method was called. 460 * 461 * @param socket a socket created by this factory. 462 * @param timeout the desired write timeout in milliseconds. 463 * @throws IllegalArgumentException if the socket was not created by this factory. 464 * 465 * @hide 466 */ 467 @UnsupportedAppUsage setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)468 public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds) 469 throws SocketException { 470 castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds); 471 } 472 473 @UnsupportedAppUsage castToOpenSSLSocket(Socket socket)474 private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) { 475 if (!(socket instanceof OpenSSLSocketImpl)) { 476 throw new IllegalArgumentException("Socket not created by this factory: " 477 + socket); 478 } 479 480 return (OpenSSLSocketImpl) socket; 481 } 482 483 /** 484 * {@inheritDoc} 485 * 486 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 487 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 488 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 489 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 490 * instead. 491 */ 492 @Override createSocket(Socket k, String host, int port, boolean close)493 public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException { 494 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close); 495 s.setNpnProtocols(mNpnProtocols); 496 s.setAlpnProtocols(mAlpnProtocols); 497 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 498 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 499 if (mSecure) { 500 verifyHostname(s, host); 501 } 502 return s; 503 } 504 505 /** 506 * Creates a new socket which is <i>not connected</i> to any remote host. 507 * You must use {@link Socket#connect} to connect the socket. 508 * 509 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 510 * with this method. You MUST verify the server's identity after connecting 511 * the socket to avoid man-in-the-middle attacks.</p> 512 */ 513 @Override createSocket()514 public Socket createSocket() throws IOException { 515 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(); 516 s.setNpnProtocols(mNpnProtocols); 517 s.setAlpnProtocols(mAlpnProtocols); 518 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 519 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 520 return s; 521 } 522 523 /** 524 * {@inheritDoc} 525 * 526 * <p>This method returns a socket that is <i>not connected</i>. 527 * 528 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 529 * with this method. You MUST verify the server's identity after connecting 530 * the socket to avoid man-in-the-middle attacks.</p> 531 */ 532 @Override createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)533 public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort) 534 throws IOException { 535 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 536 addr, port, localAddr, localPort); 537 s.setNpnProtocols(mNpnProtocols); 538 s.setAlpnProtocols(mAlpnProtocols); 539 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 540 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 541 return s; 542 } 543 544 /** 545 * {@inheritDoc} 546 * 547 * <p>This method returns a socket that is <i>not connected</i>. 548 * 549 * <p class="caution"><b>Warning:</b> Hostname verification is not performed 550 * with this method. You MUST verify the server's identity after connecting 551 * the socket to avoid man-in-the-middle attacks.</p> 552 */ 553 @Override createSocket(InetAddress addr, int port)554 public Socket createSocket(InetAddress addr, int port) throws IOException { 555 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port); 556 s.setNpnProtocols(mNpnProtocols); 557 s.setAlpnProtocols(mAlpnProtocols); 558 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 559 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 560 return s; 561 } 562 563 /** 564 * {@inheritDoc} 565 * 566 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 567 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 568 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 569 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 570 * instead. 571 */ 572 @Override createSocket(String host, int port, InetAddress localAddr, int localPort)573 public Socket createSocket(String host, int port, InetAddress localAddr, int localPort) 574 throws IOException { 575 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 576 host, port, localAddr, localPort); 577 s.setNpnProtocols(mNpnProtocols); 578 s.setAlpnProtocols(mAlpnProtocols); 579 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 580 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 581 if (mSecure) { 582 verifyHostname(s, host); 583 } 584 return s; 585 } 586 587 /** 588 * {@inheritDoc} 589 * 590 * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's 591 * certificate hostname after connecting using the {@link HostnameVerifier} obtained from 592 * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with 593 * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i> 594 * instead. 595 */ 596 @Override createSocket(String host, int port)597 public Socket createSocket(String host, int port) throws IOException { 598 OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port); 599 s.setNpnProtocols(mNpnProtocols); 600 s.setAlpnProtocols(mAlpnProtocols); 601 s.setHandshakeTimeout(mHandshakeTimeoutMillis); 602 s.setChannelIdPrivateKey(mChannelIdPrivateKey); 603 if (mSecure) { 604 verifyHostname(s, host); 605 } 606 return s; 607 } 608 609 @Override getDefaultCipherSuites()610 public String[] getDefaultCipherSuites() { 611 return getDelegate().getDefaultCipherSuites(); 612 } 613 614 @Override getSupportedCipherSuites()615 public String[] getSupportedCipherSuites() { 616 return getDelegate().getSupportedCipherSuites(); 617 } 618 } 619