1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package com.squareup.okhttp;
19
20import java.net.Proxy;
21import java.util.Collections;
22import java.util.List;
23
24import javax.net.ssl.HttpsURLConnection;
25
26public final class HttpsHandler extends HttpHandler {
27
28    /**
29     * The connection spec to use when connecting to an https:// server. Note that Android does
30     * not set the cipher suites or TLS versions to use so the socket's defaults will be used
31     * instead. When the SSLSocketFactory is provided by the app or GMS core we will not
32     * override the enabled ciphers or TLS versions set on the sockets it produces with a
33     * list hardcoded at release time. This is deliberate.
34     */
35    private static final ConnectionSpec TLS_CONNECTION_SPEC = ConnectionSpecs.builder(true)
36            .allEnabledCipherSuites()
37            .allEnabledTlsVersions()
38            .supportsTlsExtensions(true)
39            .build();
40
41    private static final List<Protocol> HTTP_1_1_ONLY =
42            Collections.singletonList(Protocol.HTTP_1_1);
43
44    private final ConfigAwareConnectionPool configAwareConnectionPool =
45            ConfigAwareConnectionPool.getInstance();
46
47    @Override protected int getDefaultPort() {
48        return 443;
49    }
50
51    @Override
52    protected OkUrlFactory newOkUrlFactory(Proxy proxy) {
53        OkUrlFactory okUrlFactory = createHttpsOkUrlFactory(proxy);
54        // For HttpsURLConnections created through java.net.URL Android uses a connection pool that
55        // is aware when the default network changes so that pooled connections are not re-used when
56        // the default network changes.
57        okUrlFactory.client().setConnectionPool(configAwareConnectionPool.get());
58        return okUrlFactory;
59    }
60
61    /**
62     * Creates an OkHttpClient suitable for creating {@link HttpsURLConnection} instances on
63     * Android.
64     */
65    // Visible for android.net.Network.
66    public static OkUrlFactory createHttpsOkUrlFactory(Proxy proxy) {
67        // The HTTPS OkHttpClient is an HTTP OkHttpClient with extra configuration.
68        OkUrlFactory okUrlFactory = HttpHandler.createHttpOkUrlFactory(proxy);
69
70        // All HTTPS requests are allowed.
71        OkUrlFactories.setUrlFilter(okUrlFactory, null);
72
73        OkHttpClient okHttpClient = okUrlFactory.client();
74
75        // Only enable HTTP/1.1 (implies HTTP/1.0). Disable SPDY / HTTP/2.0.
76        okHttpClient.setProtocols(HTTP_1_1_ONLY);
77
78        okHttpClient.setConnectionSpecs(Collections.singletonList(TLS_CONNECTION_SPEC));
79
80        // Android support certificate pinning via NetworkSecurityConfig so there is no need to
81        // also expose OkHttp's mechanism. The OkHttpClient underlying https HttpsURLConnections
82        // in Android should therefore always use the default certificate pinner, whose set of
83        // {@code hostNamesToPin} is empty.
84        okHttpClient.setCertificatePinner(CertificatePinner.DEFAULT);
85
86        // OkHttp does not automatically honor the system-wide HostnameVerifier set with
87        // HttpsURLConnection.setDefaultHostnameVerifier().
88        okUrlFactory.client().setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier());
89        // OkHttp does not automatically honor the system-wide SSLSocketFactory set with
90        // HttpsURLConnection.setDefaultSSLSocketFactory().
91        // See https://github.com/square/okhttp/issues/184 for details.
92        okHttpClient.setSslSocketFactory(HttpsURLConnection.getDefaultSSLSocketFactory());
93
94        return okUrlFactory;
95    }
96}
97