public ConnectionSpec configureSecureSocket(SSLSocket sslSocket) throws IOException { ConnectionSpec tlsConfiguration = null; int size = this.connectionSpecs.size(); for (int i = this.nextModeIndex; i < size; i++) { ConnectionSpec connectionSpec = (ConnectionSpec) this.connectionSpecs.get(i); if (connectionSpec.isCompatible(sslSocket)) { tlsConfiguration = connectionSpec; this.nextModeIndex = i + 1; break; } } if (tlsConfiguration == null) { throw new UnknownServiceException("Unable to find acceptable protocols. isFallback=" + this.isFallback + ", modes=" + this.connectionSpecs + ", supported " + "protocols=" + Arrays.toString(sslSocket.getEnabledProtocols())); } this.isFallbackPossible = isFallbackPossible(sslSocket); Internal.instance.apply(tlsConfiguration, sslSocket, this.isFallback); return tlsConfiguration; }
/** * Enable TLS 1.2 on the OkHttpClient on API 16-21, which is supported but not enabled by default. * @link https://github.com/square/okhttp/issues/2372 * @see TLS12SocketFactory */ private void enforceTls12(OkHttpClient client) { // No need to modify client as TLS 1.2 is enabled by default on API21+ // Lollipop is included because some Samsung devices face the same problem on API 21. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { return; } try { SSLContext sc = SSLContext.getInstance("TLSv1.2"); sc.init(null, null, null); client.setSslSocketFactory(new TLS12SocketFactory(sc.getSocketFactory())); ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) .build(); List<ConnectionSpec> specs = new ArrayList<>(); specs.add(cs); specs.add(ConnectionSpec.COMPATIBLE_TLS); specs.add(ConnectionSpec.CLEARTEXT); client.setConnectionSpecs(specs); } catch (NoSuchAlgorithmException | KeyManagementException e) { Log.e(TAG, "Error while setting TLS 1.2", e); } }
private static void verifyTLS12Enforced(OkHttpClient client) { ArgumentCaptor<SSLSocketFactory> factoryCaptor = ArgumentCaptor.forClass(SSLSocketFactory.class); verify(client).setSslSocketFactory(factoryCaptor.capture()); assertTrue(factoryCaptor.getValue() instanceof TLS12SocketFactory); ArgumentCaptor<List> specCaptor = ArgumentCaptor.forClass(List.class); verify(client).setConnectionSpecs(specCaptor.capture()); boolean hasTls12 = false; for (Object item : specCaptor.getValue()) { assertTrue(item instanceof ConnectionSpec); ConnectionSpec spec = (ConnectionSpec) item; if (!spec.isTls()) { continue; } List<TlsVersion> versions = spec.tlsVersions(); for (TlsVersion version : versions) { if ("TLSv1.2".equals(version.javaName())) { hasTls12 = true; break; } } } assertTrue(hasTls12); }
private void resetConnectionSpecs() { this.connectionSpecs = new ArrayList(); List localList = this.address.connectionSpecs; int i = 0; int j = localList.size(); while (i < j) { ConnectionSpec localConnectionSpec = (ConnectionSpec)localList.get(i); if (this.request.isHttps() == localConnectionSpec.tls) { this.connectionSpecs.add(localConnectionSpec); } i++; } this.nextSpecIndex = 0; }
public final void connectFailed(Connection paramConnection, IOException paramIOException) { if (Internal.instance.recycleCount(paramConnection) > 0) {} for (;;) { return; Route localRoute1 = paramConnection.route; if ((localRoute1.proxy.type() != Proxy.Type.DIRECT) && (this.address.proxySelector != null)) { this.address.proxySelector.connectFailed(this.uri, localRoute1.proxy.address(), paramIOException); } this.routeDatabase.failed(localRoute1); if ((!(paramIOException instanceof SSLHandshakeException)) && (!(paramIOException instanceof SSLProtocolException))) { while (this.nextSpecIndex < this.connectionSpecs.size()) { List localList = this.connectionSpecs; int i = this.nextSpecIndex; this.nextSpecIndex = (i + 1); ConnectionSpec localConnectionSpec = (ConnectionSpec)localList.get(i); boolean bool = shouldSendTlsFallbackIndicator(localConnectionSpec); Route localRoute2 = new Route(this.address, this.lastProxy, this.lastInetSocketAddress, localConnectionSpec, bool); this.routeDatabase.failed(localRoute2); } } } }
@Override protected ManagedChannel createChannel() { try { final int port = server.getPort(); return OkHttpChannelBuilder .forAddress("localhost", port) .negotiationType(NegotiationType.TLS) .maxInboundMessageSize(16 * 1024 * 1024) .connectionSpec(ConnectionSpec.MODERN_TLS) .overrideAuthority("example.com:" + port) .sslSocketFactory(TestUtils.newSslSocketFactoryForCa( Platform.get().getProvider(), ssc.certificate())) .build(); } catch (Exception ex) { throw new RuntimeException(ex); } }
private OkHttpChannelBuilder createChannelBuilder() { OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("localhost", getPort()) .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) .connectionSpec(new ConnectionSpec.Builder(OkHttpChannelBuilder.DEFAULT_CONNECTION_SPEC) .cipherSuites(TestUtils.preferredTestCiphers().toArray(new String[0])) .tlsVersions(ConnectionSpec.MODERN_TLS.tlsVersions().toArray(new TlsVersion[0])) .build()) .overrideAuthority(GrpcUtil.authorityFromHostAndPort( TestUtils.TEST_SERVER_HOST, getPort())); io.grpc.internal.TestingAccessor.setStatsImplementation( builder, createClientCensusStatsModule()); try { builder.sslSocketFactory(TestUtils.newSslSocketFactoryForCa(Platform.get().getProvider(), TestUtils.loadCert("ca.pem"))); } catch (Exception e) { throw new RuntimeException(e); } return builder; }
private boolean isFallbackPossible(SSLSocket socket) { for (int i = this.nextModeIndex; i < this.connectionSpecs.size(); i++) { if (((ConnectionSpec) this.connectionSpecs.get(i)).isCompatible(socket)) { return true; } } return false; }
public static OkHttpClient getHttpClient(Context context) { if (httpClient == null) { httpClient = new OkHttpClient(); httpClient.setConnectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS)); httpClient.setConnectTimeout(Constants.NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS); // Setup cache File cacheDir = new File(context.getCacheDir(), Constants.HTTP_CACHE_NAME); Cache cache = new Cache(cacheDir, Constants.HTTP_CACHE_SIZE); httpClient.setCache(cache); } return httpClient; }
@Before public void setup() throws IOException { server = new MockWebServer(); server.start(); shapeShift = new ShapeShift(); shapeShift.baseUrl = server.getUrl("/").toString(); shapeShift.client.setConnectionSpecs(Collections.singletonList(ConnectionSpec.CLEARTEXT)); }
private boolean shouldSendTlsFallbackIndicator(ConnectionSpec paramConnectionSpec) { Object localObject = this.connectionSpecs.get(0); boolean bool1 = false; if (paramConnectionSpec != localObject) { boolean bool2 = paramConnectionSpec.tls; bool1 = false; if (bool2) { bool1 = true; } } return bool1; }
private OkHttpTransportFactory(Executor executor, @Nullable SSLSocketFactory socketFactory, @Nullable HostnameVerifier hostnameVerifier, ConnectionSpec connectionSpec, int maxMessageSize, boolean enableKeepAlive, long keepAliveTimeNanos, long keepAliveTimeoutNanos, boolean keepAliveWithoutCalls, TransportTracer.Factory transportTracerFactory) { this.socketFactory = socketFactory; this.hostnameVerifier = hostnameVerifier; this.connectionSpec = connectionSpec; this.maxMessageSize = maxMessageSize; this.enableKeepAlive = enableKeepAlive; this.keepAliveTimeNanos = new AtomicBackoff("keepalive time nanos", keepAliveTimeNanos); this.keepAliveTimeoutNanos = keepAliveTimeoutNanos; this.keepAliveWithoutCalls = keepAliveWithoutCalls; usingSharedExecutor = executor == null; this.transportTracerFactory = Preconditions.checkNotNull(transportTracerFactory, "transportTracerFactory"); if (usingSharedExecutor) { // The executor was unspecified, using the shared executor. this.executor = SharedResourceHolder.get(SHARED_EXECUTOR); } else { this.executor = executor; } }
@Test public void failForUsingClearTextSpecDirectly() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("plaintext ConnectionSpec is not accepted"); OkHttpChannelBuilder.forAddress("host", 1234).connectionSpec(ConnectionSpec.CLEARTEXT); }
public ConnectionSpecSelector(List<ConnectionSpec> connectionSpecs) { this.connectionSpecs = connectionSpecs; }
public void connect(int connectTimeout, int readTimeout, int writeTimeout, List<ConnectionSpec> connectionSpecs, boolean connectionRetryEnabled) throws RouteException { if (this.protocol != null) { throw new IllegalStateException("already connected"); } RouteException routeException = null; ConnectionSpecSelector connectionSpecSelector = new ConnectionSpecSelector(connectionSpecs); Proxy proxy = this.route.getProxy(); Address address = this.route.getAddress(); if (this.route.getAddress().getSslSocketFactory() != null || connectionSpecs.contains (ConnectionSpec.CLEARTEXT)) { while (this.protocol == null) { try { Socket createSocket = (proxy.type() == Type.DIRECT || proxy.type() == Type .HTTP) ? address.getSocketFactory().createSocket() : new Socket(proxy); this.rawSocket = createSocket; connectSocket(connectTimeout, readTimeout, writeTimeout, connectionSpecSelector); } catch (IOException e) { Util.closeQuietly(this.socket); Util.closeQuietly(this.rawSocket); this.socket = null; this.rawSocket = null; this.source = null; this.sink = null; this.handshake = null; this.protocol = null; if (routeException == null) { routeException = new RouteException(e); } else { routeException.addConnectException(e); } if (!connectionRetryEnabled || !connectionSpecSelector.connectionFailed(e)) { throw routeException; } } } return; } throw new RouteException(new UnknownServiceException("CLEARTEXT communication not " + "supported: " + connectionSpecs)); }
protected Connection() { client = new OkHttpClient(); client.setConnectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS)); }
@Test public void allowUsingTlsConnectionSpec() { OkHttpChannelBuilder.forAddress("host", 1234).connectionSpec(ConnectionSpec.MODERN_TLS); }
public abstract void apply(ConnectionSpec connectionSpec, SSLSocket sSLSocket, boolean z);