mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Improve attachment checks to ensure that a stream is actually a JAR/ZIP.
This commit is contained in:
parent
2cb02c75eb
commit
347224c900
@ -21,7 +21,9 @@ import net.corda.node.services.persistence.schemas.Models
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.FilterInputStream
|
||||
import java.io.InputStream
|
||||
import java.nio.file.*
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
@ -159,14 +161,21 @@ class NodeAttachmentService(override var storePath: Path, dataSourceProperties:
|
||||
|
||||
private fun checkIsAValidJAR(stream: InputStream) {
|
||||
// Just iterate over the entries with verification enabled: should be good enough to catch mistakes.
|
||||
// Note that JarInputStream won't throw any kind of error at all if the file stream is in fact not
|
||||
// a ZIP! It'll just pretend it's an empty archive, which is kind of stupid but that's how it works.
|
||||
// So we have to check to ensure we found at least one item.
|
||||
val jar = JarInputStream(stream)
|
||||
var count = 0
|
||||
while (true) {
|
||||
val cursor = jar.nextJarEntry ?: break
|
||||
val entryPath = Paths.get(cursor.name)
|
||||
// Security check to stop zips trying to escape their rightful place.
|
||||
if (entryPath.isAbsolute || entryPath.normalize() != entryPath || '\\' in cursor.name)
|
||||
if (entryPath.isAbsolute || entryPath.normalize() != entryPath || '\\' in cursor.name || cursor.name == "." || cursor.name == "..")
|
||||
throw IllegalArgumentException("Path is either absolute or non-normalised: $entryPath")
|
||||
count++
|
||||
}
|
||||
if (count == 0)
|
||||
throw IllegalArgumentException("Stream is either empty or not a JAR/ZIP")
|
||||
}
|
||||
|
||||
// Implementations for AcceptsFileUpload
|
||||
|
@ -9,6 +9,7 @@ import net.corda.core.read
|
||||
import net.corda.core.readAll
|
||||
import net.corda.core.utilities.LogHelper
|
||||
import net.corda.core.write
|
||||
import net.corda.core.writeLines
|
||||
import net.corda.node.services.database.RequeryConfiguration
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.node.services.persistence.schemas.AttachmentEntity
|
||||
@ -86,7 +87,6 @@ class NodeAttachmentStorageTest {
|
||||
|
||||
@Test
|
||||
fun `duplicates not allowed`() {
|
||||
|
||||
val testJar = makeTestJar()
|
||||
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
|
||||
testJar.read {
|
||||
@ -126,6 +126,14 @@ class NodeAttachmentStorageTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun `non jar rejected`() {
|
||||
val storage = NodeAttachmentService(fs.getPath("/"), dataSourceProperties, MetricRegistry())
|
||||
val path = fs.getPath("notajar")
|
||||
path.writeLines(listOf("Hey", "there!"))
|
||||
path.read { storage.importAttachment(it) }
|
||||
}
|
||||
|
||||
private var counter = 0
|
||||
private fun makeTestJar(): Path {
|
||||
counter++
|
||||
|
Loading…
Reference in New Issue
Block a user