From a374f7a44b86f23cdb34e29e49b0a5ec5ecfdba2 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Thu, 16 Jan 2025 19:01:51 -0500 Subject: [PATCH] [O] Security: keychip check on remove --- .../sega/maimai2/worldslink/FutariLobby.kt | 23 +++++++++---------- .../sega/maimai2/worldslink/FutariModels.kt | 4 +++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariLobby.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariLobby.kt index b75af11b..58a5823a 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariLobby.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariLobby.kt @@ -28,8 +28,6 @@ private val KJson = Json { // Maximum time to live for a recruit record const val MAX_TTL = 30 * 1000 -data class RecruitRecord(val d: RecruitInfo, val time: Long = millis()) - @RestController @RequestMapping(path = ["/mai2-futari"]) class FutariLobby(paths: PathProps) { @@ -52,16 +50,16 @@ class FutariLobby(paths: PathProps) { writer.flush() } - fun log(data: StartRecruit, msg: String) = - log("${LocalDateTime.now().isoDateTime()}: $msg: ${data.RecruitInfo.toJson()}") + fun log(data: RecruitRecord, msg: String) = + log("${LocalDateTime.now().isoDateTime()}: $msg: ${KJson.encodeToString(data)}") - val StartRecruit.ip get() = RecruitInfo.MechaInfo.IpAddress + val RecruitRecord.ip get() = RecruitInfo.MechaInfo.IpAddress @API("recruit/start") fun startRecruit(@RB data: String) { - val d = parsing { KJson.decodeFromString(data) } + val d = parsing { KJson.decodeFromString(data) }.apply { Time = millis() } val exists = d.ip in recruits - recruits[d.ip] = RecruitRecord(d.RecruitInfo) + recruits[d.ip] = d if (!exists) log(d, "StartRecruit") d.RecruitInfo.MechaInfo.UserIDs = d.RecruitInfo.MechaInfo.UserIDs.map { it.str.hashToUInt().toLong() } @@ -69,8 +67,9 @@ class FutariLobby(paths: PathProps) { @API("recruit/finish") fun finishRecruit(@RB data: String) { - val d = parsing { KJson.decodeFromString(data) } + val d = parsing { KJson.decodeFromString(data) } if (d.ip !in recruits) 400 - "Recruit not found" + if (d.Keychip != recruits[d.ip]!!.Keychip) 400 - "Keychip mismatch" recruits.remove(d.ip) log(d, "EndRecruit") } @@ -78,16 +77,16 @@ class FutariLobby(paths: PathProps) { @API("recruit/list") fun listRecruit(): String { val time = millis() - recruits.filterValues { time - it.time > MAX_TTL }.keys.forEach { recruits.remove(it) } - return recruits.values.toList().joinToString("\n") { KJson.encodeToString(it.d) } + recruits.filterValues { time - it.Time > MAX_TTL }.keys.forEach { recruits.remove(it) } + return recruits.values.toList().joinToString("\n") { KJson.encodeToString(it.RecruitInfo) } } } fun main(args: Array) { val json = """{"RecruitInfo":{"MechaInfo":{"IsJoin":true,"IpAddress":1820162433,"MusicID":11692,"Entrys":[true,false],"UserIDs":[281474976710657,281474976710657],"UserNames":["GUEST","GUEST"],"IconIDs":[1,1],"FumenDifs":[0,-1],"Rateing":[0,0],"ClassValue":[0,0],"MaxClassValue":[0,0],"UserType":[0,0]},"MusicID":11692,"GroupID":0,"EventModeID":false,"JoinNumber":1,"PartyStance":0,"_startTimeTicks":638725464510308001,"_recvTimeTicks":0}}""" println(json.jsonMap().toJson()) - val data = KJson.decodeFromString(json) + val data = KJson.decodeFromString(json) println(json) - println(KJson.encodeToString(StartRecruit.serializer(), data)) + println(KJson.encodeToString(data)) println(data) } diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariModels.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariModels.kt index 35afb20b..e8178c54 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariModels.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/worldslink/FutariModels.kt @@ -34,6 +34,8 @@ data class RecruitInfo( ) @Serializable -data class StartRecruit( +data class RecruitRecord( val RecruitInfo: RecruitInfo, + val Keychip: String, + var Time: Long = 0 )