Skip to content

Commit

Permalink
Merge pull request #61 from phobeous/master
Browse files Browse the repository at this point in the history
New validatesSecureCertificate to bypass SSL validation
  • Loading branch information
AndreaVitale authored Nov 28, 2018
2 parents 321775c + 22754a4 commit 08bde5c
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 11 deletions.
101 changes: 91 additions & 10 deletions android/src/av/imageview/AVImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
import java.util.concurrent.TimeUnit;

import av.imageview.utils.CookiesHelper;
import av.imageview.utils.SSLHelper;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;

public class AVImageView extends TiUIView {
private static final String LCAT = "AVImageView";
Expand All @@ -77,6 +81,7 @@ public class AVImageView extends TiUIView {
private boolean handleCookies;
private boolean dontAnimate;
private String signature;
private boolean validatesSecureCertificate;

private RequestListener<String, GlideDrawable> requestListener;

Expand All @@ -92,6 +97,7 @@ public AVImageView(TiViewProxy proxy) {
this.memoryCache = true;
this.dontAnimate = false;
this.handleCookies = true;
this.validatesSecureCertificate = true;
this.signature = "";
this.okHttpClient = new OkHttpClient
.Builder() // default timeouts are 5 seconds
Expand Down Expand Up @@ -142,7 +148,8 @@ public AVImageView(TiViewProxy proxy) {
public void processProperties(KrollDict args) {
super.processProperties(args);

String[] properties = {"loadingIndicator",
String[] properties = {"validatesSecureCertificate", // Needs to be at the very begining, at least before request is launched
"loadingIndicator",
"loadingIndicatorColor",
"enableMemoryCache",
"contentMode",
Expand Down Expand Up @@ -192,14 +199,27 @@ public void applyPropertyChanges(String key, Object value) {
}
}
if (key.equals("timeout")) {
this.okHttpClient =
new OkHttpClient.Builder()
.connectTimeout(TiConvert.toInt(value), TimeUnit.MILLISECONDS)
.readTimeout(TiConvert.toInt(value), TimeUnit.MILLISECONDS)
.build();
okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(TiConvert.toInt(value), TimeUnit.MILLISECONDS)
.readTimeout(TiConvert.toInt(value), TimeUnit.MILLISECONDS);
if(!this.validatesSecureCertificate)
{
Log.d(LCAT, "Not validating SSL");
builder.sslSocketFactory(SSLHelper.trustAllSslSocketFactory, (X509TrustManager)SSLHelper.trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}

this.okHttpClient = builder.build();
}
if (key.equals("handleCookies"))
this.setHandleCookies(TiConvert.toBoolean(value));
if (key.equals("validatesSecureCertificate"))
this.setValidatesSecureCertificate(TiConvert.toBoolean(value));
}

@Override
Expand Down Expand Up @@ -403,10 +423,20 @@ public void startRequest(String url, Boolean loadingIndicator) {
}

public void setTimeout(int timeout) {
this.okHttpClient = new OkHttpClient.Builder()
.connectTimeout(timeout, TimeUnit.MILLISECONDS)
.readTimeout(timeout, TimeUnit.MILLISECONDS)
.build();
okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(TiConvert.toInt(timeout), TimeUnit.MILLISECONDS)
.readTimeout(TiConvert.toInt(timeout), TimeUnit.MILLISECONDS);
if(!this.validatesSecureCertificate)
{
builder.sslSocketFactory(SSLHelper.trustAllSslSocketFactory, (X509TrustManager)SSLHelper.trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}
this.okHttpClient = builder.build();
}

private String sanitizeUrl(String url) {
Expand Down Expand Up @@ -539,6 +569,57 @@ synchronized public void setHandleCookies(boolean handleCookies) {

synchronized public boolean getHandleCookies() { return this.handleCookies; }

synchronized public void setValidatesSecureCertificate(boolean validatesSecureCertificate) {
if(this.validatesSecureCertificate == validatesSecureCertificate)
{
return; // Nothing to do
}

if(this.okHttpClient != null)
{
if(validatesSecureCertificate)
{ // Recreate a standard OkHttpClient with pre-set timeouts
this.okHttpClient = new OkHttpClient.Builder()
.connectTimeout(this.okHttpClient.connectTimeoutMillis(), TimeUnit.MILLISECONDS)
.readTimeout(this.okHttpClient.readTimeoutMillis(), TimeUnit.MILLISECONDS)
.build();
}
else
{ // Clone existing OkHttpClient with alltrustedcertificates
this.okHttpClient = SSLHelper.trustAllSslClient(this.okHttpClient);
}
}
else
{
if(validatesSecureCertificate)
{
this.okHttpClient = new OkHttpClient.Builder() // default timeouts are 5 seconds
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
}
else
{
this.okHttpClient = new OkHttpClient.Builder() // default timeouts are 5 seconds
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.sslSocketFactory(SSLHelper.trustAllSslSocketFactory, (X509TrustManager)SSLHelper.trustAllCerts[0])
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
}
}
this.validatesSecureCertificate = validatesSecureCertificate;
}

synchronized public boolean getValidatesSecureCertificate() {
return this.validatesSecureCertificate;
}

// Utility to create a specific request listener
private class RequestListenerBuilder {
private String LCAT = "RequestListenerBuilder";
Expand Down
14 changes: 13 additions & 1 deletion android/src/av/imageview/ImageViewProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
propertyAccessors = {"defaultImage", "brokenLinkImage", "image",
"contentMode", "enableMemoryCache", "signature",
"loadingIndicator", "rounded", "requestHeader",
"handleCookies", "dontAnimate"})
"handleCookies", "dontAnimate", "validatesSecureCertificate"})
public class ImageViewProxy extends TiViewProxy {
// Standard Debugging variables
private static final String LCAT = "AVImageViewProxy";
Expand Down Expand Up @@ -344,4 +344,16 @@ public void setHandleCookies(Boolean handleCookies) {
// clang-format on
getView().setHandleCookies(handleCookies);
}

@Kroll.getProperty
@Kroll.method
public Boolean getValidatesSecureCertificate() {
return getView().getValidatesSecureCertificate();
}

@Kroll.setProperty
@Kroll.method
public void setValidatesSecureCertificate(Boolean validatesSecureCertificate) {
getView().setValidatesSecureCertificate(validatesSecureCertificate);
}
}
63 changes: 63 additions & 0 deletions android/src/av/imageview/utils/SSLHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package av.imageview.utils;

import okhttp3.OkHttpClient;

import javax.net.ssl.X509TrustManager;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.security.cert.CertificateException;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;

/**
* Helper to avoid oversizing AvImageView class
*/
public class SSLHelper
{
private static final String LCAT = "SSLHelper";

public static OkHttpClient trustAllSslClient(OkHttpClient client) {
okhttp3.OkHttpClient.Builder builder = client.newBuilder();
builder.sslSocketFactory(trustAllSslSocketFactory, (X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return builder.build();
}

public static final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};

private static final SSLContext trustAllSslContext;

static {
try {
trustAllSslContext = SSLContext.getInstance("SSL");
trustAllSslContext.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException(e);
}
}

public static final SSLSocketFactory trustAllSslSocketFactory = trustAllSslContext.getSocketFactory();
}

0 comments on commit 08bde5c

Please sign in to comment.