commit 01cec79392cf07f7ab066885337318c1bdee2b17
parent c7e8b73d9bc438c3aac270084e5f259323306064
Author: ms <ms@taler.net>
Date: Sun, 19 Sep 2021 09:23:34 +0200
Sanity-check usernames at Sandbox.
Diffstat:
6 files changed, 51 insertions(+), 23 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt
@@ -478,7 +478,7 @@ private fun getCurrency(facadeName: String): String {
}
}
-fun talerFacadeRoutes(route: Route, httpClient: HttpClient) {
+fun talerFacadeRoutes(route: Route) {
route.get("/config") {
val facadeId = ensureNonNull(call.parameters["fcid"])
call.request.requirePermission(
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -314,7 +314,7 @@ fun Route.ebicsBankConnectionRoutes(client: HttpClient) {
}
post("/download/{msgtype}") {
- val orderType = requireNotNull(call.parameters["msgtype"]).toUpperCase(Locale.ROOT)
+ val orderType = requireNotNull(call.parameters["msgtype"]).uppercase(Locale.ROOT)
if (orderType.length != 3) {
throw NexusError(HttpStatusCode.BadRequest, "ebics order type must be three characters")
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -119,22 +119,6 @@ fun ApplicationCall.expectUrlParameter(name: String): String {
?: throw NexusError(HttpStatusCode.BadRequest, "Parameter '$name' not provided in URI")
}
-fun isValidResourceName(name: String): Boolean {
- return name.matches(Regex("[a-z]([-a-z0-9]*[a-z0-9])?"))
-}
-
-fun requireValidResourceName(name: String): String {
- if (!isValidResourceName(name)) {
- throw NexusError(
- HttpStatusCode.BadRequest,
- "Invalid resource name. The first character must be a lowercase letter, " +
- "and all following characters (except for the last character) must be a dash, " +
- "lowercase letter, or digit. The last character must be a lowercase letter or digit."
- )
- }
- return name
-}
-
suspend inline fun <reified T : Any> ApplicationCall.receiveJson(): T {
try {
return this.receive()
@@ -1060,7 +1044,7 @@ fun serverMain(host: String, port: Int) {
}
}
route("/facades/{fcid}/taler-wire-gateway") {
- talerFacadeRoutes(this, client)
+ talerFacadeRoutes(this)
}
route("/facades/{fcid}/anastasis") {
anastasisFacadeRoutes(this, client)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -99,9 +99,18 @@ class Superuser : CliktCommand("Add superuser or change pw") {
execThrowableOrTerminate {
dbCreateTables(getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME))
}
+ try {
+ requireValidResourceName(username)
+ } catch (e: UtilError) {
+ println(e) // Gives instructions about the allowed format.
+ exitProcess(1)
+ }
transaction {
+ val user = SandboxUserEntity.find {
+ SandboxUsersTable.username eq username
+ }.firstOrNull()
+
val hashedPw = CryptoUtil.hashpw(password)
- val user = SandboxUserEntity.find { SandboxUsersTable.username eq username }.firstOrNull()
if (user == null) {
SandboxUserEntity.new {
this.username = this@Superuser.username
diff --git a/util/src/main/kotlin/HTTP.kt b/util/src/main/kotlin/HTTP.kt
@@ -32,9 +32,9 @@ fun extractUserAndPassword(authorizationHeader: String): Pair<String, String> {
// FIXME/note: line below doesn't check for "Basic" presence.
val split = authorizationHeader.split(" ")
val plainUserAndPass = String(base64ToBytes(split[1]), Charsets.UTF_8)
- val ret = plainUserAndPass.split(":")
- if (ret.size != 2) throw java.lang.Exception(
- "HTTP Basic auth line does not contain username and (only) password"
+ val ret = plainUserAndPass.split(":", limit = 2)
+ if (ret.size < 2) throw java.lang.Exception(
+ "HTTP Basic auth line does not contain username and password"
)
ret
} catch (e: Exception) {
diff --git a/util/src/main/kotlin/strings.kt b/util/src/main/kotlin/strings.kt
@@ -148,4 +148,39 @@ private val ibanRegex = Regex("^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{1,30}$")
fun validateIban(iban: String): Boolean {
return ibanRegex.matches(iban)
+}
+
+fun isValidResourceName(name: String): Boolean {
+ return name.matches(Regex("[a-z]([-a-z0-9]*[a-z0-9])?"))
+}
+
+fun requireValidResourceName(name: String): String {
+ if (!isValidResourceName(name)) {
+ throw UtilError(
+ HttpStatusCode.BadRequest,
+ "Invalid resource name. The first character must be a lowercase letter, " +
+ "and all following characters (except for the last character) must be a dash, " +
+ "lowercase letter, or digit. The last character must be a lowercase letter or digit.",
+ LibeufinErrorCode.LIBEUFIN_EC_GENERIC_PARAMETER_MALFORMED
+ )
+ }
+ return name
+}
+
+
+fun sanityCheckOrThrow(credentials: Pair<String, String>) {
+ if (!sanityCheckCredentials(credentials)) throw UtilError(
+ HttpStatusCode.BadRequest,
+ "Please only use alphanumeric credentials.",
+ LibeufinErrorCode.LIBEUFIN_EC_GENERIC_PARAMETER_MALFORMED
+ )
+}
+/**
+ * Sanity-check user's credentials.
+ */
+fun sanityCheckCredentials(credentials: Pair<String, String>): Boolean {
+ val allowedChars = Regex("^[a-zA-Z0-9]+$")
+ if (!allowedChars.matches(credentials.first)) return false
+ if (!allowedChars.matches(credentials.second)) return false
+ return true
}
\ No newline at end of file