Fix decoding OTP Auth #556

This commit is contained in:
J-Jamet
2020-11-12 14:39:33 +01:00
parent fe48955b94
commit eec6199413
3 changed files with 19 additions and 15 deletions

View File

@@ -51,9 +51,10 @@ class EntrySelectionLauncherActivity : AppCompatActivity() {
if ("text/plain" == intent.type) { if ("text/plain" == intent.type) {
// Retrieve web domain or OTP // Retrieve web domain or OTP
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { extra -> intent.getStringExtra(Intent.EXTRA_TEXT)?.let { extra ->
sharedWebDomain = Uri.parse(extra).host
if (OtpEntryFields.isOTPUri(extra)) if (OtpEntryFields.isOTPUri(extra))
otpString = extra otpString = extra
else
sharedWebDomain = Uri.parse(extra).host
} }
} }
} }

View File

@@ -2,6 +2,7 @@ package com.kunzisoft.keepass.model
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.net.Uri
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import com.kunzisoft.keepass.otp.OtpEntryFields import com.kunzisoft.keepass.otp.OtpEntryFields
@@ -72,7 +73,7 @@ class SearchInfo : ObjectNameResource, Parcelable {
override fun getName(resources: Resources): String { override fun getName(resources: Resources): String {
otpString?.let { otpString -> otpString?.let { otpString ->
OtpEntryFields.parseOTPUri(otpString)?.let { otpElement -> OtpEntryFields.parseOTPUri(otpString)?.let { otpElement ->
return "${otpElement.type} (${otpElement.name})" return "${otpElement.type} (${Uri.decode(otpElement.issuer)} : ${Uri.decode(otpElement.name)})"
} }
} }
return toString() return toString()

View File

@@ -26,7 +26,6 @@ import com.kunzisoft.keepass.database.element.security.ProtectedString
import com.kunzisoft.keepass.model.Field import com.kunzisoft.keepass.model.Field
import com.kunzisoft.keepass.otp.OtpElement.Companion.replaceSpaceChars import com.kunzisoft.keepass.otp.OtpElement.Companion.replaceSpaceChars
import com.kunzisoft.keepass.otp.TokenCalculator.* import com.kunzisoft.keepass.otp.TokenCalculator.*
import java.net.URLEncoder
import java.util.* import java.util.*
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -156,8 +155,15 @@ object OtpEntryFields {
} }
val nameParam = validateAndGetNameInPath(uri.path) val nameParam = validateAndGetNameInPath(uri.path)
if (nameParam != null && nameParam.isNotEmpty()) if (nameParam != null && nameParam.isNotEmpty()) {
val userIdArray = nameParam.split(":", "%3A")
if (userIdArray.size > 1) {
otpElement.issuer = userIdArray[0]
otpElement.name = userIdArray[1]
} else {
otpElement.name = nameParam otpElement.name = nameParam
}
}
val issuerParam = uri.getQueryParameter(ISSUER_URL_PARAM) val issuerParam = uri.getQueryParameter(ISSUER_URL_PARAM)
if (issuerParam != null && issuerParam.isNotEmpty()) if (issuerParam != null && issuerParam.isNotEmpty())
@@ -232,14 +238,14 @@ object OtpEntryFields {
} }
val issuer = val issuer =
if (title != null && title.isNotEmpty()) if (title != null && title.isNotEmpty())
replaceCharsForUrl(title) Uri.encode(title)
else else
replaceCharsForUrl(otpElement.issuer) Uri.encode(otpElement.issuer)
val accountName = val accountName =
if (username != null && username.isNotEmpty()) if (username != null && username.isNotEmpty())
replaceCharsForUrl(username) Uri.encode(username)
else else
replaceCharsForUrl(otpElement.name) Uri.encode(otpElement.name)
val uriString = StringBuilder("otpauth://$otpAuthority/$issuer:$accountName" + val uriString = StringBuilder("otpauth://$otpAuthority/$issuer:$accountName" +
"?$SECRET_URL_PARAM=${otpElement.getBase32Secret()}" + "?$SECRET_URL_PARAM=${otpElement.getBase32Secret()}" +
"&$counterOrPeriodLabel=$counterOrPeriodValue" + "&$counterOrPeriodLabel=$counterOrPeriodValue" +
@@ -254,10 +260,6 @@ object OtpEntryFields {
return Uri.parse(uriString.toString()) return Uri.parse(uriString.toString())
} }
private fun replaceCharsForUrl(parameter: String): String {
return URLEncoder.encode(replaceSpaceChars(parameter), "UTF-8")
}
private fun parseTOTPKeyValues(getField: (id: String) -> String?, otpElement: OtpElement): Boolean { private fun parseTOTPKeyValues(getField: (id: String) -> String?, otpElement: OtpElement): Boolean {
val plainText = getField(OTP_FIELD) val plainText = getField(OTP_FIELD)
if (plainText != null && plainText.isNotEmpty()) { if (plainText != null && plainText.isNotEmpty()) {
@@ -342,7 +344,7 @@ object OtpEntryFields {
// path is "/name", so remove leading "/", and trailing white spaces // path is "/name", so remove leading "/", and trailing white spaces
val name = path.substring(1).trim { it <= ' ' } val name = path.substring(1).trim { it <= ' ' }
return if (name.isEmpty()) { return if (name.isEmpty()) {
null // only white spaces. null
} else name } else name
} }
@@ -359,7 +361,7 @@ object OtpEntryFields {
/** /**
* Build Otp field from an OtpElement * Build Otp field from an OtpElement
*/ */
fun buildOtpField(otpElement: OtpElement, title: String?, username: String?): Field { fun buildOtpField(otpElement: OtpElement, title: String? = null, username: String? = null): Field {
return Field(OTP_FIELD, ProtectedString(true, return Field(OTP_FIELD, ProtectedString(true,
buildOtpUri(otpElement, title, username).toString())) buildOtpUri(otpElement, title, username).toString()))
} }