diff --git a/CHANGELOG.md b/CHANGELOG.md index 2876cb0..1d31087 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- [2020-07-13] Added reloading client setting without stopping client by [@radonbark] +- [2020-07-13] Added reloading client setting without stopping client by [@radonbark]. ### Changed +- [2020-07-29] Disallow unsafe ports [@m3ch_mania]. ### Deprecated ### Removed ### Fixed +- [2020-07-29] Fixed stupid libsodium bugs [@carbotaniuman]. +- [2020-07-29] Fixed issues from the Great Cache Propagation [@carbotaniuman]. ### Security diff --git a/src/main/kotlin/mdnet/base/server/ImageServer.kt b/src/main/kotlin/mdnet/base/server/ImageServer.kt index 5234389..b4dfb3b 100644 --- a/src/main/kotlin/mdnet/base/server/ImageServer.kt +++ b/src/main/kotlin/mdnet/base/server/ImageServer.kt @@ -76,8 +76,6 @@ class ImageServer( private val executor = Executors.newCachedThreadPool() fun handler(dataSaver: Boolean, tokenized: Boolean = false): HttpHandler { - val sodium = LazySodiumJava(SodiumJava()) - return baseHandler().then { request -> val chapterHash = Path.of("chapterHash")(request) val fileName = Path.of("fileName")(request) @@ -102,7 +100,7 @@ class ImageServer( val token = try { JACKSON.readValue( try { - sodium.cryptoBoxOpenEasyAfterNm( + SODIUM.cryptoBoxOpenEasyAfterNm( tokenArr.sliceArray(24 until tokenArr.size), tokenArr.sliceArray(0 until 24), serverSettings.tokenKey ) } catch (_: SodiumException) { @@ -144,12 +142,12 @@ class ImageServer( } } - if (snapshot != null && imageDatum != null) { + if (snapshot != null && imageDatum != null && imageDatum.contentType.isImageMimetype()) { request.handleCacheHit(sanitizedUri, getRc4(rc4Bytes), snapshot, imageDatum) } else { if (snapshot != null) { snapshot.close() - LOGGER.warn { "Removing cache file for $sanitizedUri without corresponding DB entry" } + LOGGER.warn { "Removing broken cache file for $sanitizedUri" } cache.removeUnsafe(imageId.toCacheId()) } @@ -218,12 +216,18 @@ class ImageServer( return Response(mdResponse.status) } - LOGGER.trace { "Upstream query for $sanitizedUri succeeded" } - val contentType = mdResponse.header("Content-Type")!! val contentLength = mdResponse.header("Content-Length") val lastModified = mdResponse.header("Last-Modified") + if (!contentType.isImageMimetype()) { + LOGGER.trace { "Upstream query for $sanitizedUri returned bad mimetype $contentType" } + mdResponse.close() + return Response(Status.INTERNAL_SERVER_ERROR) + } + + LOGGER.trace { "Upstream query for $sanitizedUri succeeded" } + val editor = cache.editUnsafe(imageId.toCacheId()) // A null editor means that this file is being written to @@ -291,6 +295,7 @@ class ImageServer( .header("X-Cache", if (cached) "HIT" else "MISS") companion object { + private val SODIUM = LazySodiumJava(SodiumJava()) private val LOGGER = LoggerFactory.getLogger(ImageServer::class.java) private val JACKSON: ObjectMapper = jacksonObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) @@ -329,3 +334,5 @@ private fun printHexString(bytes: ByteArray): String { } return sb.toString() } + +private fun String.isImageMimetype() = this.toLowerCase().startsWith("image/") \ No newline at end of file