Additions to SSL handling

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2017-10-29 23:08:59 +01:00
parent 6f5e6834f3
commit 4fa0dd6182
5 changed files with 39 additions and 58 deletions

View File

@ -21,9 +21,12 @@
package com.nextcloud.talk.activities;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.ViewGroup;
import android.webkit.SslErrorHandler;
import com.bluelinelabs.conductor.Conductor;
import com.bluelinelabs.conductor.Router;
@ -59,6 +62,8 @@ import io.requery.reactivex.ReactiveEntityStore;
@AutoInjector(NextcloudTalkApplication.class)
public final class MainActivity extends AppCompatActivity implements ActionBarProvider {
private static final String TAG = "MainActivity";
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.controller_container)
@ -105,7 +110,8 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
}
}
private void showCertificateDialog(X509Certificate cert, MagicTrustManager magicTrustManager) {
public void showCertificateDialog(X509Certificate cert, MagicTrustManager magicTrustManager,
@Nullable SslErrorHandler sslErrorHandler) {
DateFormat formatter = DateFormat.getDateInstance(DateFormat.LONG);
String validFrom = formatter.format(cert.getNotBefore());
String validUntil = formatter.format(cert.getNotAfter());
@ -130,8 +136,8 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
}
String dialogText = String.format(getResources()
.getString(R.string.nc_certificate_dialog_text), issuedBy, issuedFor,
validFrom, validUntil);
.getString(R.string.nc_certificate_dialog_text),
issuedBy, issuedFor, validFrom, validUntil);
new LovelyStandardDialog(this)
.setTopColorRes(R.color.darkRed)
@ -142,22 +148,28 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
.setMessage(dialogText)
.setPositiveButton(R.string.nc_yes, v -> {
magicTrustManager.addCertInTrustStore(cert);
if (sslErrorHandler != null) {
sslErrorHandler.proceed();
}
})
.setNegativeButton(R.string.nc_no, view1 -> {
router.setRoot(RouterTransaction.with(new
ServerSelectionController()));
if (sslErrorHandler != null) {
sslErrorHandler.cancel();
}
})
.show();
} catch (CertificateParsingException e) {
e.printStackTrace();
Log.d(TAG, "Failed to parse the certificate");
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(CertificateEvent event) {
showCertificateDialog(event.getX509Certificate(), event.getMagicTrustManager());
};
showCertificateDialog(event.getX509Certificate(), event.getMagicTrustManager(), event.getSslErrorHandler());
}
;
@Override
public void onStart() {

View File

@ -40,21 +40,21 @@ import com.nextcloud.talk.R;
import com.nextcloud.talk.api.helpers.api.ApiHelper;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.CertificateEvent;
import com.nextcloud.talk.models.LoginData;
import com.nextcloud.talk.persistence.entities.UserEntity;
import com.nextcloud.talk.utils.bundle.BundleBuilder;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
import com.yarolegovich.lovelydialog.LovelyStandardDialog;
import org.greenrobot.eventbus.EventBus;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
@ -176,50 +176,7 @@ public class WebViewLoginController extends BaseController {
magicTrustManager.checkServerTrusted(new X509Certificate[]{cert}, "generic");
handler.proceed();
} catch (CertificateException exception) {
DateFormat formatter = DateFormat.getDateInstance(DateFormat.LONG);
String validFrom = formatter.format(cert.getNotBefore());
String validUntil = formatter.format(cert.getNotAfter());
String issuedBy = cert.getIssuerDN().toString();
String issuedFor;
if (cert.getSubjectAlternativeNames() != null) {
StringBuilder stringBuilder = new StringBuilder();
for (Object o : cert.getSubjectAlternativeNames()) {
List list = (List) o;
int type = (Integer) list.get(0);
if (type == 2) {
String name = (String) list.get(1);
stringBuilder.append("[").append(type).append("]").append(name).append(" ");
}
}
issuedFor = stringBuilder.toString();
} else {
issuedFor = cert.getSubjectDN().getName();
}
String dialogText = String.format(getResources()
.getString(R.string.nc_certificate_dialog_text), issuedBy, issuedFor,
validFrom, validUntil);
new LovelyStandardDialog(getActivity())
.setTopColorRes(R.color.darkRed)
.setNegativeButtonColorRes(R.color.darkRed)
.setPositiveButtonColorRes(R.color.colorPrimaryDark)
.setIcon(R.drawable.ic_security_white_24dp)
.setTitle(R.string.nc_certificate_dialog_title)
.setMessage(dialogText)
.setPositiveButton(R.string.nc_yes, v -> {
magicTrustManager.addCertInTrustStore(cert);
handler.proceed();
})
.setNegativeButton(R.string.nc_no, view1 -> {
handler.cancel();
getRouter().setRoot(RouterTransaction.with(new
ServerSelectionController()));
})
.setCancelable(false)
.show();
EventBus.getDefault().post(new CertificateEvent(cert, magicTrustManager, handler));
}
}
} catch (Exception exception) {

View File

@ -133,7 +133,7 @@ public class RestModule {
httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
httpClient.retryOnConnectionFailure(true);
httpClient.hostnameVerifier(new MagicTrustManager().getHostnameVerifier(OkHostnameVerifier.INSTANCE));
httpClient.hostnameVerifier(magicTrustManager.getHostnameVerifier(OkHostnameVerifier.INSTANCE));
if (!Proxy.NO_PROXY.equals(proxy)) {
httpClient.proxy(proxy);

View File

@ -20,6 +20,9 @@
package com.nextcloud.talk.events;
import android.support.annotation.Nullable;
import android.webkit.SslErrorHandler;
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
import java.security.cert.X509Certificate;
@ -27,10 +30,18 @@ import java.security.cert.X509Certificate;
public class CertificateEvent {
private final X509Certificate x509Certificate;
private final MagicTrustManager magicTrustManager;
@Nullable private final SslErrorHandler sslErrorHandler;
public CertificateEvent(X509Certificate x509Certificate, MagicTrustManager magicTrustManager) {
public CertificateEvent(X509Certificate x509Certificate, MagicTrustManager magicTrustManager,
@Nullable SslErrorHandler sslErrorHandler) {
this.x509Certificate = x509Certificate;
this.magicTrustManager = magicTrustManager;
this.sslErrorHandler = sslErrorHandler;
}
@Nullable
public SslErrorHandler getSslErrorHandler() {
return sslErrorHandler;
}
public X509Certificate getX509Certificate() {

View File

@ -99,7 +99,8 @@ public class MagicTrustManager implements X509TrustManager {
return true;
} catch (CertificateException e) {
if (!isCertInMagicTrustStore(x509Certificate)) {
EventBus.getDefault().post(new CertificateEvent(x509Certificate, this));
EventBus.getDefault().post(new CertificateEvent(x509Certificate, this,
null));
long startTime = System.currentTimeMillis();
while (!isCertInMagicTrustStore(x509Certificate) && System.currentTimeMillis() <=
startTime + 15000) {