mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Refactoring verification
This commit is contained in:
@@ -170,7 +170,7 @@ class PasskeyLauncherActivity : DatabaseModeActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}) {
|
}) {
|
||||||
val searchInfo = intent.retrieveSearchInfo() ?: SearchInfo()
|
val searchInfo = intent.retrieveSearchInfo() ?: SearchInfo()
|
||||||
val appOrigin = intent.retrieveAppOrigin() ?: AppOrigin()
|
val appOrigin = intent.retrieveAppOrigin() ?: AppOrigin(verified = false)
|
||||||
val nodeId = intent.retrieveNodeId()
|
val nodeId = intent.retrieveNodeId()
|
||||||
checkSecurity(intent, nodeId)
|
checkSecurity(intent, nodeId)
|
||||||
when (mSpecialMode) {
|
when (mSpecialMode) {
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2025 Jeremy Jamet / Kunzisoft.
|
|
||||||
*
|
|
||||||
* This file is part of KeePassDX.
|
|
||||||
*
|
|
||||||
* KeePassDX is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* KeePassDX is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.kunzisoft.keepass.credentialprovider.passkey.util
|
|
||||||
|
|
||||||
import android.content.res.AssetManager
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.credentials.provider.CallingAppInfo
|
|
||||||
import com.kunzisoft.encrypt.HashManager.getApplicationFingerprints
|
|
||||||
import com.kunzisoft.keepass.model.AndroidOrigin
|
|
||||||
import com.kunzisoft.keepass.model.AppOrigin
|
|
||||||
import com.kunzisoft.keepass.model.WebOrigin
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class to manage the origin of credential provider applications
|
|
||||||
*/
|
|
||||||
@RequiresApi(Build.VERSION_CODES.P)
|
|
||||||
class OriginManager(
|
|
||||||
private val providedClientDataHash: ByteArray?,
|
|
||||||
private val callingAppInfo: CallingAppInfo?,
|
|
||||||
private val assets: AssetManager,
|
|
||||||
private val relyingParty: String,
|
|
||||||
) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the Android origin to be stored in the database,
|
|
||||||
* call [onOriginRetrieved] if the origin is already calculated by the system
|
|
||||||
* call [onOriginCreated] if the origin was created manually, origin is verified if present in the KeePass database
|
|
||||||
*/
|
|
||||||
suspend fun getOriginAtCreation(
|
|
||||||
onOriginRetrieved: (appInfoToStore: AppOrigin, clientDataHash: ByteArray) -> Unit,
|
|
||||||
onOriginCreated: (appInfoToStore: AppOrigin, origin: String) -> Unit
|
|
||||||
) {
|
|
||||||
getOrigin(
|
|
||||||
onOriginRetrieved = { androidOrigin, webOrigin, callOrigin, clientDataHash ->
|
|
||||||
onOriginRetrieved(
|
|
||||||
AppOrigin().apply {
|
|
||||||
addAndroidOrigin(androidOrigin)
|
|
||||||
addWebOrigin(webOrigin)
|
|
||||||
},
|
|
||||||
clientDataHash
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onOriginNotRetrieved = { appIdentifier, webOrigin ->
|
|
||||||
// Create a new Android Origin and prepare the signature app storage
|
|
||||||
onOriginCreated(
|
|
||||||
AppOrigin().apply {
|
|
||||||
addAndroidOrigin(appIdentifier)
|
|
||||||
addWebOrigin(webOrigin)
|
|
||||||
},
|
|
||||||
appIdentifier.toAndroidOrigin()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the origin to verify usage,
|
|
||||||
* calls [onOriginRetrieved] if the origin is already calculated by the system
|
|
||||||
* calls [onOriginCreated] if the origin was created manually, origin is verified if present in the KeePass database
|
|
||||||
*/
|
|
||||||
suspend fun getOriginAtUsage(
|
|
||||||
onOriginRetrieved: (appOrigin: AppOrigin, clientDataHash: ByteArray) -> Unit,
|
|
||||||
onOriginCreated: (appOrigin: AppOrigin) -> Unit
|
|
||||||
) {
|
|
||||||
getOrigin(
|
|
||||||
onOriginRetrieved = { androidOrigin, webOrigin, origin, clientDataHash ->
|
|
||||||
onOriginRetrieved(
|
|
||||||
AppOrigin().apply {
|
|
||||||
addAndroidOrigin(androidOrigin)
|
|
||||||
addWebOrigin(webOrigin)
|
|
||||||
},
|
|
||||||
clientDataHash
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onOriginNotRetrieved = { androidOrigin, webOrigin ->
|
|
||||||
// Check the app signature in the appOrigin, webOrigin cannot be checked now
|
|
||||||
onOriginCreated(
|
|
||||||
AppOrigin().apply {
|
|
||||||
addAndroidOrigin(androidOrigin)
|
|
||||||
addWebOrigin(webOrigin)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method to retrieve the origin asynchronously,
|
|
||||||
* checks for the presence of the application in the privilege list of the trustedPackages.json file,
|
|
||||||
* call [onOriginRetrieved] if the origin is already calculated by the system and in the privileged list
|
|
||||||
* call [onOriginNotRetrieved] if the origin is not retrieved from the system
|
|
||||||
*/
|
|
||||||
private suspend fun getOrigin(
|
|
||||||
onOriginRetrieved: (androidOrigin: AndroidOrigin, webOrigin: WebOrigin, origin: String, clientDataHash: ByteArray) -> Unit,
|
|
||||||
onOriginNotRetrieved: (androidOrigin: AndroidOrigin, webOrigin: WebOrigin) -> Unit
|
|
||||||
) {
|
|
||||||
if (callingAppInfo == null) {
|
|
||||||
throw SecurityException("Calling app info cannot be retrieved")
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
var callOrigin: String?
|
|
||||||
val privilegedAllowlist = assets.open("trustedPackages.json").bufferedReader().use {
|
|
||||||
it.readText()
|
|
||||||
}
|
|
||||||
// for trusted browsers like Chrome and Firefox
|
|
||||||
callOrigin = callingAppInfo.getOrigin(privilegedAllowlist)?.removeSuffix("/")
|
|
||||||
val androidOrigin = AndroidOrigin(
|
|
||||||
packageName = callingAppInfo.packageName,
|
|
||||||
fingerprint = callingAppInfo.signingInfo.getApplicationFingerprints(),
|
|
||||||
verified = false
|
|
||||||
)
|
|
||||||
val webOrigin = WebOrigin.fromRelyingParty(
|
|
||||||
relyingParty = relyingParty,
|
|
||||||
verified = false
|
|
||||||
)
|
|
||||||
// Check if the webDomain is validated for the
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
if (callOrigin != null && providedClientDataHash != null) {
|
|
||||||
Log.d(TAG, "Origin $callOrigin retrieved from callingAppInfo")
|
|
||||||
// TODO verified callOrigin
|
|
||||||
onOriginRetrieved(
|
|
||||||
AndroidOrigin(
|
|
||||||
packageName = androidOrigin.packageName,
|
|
||||||
fingerprint = androidOrigin.fingerprint,
|
|
||||||
verified = true
|
|
||||||
),
|
|
||||||
WebOrigin(
|
|
||||||
origin = webOrigin.origin,
|
|
||||||
verified = true
|
|
||||||
),
|
|
||||||
callOrigin,
|
|
||||||
providedClientDataHash
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
onOriginNotRetrieved(
|
|
||||||
androidOrigin,
|
|
||||||
webOrigin
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG = OriginManager::class.simpleName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -35,11 +35,13 @@ import androidx.credentials.GetPublicKeyCredentialOption
|
|||||||
import androidx.credentials.PublicKeyCredential
|
import androidx.credentials.PublicKeyCredential
|
||||||
import androidx.credentials.exceptions.CreateCredentialUnknownException
|
import androidx.credentials.exceptions.CreateCredentialUnknownException
|
||||||
import androidx.credentials.exceptions.GetCredentialUnknownException
|
import androidx.credentials.exceptions.GetCredentialUnknownException
|
||||||
|
import androidx.credentials.provider.CallingAppInfo
|
||||||
import androidx.credentials.provider.PendingIntentHandler
|
import androidx.credentials.provider.PendingIntentHandler
|
||||||
import androidx.credentials.provider.ProviderCreateCredentialRequest
|
import androidx.credentials.provider.ProviderCreateCredentialRequest
|
||||||
import androidx.credentials.provider.ProviderGetCredentialRequest
|
import androidx.credentials.provider.ProviderGetCredentialRequest
|
||||||
import com.kunzisoft.asymmetric.Signature
|
import com.kunzisoft.asymmetric.Signature
|
||||||
import com.kunzisoft.encrypt.Base64Helper.Companion.b64Encode
|
import com.kunzisoft.encrypt.Base64Helper.Companion.b64Encode
|
||||||
|
import com.kunzisoft.encrypt.HashManager.getApplicationFingerprints
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.AuthenticatorAssertionResponse
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.AuthenticatorAssertionResponse
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.AuthenticatorAttestationResponse
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.AuthenticatorAttestationResponse
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.Cbor
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.Cbor
|
||||||
@@ -51,13 +53,17 @@ import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredential
|
|||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialCreationParameters
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialCreationParameters
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialRequestOptions
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialRequestOptions
|
||||||
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialUsageParameters
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialUsageParameters
|
||||||
|
import com.kunzisoft.keepass.model.AndroidOrigin
|
||||||
import com.kunzisoft.keepass.model.AppOrigin
|
import com.kunzisoft.keepass.model.AppOrigin
|
||||||
import com.kunzisoft.keepass.model.EntryInfo
|
import com.kunzisoft.keepass.model.EntryInfo
|
||||||
import com.kunzisoft.keepass.model.Passkey
|
import com.kunzisoft.keepass.model.Passkey
|
||||||
import com.kunzisoft.keepass.model.SearchInfo
|
import com.kunzisoft.keepass.model.SearchInfo
|
||||||
|
import com.kunzisoft.keepass.model.WebOrigin
|
||||||
import com.kunzisoft.keepass.utils.StringUtil.toHexString
|
import com.kunzisoft.keepass.utils.StringUtil.toHexString
|
||||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||||
import com.kunzisoft.random.KeePassDXRandom
|
import com.kunzisoft.random.KeePassDXRandom
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -320,6 +326,59 @@ object PasskeyHelper {
|
|||||||
return request.credentialOptions[0] as GetPublicKeyCredentialOption
|
return request.credentialOptions[0] as GetPublicKeyCredentialOption
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method to retrieve the origin asynchronously,
|
||||||
|
* checks for the presence of the application in the privilege list of the trustedPackages.json file,
|
||||||
|
* call [onOriginRetrieved] if the origin is already calculated by the system and in the privileged list, return the clientDataHash
|
||||||
|
* call [onOriginNotRetrieved] if the origin is not retrieved from the system, return a new Android Origin
|
||||||
|
*/
|
||||||
|
suspend fun getOrigin(
|
||||||
|
providedClientDataHash: ByteArray?,
|
||||||
|
callingAppInfo: CallingAppInfo?,
|
||||||
|
assets: AssetManager,
|
||||||
|
relyingParty: String,
|
||||||
|
onOriginRetrieved: (appOrigin: AppOrigin, clientDataHash: ByteArray) -> Unit,
|
||||||
|
onOriginNotRetrieved: (appOrigin: AppOrigin, androidOriginString: String) -> Unit
|
||||||
|
) {
|
||||||
|
if (callingAppInfo == null) {
|
||||||
|
throw SecurityException("Calling app info cannot be retrieved")
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
var callOrigin: String?
|
||||||
|
val privilegedAllowlist = assets.open("trustedPackages.json").bufferedReader().use {
|
||||||
|
it.readText()
|
||||||
|
}
|
||||||
|
// for trusted browsers like Chrome and Firefox
|
||||||
|
callOrigin = callingAppInfo.getOrigin(privilegedAllowlist)?.removeSuffix("/")
|
||||||
|
val androidOrigin = AndroidOrigin(
|
||||||
|
packageName = callingAppInfo.packageName,
|
||||||
|
fingerprint = callingAppInfo.signingInfo.getApplicationFingerprints()
|
||||||
|
)
|
||||||
|
val webOrigin = WebOrigin.fromRelyingParty(
|
||||||
|
relyingParty = relyingParty
|
||||||
|
)
|
||||||
|
// Check if the webDomain is validated for the
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (callOrigin != null && providedClientDataHash != null) {
|
||||||
|
// Origin already defined by the system
|
||||||
|
Log.d(javaClass.simpleName, "Origin $callOrigin retrieved from callingAppInfo")
|
||||||
|
onOriginRetrieved(
|
||||||
|
AppOrigin.fromOrigin(callOrigin, androidOrigin, verified = true),
|
||||||
|
providedClientDataHash
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Add Android origin by default
|
||||||
|
onOriginNotRetrieved(
|
||||||
|
AppOrigin(verified = false).apply {
|
||||||
|
addAndroidOrigin(androidOrigin)
|
||||||
|
},
|
||||||
|
androidOrigin.toAndroidOrigin()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method to create a passkey and the associated creation request parameters
|
* Utility method to create a passkey and the associated creation request parameters
|
||||||
* [intent] allows to retrieve the request
|
* [intent] allows to retrieve the request
|
||||||
@@ -360,12 +419,11 @@ object PasskeyHelper {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// create new entry in database
|
// create new entry in database
|
||||||
OriginManager(
|
getOrigin(
|
||||||
providedClientDataHash = clientDataHash,
|
providedClientDataHash = clientDataHash,
|
||||||
callingAppInfo = callingAppInfo,
|
callingAppInfo = callingAppInfo,
|
||||||
assets = assetManager,
|
assets = assetManager,
|
||||||
relyingParty = relyingParty
|
relyingParty = relyingParty,
|
||||||
).getOriginAtCreation(
|
|
||||||
onOriginRetrieved = { appInfoToStore, clientDataHash ->
|
onOriginRetrieved = { appInfoToStore, clientDataHash ->
|
||||||
passkeyCreated.invoke(
|
passkeyCreated.invoke(
|
||||||
passkey,
|
passkey,
|
||||||
@@ -378,7 +436,7 @@ object PasskeyHelper {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOriginCreated = { appInfoToStore, origin ->
|
onOriginNotRetrieved = { appInfoToStore, origin ->
|
||||||
passkeyCreated.invoke(
|
passkeyCreated.invoke(
|
||||||
passkey,
|
passkey,
|
||||||
appInfoToStore,
|
appInfoToStore,
|
||||||
@@ -451,12 +509,11 @@ object PasskeyHelper {
|
|||||||
|
|
||||||
val requestOptions = PublicKeyCredentialRequestOptions(credentialOption.requestJson)
|
val requestOptions = PublicKeyCredentialRequestOptions(credentialOption.requestJson)
|
||||||
|
|
||||||
OriginManager(
|
getOrigin(
|
||||||
providedClientDataHash = clientDataHash,
|
providedClientDataHash = clientDataHash,
|
||||||
callingAppInfo = callingAppInfo,
|
callingAppInfo = callingAppInfo,
|
||||||
assets = assetManager,
|
assets = assetManager,
|
||||||
relyingParty = requestOptions.rpId
|
relyingParty = requestOptions.rpId,
|
||||||
).getOriginAtUsage(
|
|
||||||
onOriginRetrieved = { appOrigin, clientDataHash ->
|
onOriginRetrieved = { appOrigin, clientDataHash ->
|
||||||
result.invoke(
|
result.invoke(
|
||||||
PublicKeyCredentialUsageParameters(
|
PublicKeyCredentialUsageParameters(
|
||||||
@@ -466,7 +523,7 @@ object PasskeyHelper {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOriginCreated = { appOrigin ->
|
onOriginNotRetrieved = { appOrigin, androidOriginString ->
|
||||||
// By default we crate an usage parameter with Android origin
|
// By default we crate an usage parameter with Android origin
|
||||||
result.invoke(
|
result.invoke(
|
||||||
PublicKeyCredentialUsageParameters(
|
PublicKeyCredentialUsageParameters(
|
||||||
@@ -474,7 +531,7 @@ object PasskeyHelper {
|
|||||||
clientDataResponse = ClientDataBuildResponse(
|
clientDataResponse = ClientDataBuildResponse(
|
||||||
type = ClientDataBuildResponse.Type.GET,
|
type = ClientDataBuildResponse.Type.GET,
|
||||||
challenge = requestOptions.challenge,
|
challenge = requestOptions.challenge,
|
||||||
origin = appOrigin.toAppOrigin()
|
origin = androidOriginString
|
||||||
),
|
),
|
||||||
appOrigin = appOrigin
|
appOrigin = appOrigin
|
||||||
)
|
)
|
||||||
@@ -522,7 +579,7 @@ object PasskeyHelper {
|
|||||||
return if (appToCheck.verified) {
|
return if (appToCheck.verified) {
|
||||||
usageParameters.clientDataResponse
|
usageParameters.clientDataResponse
|
||||||
} else {
|
} else {
|
||||||
appOrigin.checkAppOrigin(appToCheck)?.let { origin ->
|
appToCheck.checkAppOrigin(appOrigin)?.let { origin ->
|
||||||
// Origin checked by Android app signature
|
// Origin checked by Android app signature
|
||||||
ClientDataBuildResponse(
|
ClientDataBuildResponse(
|
||||||
type = ClientDataBuildResponse.Type.GET,
|
type = ClientDataBuildResponse.Type.GET,
|
||||||
|
|||||||
@@ -20,13 +20,16 @@
|
|||||||
package com.kunzisoft.keepass.model
|
package com.kunzisoft.keepass.model
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import android.util.Log
|
||||||
import com.kunzisoft.encrypt.HashManager.fingerprintToUrlSafeBase64
|
import com.kunzisoft.encrypt.HashManager.fingerprintToUrlSafeBase64
|
||||||
|
import com.kunzisoft.keepass.model.WebOrigin.Companion.RELYING_PARTY_DEFAULT_PROTOCOL
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class AppOrigin(
|
data class AppOrigin(
|
||||||
|
val verified: Boolean,
|
||||||
val androidOrigins: MutableList<AndroidOrigin> = mutableListOf(),
|
val androidOrigins: MutableList<AndroidOrigin> = mutableListOf(),
|
||||||
val webOrigins: MutableList<WebOrigin> = mutableListOf()
|
val webOrigins: MutableList<WebOrigin> = mutableListOf(),
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
fun addAndroidOrigin(androidOrigin: AndroidOrigin) {
|
fun addAndroidOrigin(androidOrigin: AndroidOrigin) {
|
||||||
@@ -37,22 +40,21 @@ data class AppOrigin(
|
|||||||
this.webOrigins.add(webOrigin)
|
this.webOrigins.add(webOrigin)
|
||||||
}
|
}
|
||||||
|
|
||||||
val verified: Boolean
|
|
||||||
get() = androidOrigins.any { it.verified }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the app origin by comparing it to the list of android origins,
|
* Verify the app origin by comparing it to the list of android origins,
|
||||||
* return the first verified origin or null if none is found
|
* return the first verified origin or null if none is found
|
||||||
*/
|
*/
|
||||||
fun checkAppOrigin(appToCheck: AppOrigin): String? {
|
fun checkAppOrigin(compare: AppOrigin): String? {
|
||||||
return androidOrigins.firstOrNull { androidOrigin ->
|
return androidOrigins.firstOrNull { androidOrigin ->
|
||||||
appToCheck.androidOrigins.any {
|
compare.androidOrigins.any {
|
||||||
it.packageName == androidOrigin.packageName
|
it.packageName == androidOrigin.packageName
|
||||||
&& it.fingerprint == androidOrigin.fingerprint
|
&& it.fingerprint == androidOrigin.fingerprint
|
||||||
}
|
}
|
||||||
}?.let {
|
}?.let {
|
||||||
AndroidOrigin(it.packageName, it.fingerprint, true)
|
AndroidOrigin(
|
||||||
.toAndroidOrigin()
|
packageName = it.packageName,
|
||||||
|
fingerprint = it.fingerprint
|
||||||
|
).toAndroidOrigin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +67,6 @@ data class AppOrigin(
|
|||||||
return androidOrigins.isEmpty() && webOrigins.isEmpty()
|
return androidOrigins.isEmpty() && webOrigins.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toAppOrigin(): String {
|
|
||||||
return androidOrigins.firstOrNull()?.toAndroidOrigin()
|
|
||||||
?: throw SecurityException("No app origin found")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toName(): String? {
|
fun toName(): String? {
|
||||||
return if (androidOrigins.isNotEmpty()) {
|
return if (androidOrigins.isNotEmpty()) {
|
||||||
androidOrigins.first().packageName
|
androidOrigins.first().packageName
|
||||||
@@ -77,13 +74,32 @@ data class AppOrigin(
|
|||||||
webOrigins.first().origin
|
webOrigins.first().origin
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val TAG = AppOrigin::class.java.simpleName
|
||||||
|
|
||||||
|
fun fromOrigin(origin: String, androidOrigin: AndroidOrigin, verified: Boolean): AppOrigin {
|
||||||
|
val appOrigin = AppOrigin(verified)
|
||||||
|
if (origin.startsWith(RELYING_PARTY_DEFAULT_PROTOCOL)) {
|
||||||
|
appOrigin.apply {
|
||||||
|
addWebOrigin(WebOrigin(origin))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Unknown verified origin $origin")
|
||||||
|
appOrigin.apply {
|
||||||
|
addAndroidOrigin(androidOrigin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appOrigin
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class AndroidOrigin(
|
data class AndroidOrigin(
|
||||||
val packageName: String,
|
val packageName: String,
|
||||||
val fingerprint: String?,
|
val fingerprint: String?
|
||||||
val verified: Boolean = true
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,8 +123,7 @@ data class AndroidOrigin(
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class WebOrigin(
|
data class WebOrigin(
|
||||||
val origin: String,
|
val origin: String
|
||||||
val verified: Boolean = true,
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
fun toWebOrigin(): String {
|
fun toWebOrigin(): String {
|
||||||
@@ -121,9 +136,8 @@ data class WebOrigin(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val RELYING_PARTY_DEFAULT_PROTOCOL = "https"
|
const val RELYING_PARTY_DEFAULT_PROTOCOL = "https"
|
||||||
fun fromRelyingParty(relyingParty: String, verified: Boolean): WebOrigin = WebOrigin(
|
fun fromRelyingParty(relyingParty: String): WebOrigin = WebOrigin(
|
||||||
origin ="$RELYING_PARTY_DEFAULT_PROTOCOL://$relyingParty",
|
origin ="$RELYING_PARTY_DEFAULT_PROTOCOL://$relyingParty"
|
||||||
verified = verified
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ object AppOriginEntryField {
|
|||||||
* Parse fields of an entry to retrieve a an AppOrigin
|
* Parse fields of an entry to retrieve a an AppOrigin
|
||||||
*/
|
*/
|
||||||
fun parseFields(getField: (id: String) -> String?): AppOrigin {
|
fun parseFields(getField: (id: String) -> String?): AppOrigin {
|
||||||
val appOrigin = AppOrigin()
|
val appOrigin = AppOrigin(verified = true)
|
||||||
// Get Application identifiers
|
// Get Application identifiers
|
||||||
generateSequence(0) { it + 1 }
|
generateSequence(0) { it + 1 }
|
||||||
.map { position ->
|
.map { position ->
|
||||||
@@ -141,8 +141,7 @@ object AppOriginEntryField {
|
|||||||
setApplicationId(appIdentifier.packageName, appIdentifier.fingerprint)
|
setApplicationId(appIdentifier.packageName, appIdentifier.fingerprint)
|
||||||
}
|
}
|
||||||
appOrigin?.webOrigins?.forEach { webOrigin ->
|
appOrigin?.webOrigins?.forEach { webOrigin ->
|
||||||
if (webOrigin.verified)
|
setWebDomain(webOrigin.origin, null, customFieldsAllowed)
|
||||||
setWebDomain(webOrigin.origin, null, customFieldsAllowed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user