Skip to content

Commit

Permalink
MOB-880: Support TLS v1.2 (#209)
Browse files Browse the repository at this point in the history
Mob-880: support tls1 2
  • Loading branch information
chris-pound-bazaarvoice authored Aug 7, 2018
1 parent 89cf9f9 commit b6dcffc
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 6 deletions.
71 changes: 65 additions & 6 deletions bvcommon/src/main/java/com/bazaarvoice/bvandroidsdk/BVSDK.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/**
* Copyright 2016 Bazaarvoice Inc. All rights reserved.
* Copyright 2016 Bazaarvoice Inc. All rights reserved.
*/

package com.bazaarvoice.bvandroidsdk;

import android.app.Application;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
Expand All @@ -18,6 +19,11 @@
import com.google.gson.GsonBuilder;

import java.io.File;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
Expand All @@ -28,8 +34,15 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import okhttp3.TlsVersion;

import static android.os.Process.THREAD_PRIORITY_BACKGROUND;

Expand All @@ -55,7 +68,7 @@ public class BVSDK {
private static final String BAZAARVOICE_ROOT_URL_STAGING = "https://stg.api.bazaarvoice.com/";
private static final String BAZAARVOICE_ROOT_URL_PRODUCTION = "https://api.bazaarvoice.com/";
private static final String NOTIFICATION_CONFIG_URL = "https://s3.amazonaws.com/";
private static final String BVSDK_USER_AGENT = "bvsdk-android/v"+ BuildConfig.BVSDK_VERSION_NAME;
private static final String BVSDK_USER_AGENT = "bvsdk-android/v" + BuildConfig.BVSDK_VERSION_NAME;
private static final String BACKGROUND_THREAD_NAME = "BackgroundThread";
static final int BVHandlePayload = 123;
static volatile BVSDK singleton;
Expand Down Expand Up @@ -102,6 +115,7 @@ public static BVSDK getInstance() {
/**
* Tell BVSDK who the user is. This is the essential step in providing targeted, personalized
* information about the user.
*
* @param userAuthString The Bazaarvoice-specific User Auth String. See the online documentation
* for information on where this auth string comes from, and why it is
* necessary.
Expand Down Expand Up @@ -465,17 +479,30 @@ public BVSDK build() {
this.okHttpClient = new OkHttpClient();
}

BVLogger bvLogger = new BVLogger(logLevel);

// Use their OkHttp instance or ours, and add the options we want
File httpCacheFile = new File(application.getCacheDir(), "bvsdk_http_cache");
long maxCacheSize = 1024 * 1024 * 10; // 10MiB
Cache httpCache = new Cache(httpCacheFile, maxCacheSize);
this.okHttpClient = okHttpClient
OkHttpClient.Builder clientBuilder = okHttpClient
.newBuilder()
.cache(httpCache)
.connectTimeout(30, TimeUnit.SECONDS)
.build();
.connectTimeout(30, TimeUnit.SECONDS);

try {
okHttpClient = addSupportForTLS1_2OnPreLollipop(clientBuilder).build();
} catch (KeyManagementException e) {
bvLogger.e("BVSDK", "BVSDK failed to enable TLS v1.2 support for pre lollipop. " +
"Support for TLS v1.2 or higher is required");
} catch (NoSuchAlgorithmException e) {
bvLogger.e("BVSDK", "BVSDK failed to enable TLS v1.2 support for pre lollipop. " +
"Support for TLS v1.2 or higher is required");
} catch (KeyStoreException e) {
bvLogger.e("BVSDK", "BVSDK failed to enable TLS v1.2 support for pre lollipop. " +
"Support for TLS v1.2 or higher is required");
}

BVLogger bvLogger = new BVLogger(logLevel);

Locale defaultLocale = finalConfig.getAnalyticsDefaultLocale();
if (defaultLocale == null) {
Expand Down Expand Up @@ -641,5 +668,37 @@ public Looper getBackgroundLooper() {
}
}

private static X509TrustManager getSystemDefaultTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}

private static OkHttpClient.Builder addSupportForTLS1_2OnPreLollipop(OkHttpClient.Builder client) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {

SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, null, null);

ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.build();

List<ConnectionSpec> specs = new ArrayList<>();
specs.add(cs);

client.sslSocketFactory(new TLSSocketFactory(sc.getSocketFactory()), getSystemDefaultTrustManager())
.connectionSpecs(specs);
}

return client;
}

// endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.bazaarvoice.bvandroidsdk;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory delegate;
private static final String[] SUPPORTED_PROTOCOLS = {"TLSv1.2"};


TLSSocketFactory(SSLSocketFactory base) throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
delegate = base;
}

@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}

@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(delegate.createSocket());
}


@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port));

}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
}

/**
* Enable Supported Protocols: TLS1.2
*/
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(SUPPORTED_PROTOCOLS);
}
return socket;
}
}

0 comments on commit b6dcffc

Please sign in to comment.