mirror of
https://gitlab.com/oeffi/oeffi.git
synced 2025-07-09 10:48:47 +00:00
Application: On Android 4.4 (KitKat) with Google Play Services installed, manually enable TLS 1.2.
This has two steps: - Use SafetyNet ProviderInstaller.insertProvider() to load a recent version of Conscrypt. - Enable TLS 1.2 in the socket factory by wrapping it.
This commit is contained in:
parent
2ffe808276
commit
ad2a0d6891
2 changed files with 143 additions and 0 deletions
|
@ -18,6 +18,7 @@
|
|||
package de.schildbach.oeffi;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -89,6 +90,13 @@ public class Application extends android.app.Application {
|
|||
});
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
|
||||
builder.addNetworkInterceptor(interceptor);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
log.info("manually enabling TLS 1.2 on API level {}", Build.VERSION.SDK_INT);
|
||||
if (safetyNetInsertProvider()) {
|
||||
final Tls12SocketFactory socketFactory = new Tls12SocketFactory();
|
||||
builder.sslSocketFactory(socketFactory, socketFactory.getTrustManager());
|
||||
}
|
||||
}
|
||||
okHttpClient = builder.build();
|
||||
|
||||
initMaps();
|
||||
|
@ -154,6 +162,23 @@ public class Application extends android.app.Application {
|
|||
initNotificationManager();
|
||||
}
|
||||
|
||||
private boolean safetyNetInsertProvider() {
|
||||
// This piece of code uses SafetyNet (Google Play Services) to insert a recent version of Conscrypt, if
|
||||
// available. We use reflection to avoid the proprietary Google Play Services client library.
|
||||
try {
|
||||
final Stopwatch watch = Stopwatch.createStarted();
|
||||
final Context remoteContext = createPackageContext("com.google.android.gms", 3);
|
||||
final Method insertProvider = remoteContext.getClassLoader().loadClass("com.google.android.gms.common" +
|
||||
".security.ProviderInstallerImpl").getMethod("insertProvider", new Class[] { Context.class });
|
||||
insertProvider.invoke(null, new Object[] { remoteContext });
|
||||
log.info("insertProvider successful, took {}", watch.stop());
|
||||
return true;
|
||||
} catch (final Exception x) {
|
||||
log.warn("insertProvider failed", x);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initLogging() {
|
||||
final File logDir = new File(getFilesDir(), "log");
|
||||
final File logFile = new File(logDir, "oeffi.log");
|
||||
|
|
118
oeffi/src/de/schildbach/oeffi/Tls12SocketFactory.java
Normal file
118
oeffi/src/de/schildbach/oeffi/Tls12SocketFactory.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.schildbach.oeffi;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import okhttp3.TlsVersion;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public final class Tls12SocketFactory extends SSLSocketFactory {
|
||||
private final SSLSocketFactory delegate;
|
||||
private final TrustManager[] trustManagers;
|
||||
|
||||
public Tls12SocketFactory() {
|
||||
try {
|
||||
final TrustManagerFactory trustManagerFactory =
|
||||
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
trustManagers = trustManagerFactory.getTrustManagers();
|
||||
final SSLContext context = SSLContext.getInstance(TlsVersion.TLS_1_2.javaName());
|
||||
context.init(null, trustManagers, null);
|
||||
delegate = context.getSocketFactory();
|
||||
} catch (final NoSuchAlgorithmException | KeyManagementException | KeyStoreException x) {
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public X509TrustManager getTrustManager() {
|
||||
for (final TrustManager tm : trustManagers)
|
||||
if (tm instanceof X509TrustManager)
|
||||
return (X509TrustManager) tm;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return patchForTls12(delegate.createSocket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return patchForTls12(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||
return patchForTls12(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException,
|
||||
UnknownHostException {
|
||||
return patchForTls12(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return patchForTls12(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return patchForTls12(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
private Socket patchForTls12(final Socket socket) {
|
||||
if (socket != null && (socket instanceof SSLSocket)) {
|
||||
final SSLSocket sslSocket = (SSLSocket) socket;
|
||||
final Set<String> protocols = new TreeSet<>();
|
||||
protocols.addAll(Arrays.asList(sslSocket.getEnabledProtocols()));
|
||||
protocols.add(TlsVersion.TLS_1_2.javaName());
|
||||
sslSocket.setEnabledProtocols(protocols.toArray(new String[0]));
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue