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