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;
21ed065024a59cf008ba711ff79e223ed99cb8b7c5John Reck
22ed065024a59cf008ba711ff79e223ed99cb8b7c5John Reckimport com.android.internal.os.RoSystemProperties;
237fdce769c3ef3885ec8f1716bdeedfc8b056a1d7Kenny Rootimport com.android.org.conscrypt.Conscrypt;
2412e752225aa96888358294be0d725d499a1c9f03Kenny Rootimport com.android.org.conscrypt.OpenSSLContextImpl;
2512e752225aa96888358294be0d725d499a1c9f03Kenny Rootimport com.android.org.conscrypt.OpenSSLSocketImpl;
2612e752225aa96888358294be0d725d499a1c9f03Kenny Rootimport com.android.org.conscrypt.SSLClientSessionCache;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.InetAddress;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket;
307ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstromimport java.net.SocketException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.KeyManagementException;
32ac5eb03a7c317e21573155b88641f4f1daef2eb9Alex Klyubinimport java.security.PrivateKey;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.security.cert.X509Certificate;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.SocketFactory;
357fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HostnameVerifier;
367fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.HttpsURLConnection;
371b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komaloimport javax.net.ssl.KeyManager;
387fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLException;
397fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLPeerUnverifiedException;
407fc93c36ae235115727296780dbc35101622bbd4Dan Egnorimport javax.net.ssl.SSLSession;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocket;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.SSLSocketFactory;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.TrustManager;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport javax.net.ssl.X509TrustManager;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * SSLSocketFactory implementation with several extra features:
487fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
4960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <ul>
5060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Timeout specification for SSL handshake operations
517fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <li>Hostname verification in most cases (see WARNINGs below)
5260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * <li>Optional SSL session caching with {@link SSLSessionCache}
539d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor * <li>Optionally bypass all SSL certificate checks
5460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * </ul>
557fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * The handshake timeout does not apply to actual TCP socket connection.
577fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * If you want a connection timeout as well, use {@link #createSocket()}
587fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * and {@link Socket#connect(SocketAddress, int)}, after which you
597fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * must verify the identity of the server you are connected to.
607fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
617fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not
627fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * verify the server's identity, allowing man-in-the-middle attacks.</b>
637fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * This implementation does check the server's certificate hostname, but only
647fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * for createSocket variants that specify a hostname.  When using methods that
657fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * use {@link InetAddress} or which return an unconnected socket, you MUST
66f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody * verify the server's identity yourself to ensure a secure connection.
67f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody *
68f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody * Refer to
69f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody * <a href="https://developer.android.com/training/articles/security-gms-provider.html">
70f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody * Updating Your Security Provider to Protect Against SSL Exploits</a>
71f72e8263c7e08d3e4a04de29c17bbada2bd2829aJonathan Dormody * for further information.</p>
727fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
737fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>One way to verify the server's identity is to use
747fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * {@link HostnameVerifier} to verify the certificate hostname.
767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor *
777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * SSL certificate and hostname checks for testing purposes.  This setting
797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor * requires root access.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SSLCertificateSocketFactory extends SSLSocketFactory {
8260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private static final String TAG = "SSLCertificateSocketFactory";
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new X509TrustManager() {
8660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public X509Certificate[] getAcceptedIssuers() { return null; }
8760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
8860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            public void checkServerTrusted(X509Certificate[] certs, String authType) { }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private SSLSocketFactory mInsecureFactory = null;
9360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private SSLSocketFactory mSecureFactory = null;
941b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    private TrustManager[] mTrustManagers = null;
951b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    private KeyManager[] mKeyManagers = null;
96f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    private byte[] mNpnProtocols = null;
97100d7290264338c6536739abd59879aaaa812537Kenny Root    private byte[] mAlpnProtocols = null;
98ac5eb03a7c317e21573155b88641f4f1daef2eb9Alex Klyubin    private PrivateKey mChannelIdPrivateKey = null;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private final int mHandshakeTimeoutMillis;
10160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private final SSLClientSessionCache mSessionCache;
1029d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor    private final boolean mSecure;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    /** @deprecated Use {@link #getDefault(int)} instead. */
10528c742573ccaeb55c16bc02fb25fdd86b8d1f76aJesse Wilson    @Deprecated
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(
111992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom            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.
134ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson     * @param cache The {@link SSLSessionCache} 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
146e19ca078bf1778a344366672de020e63a80252a9Kenny Root     * 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.
150ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson     * @param cache The {@link SSLSessionCache} 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.
163ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson     * @param cache The {@link SSLSessionCache} to use, or null for no cache.
16460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     * @return a new SocketFactory with the specified parameters
165823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath     *
166823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath     * @deprecated Use {@link #getDefault()} along with a {@link javax.net.ssl.HttpsURLConnection}
167823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath     *     instead. The Apache HTTP client is no longer maintained and may be removed in a future
168823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath     *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
169823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath     *     for further details.
170406e1ed9883010928cfb42246cfd2710ebf3da74Narayan Kamath     *
171406e1ed9883010928cfb42246cfd2710ebf3da74Narayan Kamath     * @removed
17260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor     */
173823675fdbb7f974b8e2fa9fbb71774b32487582dNarayan Kamath    @Deprecated
17460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
175ff5569948fda346d95d4615de6578f82d9614be3Jesse Wilson            int handshakeTimeoutMillis, SSLSessionCache cache) {
17660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return new org.apache.http.conn.ssl.SSLSocketFactory(
1779d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache, true));
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
1817fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * Verify the hostname of the certificate used by the other end of a
1827fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * connected socket.  You MUST call this if you did not supply a hostname
1837fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * to {@link #createSocket()}.  It is harmless to call this method
1847fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * redundantly if the hostname has already been verified.
1857fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1867fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p>Wildcard certificates are allowed to verify any matching hostname,
1877fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * so "foo.bar.example.com" is verified if the peer has a certificate
1887fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * for "*.example.com".
1897fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1907fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @param socket An SSL socket which has been connected to a server
1917fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @param hostname The expected hostname of the remote server
1927fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @throws IOException if something goes wrong handshaking with the server
1937fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @throws SSLPeerUnverifiedException if the server cannot prove its identity
1947fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
1957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * @hide
1967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
1977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    public static void verifyHostname(Socket socket, String hostname) throws IOException {
1987fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!(socket instanceof SSLSocket)) {
1997fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            throw new IllegalArgumentException("Attempt to verify non-SSL socket");
2007fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        }
2017fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
2027fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!isSslCheckRelaxed()) {
2037fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            // The code at the start of OpenSSLSocketImpl.startHandshake()
2047fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            // ensures that the call is idempotent, so we can safely call it.
2057fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            SSLSocket ssl = (SSLSocket) socket;
2067fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            ssl.startHandshake();
2077fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
2087fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            SSLSession session = ssl.getSession();
2097fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            if (session == null) {
2107fc93c36ae235115727296780dbc35101622bbd4Dan Egnor                throw new SSLException("Cannot verify SSL socket without session");
2117fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            }
212928ee1e48fa89302d02fdf8a8a2c7315d7195e7cKenny Root            if (!HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session)) {
2137fc93c36ae235115727296780dbc35101622bbd4Dan Egnor                throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
2147fc93c36ae235115727296780dbc35101622bbd4Dan Egnor            }
2157fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        }
2167fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    }
2177fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
2181b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    private SSLSocketFactory makeSocketFactory(
2191b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo            KeyManager[] keyManagers, TrustManager[] trustManagers) {
22060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        try {
2217fdce769c3ef3885ec8f1716bdeedfc8b056a1d7Kenny Root            OpenSSLContextImpl sslContext =  (OpenSSLContextImpl) Conscrypt.newPreferredSSLContextSpi();
2221b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo            sslContext.engineInit(keyManagers, trustManagers, null);
2232c42c8fbaf02be1f3ea6298077128d0c419526f0Brian Carlstrom            sslContext.engineGetClientSessionContext().setPersistentCache(mSessionCache);
22460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return sslContext.engineGetSocketFactory();
22560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        } catch (KeyManagementException e) {
22660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            Log.wtf(TAG, e);
22760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return (SSLSocketFactory) SSLSocketFactory.getDefault();  // Fallback
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2317fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    private static boolean isSslCheckRelaxed() {
232ed065024a59cf008ba711ff79e223ed99cb8b7c5John Reck        return RoSystemProperties.DEBUGGABLE &&
233ed065024a59cf008ba711ff79e223ed99cb8b7c5John Reck            SystemProperties.getBoolean("socket.relaxsslcheck", false);
2347fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    }
2357fc93c36ae235115727296780dbc35101622bbd4Dan Egnor
23660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    private synchronized SSLSocketFactory getDelegate() {
2379d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor        // Relax the SSL check if instructed (for this factory, or systemwide)
2387fc93c36ae235115727296780dbc35101622bbd4Dan Egnor        if (!mSecure || isSslCheckRelaxed()) {
23960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            if (mInsecureFactory == null) {
2409d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                if (mSecure) {
2419d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                    Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***");
242e19ca078bf1778a344366672de020e63a80252a9Kenny Root                } else {
243e19ca078bf1778a344366672de020e63a80252a9Kenny Root                    Log.w(TAG, "Bypassing SSL security checks at caller's request");
2449d4b57545300c6de1722094404ae09bf0f6be937Dan Egnor                }
2451b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo                mInsecureFactory = makeSocketFactory(mKeyManagers, INSECURE_TRUST_MANAGER);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return mInsecureFactory;
24860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        } else {
24960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            if (mSecureFactory == null) {
2501b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo                mSecureFactory = makeSocketFactory(mKeyManagers, mTrustManagers);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            return mSecureFactory;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
2571b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo     * Sets the {@link TrustManager}s to be used for connections made by this factory.
2581b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo     */
2591b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    public void setTrustManagers(TrustManager[] trustManager) {
2601b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        mTrustManagers = trustManager;
2611b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo
2621b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        // Clear out all cached secure factories since configurations have changed.
2631b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        mSecureFactory = null;
2641b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        // Note - insecure factories only ever use the INSECURE_TRUST_MANAGER so they need not
2651b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        // be cleared out here.
2661b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    }
2671b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo
2681b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    /**
269f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * Sets the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next
270f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * Protocol Negotiation (NPN)</a> protocols that this peer is interested in.
271f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     *
272f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * <p>For servers this is the sequence of protocols to advertise as
273f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * supported, in order of preference. This list is sent unencrypted to
274f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * all clients that support NPN.
275f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     *
276f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * <p>For clients this is a list of supported protocols to match against the
277f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * server's list. If there is no protocol supported by both client and
278f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * server then the first protocol in the client's list will be selected.
279f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * The order of the client's protocols is otherwise insignificant.
280f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     *
2812108ead7f125536874d6de6ca1c0c4cffbf61b44Jesse Wilson     * @param npnProtocols a non-empty list of protocol byte arrays. All arrays
2822108ead7f125536874d6de6ca1c0c4cffbf61b44Jesse Wilson     *     must be non-empty and of length less than 256.
283f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     */
284f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    public void setNpnProtocols(byte[][] npnProtocols) {
285100d7290264338c6536739abd59879aaaa812537Kenny Root        this.mNpnProtocols = toLengthPrefixedList(npnProtocols);
286100d7290264338c6536739abd59879aaaa812537Kenny Root    }
287100d7290264338c6536739abd59879aaaa812537Kenny Root
288100d7290264338c6536739abd59879aaaa812537Kenny Root    /**
289100d7290264338c6536739abd59879aaaa812537Kenny Root     * Sets the
290100d7290264338c6536739abd59879aaaa812537Kenny Root     * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">
291100d7290264338c6536739abd59879aaaa812537Kenny Root     * Application Layer Protocol Negotiation (ALPN)</a> protocols that this peer
292100d7290264338c6536739abd59879aaaa812537Kenny Root     * is interested in.
293100d7290264338c6536739abd59879aaaa812537Kenny Root     *
294100d7290264338c6536739abd59879aaaa812537Kenny Root     * <p>For servers this is the sequence of protocols to advertise as
295100d7290264338c6536739abd59879aaaa812537Kenny Root     * supported, in order of preference. This list is sent unencrypted to
296100d7290264338c6536739abd59879aaaa812537Kenny Root     * all clients that support ALPN.
297100d7290264338c6536739abd59879aaaa812537Kenny Root     *
298100d7290264338c6536739abd59879aaaa812537Kenny Root     * <p>For clients this is a list of supported protocols to match against the
299100d7290264338c6536739abd59879aaaa812537Kenny Root     * server's list. If there is no protocol supported by both client and
300100d7290264338c6536739abd59879aaaa812537Kenny Root     * server then the first protocol in the client's list will be selected.
301100d7290264338c6536739abd59879aaaa812537Kenny Root     * The order of the client's protocols is otherwise insignificant.
302100d7290264338c6536739abd59879aaaa812537Kenny Root     *
303100d7290264338c6536739abd59879aaaa812537Kenny Root     * @param protocols a non-empty list of protocol byte arrays. All arrays
304100d7290264338c6536739abd59879aaaa812537Kenny Root     *     must be non-empty and of length less than 256.
305100d7290264338c6536739abd59879aaaa812537Kenny Root     * @hide
306100d7290264338c6536739abd59879aaaa812537Kenny Root     */
307100d7290264338c6536739abd59879aaaa812537Kenny Root    public void setAlpnProtocols(byte[][] protocols) {
308100d7290264338c6536739abd59879aaaa812537Kenny Root        this.mAlpnProtocols = toLengthPrefixedList(protocols);
309f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    }
310f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson
311f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    /**
312f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * Returns an array containing the concatenation of length-prefixed byte
313f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * strings.
314f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     */
315100d7290264338c6536739abd59879aaaa812537Kenny Root    static byte[] toLengthPrefixedList(byte[]... items) {
316100d7290264338c6536739abd59879aaaa812537Kenny Root        if (items.length == 0) {
317100d7290264338c6536739abd59879aaaa812537Kenny Root            throw new IllegalArgumentException("items.length == 0");
3182108ead7f125536874d6de6ca1c0c4cffbf61b44Jesse Wilson        }
319f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        int totalLength = 0;
320100d7290264338c6536739abd59879aaaa812537Kenny Root        for (byte[] s : items) {
321f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            if (s.length == 0 || s.length > 255) {
322f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson                throw new IllegalArgumentException("s.length == 0 || s.length > 255: " + s.length);
323f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            }
324f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            totalLength += 1 + s.length;
325f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        }
326f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        byte[] result = new byte[totalLength];
327f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        int pos = 0;
328100d7290264338c6536739abd59879aaaa812537Kenny Root        for (byte[] s : items) {
329f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            result[pos++] = (byte) s.length;
330f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            for (byte b : s) {
331f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson                result[pos++] = b;
332f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson            }
333f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        }
334f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        return result;
335f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    }
336f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson
337f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    /**
338f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * Returns the <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next
339f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * Protocol Negotiation (NPN)</a> protocol selected by client and server, or
340f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * null if no protocol was negotiated.
341f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     *
342f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     * @param socket a socket created by this factory.
343b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @throws IllegalArgumentException if the socket was not created by this factory.
344f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson     */
345f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    public byte[] getNpnSelectedProtocol(Socket socket) {
346b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        return castToOpenSSLSocket(socket).getNpnSelectedProtocol();
347f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    }
348f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson
349f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson    /**
350100d7290264338c6536739abd59879aaaa812537Kenny Root     * Returns the
351100d7290264338c6536739abd59879aaaa812537Kenny Root     * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">Application
352100d7290264338c6536739abd59879aaaa812537Kenny Root     * Layer Protocol Negotiation (ALPN)</a> protocol selected by client and server, or null
353100d7290264338c6536739abd59879aaaa812537Kenny Root     * if no protocol was negotiated.
354100d7290264338c6536739abd59879aaaa812537Kenny Root     *
355100d7290264338c6536739abd59879aaaa812537Kenny Root     * @param socket a socket created by this factory.
356100d7290264338c6536739abd59879aaaa812537Kenny Root     * @throws IllegalArgumentException if the socket was not created by this factory.
357100d7290264338c6536739abd59879aaaa812537Kenny Root     * @hide
358100d7290264338c6536739abd59879aaaa812537Kenny Root     */
359100d7290264338c6536739abd59879aaaa812537Kenny Root    public byte[] getAlpnSelectedProtocol(Socket socket) {
360100d7290264338c6536739abd59879aaaa812537Kenny Root        return castToOpenSSLSocket(socket).getAlpnSelectedProtocol();
361100d7290264338c6536739abd59879aaaa812537Kenny Root    }
362100d7290264338c6536739abd59879aaaa812537Kenny Root
363100d7290264338c6536739abd59879aaaa812537Kenny Root    /**
3641b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo     * Sets the {@link KeyManager}s to be used for connections made by this factory.
3651b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo     */
3661b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    public void setKeyManagers(KeyManager[] keyManagers) {
3671b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        mKeyManagers = keyManagers;
3681b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo
3691b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        // Clear out any existing cached factories since configurations have changed.
3701b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        mSecureFactory = null;
3711b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo        mInsecureFactory = null;
3721b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    }
3731b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo
374b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    /**
375ac5eb03a7c317e21573155b88641f4f1daef2eb9Alex Klyubin     * Sets the private key to be used for TLS Channel ID by connections made by this
3764ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     * factory.
3774ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     *
3784ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
3794ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     *        TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the
3804ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     *        NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
3814ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     *
3824ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     * @hide
3834ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin     */
384ac5eb03a7c317e21573155b88641f4f1daef2eb9Alex Klyubin    public void setChannelIdPrivateKey(PrivateKey privateKey) {
3854ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        mChannelIdPrivateKey = privateKey;
3864ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin    }
3874ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin
3884ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin    /**
389b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a>
390b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * support on the given socket.
391b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     *
392b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @param socket a socket created by this factory
393b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @param useSessionTickets {@code true} to enable session ticket support on this socket.
394b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @throws IllegalArgumentException if the socket was not created by this factory.
395b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     */
396b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    public void setUseSessionTickets(Socket socket, boolean useSessionTickets) {
397b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        castToOpenSSLSocket(socket).setUseSessionTickets(useSessionTickets);
398b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    }
399b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath
400b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    /**
401b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * Turns on <a href="http://tools.ietf.org/html/rfc6066#section-3">Server
402b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * Name Indication (SNI)</a> on a given socket.
403b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     *
404b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @param socket a socket created by this factory.
405b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @param hostName the desired SNI hostname, null to disable.
406b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     * @throws IllegalArgumentException if the socket was not created by this factory.
407b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath     */
408b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    public void setHostname(Socket socket, String hostName) {
409b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        castToOpenSSLSocket(socket).setHostname(hostName);
410b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    }
411b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath
4127ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom    /**
4137ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     * Sets this socket's SO_SNDTIMEO write timeout in milliseconds.
4147ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     * Use 0 for no timeout.
4157ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     * To take effect, this option must be set before the blocking method was called.
4167ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     *
4177ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     * @param socket a socket created by this factory.
418992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom     * @param timeout the desired write timeout in milliseconds.
4197ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     * @throws IllegalArgumentException if the socket was not created by this factory.
420992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom     *
421992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom     * @hide
4227ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom     */
4237ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom    public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)
4247ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom            throws SocketException {
4257ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom        castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds);
4267ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom    }
4277ab7a8b582b29d34ec0fdbd0c727e225f350bb30Brian Carlstrom
428b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) {
429b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        if (!(socket instanceof OpenSSLSocketImpl)) {
430b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath            throw new IllegalArgumentException("Socket not created by this factory: "
431b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath                    + socket);
432b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        }
433b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath
434b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath        return (OpenSSLSocketImpl) socket;
435b4db962da0fecd9a6f2714148bbdea023610842fNarayan Kamath    }
4361b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo
4371b52806e21270ccbe90d27f3dd93cbee1a81d09eBen Komalo    /**
4387fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
4397fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
440df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
441df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
4427fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
44360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
44460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
44560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
446f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
447100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
44860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
4494ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
450df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        if (mSecure) {
451df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler            verifyHostname(s, host);
452df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        }
45360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4567fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
4577fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * Creates a new socket which is not connected to any remote host.
4587fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * You must use {@link Socket#connect} to connect the socket.
4597fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
4607fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
4617fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
4627fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
4637fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
46460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
46560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket() throws IOException {
46660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
467f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
468100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
46960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
4704ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
47160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4747fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
4757fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
4767fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
4777fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
4787fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
4797fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
4807fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
48160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
48260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)
48360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
48460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
48560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                addr, port, localAddr, localPort);
486f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
487100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
48860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
4894ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
49060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4937fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
4947fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
4957fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
4967fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * <p class="caution"><b>Warning:</b> Hostname verification is not performed
4977fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * with this method.  You MUST verify the server's identity after connecting
4987fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * the socket to avoid man-in-the-middle attacks.</p>
4997fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
50060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
50160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(InetAddress addr, int port) throws IOException {
50260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
503f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
504100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
50560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
5064ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
50760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5107fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
5117fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
5127fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
513df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
514df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
5157fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
51660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
51760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
51860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor            throws IOException {
51960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
52060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor                host, port, localAddr, localPort);
521f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
522100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
52360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
5244ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
525df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        if (mSecure) {
526df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler            verifyHostname(s, host);
527df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        }
52860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
52960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5317fc93c36ae235115727296780dbc35101622bbd4Dan Egnor    /**
5327fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     * {@inheritDoc}
5337fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     *
534df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * <p>This method verifies the peer's certificate hostname after connecting
535df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
5367fc93c36ae235115727296780dbc35101622bbd4Dan Egnor     */
53760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
53860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    public Socket createSocket(String host, int port) throws IOException {
53960586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
540f5fb5e80963abeabdf0ff10dcee068344235082eJesse Wilson        s.setNpnProtocols(mNpnProtocols);
541100d7290264338c6536739abd59879aaaa812537Kenny Root        s.setAlpnProtocols(mAlpnProtocols);
54260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
5434ef6c9b6a16c9b65699705aaa64977fc60dd3331Alex Klyubin        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
544df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        if (mSecure) {
545df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler            verifyHostname(s, host);
546df27c0c26209fe04de332497beafcafc1fbaad2bAndrew Stadler        }
54760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return s;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55060586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getDefaultCipherSuites() {
552019118af67c60448030540deca37d972c8839d38Alex Klyubin        return getDelegate().getDefaultCipherSuites();
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55560586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor    @Override
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getSupportedCipherSuites() {
55760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor        return getDelegate().getSupportedCipherSuites();
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
560