This repository was archived by the owner on Jun 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 545
Expand file tree
/
Copy pathClientCertHelper.kt
More file actions
161 lines (134 loc) · 5.97 KB
/
ClientCertHelper.kt
File metadata and controls
161 lines (134 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package chat.rocket.android.helper
import android.app.Application
import android.os.AsyncTask
import android.security.KeyChain
import java.net.Socket
import java.security.KeyStore
import java.security.Principal
import java.security.PrivateKey
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import javax.net.ssl.X509ExtendedKeyManager
import javax.net.ssl.KeyManager
import chat.rocket.android.server.domain.GetClientCertInteractor
import chat.rocket.android.util.HttpLoggingInterceptor
import chat.rocket.android.util.BasicAuthenticatorInterceptor
import okhttp3.OkHttpClient
import javax.inject.Inject
import javax.inject.Singleton
import java.util.concurrent.TimeUnit
import chat.rocket.android.util.ClientCertInterceptor
data class SslStuff(val privKey: PrivateKey, val certChain: Array<X509Certificate>)
class SslTask @Inject constructor(
private val context: Application,
private val getClientCertInteractor: GetClientCertInteractor,
private val logger: HttpLoggingInterceptor,
private val basicAuthenticator: BasicAuthenticatorInterceptor,
private val clientCertHelper: ClientCertHelper
): AsyncTask<Void, Void, SslStuff>() {
override fun doInBackground(vararg params: Void?): SslStuff {
var alias = getClientCertInteractor.get()
alias = alias.toString()
val privKey = KeyChain.getPrivateKey(context.applicationContext, alias)
val certChain = KeyChain.getCertificateChain(context.applicationContext, alias)
return SslStuff(privKey, certChain)
}
override fun onPostExecute(result: SslStuff?) {
var alias = getClientCertInteractor.get()
if (result != null && !clientCertHelper.getSetSslSocket()) {
alias = alias.toString()
val (privateKey, certificates) = result
val trustStore = KeyStore.getInstance(KeyStore.getDefaultType())
val keyManager = object : X509ExtendedKeyManager() {
override fun chooseClientAlias(strings: Array<String>, principals: Array<Principal>?, socket: Socket): String {
return alias
}
override fun chooseServerAlias(s: String, principals: Array<Principal>, socket: Socket): String {
return alias
}
override fun getCertificateChain(s: String): Array<X509Certificate>? {
return certificates
}
override fun getClientAliases(s: String, principals: Array<Principal>): Array<String> {
return arrayOf(alias)
}
override fun getServerAliases(s: String, principals: Array<Principal>): Array<String> {
return arrayOf(alias)
}
override fun getPrivateKey(s: String): PrivateKey? {
return privateKey
}
}
val trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustFactory.init(trustStore)
val tm = arrayOf<X509TrustManager>(object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return certificates
}
fun isClientTrusted(arg0: Array<X509Certificate>): Boolean {
return true
}
fun isServerTrusted(arg0: Array<X509Certificate>): Boolean {
return true
}
})
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(arrayOf<KeyManager>(keyManager), tm, null)
SSLContext.setDefault(sslContext)
if (!clientCertHelper.getSetSslSocket()) {
clientCertHelper.setOkHttpClient(OkHttpClient.Builder()
.addInterceptor(logger)
.addInterceptor(basicAuthenticator)
.sslSocketFactory(sslContext.socketFactory)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build())
}
}
}
}
@Singleton
class ClientCertHelper @Inject constructor(
private val context: Application,
private val getClientCertInteractor: GetClientCertInteractor,
private val logger: HttpLoggingInterceptor,
private val basicAuthenticator: BasicAuthenticatorInterceptor
) {
private val clientCert: ClientCertInterceptor = ClientCertInterceptor(this)
private var setSslSocket: Boolean = false
private var okHttpClient: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(clientCert)
.addInterceptor(logger)
.addInterceptor(basicAuthenticator)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build()
fun getEnabled(): Boolean {
var alias = getClientCertInteractor.get()
return !alias.isNullOrEmpty()
}
fun getSetSslSocket(): Boolean {
return this.setSslSocket
}
fun setOkHttpClient(client: OkHttpClient) {
this.okHttpClient = client
this.setSslSocket = true
}
fun getClient(): OkHttpClient {
if (this.getEnabled() && !this.setSslSocket) {
SslTask(context, getClientCertInteractor, logger, basicAuthenticator, this).execute()
}
return this.okHttpClient
}
}