libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit a48071fa8bb1de5bfb6b07102f170cc5053212da
parent 575613d4d9f4c63a07ed22f245944f5b34214a8b
Author: Florian Dold <florian@dold.me>
Date:   Sat,  7 Aug 2021 21:40:49 +0200

bic validation

Diffstat:
Mdebian/changelog | 6++++++
Mnexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt | 3+++
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 12+++++++++++-
Mutil/src/main/kotlin/strings.kt | 26+++++++++++++++++++++-----
4 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/debian/changelog b/debian/changelog @@ -1,3 +1,9 @@ +libeufin (0.0.1-10) unstable; urgency=medium + + * Add BIC validation to nexus and sandbox. + + -- Florian Dold <florian@dold.me> Sat, 07 Aug 2021 21:40:28 +0200 + libeufin (0.0.1-9) unstable; urgency=medium * Various bugfixes. diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt @@ -646,6 +646,9 @@ fun serverMain(host: String, port: Int) { requireSuperuser(call.request) val body = call.receive<CreatePaymentInitiationRequest>() val accountId = ensureNonNull(call.parameters["accountid"]) + if (!validateBic(body.bic)) { + throw NexusError(HttpStatusCode.BadRequest, "invalid BIC (${body.bic})") + } val res = transaction { authenticateRequest(call.request) val bankAccount = NexusBankAccountEntity.findByName(accountId) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -492,6 +492,13 @@ fun serverMain(dbName: String, port: Int) { "invalid amount (should be plain amount without currency)" ) } + val reqDebtorBic = body.debtorBic + if (reqDebtorBic != null && !validateBic(reqDebtorBic)) { + throw SandboxError( + HttpStatusCode.BadRequest, + "invalid BIC" + ) + } transaction { val account = getBankAccountFromLabel(accountLabel) val randId = getRandomString(16) @@ -500,7 +507,7 @@ fun serverMain(dbName: String, port: Int) { it[creditorBic] = account.bic it[creditorName] = account.name it[debtorIban] = body.debtorIban - it[debtorBic] = body.debtorBic + it[debtorBic] = reqDebtorBic it[debtorName] = body.debtorName it[subject] = body.subject it[amount] = body.amount @@ -550,6 +557,9 @@ fun serverMain(dbName: String, port: Int) { */ post("/admin/ebics/bank-accounts") { val body = call.receiveJson<BankAccountRequest>() + if (!validateBic(body.bic)) { + throw SandboxError(HttpStatusCode.BadRequest, "invalid BIC") + } transaction { val subscriber = getEbicsSubscriberFromDetails( body.subscriber.userID, diff --git a/util/src/main/kotlin/strings.kt b/util/src/main/kotlin/strings.kt @@ -25,7 +25,7 @@ import java.math.BigInteger import java.math.BigDecimal import java.util.* -fun ByteArray.toHexString() : String { +fun ByteArray.toHexString(): String { return this.joinToString("") { java.lang.String.format("%02X", it) } @@ -67,7 +67,11 @@ fun base64ToBytes(encoding: String): ByteArray { fun BigInteger.toUnsignedHexString(): String { val signedValue = this.toByteArray() require(this.signum() > 0) { "number must be positive" } - val start = if (signedValue[0] == 0.toByte()) { 1 } else { 0 } + val start = if (signedValue[0] == 0.toByte()) { + 1 + } else { + 0 + } val bytes = Arrays.copyOfRange(signedValue, start, signedValue.size) return bytes.toHexString() } @@ -114,9 +118,21 @@ fun parseAmount(amount: String): AmountWithCurrency { return AmountWithCurrency(currency, Amount(number)) } -fun getRandomString(length: Int) : String { - val allowedChars = ('A'..'Z') + ('0'..'9') - return (1..length) +fun getRandomString(length: Int): String { + val allowedChars = ('A' .. 'Z') + ('0' .. '9') + return (1 .. length) .map { allowedChars.random() } .joinToString("") +} + +private val bicRegex = Regex("^[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$") + +fun validateBic(bic: String): Boolean { + return bicRegex.matches(bic) +} + +private val ibanRegex = Regex("^[A-Z]{2}[A-Za-z0-9]{6,32}$") + +fun validateIban(iban: String): Boolean { + return ibanRegex.matches(iban) } \ No newline at end of file