Skip to content

Commit e684145

Browse files
committed
add support for upcoming lets encrypt certificates on android 7.1.1 and earlier
1 parent e9b71cc commit e684145

File tree

6 files changed

+106
-3
lines changed

6 files changed

+106
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [0.29.8]
5+
6+
### Changed
7+
- Add support for lets encrypt certificates on Android versions before 7.1.1
8+
49
## [0.29.7]
510

611
- More vendor specific strings

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ allprojects {
2929
}
3030

3131
project.ext {
32-
sdkVersion='0.29.7'
32+
sdkVersion='0.29.8'
3333
versionCode=1
3434

3535
compileSdkVersion=29
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.snabble.sdk;
2+
3+
import androidx.test.filters.LargeTest;
4+
import androidx.test.runner.AndroidJUnit4;
5+
6+
import org.junit.Assert;
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import java.io.IOException;
11+
12+
import okhttp3.OkHttpClient;
13+
import okhttp3.Request;
14+
import okhttp3.Response;
15+
16+
@RunWith(AndroidJUnit4.class)
17+
@LargeTest
18+
public class NetworkTest extends SnabbleSdkTest {
19+
@Test
20+
public void testLetsEncrypt() throws IOException {
21+
OkHttpClient okHttpClient = project.getOkHttpClient();
22+
23+
Response response = okHttpClient.newCall(new Request.Builder().url("https://valid-isrgrootx1.letsencrypt.org/robots.txt").build()).execute();
24+
Assert.assertTrue(response.code() == 404 || response.code() == 200);
25+
response = okHttpClient.newCall(new Request.Builder().url("https://google.com/robots.txt").build()).execute();
26+
Assert.assertTrue(response.code() == 404 || response.code() == 200);
27+
}
28+
}

core/src/main/java/io/snabble/sdk/OkHttpClientFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package io.snabble.sdk;
22

33
import android.app.Application;
4-
54
import java.util.concurrent.TimeUnit;
6-
5+
import io.snabble.sdk.utils.LetsEncryptCertHelper;
76
import io.snabble.sdk.utils.Logger;
87
import okhttp3.Cache;
98
import okhttp3.CertificatePinner;
@@ -59,6 +58,8 @@ public void log(String message) {
5958

6059
if (config.sslSocketFactory != null && config.x509TrustManager != null) {
6160
builder.sslSocketFactory(config.sslSocketFactory, config.x509TrustManager);
61+
} else {
62+
LetsEncryptCertHelper.addLetsEncryptCertificatesForMarshmallowOrEarlier(builder);
6263
}
6364

6465
return builder.build();

utils/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ dependencies {
4545

4646
implementation 'commons-io:commons-io:2.5'
4747
implementation "com.squareup.okhttp3:okhttp:${project.okhttpVersion}"
48+
implementation "com.squareup.okhttp3:okhttp-tls:${project.okhttpVersion}"
4849
implementation 'androidx.appcompat:appcompat:1.2.0'
4950
implementation 'com.google.code.gson:gson:2.8.6'
5051

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.snabble.sdk.utils;
2+
3+
import android.os.Build;
4+
5+
import java.io.ByteArrayInputStream;
6+
import java.io.UnsupportedEncodingException;
7+
import java.security.cert.Certificate;
8+
import java.security.cert.CertificateException;
9+
import java.security.cert.CertificateFactory;
10+
import java.security.cert.X509Certificate;
11+
12+
import okhttp3.OkHttpClient;
13+
import okhttp3.tls.HandshakeCertificates;
14+
15+
public class LetsEncryptCertHelper {
16+
public static void addLetsEncryptCertificatesForMarshmallowOrEarlier(OkHttpClient.Builder builder) {
17+
boolean androidMorEarlier = Build.VERSION.SDK_INT <= Build.VERSION_CODES.N;
18+
19+
if (androidMorEarlier) {
20+
String isgCert =
21+
"-----BEGIN CERTIFICATE-----\n" +
22+
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" +
23+
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" +
24+
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" +
25+
"WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" +
26+
"ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" +
27+
"MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" +
28+
"h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" +
29+
"0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" +
30+
"A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" +
31+
"T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" +
32+
"B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" +
33+
"B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" +
34+
"KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" +
35+
"OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" +
36+
"jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" +
37+
"qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" +
38+
"rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" +
39+
"HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" +
40+
"hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" +
41+
"ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" +
42+
"3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" +
43+
"NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" +
44+
"ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" +
45+
"TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" +
46+
"jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" +
47+
"oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" +
48+
"4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" +
49+
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" +
50+
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" +
51+
"-----END CERTIFICATE-----";
52+
53+
try {
54+
CertificateFactory cf = CertificateFactory.getInstance("X.509");
55+
Certificate isgCertificate = cf.generateCertificate(new ByteArrayInputStream(isgCert.getBytes("UTF-8")));
56+
57+
HandshakeCertificates certificates = new HandshakeCertificates.Builder()
58+
.addTrustedCertificate((X509Certificate) isgCertificate)
59+
.addPlatformTrustedCertificates()
60+
.build();
61+
62+
builder.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager());
63+
} catch (CertificateException | UnsupportedEncodingException e) {
64+
// ignore
65+
}
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)