mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-31 08:35:19 +01:00
Implement SSL error handling
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
4addd43aa2
commit
6f5e6834f3
@ -129,6 +129,8 @@ dependencies {
|
|||||||
implementation "com.google.android.gms:play-services-gcm:${googleLibraryVersion}"
|
implementation "com.google.android.gms:play-services-gcm:${googleLibraryVersion}"
|
||||||
implementation "com.google.firebase:firebase-core:${googleLibraryVersion}"
|
implementation "com.google.firebase:firebase-core:${googleLibraryVersion}"
|
||||||
|
|
||||||
|
implementation 'com.yarolegovich:lovely-dialog:1.0.7'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.1', {
|
androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.1', {
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
@ -34,7 +34,19 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|||||||
import com.nextcloud.talk.controllers.BottomNavigationController;
|
import com.nextcloud.talk.controllers.BottomNavigationController;
|
||||||
import com.nextcloud.talk.controllers.ServerSelectionController;
|
import com.nextcloud.talk.controllers.ServerSelectionController;
|
||||||
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider;
|
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider;
|
||||||
|
import com.nextcloud.talk.events.CertificateEvent;
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
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 org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
|
import java.security.cert.CertificateParsingException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -57,6 +69,9 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
|
|||||||
@Inject
|
@Inject
|
||||||
ReactiveEntityStore<Persistable> dataStore;
|
ReactiveEntityStore<Persistable> dataStore;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
EventBus eventBus;
|
||||||
|
|
||||||
private Router router;
|
private Router router;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -72,7 +87,6 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
|
|||||||
|
|
||||||
router = Conductor.attachRouter(this, container, savedInstanceState);
|
router = Conductor.attachRouter(this, container, savedInstanceState);
|
||||||
|
|
||||||
|
|
||||||
if (!router.hasRootController() && userUtils.anyUserExists()) {
|
if (!router.hasRootController() && userUtils.anyUserExists()) {
|
||||||
router.setRoot(RouterTransaction.with(new BottomNavigationController(R.menu.menu_navigation))
|
router.setRoot(RouterTransaction.with(new BottomNavigationController(R.menu.menu_navigation))
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
.pushChangeHandler(new HorizontalChangeHandler())
|
||||||
@ -90,4 +104,70 @@ public final class MainActivity extends AppCompatActivity implements ActionBarPr
|
|||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showCertificateDialog(X509Certificate cert, MagicTrustManager magicTrustManager) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
try {
|
||||||
|
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(this)
|
||||||
|
.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);
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.nc_no, view1 -> {
|
||||||
|
router.setRoot(RouterTransaction.with(new
|
||||||
|
ServerSelectionController()));
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
|
||||||
|
} catch (CertificateParsingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onMessageEvent(CertificateEvent event) {
|
||||||
|
showCertificateDialog(event.getX509Certificate(), event.getMagicTrustManager());
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
eventBus.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
eventBus.unregister(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ import com.nextcloud.talk.api.helpers.api.ApiHelper;
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
import com.nextcloud.talk.controllers.base.BaseController;
|
||||||
|
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import autodagger.AutoInjector;
|
import autodagger.AutoInjector;
|
||||||
@ -123,10 +125,12 @@ public class ServerSelectionController extends BaseController {
|
|||||||
true);
|
true);
|
||||||
} else if (status.isNeedsUpgrade()) {
|
} else if (status.isNeedsUpgrade()) {
|
||||||
textFieldBoxes.setError(String.format(getResources().
|
textFieldBoxes.setError(String.format(getResources().
|
||||||
getString(R.string.nc_server_db_upgrade_needed), productName), true);
|
getString(R.string.nc_server_db_upgrade_needed),
|
||||||
|
productName), true);
|
||||||
} else if (status.isMaintenance()) {
|
} else if (status.isMaintenance()) {
|
||||||
textFieldBoxes.setError(String.format(getResources().
|
textFieldBoxes.setError(String.format(getResources().
|
||||||
getString(R.string.nc_server_maintenance), productName),
|
getString(R.string.nc_server_maintenance),
|
||||||
|
productName),
|
||||||
true);
|
true);
|
||||||
} else if (!status.getProductName().equals(
|
} else if (!status.getProductName().equals(
|
||||||
getResources().getString(R.string.nc_server_product_name))) {
|
getResources().getString(R.string.nc_server_product_name))) {
|
||||||
@ -137,7 +141,12 @@ public class ServerSelectionController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}, throwable -> {
|
}, throwable -> {
|
||||||
textFieldBoxes.setError(throwable.getLocalizedMessage(), true);
|
if (throwable.getLocalizedMessage() != null) {
|
||||||
|
textFieldBoxes.setError(throwable.getLocalizedMessage(), true);
|
||||||
|
} else if (throwable.getCause() instanceof CertificateException) {
|
||||||
|
textFieldBoxes.setError(getResources().getString(R.string.nc_certificate_error),
|
||||||
|
true);
|
||||||
|
}
|
||||||
if (serverEntry != null) {
|
if (serverEntry != null) {
|
||||||
serverEntry.setEnabled(true);
|
serverEntry.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,15 @@ import com.nextcloud.talk.utils.bundle.BundleBuilder;
|
|||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||||
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
|
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
|
||||||
|
import com.yarolegovich.lovelydialog.LovelyStandardDialog;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.text.DateFormat;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -148,7 +151,9 @@ public class WebViewLoginController extends BaseController {
|
|||||||
@Override
|
@Override
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
if (!basePageLoaded) {
|
if (!basePageLoaded) {
|
||||||
progressBar.setVisibility(View.GONE);
|
if (progressBar != null) {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
webView.setVisibility(View.VISIBLE);
|
webView.setVisibility(View.VISIBLE);
|
||||||
basePageLoaded = true;
|
basePageLoaded = true;
|
||||||
}
|
}
|
||||||
@ -171,8 +176,50 @@ public class WebViewLoginController extends BaseController {
|
|||||||
magicTrustManager.checkServerTrusted(new X509Certificate[]{cert}, "generic");
|
magicTrustManager.checkServerTrusted(new X509Certificate[]{cert}, "generic");
|
||||||
handler.proceed();
|
handler.proceed();
|
||||||
} catch (CertificateException exception) {
|
} catch (CertificateException exception) {
|
||||||
// cancel for now, as we don't have a way to accept custom certificates
|
DateFormat formatter = DateFormat.getDateInstance(DateFormat.LONG);
|
||||||
handler.cancel();
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
|
@ -37,6 +37,7 @@ import com.nextcloud.talk.utils.ssl.SSLSocketFactoryCompat;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
@ -59,6 +60,8 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
|||||||
@Module(includes = DatabaseModule.class)
|
@Module(includes = DatabaseModule.class)
|
||||||
public class RestModule {
|
public class RestModule {
|
||||||
|
|
||||||
|
private static final String TAG = "RestModule";
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
NcApi provideNcApi(Retrofit retrofit) {
|
NcApi provideNcApi(Retrofit retrofit) {
|
||||||
@ -98,7 +101,6 @@ public class RestModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
MagicTrustManager provideMagicTrustManager() {
|
MagicTrustManager provideMagicTrustManager() {
|
||||||
return new MagicTrustManager();
|
return new MagicTrustManager();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@ -110,9 +112,14 @@ public class RestModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
OkHttpClient provideHttpClient(Proxy proxy, AppPreferences appPreferences,
|
OkHttpClient provideHttpClient(Proxy proxy, AppPreferences appPreferences,
|
||||||
MagicTrustManager magicTrustManager, SSLSocketFactoryCompat sslSocketFactoryCompat) {
|
MagicTrustManager magicTrustManager,
|
||||||
|
SSLSocketFactoryCompat sslSocketFactoryCompat) {
|
||||||
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
|
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
|
||||||
|
|
||||||
|
httpClient.connectTimeout(30, TimeUnit.SECONDS);
|
||||||
|
httpClient.readTimeout(30, TimeUnit.SECONDS);
|
||||||
|
httpClient.writeTimeout(30, TimeUnit.SECONDS);
|
||||||
|
|
||||||
int cacheSize = 128 * 1024 * 1024; // 128 MB
|
int cacheSize = 128 * 1024 * 1024; // 128 MB
|
||||||
|
|
||||||
httpClient.cache(new Cache(NextcloudTalkApplication.getSharedApplication().getCacheDir(), cacheSize));
|
httpClient.cache(new Cache(NextcloudTalkApplication.getSharedApplication().getCacheDir(), cacheSize));
|
||||||
@ -125,7 +132,8 @@ public class RestModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
|
httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
|
||||||
httpClient.hostnameVerifier(magicTrustManager.getHostnameVerifier(OkHostnameVerifier.INSTANCE));
|
httpClient.retryOnConnectionFailure(true);
|
||||||
|
httpClient.hostnameVerifier(new MagicTrustManager().getHostnameVerifier(OkHostnameVerifier.INSTANCE));
|
||||||
|
|
||||||
if (!Proxy.NO_PROXY.equals(proxy)) {
|
if (!Proxy.NO_PROXY.equals(proxy)) {
|
||||||
httpClient.proxy(proxy);
|
httpClient.proxy(proxy);
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.events;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.utils.ssl.MagicTrustManager;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
public class CertificateEvent {
|
||||||
|
private final X509Certificate x509Certificate;
|
||||||
|
private final MagicTrustManager magicTrustManager;
|
||||||
|
|
||||||
|
public CertificateEvent(X509Certificate x509Certificate, MagicTrustManager magicTrustManager) {
|
||||||
|
this.x509Certificate = x509Certificate;
|
||||||
|
this.magicTrustManager = magicTrustManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509Certificate getX509Certificate() {
|
||||||
|
return x509Certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MagicTrustManager getMagicTrustManager() {
|
||||||
|
return magicTrustManager;
|
||||||
|
}
|
||||||
|
}
|
@ -36,8 +36,6 @@ import com.nextcloud.talk.persistence.entities.UserEntity;
|
|||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -103,7 +101,6 @@ public class PushUtils {
|
|||||||
Signature signature = null;
|
Signature signature = null;
|
||||||
PushConfigurationState pushConfigurationState;
|
PushConfigurationState pushConfigurationState;
|
||||||
PublicKey publicKey;
|
PublicKey publicKey;
|
||||||
JSONObject jsonObject;
|
|
||||||
SignatureVerification signatureVerification = new SignatureVerification();
|
SignatureVerification signatureVerification = new SignatureVerification();
|
||||||
signatureVerification.setSignatureValid(false);
|
signatureVerification.setSignatureValid(false);
|
||||||
|
|
||||||
|
@ -26,6 +26,9 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
|
import com.nextcloud.talk.events.CertificateEvent;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -50,10 +53,6 @@ public class MagicTrustManager implements X509TrustManager {
|
|||||||
private X509TrustManager systemTrustManager = null;
|
private X509TrustManager systemTrustManager = null;
|
||||||
private KeyStore trustedKeyStore = null;
|
private KeyStore trustedKeyStore = null;
|
||||||
|
|
||||||
public HostnameVerifier getHostnameVerifier(HostnameVerifier defaultHostNameVerifier) {
|
|
||||||
return new MagicHostnameVerifier(defaultHostNameVerifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MagicTrustManager() {
|
public MagicTrustManager() {
|
||||||
keystoreFile = new File(NextcloudTalkApplication.getSharedApplication().getDir("CertsKeystore",
|
keystoreFile = new File(NextcloudTalkApplication.getSharedApplication().getDir("CertsKeystore",
|
||||||
Context.MODE_PRIVATE), "keystore.bks");
|
Context.MODE_PRIVATE), "keystore.bks");
|
||||||
@ -89,15 +88,30 @@ public class MagicTrustManager implements X509TrustManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HostnameVerifier getHostnameVerifier(HostnameVerifier defaultHostNameVerifier) {
|
||||||
|
return new MagicHostnameVerifier(defaultHostNameVerifier);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCertInTrustStore(X509Certificate x509Certificate) {
|
public boolean isCertInTrustStore(X509Certificate x509Certificate) {
|
||||||
if (systemTrustManager != null) {
|
if (systemTrustManager != null) {
|
||||||
try {
|
try {
|
||||||
systemTrustManager.checkServerTrusted(new X509Certificate[]{x509Certificate}, "generic");
|
systemTrustManager.checkServerTrusted(new X509Certificate[]{x509Certificate}, "generic");
|
||||||
return true;
|
return true;
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
return isCertInMagicTrustStore(x509Certificate);
|
if (!isCertInMagicTrustStore(x509Certificate)) {
|
||||||
|
EventBus.getDefault().post(new CertificateEvent(x509Certificate, this));
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
while (!isCertInMagicTrustStore(x509Certificate) && System.currentTimeMillis() <=
|
||||||
|
startTime + 15000) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
return isCertInMagicTrustStore(x509Certificate);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +173,6 @@ public class MagicTrustManager implements X509TrustManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
X509Certificate[] certificates = (X509Certificate[]) sslSession.getPeerCertificates();
|
X509Certificate[] certificates = (X509Certificate[]) sslSession.getPeerCertificates();
|
||||||
if (certificates.length > 0 && certificates[0] != null && isCertInMagicTrustStore(certificates[0])) {
|
if (certificates.length > 0 && certificates[0] != null && isCertInMagicTrustStore(certificates[0])) {
|
||||||
|
25
app/src/main/res/drawable/ic_security_white_24dp.xml
Normal file
25
app/src/main/res/drawable/ic_security_white_24dp.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
~ Nextcloud Talk application
|
||||||
|
~
|
||||||
|
~ @author Mario Danic
|
||||||
|
~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||||
|
~
|
||||||
|
~ 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 <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector android:autoMirrored="true" android:height="24dp"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FFFFFF" android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM12,11.99h7c-0.53,4.12 -3.28,7.79 -7,8.94L12,12L5,12L5,6.3l7,-3.11v8.8z"/>
|
||||||
|
</vector>
|
@ -3,4 +3,7 @@
|
|||||||
<color name="colorPrimary">#0082c9</color>
|
<color name="colorPrimary">#0082c9</color>
|
||||||
<color name="colorPrimaryDark">#006AA3</color>
|
<color name="colorPrimaryDark">#006AA3</color>
|
||||||
<color name="colorAccent">#007CC2</color>
|
<color name="colorAccent">#007CC2</color>
|
||||||
|
|
||||||
|
<color name="darkRed">#D32F2F</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
@ -22,7 +22,14 @@
|
|||||||
|
|
||||||
<string name="nc_invited">Invited</string>
|
<string name="nc_invited">Invited</string>
|
||||||
<string name="nc_never">Never</string>
|
<string name="nc_never">Never</string>
|
||||||
|
|
||||||
<string name="nc_search">Search</string>
|
<string name="nc_search">Search</string>
|
||||||
|
|
||||||
|
<string name="nc_certificate_dialog_title">Trust the certificate?</string>
|
||||||
|
<string name="nc_certificate_dialog_text">We encountered an SSL certificate issued by %1$s for %2$s and valid
|
||||||
|
from %3$s to %4$s. Trust it?</string>
|
||||||
|
<string name="nc_yes">Yes</string>
|
||||||
|
<string name="nc_no">No</string>
|
||||||
|
<string name="nc_details">Details</string>
|
||||||
|
<string name="nc_certificate_error">Your SSL setup prevented us from connecting</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user