commit e3613d161e17748a97e99f27b6b2c17242602ecc
parent 2e2101a2dacbaf985fe0a57bbce7a14064c5704b
Author: Antoine A <>
Date: Tue, 22 Oct 2024 16:48:12 +0200
bank: add flag to disable password quality check
Diffstat:
8 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/bank/conf/test_no_password_check.conf b/bank/conf/test_no_password_check.conf
@@ -0,0 +1,11 @@
+[libeufin-bank]
+CURRENCY = KUDOS
+WIRE_TYPE = iban
+IBAN_PAYTO_BIC = SANDBOXX
+ALLOW_REGISTRATION = yes
+ALLOW_ACCOUNT_DELETION = yes
+PWD_HASH_CONFIG = { "cost": 4 }
+PWD_CHECK = no
+
+[libeufin-bankdb-postgres]
+CONFIG = postgresql:///libeufincheck
+\ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
@@ -53,7 +53,8 @@ data class BankConfig(
val pwCrypto: PwCrypto,
val gcAbortAfter: Duration,
val gcCleanAfter: Duration,
- val gcDeleteAfter: Duration
+ val gcDeleteAfter: Duration,
+ val pwdCheckQuality: Boolean
) {
val dbCfg: DatabaseConfig by lazy {
val sect = cfg.section("libeufin-bankdb-postgres")
@@ -154,6 +155,7 @@ private fun TalerConfig.loadBankConfig(): BankConfig = section("libeufin-bank").
gcAbortAfter = duration("gc_abort_after").require(),
gcCleanAfter = duration("gc_clean_after").require(),
gcDeleteAfter = duration("gc_delete_after").require(),
+ pwdCheckQuality = boolean("pwd_check").default(true)
)
}
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt
@@ -208,7 +208,7 @@ suspend fun createAccount(
TalerErrorCode.END
)
- val password = req.password.checkPw()
+ val password = req.password.checkPw(cfg.pwdCheckQuality)
suspend fun doDb(internalPayto: Payto) = db.account.create(
username = req.username,
@@ -401,7 +401,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) {
TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD
)
}
- val newPassword = req.new_password.checkPw()
+ val newPassword = req.new_password.checkPw(ctx.pwdCheckQuality)
when (db.account.reconfigPassword(call.username, newPassword, req.old_password, call.isAdmin || challenge != null, ctx.pwCrypto)) {
AccountPatchAuthResult.Success -> call.respond(HttpStatusCode.NoContent)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/cli/ChangePw.kt b/bank/src/main/kotlin/tech/libeufin/bank/cli/ChangePw.kt
@@ -61,8 +61,8 @@ class ChangePw : CliktCommand("passwd") {
).ask()!!
}
override fun run() = cliCmd(logger, common.log) {
- val password = password.checkPw()
bankConfig(common.config).withDb { db, cfg ->
+ val password = password.checkPw(cfg.pwdCheckQuality)
val res = db.account.reconfigPassword(username, password, null, true, cfg.pwCrypto)
when (res) {
AccountPatchAuthResult.UnknownAccount ->
diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt
@@ -267,7 +267,7 @@ class CoreBankTokenApiTest {
}
class CoreBankAccountsApiTest {
- // Testing the account creation and its idempotency
+ // POST /accounts
@Test
fun create() = bankSetup {
// Check generated payto
@@ -560,6 +560,27 @@ class CoreBankAccountsApiTest {
}.assertConflict(TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED)
}
+ // POST /accounts
+ @Test
+ fun createNoCheck() = bankSetup("test_no_password_check.conf") {
+ // Testing short password
+ client.post("/accounts") {
+ json {
+ "username" to "short"
+ "name" to "John Smith"
+ "password" to "short"
+ }
+ }.assertOk()
+ // Testing long password
+ client.post("/accounts") {
+ json {
+ "username" to "long"
+ "name" to "Jane Smith"
+ "password" to "loooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password"
+ }
+ }.assertOk()
+ }
+
// DELETE /accounts/USERNAME
@Test
fun delete() = bankSetup { db ->
@@ -946,6 +967,26 @@ class CoreBankAccountsApiTest {
}.assertNoContent()
}
+ // PATCH /accounts/USERNAME/auth
+ @Test
+ fun passwordChangeNoCheck() = bankSetup("test_no_password_check.conf") {
+ // Testing short password
+ client.patchA("/accounts/merchant/auth") {
+ json {
+ "old_password" to "merchant-password"
+ "new_password" to "short"
+ }
+ }.assertNoContent()
+ // Testing long password
+ client.patch("/accounts/merchant/auth") {
+ basicAuth("merchant", "short")
+ json {
+ "old_password" to "short"
+ "new_password" to "looooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password"
+ }
+ }.assertNoContent()
+ }
+
// GET /public-accounts and GET /accounts
@Test
fun list() = bankSetup(conf = "test_no_conversion.conf") { db ->
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
@@ -344,7 +344,7 @@ suspend fun HttpResponse.assertChallenge(
check: suspend (TanChannel, String) -> Unit = { _, _ -> }
): HttpResponse {
val id = assertAcceptedJson<TanChallenge>().challenge_id
- val username = call.request.url.pathSegments[2]
+ val username = call.request.url.segments[1]
val res = call.client.postA("/accounts/$username/challenge/$id").assertOkJson<TanTransmission>()
check(res.tan_channel, res.tan_info)
val code = tanCode(res.tan_info)
diff --git a/common/src/main/kotlin/crypto/PwCrypto.kt b/common/src/main/kotlin/crypto/PwCrypto.kt
@@ -30,7 +30,8 @@ private const val PASSWORD_MIN_LEN = 8
private const val PASSWORD_MAX_LEN = 64
/** Check if a string is a valid password */
-fun String.checkPw(): Password {
+fun String.checkPw(checkQuality: Boolean): Password {
+ if (!checkQuality) return Password(this)
val len = this.length
return when {
len < PASSWORD_MIN_LEN -> throw conflict(
diff --git a/contrib/bank.conf b/contrib/bank.conf
@@ -91,6 +91,10 @@ PWD_HASH_ALGORITHM = bcrypt
# When PWD_HASH_ALGORITHM = bcrypt you can configure cost
PWD_HASH_CONFIG = { "cost": 8 }
+# Whether to check password quality
+# Unstable flag, will become a non configurable default in a future version
+PWD_CHECK = yes
+
# Time after which pending operations are aborted during garbage collection
GC_ABORT_AFTER = 15m