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;
3834c0b2ee11c237be5244eecc34814862b3003822Dan Egnorimport javax.net.ssl.HostnameVerifier;
3934c0b2ee11c237be5244eecc34814862b3003822Dan Egnorimport javax.net.ssl.HttpsURLConnection;
4034c0b2ee11c237be5244eecc34814862b3003822Dan Egnorimport javax.net.ssl.SSLException;
4134c0b2ee11c237be5244eecc34814862b3003822Dan Egnorimport javax.net.ssl.SSLPeerUnverifiedException;
4234c0b2ee11c237be5244eecc34814862b3003822Dan 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:
5634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor *
5760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <ul>
5860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Timeout specification for SSL handshake operations
5934c0b2ee11c237be5244eecc34814862b3003822Dan 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>
6334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor *
6434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * The handshake timeout does not apply to actual TCP socket connection.
6534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * If you want a connection timeout as well, use {@link #createSocket()}
6634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * and {@link Socket#connect(SocketAddress, int)}, after which you
6734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * must verify the identity of the server you are connected to.
6834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor *
6934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not
7034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * verify the server's identity, allowing man-in-the-middle attacks.</b>
7134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * This implementation does check the server's certificate hostname, but only
7234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * for createSocket variants that specify a hostname.  When using methods that
7334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * use {@link InetAddress} or which return an unconnected socket, you MUST
7434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * verify the server's identity yourself to ensure a secure connection.</p>
7534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor *
7634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * <p>One way to verify the server's identity is to use
7734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
7834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * {@link HostnameVerifier} to verify the certificate hostname.
7934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor *
8034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
8134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor * SSL certificate and hostname checks for testing purposes.  This setting
8234c0b2ee11c237be5244eecc34814862b3003822Dan 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
9534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    private static final HostnameVerifier HOSTNAME_VERIFIER =
9634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        HttpsURLConnection.getDefaultHostnameVerifier();
9734c0b2ee11c237be5244eecc34814862b3003822Dan 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.
12234c0b2ee11c237be5244eecc34814862b3003822Dan 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.
13534c0b2ee11c237be5244eecc34814862b3003822Dan 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.
14434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
14534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * <p class="caution"><b>Warning:</b> Sockets created using this factory
14634c0b2ee11c237be5244eecc34814862b3003822Dan 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.
15134c0b2ee11c237be5244eecc34814862b3003822Dan 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
17334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
17434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * Verify the hostname of the certificate used by the other end of a
17534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * connected socket.  You MUST call this if you did not supply a hostname
17634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * to {@link #createSocket()}.  It is harmless to call this method
17734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * redundantly if the hostname has already been verified.
17834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
17934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * <p>Wildcard certificates are allowed to verify any matching hostname,
18034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * so "foo.bar.example.com" is verified if the peer has a certificate
18134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * for "*.example.com".
18234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
18334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * @param socket An SSL socket which has been connected to a server
18434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * @param hostname The expected hostname of the remote server
18534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * @throws IOException if something goes wrong handshaking with the server
18634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * @throws SSLPeerUnverifiedException if the server cannot prove its identity
18734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
18834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * @hide
18934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
19034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    public static void verifyHostname(Socket socket, String hostname) throws IOException {
19134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        if (!(socket instanceof SSLSocket)) {
19234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            throw new IllegalArgumentException("Attempt to verify non-SSL socket");
19334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        }
19434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor
19534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        if (!isSslCheckRelaxed()) {
19634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            // The code at the start of OpenSSLSocketImpl.startHandshake()
19734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            // ensures that the call is idempotent, so we can safely call it.
19834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            SSLSocket ssl = (SSLSocket) socket;
19934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            ssl.startHandshake();
20034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor
20134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            SSLSession session = ssl.getSession();
20234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            if (session == null) {
20334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor                throw new SSLException("Cannot verify SSL socket without session");
20434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            }
20534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
20634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor                throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
20734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            }
20834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        }
20934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    }
21034c0b2ee11c237be5244eecc34814862b3003822Dan 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
22234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    private static boolean isSslCheckRelaxed() {
22334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor        return "1".equals(SystemProperties.get("ro.debuggable")) &&
22434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor            "yes".equals(SystemProperties.get("socket.relaxsslcheck"));
22534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    }
22634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor
22760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private synchronized SSLSocketFactory getDelegate() {
2289d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        // Relax the SSL check if instructed (for this factory, or systemwide)
22934c0b2ee11c237be5244eecc34814862b3003822Dan 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
24734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
24834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * {@inheritDoc}
24934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
250f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
251f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
25234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
25360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
25460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
25560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
25660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
257f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        if (mSecure) {
258f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler            verifyHostname(s, host);
259f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        }
26060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
26434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * Creates a new socket which is not connected to any remote host.
26534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * You must use {@link Socket#connect} to connect the socket.
26634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
26734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
26834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
26934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
27034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
27160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
27260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket() throws IOException {
27360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
27460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
27560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
27934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * {@inheritDoc}
28034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
28134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
28234c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
28334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
28434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
28560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
28660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)
28760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
28860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
28960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                addr, port, localAddr, localPort);
29060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
29160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29434c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
29534c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * {@inheritDoc}
29634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
29734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
29834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
29934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
30034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
30160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
30260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port) throws IOException {
30360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
30460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
30560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
30934c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * {@inheritDoc}
31034c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
311f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
312f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
31334c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
31460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
31560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
31660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
31760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
31860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                host, port, localAddr, localPort);
31960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
320f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        if (mSecure) {
321f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler            verifyHostname(s, host);
322f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        }
32360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
32460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32634c0b2ee11c237be5244eecc34814862b3003822Dan Egnor    /**
32734c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     * {@inheritDoc}
32834c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     *
329f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
330f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
33134c0b2ee11c237be5244eecc34814862b3003822Dan Egnor     */
33260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
33360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port) throws IOException {
33460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
33560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
336f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        if (mSecure) {
337f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler            verifyHostname(s, host);
338f1f07993792dbf2d49613d474a696ec0927828d2Andrew Stadler        }
33960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getDefaultCipherSuites() {
34460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return getDelegate().getSupportedCipherSuites();
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getSupportedCipherSuites() {
34960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return getDelegate().getSupportedCipherSuites();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
352