feature: add ServerUrl
This commit is contained in:
parent
d928433590
commit
9dfd8602ec
|
|
@ -72,7 +72,7 @@ fun BaseExtension.addLibBuildType(
|
|||
buildConfigField("String", "VERSION_NAME", "\"${versionCatalog.versionName}\"")
|
||||
if (enableConfig) {
|
||||
val server = serverType ?: type.serverType
|
||||
// buildConfigField("ru.template.data.network.ServerUrl", "DEFAULT_SERVER", type.defaultServer)
|
||||
buildConfigField("ru.template.data.network.ServerUrl", "DEFAULT_SERVER", type.defaultServer)
|
||||
buildConfigField("String", "DEFAULT_SERVER_TYPE", "\"$server\"")
|
||||
buildConfigField("Boolean", "ENABLE_SSL_PINNING", type.enableSslPinning.toString())
|
||||
buildConfigField("Boolean", "ENABLE_LOGS", type.enabledLogs.toString())
|
||||
|
|
@ -132,4 +132,4 @@ sealed class BuildType(
|
|||
serverType = "Prod",
|
||||
matchingFallbacks = "release"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
import ru.template.data.network.sslpinning.ServerInfo
|
||||
import ru.template.data.network.sslpinning.UrlInfo
|
||||
|
||||
enum class ServerUrl(
|
||||
val title: String,
|
||||
val serverType: String,
|
||||
val serverInfo: ServerInfo
|
||||
) {
|
||||
CUSTOMER_PROD(
|
||||
title = "customerProd",
|
||||
serverType = "Prod",
|
||||
ServerInfo(
|
||||
UrlInfo(
|
||||
protocol = "https",
|
||||
url = "customerProd", // TODO change this url
|
||||
),
|
||||
pinsHashSet = hashSetOf()
|
||||
)
|
||||
),
|
||||
|
||||
CUSTOMER_STAGE(
|
||||
title = "customerStage",
|
||||
serverType = "Stage",
|
||||
ServerInfo(
|
||||
UrlInfo(
|
||||
protocol = "https",
|
||||
url = "customerStage", // TODO change this url
|
||||
),
|
||||
pinsHashSet = hashSetOf()
|
||||
)
|
||||
),
|
||||
|
||||
TOUCHIN_MOCK(
|
||||
title = "touchinMock",
|
||||
serverType = "Dev",
|
||||
ServerInfo(
|
||||
UrlInfo(
|
||||
protocol = "https",
|
||||
url = "touchinMock", // TODO change this url
|
||||
),
|
||||
pinsHashSet = hashSetOf()
|
||||
)
|
||||
),
|
||||
|
||||
CUSTOMER_TEST(
|
||||
title = "customerTest",
|
||||
serverType = "Test",
|
||||
ServerInfo(
|
||||
UrlInfo(
|
||||
protocol = "https",
|
||||
url = "customerTest", // TODO change this url
|
||||
),
|
||||
pinsHashSet = hashSetOf()
|
||||
)
|
||||
);
|
||||
|
||||
companion object {
|
||||
fun fromTitle(title: String?): ServerUrl? = values().associateBy { it.title }[title]
|
||||
|
||||
fun fromServerType(type: String?): ServerUrl? = values().associateBy { it.serverType }[type]
|
||||
}
|
||||
|
||||
override fun toString() = title
|
||||
|
||||
fun getBaseUrl() = serverInfo.urlInfo.getBaseUrl()
|
||||
|
||||
fun getAddress() = serverInfo.urlInfo.getAddress()
|
||||
|
||||
fun getId() = ordinal
|
||||
|
||||
fun getPins() = serverInfo.getPins()
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.template.data.network.sslpinning
|
||||
|
||||
import ru.template.data.network.storage.EncryptedStorage
|
||||
|
||||
data class ServerInfo(
|
||||
val urlInfo: UrlInfo,
|
||||
val pinsHashSet: HashSet<String>
|
||||
) {
|
||||
fun getPins() = pinsHashSet.toSet()
|
||||
|
||||
fun addPins(pinSet: Set<String>) = pinsHashSet.addAll(pinSet)
|
||||
|
||||
fun updatePins(baseUrl: String, encryptedStorage: EncryptedStorage) {
|
||||
with(pinsHashSet) {
|
||||
addAll(encryptedStorage.getCertificatesSet(baseUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.redmadrobot.data.network.sslpinning
|
||||
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
object TrustManagerUnsafe: X509TrustManager {
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) = Unit
|
||||
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) = Unit
|
||||
|
||||
override fun getAcceptedIssuers() = emptyArray<X509Certificate>()
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.redmadrobot.data.network.sslpinning
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.redmadrobot.data.network.NetworkConfig
|
||||
import com.redmadrobot.domain.extension.toHex
|
||||
import com.redmadrobot.domain.repository.ssl.SslPublicKeyRepository
|
||||
import java.security.MessageDigest
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.Locale
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
@SuppressLint("CustomX509TrustManager")
|
||||
class TrustManagerWithoutTls(
|
||||
private val networkConfig: NetworkConfig,
|
||||
private val sslPublicKeyRepository: SslPublicKeyRepository
|
||||
) : X509TrustManager {
|
||||
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) = Unit
|
||||
|
||||
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
|
||||
if (networkConfig.isSslPinningEnabled()) {
|
||||
chain?.let { checkCertificateFingerprint(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
|
||||
|
||||
private fun checkCertificateFingerprint(chain: Array<X509Certificate?>) {
|
||||
val pinFromServer = chain[0]?.let { getSha256FingerprintFormatted(it) }
|
||||
networkConfig.getCurrentServer().getPins().also {
|
||||
if (it.contains(pinFromServer)) {
|
||||
sslPublicKeyRepository.setPublicKey(isValid = true)
|
||||
return
|
||||
}
|
||||
}
|
||||
sslPublicKeyRepository.setPublicKey(isValid = false)
|
||||
throw CertificateException("Cannot validate server certificate")
|
||||
}
|
||||
|
||||
private fun getSha256FingerprintFormatted(certificate: X509Certificate): String {
|
||||
return MessageDigest
|
||||
.getInstance("SHA-256")
|
||||
.digest(certificate.encoded)
|
||||
.toHex(separator = ":").toUpperCase(Locale.getDefault())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package ru.template.data.network.sslpinning
|
||||
|
||||
data class UrlInfo(
|
||||
private val protocol: String,
|
||||
private val url: String,
|
||||
) {
|
||||
fun getAddress(): String = "$protocol://$url/api/v1/"
|
||||
|
||||
fun getBaseUrl(): String = url
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package ru.template.data.network.storage
|
||||
|
||||
import android.content.SharedPreferences
|
||||
|
||||
class EncryptedStorage(private val preferences: SharedPreferences) {
|
||||
|
||||
fun saveCertificatesToSet(host: String, certificates: Set<String>) =
|
||||
preferences.edit().putStringSet(host,
|
||||
getCertificatesSet(host).toMutableSet().apply { addAll(certificates) }.toSet()).apply()
|
||||
|
||||
|
||||
fun getCertificatesSet(host: String): Set<String>
|
||||
= preferences.getStringSet(host, emptySet()) ?: emptySet()
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue