Browse Source

add network security config and load CA certs with it

master
R4SAS 6 years ago
parent
commit
c4e9305603
  1. 2
      app/src/main/AndroidManifest.xml
  2. 24
      app/src/main/assets/cert/purplei2p.crt
  3. 16
      app/src/main/java/org/purplei2p/lightning/utils/Utils.java
  4. 34
      app/src/main/java/org/purplei2p/lightning/view/LightningWebClient.java
  5. BIN
      app/src/main/res/raw/purplei2p.crt
  6. 10
      app/src/main/res/xml/network_security_config.xml
  7. 2
      build.gradle

2
app/src/main/AndroidManifest.xml

@ -23,7 +23,7 @@
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:usesCleartextTraffic="true"> android:networkSecurityConfig="@xml/network_security_config">
<meta-data <meta-data
android:name="android.webkit.WebView.MetricsOptOut" android:name="android.webkit.WebView.MetricsOptOut"
android:value="true"/> android:value="true"/>

24
app/src/main/assets/cert/purplei2p.crt

@ -1,24 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID9zCCAt+gAwIBAgIUervWv7EoWkk4Gt8J34xDR9nhH50wDQYJKoZIhvcNAQEL
BQAwgYIxCzAJBgNVBAYTAldXMRQwEgYDVQQIDAtJMlAgTmV0d29yazESMBAGA1UE
CgwJUHVycGxlSTJQMSowKAYDVQQDDCFQdXJwbGVJMlAgQ2VydGlmaWNhdGlvbiBB
dXRob3JpdHkxHTAbBgkqhkiG9w0BCQEWDnI0c2FzQG1haWwuaTJwMB4XDTE5MDMw
MzE2MjcxNFoXDTI5MDIyODE2MjcxNFowgYIxCzAJBgNVBAYTAldXMRQwEgYDVQQI
DAtJMlAgTmV0d29yazESMBAGA1UECgwJUHVycGxlSTJQMSowKAYDVQQDDCFQdXJw
bGVJMlAgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHTAbBgkqhkiG9w0BCQEWDnI0
c2FzQG1haWwuaTJwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwLEy
A0TamzrfORA+aIM/NRRGrKYkI9o5Q9UB/pTM8IFlSBREGleUfnC6LFHZeNV+Y1Tn
jrMBOZ7PmIKjPIv+fJP7KjhHACZdk6iqVZqkiGqE0/V17kG16g1+g05Bj2lkWr94
mp1rhzBeKJJSI8cG82824qdfDcgWZheziye+O0okENhi0o2bDhg78EnyysJiN/tu
OuoZSGfC9ZdITbpMWgqwuQcdeBg0FNy4hEqUJWoYNgrghe5uc0WMOjTAegSntYPE
MeaaZyzlGICZ2F+rKZgTjnzVYW60QlHqfg7sShieSPYIZmeN5l5hZ5GZk9Giaj/X
4pz4sup2iafKclWAmQIDAQABo2MwYTAdBgNVHQ4EFgQUCARvpDaXqPaF4amObzzV
GaDoZm4wHwYDVR0jBBgwFoAUCARvpDaXqPaF4amObzzVGaDoZm4wDwYDVR0TBAgw
BgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAKcmGUXV
gCw8PRHe0+XlkcSTX69e0TIPP+j5uJxMT3BHasvBdyV4FcjuUokHGjAnHal5OV4N
yWdbRPnIge7su4yLQZzlNM1OzbcRds1wSbqTEpb68R/6E8mv3ms6Rc8AcRoXwusc
byZvzS9tBSXTQ21wCVrltnIARAYabWlWu+URv+DFvlwMik6H8+DklHSVkPC6K3Ov
V1aMJztMnJ/XTTsFDS/yvaTfmJFG16LABIiSsEAW5QK64sWsN4sxvpcg0D6/EjWP
knyLM4KXuD3i08mzwzus8d97AjGxC5RCEFL5ADBpVaDU/5CpmZmZdY1daYjiHrXm
EVNoSbqid1fAVyA=
-----END CERTIFICATE-----

16
app/src/main/java/org/purplei2p/lightning/utils/Utils.java

@ -174,6 +174,20 @@ public final class Utils {
*/ */
@Nullable @Nullable
public static String getDomainName(@Nullable String url) { public static String getDomainName(@Nullable String url) {
return getDomainName(url, false);
}
/**
* Extracts the domain name from a URL.
*
* @param url the URL to extract the domain from.
* @param domainonly flag to return only domain without scheme.
* @return the domain name, or the URL if the domain
* could not be extracted. The domain name may include
* HTTPS if the URL is an SSL supported URL and domainonly is false.
*/
@Nullable
public static String getDomainName(@Nullable String url, boolean domainonly) {
if (url == null || url.isEmpty()) return ""; if (url == null || url.isEmpty()) return "";
boolean ssl = URLUtil.isHttpsUrl(url); boolean ssl = URLUtil.isHttpsUrl(url);
@ -195,7 +209,7 @@ public final class Utils {
if (domain == null || domain.isEmpty()) { if (domain == null || domain.isEmpty()) {
return url; return url;
} }
if (ssl) if (ssl && !domainonly)
return Constants.HTTPS + domain; return Constants.HTTPS + domain;
else else
return domain.startsWith("www.") ? domain.substring(4) : domain; return domain.startsWith("www.") ? domain.substring(4) : domain;

34
app/src/main/java/org/purplei2p/lightning/view/LightningWebClient.java

@ -98,22 +98,16 @@ public class LightningWebClient extends WebViewClient {
CertificateException, FileNotFoundException, CertificateException, FileNotFoundException,
IOException, KeyStoreException, NoSuchAlgorithmException { IOException, KeyStoreException, NoSuchAlgorithmException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = mActivity.getResources().openRawResource(R.raw.purplei2p);
final Certificate ca = cf.generateCertificate(caInput);
Log.d(TAG, "ca-root DN=" + ((X509Certificate) ca).getSubjectDN());
caInput.close();
// Create a KeyStore containing our trusted CAs // Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType(); String keyStoreType = KeyStore.getDefaultType();
KeyStore trustedKeyStore = KeyStore.getInstance(keyStoreType); KeyStore trustedKeyStore = KeyStore.getInstance(keyStoreType);
trustedKeyStore.load(null, null); trustedKeyStore.load(null, null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(mActivity.getResources().getAssets().open("cert/purplei2p.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d(TAG, "ca-root DN=" + ((X509Certificate) ca).getSubjectDN());
}
finally {
caInput.close();
}
trustedKeyStore.setCertificateEntry("ca", ca); trustedKeyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore // Create a TrustManager that trusts the CAs in our KeyStore
@ -280,7 +274,8 @@ public class LightningWebClient extends WebViewClient {
X509TrustManager x509TrustManager = (X509TrustManager)trustManager; X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
try{ try{
x509TrustManager.checkServerTrusted(chain, "generic"); x509TrustManager.checkServerTrusted(chain, "generic");
passVerify = true;break; passVerify = true;
break;
}catch(Exception e){ }catch(Exception e){
Log.e(TAG, "SslError verify trustManager failed", e); Log.e(TAG, "SslError verify trustManager failed", e);
passVerify = false; passVerify = false;
@ -292,11 +287,24 @@ public class LightningWebClient extends WebViewClient {
Log.e(TAG, "SslError verify cert fail", e); Log.e(TAG, "SslError verify cert fail", e);
} }
} }
if(passVerify == true) { if(passVerify == true) {
handler.proceed(); handler.proceed();
return; return;
} }
if(error.getPrimaryError() == SslError.SSL_IDMISMATCH){
// Due to strange bug in android when trust anchors used, we must revalidate that hostname in request and in certificate is not matching.
SslCertificate cert = error.getCertificate();
String TargetURL = error.getUrl();
String reqHost = Utils.getDomainName(TargetURL, true);
String subjCN = cert.getIssuedTo().getCName();
if(reqHost.equals(subjCN)){
handler.proceed();
return;
}
}
List<Integer> errorCodeMessageCodes = getAllSslErrorMessageCodes(error); List<Integer> errorCodeMessageCodes = getAllSslErrorMessageCodes(error);
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();

BIN
app/src/main/res/raw/purplei2p.crt

Binary file not shown.

10
app/src/main/res/xml/network_security_config.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="@raw/purplei2p" />
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>

2
build.gradle

@ -22,5 +22,5 @@ ext {
buildToolsVersion = '28.0.3' buildToolsVersion = '28.0.3'
versionName = '0.1.2' versionName = '0.1.2'
versionCode = 125 versionCode = 126
} }

Loading…
Cancel
Save