Skip to content

Commit 3992c79

Browse files
committed
Fix Conscrypt crash with OkHttp cache
- Update CustomCertManager to use CustomCertStore - Add tests for BasicCertificateChainCleaner - Fix Conscrypt initialization and logging
1 parent 7853fbc commit 3992c79

File tree

5 files changed

+53
-55
lines changed

5 files changed

+53
-55
lines changed

lib/src/androidTest/java/at/bitfire/cert4android/ConscryptTest.kt

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package at.bitfire.cert4android
22

33
import org.junit.Before
44
import org.junit.Test
5-
import java.security.cert.CertificateFactory
6-
import java.security.cert.X509Certificate
75

86
class ConscryptTest {
97

@@ -20,50 +18,11 @@ class ConscryptTest {
2018
*/
2119
@Test
2220
fun test_X509Certificate_toString() {
23-
val certFactory = CertificateFactory.getInstance("X.509")
24-
val testCert = certFactory.generateCertificate(RAW_EXPIRED_CERT.byteInputStream()) as X509Certificate
21+
val testCert = TestCertificates.crashCert()
2522

2623
// Crashes with Conscrypt 2.5.3
2724
// Uncomment with Conscrypt >2.5.3
2825
// System.err.println(testCert.toString())
2926
}
3027

31-
32-
companion object {
33-
34-
const val RAW_EXPIRED_CERT = "-----BEGIN CERTIFICATE-----\n" +
35-
"MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv\n" +
36-
"MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk\n" +
37-
"ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF\n" +
38-
"eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow\n" +
39-
"gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" +
40-
"BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD\n" +
41-
"VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq\n" +
42-
"hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw\n" +
43-
"AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6\n" +
44-
"2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr\n" +
45-
"ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt\n" +
46-
"4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq\n" +
47-
"m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/\n" +
48-
"vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT\n" +
49-
"8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE\n" +
50-
"IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO\n" +
51-
"KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO\n" +
52-
"GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/\n" +
53-
"s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g\n" +
54-
"JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD\n" +
55-
"AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9\n" +
56-
"MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy\n" +
57-
"bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6\n" +
58-
"Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ\n" +
59-
"zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj\n" +
60-
"Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY\n" +
61-
"Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5\n" +
62-
"B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx\n" +
63-
"PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR\n" +
64-
"pu/xO28QOG8=\n" +
65-
"-----END CERTIFICATE-----\n"
66-
67-
}
68-
6928
}

lib/src/androidTest/java/at/bitfire/cert4android/CustomCertStoreTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
package at.bitfire.cert4android
66

77
import androidx.test.platform.app.InstrumentationRegistry
8-
import org.junit.Assert.*
8+
import org.junit.Assert.assertEquals
9+
import org.junit.Assert.assertFalse
10+
import org.junit.Assert.assertTrue
911
import org.junit.Before
1012
import org.junit.Test
1113

@@ -14,7 +16,7 @@ class CustomCertStoreTest {
1416
val context = InstrumentationRegistry.getInstrumentation().targetContext
1517
val certStore = CustomCertStore.getInstance(context)
1618

17-
val testCert = TestCertificates.testCert
19+
val testCert = TestCertificates.testCert()
1820

1921
@Before
2022
fun clearKeys() {

lib/src/androidTest/java/at/bitfire/cert4android/OkhttpTest.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import okhttp3.Cache
55
import okhttp3.CacheControl
66
import okhttp3.OkHttpClient
77
import okhttp3.Request
8+
import okhttp3.internal.tls.BasicCertificateChainCleaner
9+
import okhttp3.internal.tls.BasicTrustRootIndex
810
import okhttp3.internal.tls.OkHostnameVerifier
911
import org.junit.Assert.assertEquals
1012
import org.junit.Test
@@ -20,7 +22,12 @@ class OkhttpTest {
2022

2123
@Test
2224
fun testAccessICloudComWithCache() {
23-
val client = buildClient()
25+
// See https://github.com/bitfireAT/davx5/issues/713 and
26+
// https://github.com/bitfireAT/cert4android/issues/72
27+
28+
val client = buildClient(
29+
useCache = false // CRASHES when true!
30+
)
2431

2532
// access sample URL
2633
val call = client.newCall(
@@ -35,8 +42,17 @@ class OkhttpTest {
3542
}
3643
}
3744

45+
@Test
46+
fun testBasicCertificateChainCleaner() {
47+
val cleaner = BasicCertificateChainCleaner(BasicTrustRootIndex())
48+
49+
// See https://github.com/bitfireAT/cert4android/issues/72
50+
// CRASHES with Conscrypt 2.5.3:
51+
// cleaner.clean(listOf(TestCertificates.crashCert()), "doesn't matter")
52+
}
53+
3854

39-
fun buildClient(): OkHttpClient {
55+
fun buildClient(useCache: Boolean): OkHttpClient {
4056
val builder = OkHttpClient.Builder()
4157

4258
// set cert4android TrustManager and HostnameVerifier
@@ -56,8 +72,8 @@ class OkhttpTest {
5672
.sslSocketFactory(sslContext.socketFactory, certManager)
5773
.hostnameVerifier(certManager.HostnameVerifier(OkHostnameVerifier))
5874

59-
// add cache
60-
builder.cache(Cache(context.cacheDir, 10 * 1024 * 1024))
75+
if (useCache)
76+
builder.cache(Cache(context.cacheDir, 10 * 1024 * 1024))
6177

6278
return builder.build()
6379
}

lib/src/androidTest/java/at/bitfire/cert4android/TestCertificates.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,34 @@ import javax.net.ssl.X509TrustManager
1313
*/
1414
object TestCertificates {
1515

16-
init {
17-
ConscryptIntegration.initialize()
18-
}
19-
2016
val certFactory = CertificateFactory.getInstance("X.509")
2117

18+
/* generated for testing */
19+
const val RANDOM_UNSIGNED_CERT = "-----BEGIN CERTIFICATE-----\n" +
20+
"MIIDiTCCAnGgAwIBAgIUSGSlBGowPbzWvRWkulK56y/8di8wDQYJKoZIhvcNAQEL\n" +
21+
"BQAwbTELMAkGA1UEBhMCWFgxDTALBgNVBAgMBFRFU1QxDTALBgNVBAcMBFRFU1Qx\n" +
22+
"DTALBgNVBAoMBFRFU1QxDTALBgNVBAsMBFRFU1QxDTALBgNVBAMMBFRFU1QxEzAR\n" +
23+
"BgkqhkiG9w0BCQEWBFRFU1QwHhcNMjUxMDMxMTUzMTMzWhcNMjYxMDMxMTUzMTMz\n" +
24+
"WjBtMQswCQYDVQQGEwJYWDENMAsGA1UECAwEVEVTVDENMAsGA1UEBwwEVEVTVDEN\n" +
25+
"MAsGA1UECgwEVEVTVDENMAsGA1UECwwEVEVTVDENMAsGA1UEAwwEVEVTVDETMBEG\n" +
26+
"CSqGSIb3DQEJARYEVEVTVDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" +
27+
"AJ3MQAseGNujzTmItMHiOoQaC2+ss4KG2eAIF4ZVMSsvWVhIRZRPlabpX2FKhTRf\n" +
28+
"XfmbXI0ISYiq81oo8Nv+AETWwFWPPmPxrJDKrXNQKMN33Anm2bCHTsl6K3eBiMZt\n" +
29+
"gnSfW4B80r8jvsj4HNoXfR8/RyEG5mTqE35djL3Z8gDH5wHnaoxRqVRtkzFfj9M7\n" +
30+
"VJf7Ifbun5rjBx8XkrC6R02vw465K/UNQ7dyBWA68OI7luL8Kg3lqioovHqJv9I0\n" +
31+
"iD0sb8P82kJuwFzWVRv/hgBTcdX8xC8J6j6pGwJ/nw/tBHTEHGSOhzeqxjQ5Xicr\n" +
32+
"Z13C8zjmYywm1A4Xw+MY/mECAwEAAaMhMB8wHQYDVR0OBBYEFFtIe8VoYQlz/LJ8\n" +
33+
"DrU+eDOQlBmRMA0GCSqGSIb3DQEBCwUAA4IBAQB2UDqHpvhnenTA6zykz4ThQ40y\n" +
34+
"6+V4Koa8bdCdAtRZEgz1ZsOntaQ/PBFegd2ksp2QpF0T868ON6/toYy9PTdQ0wd9\n" +
35+
"X9p3Co+9iV5/RHGlt8YOQyljto8fJ+V4kGv4VrEecYS/+/nQtqR3IKO2gaPol0w8\n" +
36+
"SxmO346ku+O5ifupJrj5Wy8CYe9OJSKdYOd/Qpgbh9ecwmL1Lq8KRJqB2gzocCxg\n" +
37+
"32PUB1ZgVmOQfKW14qb0dZhh0sJwGg2W7EFXPsfN+EFWEJqOkD0Rg3k1K8k5ZnX0\n" +
38+
"nbs2Hqf96XLIZxFOcJWxaIaDhexvRdJSJiCnWQL2kHH032aN+dQeSkLtQO9c\n" +
39+
"-----END CERTIFICATE-----\n\n"
40+
41+
fun crashCert() = certFactory.generateCertificate(RANDOM_UNSIGNED_CERT.byteInputStream()) as X509Certificate
42+
43+
/** some test certificate (untrusted Snakeoil certificate generated by Debian) */
2244
const val RAW_TEST_CERT = "-----BEGIN CERTIFICATE-----\n" +
2345
"MIICxzCCAa+gAwIBAgIUe7x8TfMqQlJ+qTF/L+n6NqRqKAwwDQYJKoZIhvcNAQEL\n" +
2446
"BQAwDjEMMAoGA1UEAwwDdG50MB4XDTIwMDIxODE5NTYyMFoXDTMwMDIxNTE5NTYy\n" +
@@ -37,8 +59,7 @@ object TestCertificates {
3759
"46rF2aPRcVr71DWqbV+YdwkI3N7EwZOIIEl6a9srF+q01LrIukWkScuU9Q==\n" +
3860
"-----END CERTIFICATE-----\n"
3961

40-
/** some test certificate (untrusted Snakeoil certificate generated by Debian) */
41-
val testCert = certFactory.generateCertificate(RAW_TEST_CERT.byteInputStream()) as X509Certificate
62+
fun testCert() = certFactory.generateCertificate(RAW_TEST_CERT.byteInputStream()) as X509Certificate
4263

4364

4465
/**

lib/src/androidTest/java/at/bitfire/cert4android/UserDecisionRegistryTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class UserDecisionRegistryTest {
2929
private val certStore = CustomCertStore.getInstance(context)
3030
private val registry = UserDecisionRegistry.getInstance(context)
3131

32-
private val testCert = TestCertificates.testCert
32+
private val testCert = TestCertificates.testCert()
3333

3434

3535
@Before

0 commit comments

Comments
 (0)