SSLCertificateSocketFactory.java revision 7fc93c36ae235115727296780dbc35101622bbd4
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
192269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.net.DomainNameValidator;
202269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackborn
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
258f028a94fc533e75077485a7d11a04e4de820335Makoto Onuki
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.InetAddress;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.GeneralSecurityException;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.KeyManagementException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.KeyStore;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.KeyStoreException;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.NoSuchAlgorithmException;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.cert.Certificate;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.cert.X509Certificate;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.SocketFactory;
387fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HostnameVerifier;
397fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HttpsURLConnection;
407fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLException;
417fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLPeerUnverifiedException;
427fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLSession;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocket;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocketFactory;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.TrustManager;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.TrustManagerFactory;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.X509TrustManager;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnorimport org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
52e97c2006bf7c391c933307e520a392e532aa5d6aBob Leeimport org.apache.harmony.xnet.provider.jsse.SSLParameters;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
5560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * SSLSocketFactory implementation with several extra features:
567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
5760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <ul>
5860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Timeout specification for SSL handshake operations
597fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <li>Hostname verification in most cases (see WARNINGs below)
6060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Optional SSL session caching with {@link SSLSessionCache}
619d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * <li>Optionally bypass all SSL certificate checks
6260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * </ul>
637fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
647fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * The handshake timeout does not apply to actual TCP socket connection.
657fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * If you want a connection timeout as well, use {@link #createSocket()}
667fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * and {@link Socket#connect(SocketAddress, int)}, after which you
677fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * must verify the identity of the server you are connected to.
687fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
697fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not
707fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * verify the server's identity, allowing man-in-the-middle attacks.</b>
717fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * This implementation does check the server's certificate hostname, but only
727fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * for createSocket variants that specify a hostname.  When using methods that
737fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * use {@link InetAddress} or which return an unconnected socket, you MUST
747fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * verify the server's identity yourself to ensure a secure connection.</p>
757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>One way to verify the server's identity is to use
777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HostnameVerifier} to verify the certificate hostname.
797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * SSL certificate and hostname checks for testing purposes.  This setting
827fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * requires root access.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SSLCertificateSocketFactory extends SSLSocketFactory {
8560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private static final String TAG = "SSLCertificateSocketFactory";
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new X509TrustManager() {
8960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public X509Certificate[] getAcceptedIssuers() { return null; }
9060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
9160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public void checkServerTrusted(X509Certificate[] certs, String authType) { }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    private static final HostnameVerifier HOSTNAME_VERIFIER =
967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        HttpsURLConnection.getDefaultHostnameVerifier();
977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
9860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private SSLSocketFactory mInsecureFactory = null;
9960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private SSLSocketFactory mSecureFactory = null;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private final int mHandshakeTimeoutMillis;
10260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private final SSLClientSessionCache mSessionCache;
1039d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    private final boolean mSecure;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    /** @deprecated Use {@link #getDefault(int)} instead. */
10660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public SSLCertificateSocketFactory(int handshakeTimeoutMillis) {
1079d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        this(handshakeTimeoutMillis, null, true);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    private SSLCertificateSocketFactory(
1119d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor            int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure) {
11260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        mHandshakeTimeoutMillis = handshakeTimeoutMillis;
11360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        mSessionCache = cache == null ? null : cache.mSessionCache;
1149d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        mSecure = secure;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1189d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * Returns a new socket factory instance with an optional handshake timeout.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
12160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     *         for none.  The socket timeout is reset to 0 after the handshake.
1227fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @return a new SSLSocketFactory with the specified parameters
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public static SocketFactory getDefault(int handshakeTimeoutMillis) {
1259d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        return new SSLCertificateSocketFactory(handshakeTimeoutMillis, null, true);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1299d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * Returns a new socket factory instance with an optional handshake timeout
1309d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * and SSL session cache.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
13360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     *         for none.  The socket timeout is reset to 0 after the handshake.
13460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @param cache The {@link SSLClientSessionCache} to use, or null for no cache.
1357fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @return a new SSLSocketFactory with the specified parameters
13660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     */
1379d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    public static SSLSocketFactory getDefault(int handshakeTimeoutMillis, SSLSessionCache cache) {
1389d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true);
1399d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    }
1409d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor
1419d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    /**
1429d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * Returns a new instance of a socket factory with all SSL security checks
1439d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * disabled, using an optional handshake timeout and SSL session cache.
1447fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1457fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Sockets created using this factory
1467fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * are vulnerable to man-in-the-middle attacks!</p>
1479d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     *
1489d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
1499d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     *         for none.  The socket timeout is reset to 0 after the handshake.
1509d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     * @param cache The {@link SSLClientSessionCache} to use, or null for no cache.
1517fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @return an insecure SSLSocketFactory with the specified parameters
1529d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor     */
1539d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    public static SSLSocketFactory getInsecure(int handshakeTimeoutMillis, SSLSessionCache cache) {
1549d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, false);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    /**
15860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * Returns a socket factory (also named SSLSocketFactory, but in a different
15960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * namespace) for use with the Apache HTTP stack.
16060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     *
16160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
16260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     *         for none.  The socket timeout is reset to 0 after the handshake.
16360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @param cache The {@link SSLClientSessionCache} to use, or null for no cache.
16460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @return a new SocketFactory with the specified parameters
16560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     */
16660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
16760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            int handshakeTimeoutMillis,
16860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            SSLSessionCache cache) {
16960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return new org.apache.http.conn.ssl.SSLSocketFactory(
1709d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true));
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1737fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
1747fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * Verify the hostname of the certificate used by the other end of a
1757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * connected socket.  You MUST call this if you did not supply a hostname
1767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * to {@link #createSocket()}.  It is harmless to call this method
1777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * redundantly if the hostname has already been verified.
1787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p>Wildcard certificates are allowed to verify any matching hostname,
1807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * so "foo.bar.example.com" is verified if the peer has a certificate
1817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * for "*.example.com".
1827fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1837fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @param socket An SSL socket which has been connected to a server
1847fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @param hostname The expected hostname of the remote server
1857fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @throws IOException if something goes wrong handshaking with the server
1867fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @throws SSLPeerUnverifiedException if the server cannot prove its identity
1877fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1887fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @hide
1897fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
1907fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    public static void verifyHostname(Socket socket, String hostname) throws IOException {
1917fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!(socket instanceof SSLSocket)) {
1927fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            throw new IllegalArgumentException("Attempt to verify non-SSL socket");
1937fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        }
1947fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
1957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!isSslCheckRelaxed()) {
1967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            // The code at the start of OpenSSLSocketImpl.startHandshake()
1977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            // ensures that the call is idempotent, so we can safely call it.
1987fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            SSLSocket ssl = (SSLSocket) socket;
1997fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            ssl.startHandshake();
2007fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
2017fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            SSLSession session = ssl.getSession();
2027fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            if (session == null) {
2037fc93c36ae235115727296780dbc35101622bbd4Dan Egnor                throw new SSLException("Cannot verify SSL socket without session");
2047fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            }
2057fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
2067fc93c36ae235115727296780dbc35101622bbd4Dan Egnor                throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
2077fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            }
2087fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        }
2097fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    }
2107fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
21160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private SSLSocketFactory makeSocketFactory(TrustManager[] trustManagers) {
21260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        try {
21360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            SSLContextImpl sslContext = new SSLContextImpl();
21460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            sslContext.engineInit(null, trustManagers, null, mSessionCache, null);
21560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return sslContext.engineGetSocketFactory();
21660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        } catch (KeyManagementException e) {
21760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            Log.wtf(TAG, e);
21860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return (SSLSocketFactory) SSLSocketFactory.getDefault();  // Fallback
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2227fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    private static boolean isSslCheckRelaxed() {
2237fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        return "1".equals(SystemProperties.get("ro.debuggable")) &&
2247fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            "yes".equals(SystemProperties.get("socket.relaxsslcheck"));
2257fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    }
2267fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
22760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private synchronized SSLSocketFactory getDelegate() {
2289d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        // Relax the SSL check if instructed (for this factory, or systemwide)
2297fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!mSecure || isSslCheckRelaxed()) {
23060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            if (mInsecureFactory == null) {
2319d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                if (mSecure) {
2329d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                    Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***");
2339d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                } else {
2349d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                    Log.w(TAG, "Bypassing SSL security checks at caller's request");
2359d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                }
23660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                mInsecureFactory = makeSocketFactory(INSECURE_TRUST_MANAGER);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return mInsecureFactory;
23960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        } else {
24060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            if (mSecureFactory == null) {
24160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                mSecureFactory = makeSocketFactory(null);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return mSecureFactory;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2477fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
2487fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
2497fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
2507fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p>This method verifies the peer's certificate hostname after connecting.
2517fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
25260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
25360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
25460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
25560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
2567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        verifyHostname(s, host);
25760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2607fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
2617fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * Creates a new socket which is not connected to any remote host.
2627fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * You must use {@link Socket#connect} to connect the socket.
2637fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
2647fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
2657fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
2667fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
2677fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
26860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
26960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket() throws IOException {
27060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
27160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
27260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
2767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
2777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
2787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
2797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
2807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
2817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
28260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
28360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)
28460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
28560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
28660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                addr, port, localAddr, localPort);
28760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
28860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2917fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
2927fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
2937fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
2947fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
2957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
2967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
2977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
29860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
29960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port) throws IOException {
30060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
30160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
30260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3057fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
3067fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
3077fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
3087fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p>This method verifies the peer's certificate hostname after connecting.
3097fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
31060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
31160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
31260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
31360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
31460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                host, port, localAddr, localPort);
31560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
3167fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        verifyHostname(s, host);
31760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
31860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3207fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
3217fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
3227fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
3237fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p>This method verifies the peer's certificate hostname after connecting.
3247fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
32560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
32660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port) throws IOException {
32760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
32860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
3297fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        verifyHostname(s, host);
33060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getDefaultCipherSuites() {
33560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return getDelegate().getSupportedCipherSuites();
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getSupportedCipherSuites() {
34060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return getDelegate().getSupportedCipherSuites();
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
343