@@ -3,8 +3,8 @@ package at.bitfire.cert4android.demo
33import android.Manifest
44import android.annotation.SuppressLint
55import android.app.Application
6+ import android.content.Context
67import android.content.pm.PackageManager
7- import android.net.SSLCertificateSocketFactory
88import android.os.Build
99import android.os.Bundle
1010import android.util.Log
@@ -37,10 +37,12 @@ import at.bitfire.cert4android.ThemeManager
3737import kotlinx.coroutines.Dispatchers
3838import kotlinx.coroutines.flow.MutableStateFlow
3939import kotlinx.coroutines.launch
40+ import okhttp3.OkHttpClient
41+ import okhttp3.Request
42+ import okhttp3.internal.tls.OkHostnameVerifier
4043import org.apache.http.conn.ssl.AllowAllHostnameVerifier
41- import org.apache.http.conn.ssl.StrictHostnameVerifier
42- import java.net.URL
4344import javax.net.ssl.HttpsURLConnection
45+ import javax.net.ssl.SSLContext
4446
4547class MainActivity : ComponentActivity () {
4648
@@ -66,15 +68,15 @@ class MainActivity : ComponentActivity() {
6668 }
6769
6870 Button (onClick = {
69- model.testAccess(" https://www.github .com" )
71+ model.testAccess(" https://icloud .com" )
7072 }, modifier = Modifier .padding(top = 16 .dp)) {
71- Text (" Access normal URL with trusted system certs" )
73+ Text (" Access icloud.com with trusted system certs" )
7274 }
7375
7476 Button (onClick = {
75- model.testAccess(" https://www.github .com" , trustSystemCerts = false )
77+ model.testAccess(" https://icloud .com" , trustSystemCerts = false )
7678 }, modifier = Modifier .padding(top = 16 .dp)) {
77- Text (" Access normal URL with distrusted system certs" )
79+ Text (" Access icloud.com with distrusted system certs" )
7880 }
7981
8082 Button (onClick = {
@@ -125,11 +127,8 @@ class MainActivity : ComponentActivity() {
125127
126128 class Model (application : Application ): AndroidViewModel(application) {
127129
128- companion object {
129-
130- const val TAG = " cert4android.sample-app"
131-
132- }
130+ val context: Context
131+ get() = getApplication()
133132
134133 val appInForeground = MutableStateFlow (true )
135134 val resultMessage = MutableLiveData <String >()
@@ -141,7 +140,7 @@ class MainActivity : ComponentActivity() {
141140 }
142141
143142 fun reset () = viewModelScope.launch(Dispatchers .IO ) {
144- CustomCertStore .getInstance(getApplication() ).clearUserDecisions()
143+ CustomCertStore .getInstance(context ).clearUserDecisions()
145144 }
146145
147146 fun setInForeground (foreground : Boolean ) {
@@ -150,31 +149,57 @@ class MainActivity : ComponentActivity() {
150149
151150 fun testAccess (url : String , trustSystemCerts : Boolean = true) = viewModelScope.launch(Dispatchers .IO ) {
152151 try {
153- val urlConn = URL (url).openConnection() as HttpsURLConnection
152+ val client = buildClient(trustSystemCerts)
154153
155- // set cert4android TrustManager and HostnameVerifier
156- val certMgr = CustomCertManager (
157- getApplication(),
158- trustSystemCerts = trustSystemCerts,
159- appInForeground = appInForeground
154+ // access sample URL
155+ val call = client.newCall(
156+ Request .Builder ()
157+ .get()
158+ .url(url)
159+ .build()
160160 )
161- urlConn.hostnameVerifier = certMgr.HostnameVerifier (StrictHostnameVerifier ())
162- urlConn.sslSocketFactory = object : SSLCertificateSocketFactory (/* handshakeTimeoutMillis = */ 1000 ) {
163- init {
164- setTrustManagers(arrayOf(certMgr))
165- }
161+ call.execute().use { response ->
162+ // log result
163+ Log .i(TAG , " testAccess(): HTTP ${response.code} " )
164+ resultMessage.postValue(" ${response.code} ${response.message} " )
166165 }
167-
168- // access sample URL
169- Log .i(TAG , " testAccess(): HTTP ${urlConn.responseCode} " )
170- resultMessage.postValue(" ${urlConn.responseCode} ${urlConn.responseMessage} " )
171- urlConn.inputStream.close()
172166 } catch (e: Exception ) {
173167 resultMessage.postValue(" testAccess() ERROR: ${e.message} " )
174168 Log .w(TAG , " testAccess(): ERROR: ${e.message} " )
175169 }
176170 }
177171
172+ fun buildClient (trustSystemCerts : Boolean ): OkHttpClient {
173+ val builder = OkHttpClient .Builder ()
174+
175+ // set cert4android TrustManager and HostnameVerifier
176+ val certManager = CustomCertManager (
177+ context,
178+ trustSystemCerts = trustSystemCerts,
179+ appInForeground = appInForeground
180+ )
181+
182+ val sslContext = SSLContext .getInstance(" TLS" )
183+ sslContext.init (
184+ /* km = */ null ,
185+ /* tm = */ arrayOf(certManager),
186+ /* random = */ null
187+ )
188+ builder
189+ .sslSocketFactory(sslContext.socketFactory, certManager)
190+ .hostnameVerifier(certManager.HostnameVerifier (OkHostnameVerifier ))
191+
192+ // add cache
193+ // builder.cache(Cache(context.cacheDir, 10 * 1024 * 1024))
194+
195+ return builder.build()
196+ }
197+
198+ }
199+
200+
201+ companion object {
202+ const val TAG = " cert4android.sample-app"
178203 }
179204
180205}
0 commit comments