1
0
mirror of https://github.com/square/okhttp.git synced 2026-01-18 20:40:58 +03:00

Merge pull request #1073 from square/jwilson_1005_cipher_suites

Take control of the enabled cipher suites.
This commit is contained in:
Jesse Wilson
2014-10-10 20:38:40 -04:00
2 changed files with 65 additions and 0 deletions

View File

@@ -17,6 +17,7 @@
package com.squareup.okhttp;
import com.squareup.okhttp.internal.Platform;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.http.HttpConnection;
import com.squareup.okhttp.internal.http.HttpEngine;
import com.squareup.okhttp.internal.http.HttpTransport;
@@ -28,10 +29,14 @@ import java.io.IOException;
import java.net.Proxy;
import java.net.Socket;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSocket;
import static com.squareup.okhttp.internal.Util.getDefaultPort;
import static com.squareup.okhttp.internal.Util.getEffectivePort;
import static com.squareup.okhttp.internal.Util.immutableList;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
@@ -62,6 +67,39 @@ import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
* should the attempt fail.
*/
public final class Connection {
/**
* This is a subset of the cipher suites supported in Chrome 37, current as of 2014-10-5. All of
* these suites are available on Android L; earlier releases support a subset of these suites.
* https://github.com/square/okhttp/issues/330
*/
private static final List<String> CIPHER_SUITES = immutableList(
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // 0xC0,0x2B Android L
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // 0xC0,0x2F Android L
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", // 0x00,0x9E Android L
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", // 0xC0,0x0A Android 4.0
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // 0xC0,0x09 Android 4.0
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // 0xC0,0x13 Android 4.0
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", // 0xC0,0x14 Android 4.0
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", // 0xC0,0x07 Android 4.0
"TLS_ECDHE_RSA_WITH_RC4_128_SHA", // 0xC0,0x11 Android 4.0
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA", // 0x00,0x33 Android 2.3
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA", // 0x00,0x32 Android 2.3
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA", // 0x00,0x39 Android 2.3
"TLS_RSA_WITH_AES_128_GCM_SHA256", // 0x00,0x9C
"TLS_RSA_WITH_AES_128_CBC_SHA", // 0x00,0x2F Android 2.3
"TLS_RSA_WITH_AES_256_CBC_SHA", // 0x00,0x35 Android 2.3
"SSL_RSA_WITH_3DES_EDE_CBC_SHA", // 0x00,0x0A Android 2.3 (Deprecated in L)
"SSL_RSA_WITH_RC4_128_SHA", // 0x00,0x05 Android 2.3
"SSL_RSA_WITH_RC4_128_MD5" // 0x00,0x04 Android 2.3 (Deprecated in L)
);
/**
* Cache of the intersection between {@link #CIPHER_SUITES} and the platform's supported suites.
* It's possible that the platform hosts multiple implementations of {@link SSLSocket}, in which
* case this cache will be incorrect.
*/
private static final AtomicReference<String[]> SELECTED_CIPHER_SUITES = new AtomicReference<>();
private final ConnectionPool pool;
private final Route route;
@@ -227,6 +265,7 @@ public final class Connection {
socket = route.address.sslSocketFactory
.createSocket(socket, route.address.uriHost, route.address.uriPort, true /* autoClose */);
SSLSocket sslSocket = (SSLSocket) socket;
sslSocket.setEnabledCipherSuites(cipherSuites(sslSocket));
platform.configureTls(sslSocket, route.address.uriHost, route.tlsVersion);
boolean useNpn = route.supportsNpn();
@@ -259,6 +298,17 @@ public final class Connection {
}
}
private String[] cipherSuites(SSLSocket sslSocket) {
String[] result = SELECTED_CIPHER_SUITES.get();
if (result == null) {
List<String> intersection = Util.intersect(CIPHER_SUITES,
Arrays.asList(sslSocket.getSupportedCipherSuites()));
result = intersection.toArray(new String[intersection.size()]);
SELECTED_CIPHER_SUITES.set(result);
}
return result;
}
/** Returns true if {@link #connect} has been attempted on this connection. */
boolean isConnected() {
return connected;

View File

@@ -31,6 +31,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ThreadFactory;
@@ -229,4 +230,18 @@ public final class Util {
}
private static final RetryableSink EMPTY_SINK = new RetryableSink(0);
/**
* Returns a copy of {@code a} containing only elements also in {@code b}. The returned elements
* are in the same order as in {@code a}.
*/
public static <T> List<T> intersect(Collection<T> a, Collection<T> b) {
List<T> result = new ArrayList<>();
for (T t : a) {
if (b.contains(t)) {
result.add(t);
}
}
return Collections.unmodifiableList(result);
}
}