From 435a8b4effd3535f07a6a7074858c1cb3465177f Mon Sep 17 00:00:00 2001 From: Graham Date: Sat, 2 Jan 2021 20:24:32 +0000 Subject: [PATCH] Validate checksums in the JS5 client Signed-off-by: Graham --- .../archive/cache/Js5ChannelHandler.kt | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt b/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt index 94cc23bf19..39b576e64b 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/cache/Js5ChannelHandler.kt @@ -6,6 +6,7 @@ import io.netty.channel.ChannelHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler import kotlinx.coroutines.runBlocking +import org.openrs2.buffer.crc32 import org.openrs2.buffer.use import org.openrs2.cache.Js5Archive import org.openrs2.cache.Js5Compression @@ -38,6 +39,7 @@ public class Js5ChannelHandler( private val maxVersion = version + maxVersionAttempts private val inFlightRequests = mutableSetOf() private val pendingRequests = ArrayDeque() + private var masterIndex: Js5MasterIndex? = null private lateinit var indexes: Array private val groups = mutableListOf() @@ -116,7 +118,13 @@ public class Js5ChannelHandler( } else if (response.archive == Js5Archive.ARCHIVESET) { processIndex(response.group, response.data) } else { - val version = indexes[response.archive]!![response.group]!!.version + val entry = indexes[response.archive]!![response.group]!! + + if (response.data.crc32() != entry.checksum) { + throw Exception("Group checksum invalid") + } + + val version = entry.version val encrypted = Js5Compression.isEncrypted(response.data.slice()) groups += CacheImporter.Group(response.archive, response.group, response.data.retain(), version, encrypted) } @@ -138,11 +146,11 @@ public class Js5ChannelHandler( } private fun processMasterIndex(buf: ByteBuf) { - val masterIndex = Js5Compression.uncompress(buf.slice()).use { uncompressed -> + masterIndex = Js5Compression.uncompress(buf.slice()).use { uncompressed -> Js5MasterIndex.read(uncompressed) } - val rawIndexes = runBlocking { importer.importMasterIndexAndGetIndexes(masterIndex, buf) } + val rawIndexes = runBlocking { importer.importMasterIndexAndGetIndexes(masterIndex!!, buf) } try { indexes = arrayOfNulls(rawIndexes.size) @@ -159,11 +167,20 @@ public class Js5ChannelHandler( } private fun processIndex(archive: Int, buf: ByteBuf) { + val entry = masterIndex!!.entries[archive] + if (buf.crc32() != entry.checksum) { + throw Exception("Index checksum invalid") + } + val index = Js5Compression.uncompress(buf.slice()).use { uncompressed -> Js5Index.read(uncompressed) } indexes[archive] = index + if (index.version != entry.version) { + throw Exception("Index version invalid") + } + val groups = runBlocking { importer.importIndexAndGetMissingGroups(archive, index, buf) }