95 lines
3.2 KiB
Kotlin
95 lines
3.2 KiB
Kotlin
package org.moire.ultrasonic.api.subsonic
|
|
|
|
import okhttp3.mockwebserver.MockWebServer
|
|
import org.amshove.kluent.`should throw`
|
|
import org.junit.After
|
|
import org.junit.Before
|
|
import org.junit.Test
|
|
import java.io.InputStream
|
|
import java.net.InetAddress
|
|
import java.security.KeyStore
|
|
import java.security.cert.CertificateFactory
|
|
import java.security.cert.X509Certificate
|
|
import javax.net.ssl.KeyManagerFactory
|
|
import javax.net.ssl.SSLContext
|
|
import javax.net.ssl.SSLHandshakeException
|
|
import javax.net.ssl.TrustManagerFactory
|
|
|
|
private const val PORT = 8443
|
|
private const val HOST = "localhost"
|
|
|
|
/**
|
|
* Integration test to check [SubsonicAPIClient] interaction with different SSL scenarios.
|
|
*/
|
|
class SubsonicApiSSLTest {
|
|
private val mockWebServer = MockWebServer()
|
|
|
|
@Before
|
|
fun setUp() {
|
|
val sslContext = createSSLContext(loadResourceStream("self-signed.pem"),
|
|
loadResourceStream("self-signed.p12"), "")
|
|
mockWebServer.useHttps(sslContext.socketFactory, false)
|
|
mockWebServer.start(InetAddress.getByName(HOST), PORT)
|
|
}
|
|
|
|
@After
|
|
fun tearDown() {
|
|
mockWebServer.shutdown()
|
|
}
|
|
|
|
private fun createSSLContext(certificatePemStream: InputStream,
|
|
certificatePkcs12Stream: InputStream,
|
|
password: String): SSLContext {
|
|
var cert: X509Certificate? = null
|
|
val trustStore = KeyStore.getInstance(KeyStore.getDefaultType())
|
|
trustStore.load(null)
|
|
|
|
certificatePemStream.use {
|
|
cert = (CertificateFactory.getInstance("X.509")
|
|
.generateCertificate(certificatePemStream)) as X509Certificate
|
|
}
|
|
val alias = cert?.subjectX500Principal?.name
|
|
?: throw IllegalStateException("Failed to load certificate")
|
|
trustStore.setCertificateEntry(alias, cert)
|
|
|
|
val tmf = TrustManagerFactory.getInstance("X509")
|
|
tmf.init(trustStore)
|
|
val trustManagers = tmf.trustManagers
|
|
val sslContext = SSLContext.getInstance("TLS")
|
|
|
|
val ks = KeyStore.getInstance("PKCS12")
|
|
ks.load(certificatePkcs12Stream, password.toCharArray())
|
|
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
|
|
kmf.init(ks, password.toCharArray())
|
|
|
|
sslContext.init(kmf.keyManagers, trustManagers, null)
|
|
return sslContext
|
|
}
|
|
|
|
@Test
|
|
fun `Should fail request if self-signed certificate support is disabled`() {
|
|
val client = createSubsonicClient(false)
|
|
mockWebServer.enqueueResponse("ping_ok.json")
|
|
|
|
val fail = {
|
|
client.api.ping().execute()
|
|
}
|
|
|
|
fail `should throw` SSLHandshakeException::class
|
|
}
|
|
|
|
@Test
|
|
fun `Should pass request if self-signed certificate support is enabled`() {
|
|
val client = createSubsonicClient(true)
|
|
mockWebServer.enqueueResponse("ping_ok.json")
|
|
|
|
val response = client.api.ping().execute()
|
|
|
|
assertResponseSuccessful(response)
|
|
}
|
|
|
|
private fun createSubsonicClient(allowSelfSignedCertificate: Boolean) = SubsonicAPIClient(
|
|
"https://$HOST:$PORT/", USERNAME, PASSWORD, CLIENT_VERSION, CLIENT_ID,
|
|
allowSelfSignedCertificate = allowSelfSignedCertificate)
|
|
}
|