19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.InetAddress; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.KeyManagementException; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.cert.X509Certificate; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.SocketFactory; 297fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HostnameVerifier; 307fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HttpsURLConnection; 311b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komaloimport javax.net.ssl.KeyManager; 327fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLException; 337fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLPeerUnverifiedException; 347fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLSession; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocket; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocketFactory; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.TrustManager; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.X509TrustManager; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 403c7c351a6217ac48b741740167c201a679a0ca65Brian Carlstromimport org.apache.harmony.xnet.provider.jsse.OpenSSLContextImpl; 4160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnorimport org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 4560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * SSLSocketFactory implementation with several extra features: 467fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 4760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <ul> 4860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Timeout specification for SSL handshake operations 497fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <li>Hostname verification in most cases (see WARNINGs below) 5060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Optional SSL session caching with {@link SSLSessionCache} 519d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * <li>Optionally bypass all SSL certificate checks 5260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * </ul> 537fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 547fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * The handshake timeout does not apply to actual TCP socket connection. 557fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * If you want a connection timeout as well, use {@link #createSocket()} 567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * and {@link Socket#connect(SocketAddress, int)}, after which you 577fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * must verify the identity of the server you are connected to. 587fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 597fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not 607fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * verify the server's identity, allowing man-in-the-middle attacks.</b> 617fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * This implementation does check the server's certificate hostname, but only 627fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * for createSocket variants that specify a hostname. When using methods that 637fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * use {@link InetAddress} or which return an unconnected socket, you MUST 647fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * verify the server's identity yourself to ensure a secure connection.</p> 657fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 667fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>One way to verify the server's identity is to use 677fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a 687fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HostnameVerifier} to verify the certificate hostname. 697fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 707fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all 717fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * SSL certificate and hostname checks for testing purposes. This setting 727fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * requires root access. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SSLCertificateSocketFactory extends SSLSocketFactory { 7560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private static final String TAG = "SSLCertificateSocketFactory"; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new X509TrustManager() { 7960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public X509Certificate[] getAcceptedIssuers() { return null; } 8060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public void checkClientTrusted(X509Certificate[] certs, String authType) { } 8160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public void checkServerTrusted(X509Certificate[] certs, String authType) { } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 857fc93c36ae235115727296780dbc35101622bbd4Dan Egnor private static final HostnameVerifier HOSTNAME_VERIFIER = 867fc93c36ae235115727296780dbc35101622bbd4Dan Egnor HttpsURLConnection.getDefaultHostnameVerifier(); 877fc93c36ae235115727296780dbc35101622bbd4Dan Egnor 8860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private SSLSocketFactory mInsecureFactory = null; 8960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private SSLSocketFactory mSecureFactory = null; 901b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo private TrustManager[] mTrustManagers = null; 911b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo private KeyManager[] mKeyManagers = null; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private final int mHandshakeTimeoutMillis; 9460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private final SSLClientSessionCache mSessionCache; 959d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor private final boolean mSecure; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor /** @deprecated Use {@link #getDefault(int)} instead. */ 9828c742573ccaeb55c16bc02fb25fdd86b8d1f76aJesse Wilson @Deprecated 9960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public SSLCertificateSocketFactory(int handshakeTimeoutMillis) { 1009d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor this(handshakeTimeoutMillis, null, true); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor private SSLCertificateSocketFactory( 1049d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure) { 10560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor mHandshakeTimeoutMillis = handshakeTimeoutMillis; 10660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor mSessionCache = cache == null ? null : cache.mSessionCache; 1079d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor mSecure = secure; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1119d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * Returns a new socket factory instance with an optional handshake timeout. 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 11460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * for none. The socket timeout is reset to 0 after the handshake. 1157fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @return a new SSLSocketFactory with the specified parameters 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public static SocketFactory getDefault(int handshakeTimeoutMillis) { 1189d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor return new SSLCertificateSocketFactory(handshakeTimeoutMillis, null, true); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1229d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * Returns a new socket factory instance with an optional handshake timeout 1239d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * and SSL session cache. 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 12660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * for none. The socket timeout is reset to 0 after the handshake. 127ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson * @param cache The {@link SSLSessionCache} to use, or null for no cache. 1287fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @return a new SSLSocketFactory with the specified parameters 12960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor */ 1309d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor public static SSLSocketFactory getDefault(int handshakeTimeoutMillis, SSLSessionCache cache) { 1319d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true); 1329d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor } 1339d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor 1349d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor /** 1359d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * Returns a new instance of a socket factory with all SSL security checks 1369d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * disabled, using an optional handshake timeout and SSL session cache. 1377fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 1387fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Warning:</b> Sockets created using this factory 1397fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * are vulnerable to man-in-the-middle attacks!</p> 1409d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * 1419d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 1429d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * for none. The socket timeout is reset to 0 after the handshake. 143ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson * @param cache The {@link SSLSessionCache} to use, or null for no cache. 1447fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @return an insecure SSLSocketFactory with the specified parameters 1459d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor */ 1469d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor public static SSLSocketFactory getInsecure(int handshakeTimeoutMillis, SSLSessionCache cache) { 1479d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, false); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor /** 15160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * Returns a socket factory (also named SSLSocketFactory, but in a different 15260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * namespace) for use with the Apache HTTP stack. 15360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * 15460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0 15560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * for none. The socket timeout is reset to 0 after the handshake. 156ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson * @param cache The {@link SSLSessionCache} to use, or null for no cache. 15760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @return a new SocketFactory with the specified parameters 15860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor */ 15960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory( 160ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson int handshakeTimeoutMillis, SSLSessionCache cache) { 16160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return new org.apache.http.conn.ssl.SSLSocketFactory( 1629d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true)); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1657fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 1667fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * Verify the hostname of the certificate used by the other end of a 1677fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * connected socket. You MUST call this if you did not supply a hostname 1687fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * to {@link #createSocket()}. It is harmless to call this method 1697fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * redundantly if the hostname has already been verified. 1707fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 1717fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>Wildcard certificates are allowed to verify any matching hostname, 1727fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * so "foo.bar.example.com" is verified if the peer has a certificate 1737fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * for "*.example.com". 1747fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 1757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @param socket An SSL socket which has been connected to a server 1767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @param hostname The expected hostname of the remote server 1777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @throws IOException if something goes wrong handshaking with the server 1787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @throws SSLPeerUnverifiedException if the server cannot prove its identity 1797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 1807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * @hide 1817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 1827fc93c36ae235115727296780dbc35101622bbd4Dan Egnor public static void verifyHostname(Socket socket, String hostname) throws IOException { 1837fc93c36ae235115727296780dbc35101622bbd4Dan Egnor if (!(socket instanceof SSLSocket)) { 1847fc93c36ae235115727296780dbc35101622bbd4Dan Egnor throw new IllegalArgumentException("Attempt to verify non-SSL socket"); 1857fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 1867fc93c36ae235115727296780dbc35101622bbd4Dan Egnor 1877fc93c36ae235115727296780dbc35101622bbd4Dan Egnor if (!isSslCheckRelaxed()) { 1887fc93c36ae235115727296780dbc35101622bbd4Dan Egnor // The code at the start of OpenSSLSocketImpl.startHandshake() 1897fc93c36ae235115727296780dbc35101622bbd4Dan Egnor // ensures that the call is idempotent, so we can safely call it. 1907fc93c36ae235115727296780dbc35101622bbd4Dan Egnor SSLSocket ssl = (SSLSocket) socket; 1917fc93c36ae235115727296780dbc35101622bbd4Dan Egnor ssl.startHandshake(); 1927fc93c36ae235115727296780dbc35101622bbd4Dan Egnor 1937fc93c36ae235115727296780dbc35101622bbd4Dan Egnor SSLSession session = ssl.getSession(); 1947fc93c36ae235115727296780dbc35101622bbd4Dan Egnor if (session == null) { 1957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor throw new SSLException("Cannot verify SSL socket without session"); 1967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 1977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor if (!HOSTNAME_VERIFIER.verify(hostname, session)) { 1987fc93c36ae235115727296780dbc35101622bbd4Dan Egnor throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname); 1997fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 2007fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 2017fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 2027fc93c36ae235115727296780dbc35101622bbd4Dan Egnor 2031b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo private SSLSocketFactory makeSocketFactory( 2041b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo KeyManager[] keyManagers, TrustManager[] trustManagers) { 20560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor try { 2063c7c351a6217ac48b741740167c201a679a0ca65Brian Carlstrom OpenSSLContextImpl sslContext = new OpenSSLContextImpl(); 2071b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo sslContext.engineInit(keyManagers, trustManagers, null); 2082c42c8fbaf02be1f3ea6298077128d0c419526f0Brian Carlstrom sslContext.engineGetClientSessionContext().setPersistentCache(mSessionCache); 20960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return sslContext.engineGetSocketFactory(); 21060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor } catch (KeyManagementException e) { 21160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor Log.wtf(TAG, e); 21260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return (SSLSocketFactory) SSLSocketFactory.getDefault(); // Fallback 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2167fc93c36ae235115727296780dbc35101622bbd4Dan Egnor private static boolean isSslCheckRelaxed() { 2177fc93c36ae235115727296780dbc35101622bbd4Dan Egnor return "1".equals(SystemProperties.get("ro.debuggable")) && 2187fc93c36ae235115727296780dbc35101622bbd4Dan Egnor "yes".equals(SystemProperties.get("socket.relaxsslcheck")); 2197fc93c36ae235115727296780dbc35101622bbd4Dan Egnor } 2207fc93c36ae235115727296780dbc35101622bbd4Dan Egnor 22160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor private synchronized SSLSocketFactory getDelegate() { 2229d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor // Relax the SSL check if instructed (for this factory, or systemwide) 2237fc93c36ae235115727296780dbc35101622bbd4Dan Egnor if (!mSecure || isSslCheckRelaxed()) { 22460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor if (mInsecureFactory == null) { 2259d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor if (mSecure) { 2269d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***"); 2279d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor } else { 2289d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor Log.w(TAG, "Bypassing SSL security checks at caller's request"); 2299d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor } 2301b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mInsecureFactory = makeSocketFactory(mKeyManagers, INSECURE_TRUST_MANAGER); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return mInsecureFactory; 23360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor } else { 23460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor if (mSecureFactory == null) { 2351b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mSecureFactory = makeSocketFactory(mKeyManagers, mTrustManagers); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return mSecureFactory; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2417fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 2421b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo * Sets the {@link TrustManager}s to be used for connections made by this factory. 2431b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo */ 2441b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo public void setTrustManagers(TrustManager[] trustManager) { 2451b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mTrustManagers = trustManager; 2461b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo 2471b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo // Clear out all cached secure factories since configurations have changed. 2481b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mSecureFactory = null; 2491b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo // Note - insecure factories only ever use the INSECURE_TRUST_MANAGER so they need not 2501b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo // be cleared out here. 2511b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo } 2521b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo 2531b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo /** 2541b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo * Sets the {@link KeyManager}s to be used for connections made by this factory. 2551b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo */ 2561b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo public void setKeyManagers(KeyManager[] keyManagers) { 2571b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mKeyManagers = keyManagers; 2581b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo 2591b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo // Clear out any existing cached factories since configurations have changed. 2601b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mSecureFactory = null; 2611b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo mInsecureFactory = null; 2621b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo } 2631b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo 2641b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo 2651b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo /** 2667fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@inheritDoc} 2677fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 268df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * <p>This method verifies the peer's certificate hostname after connecting 269df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * (unless created with {@link #getInsecure(int, SSLSessionCache)}). 2707fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 27160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 27260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException { 27360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close); 27460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 275df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler if (mSecure) { 276df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler verifyHostname(s, host); 277df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler } 27860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 2827fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * Creates a new socket which is not connected to any remote host. 2837fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * You must use {@link Socket#connect} to connect the socket. 2847fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 2857fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Warning:</b> Hostname verification is not performed 2867fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * with this method. You MUST verify the server's identity after connecting 2877fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * the socket to avoid man-in-the-middle attacks.</p> 2887fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 28960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 29060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket() throws IOException { 29160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(); 29260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 29360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 2977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@inheritDoc} 2987fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 2997fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Warning:</b> Hostname verification is not performed 3007fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * with this method. You MUST verify the server's identity after connecting 3017fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * the socket to avoid man-in-the-middle attacks.</p> 3027fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 30360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 30460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort) 30560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor throws IOException { 30660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 30760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor addr, port, localAddr, localPort); 30860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 30960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3127fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 3137fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@inheritDoc} 3147fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 3157fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Warning:</b> Hostname verification is not performed 3167fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * with this method. You MUST verify the server's identity after connecting 3177fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * the socket to avoid man-in-the-middle attacks.</p> 3187fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 31960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 32060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket(InetAddress addr, int port) throws IOException { 32160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port); 32260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 32360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3267fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 3277fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@inheritDoc} 3287fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 329df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * <p>This method verifies the peer's certificate hostname after connecting 330df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * (unless created with {@link #getInsecure(int, SSLSessionCache)}). 3317fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 33260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 33360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket(String host, int port, InetAddress localAddr, int localPort) 33460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor throws IOException { 33560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket( 33660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor host, port, localAddr, localPort); 33760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 338df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler if (mSecure) { 339df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler verifyHostname(s, host); 340df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler } 34160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 34260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3447fc93c36ae235115727296780dbc35101622bbd4Dan Egnor /** 3457fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@inheritDoc} 3467fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * 347df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * <p>This method verifies the peer's certificate hostname after connecting 348df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler * (unless created with {@link #getInsecure(int, SSLSessionCache)}). 3497fc93c36ae235115727296780dbc35101622bbd4Dan Egnor */ 35060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 35160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public Socket createSocket(String host, int port) throws IOException { 35260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port); 35360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor s.setHandshakeTimeout(mHandshakeTimeoutMillis); 354df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler if (mSecure) { 355df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler verifyHostname(s, host); 356df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler } 35760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return s; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String[] getDefaultCipherSuites() { 36260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return getDelegate().getSupportedCipherSuites(); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor @Override 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String[] getSupportedCipherSuites() { 36760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return getDelegate().getSupportedCipherSuites(); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 370