Add SslManager

This commit is contained in:
Aidan Follestad 2019-01-11 17:56:21 -08:00
commit 55ea6674e6
3 changed files with 94 additions and 1 deletions

2
.idea/misc.xml generated
View file

@ -40,7 +40,7 @@
</value> </value>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View file

@ -15,6 +15,8 @@
*/ */
package com.afollestad.nocknock.engine package com.afollestad.nocknock.engine
import com.afollestad.nocknock.engine.ssl.RealSslManager
import com.afollestad.nocknock.engine.ssl.SslManager
import com.afollestad.nocknock.engine.validation.RealValidationExecutor import com.afollestad.nocknock.engine.validation.RealValidationExecutor
import com.afollestad.nocknock.engine.validation.ValidationExecutor import com.afollestad.nocknock.engine.validation.ValidationExecutor
import org.koin.dsl.module.module import org.koin.dsl.module.module
@ -25,4 +27,6 @@ val engineModule = module {
single { single {
RealValidationExecutor(get(), get(), get(), get(), get(), get()) RealValidationExecutor(get(), get(), get(), get(), get(), get())
} bind ValidationExecutor::class } bind ValidationExecutor::class
factory { RealSslManager(get()) } bind SslManager::class
} }

View file

@ -0,0 +1,89 @@
/**
* Designed and developed by Aidan Follestad (@afollestad)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.afollestad.nocknock.engine.ssl
import android.app.Application
import android.content.Context
import android.net.Uri
import androidx.annotation.CheckResult
import okhttp3.OkHttpClient
import java.io.BufferedInputStream
import java.io.FileInputStream
import java.security.KeyStore
import java.security.cert.CertificateFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import timber.log.Timber.d as log
/** @author Aidan Follestad (@afollestad) */
interface SslManager {
@CheckResult fun clientForCertificate(
certUri: Uri,
host: String,
client: OkHttpClient
): OkHttpClient
}
/** @author Aidan Follestad (@afollestad) **/
class RealSslManager(
private val app: Application
) : SslManager {
override fun clientForCertificate(
certUri: Uri,
host: String,
client: OkHttpClient
): OkHttpClient {
log("Loading certificate $certUri for host $host")
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null, null)
val certInputStream = app.openUri(certUri)
val bis = BufferedInputStream(certInputStream)
val certificateFactory = CertificateFactory.getInstance("X.509")
while (bis.available() > 0) {
val cert = certificateFactory.generateCertificate(bis)
keyStore.setCertificateEntry(host, cert)
}
val trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)
val trustManagers = trustManagerFactory.trustManagers
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustManagers, null)
val trustManager = trustManagers.first() as X509TrustManager
log("Loaded successfully!")
return client.newBuilder()
.sslSocketFactory(sslContext.socketFactory, trustManager)
.build()
}
}
private fun Context.openUri(uri: Uri) = when (uri.scheme) {
"content" -> {
contentResolver.openInputStream(uri) ?: throw IllegalStateException(
"Unable to open input stream to $uri"
)
}
"file" -> FileInputStream(uri.path)
else -> FileInputStream(uri.toString())
}