From c84e0a2962e1764c8e259c1a5aab7047824943a6 Mon Sep 17 00:00:00 2001 From: Leonardo Colman Date: Wed, 3 Mar 2021 13:47:57 -0300 Subject: [PATCH] Escape SFTP passwords correctly (#6) This commit changes how we handle the SFTP URI. Currently we don't escape anything, and that might lead to failures. What this commit does is use java.net.URI class and it's uri-escaping-properties to mitigate this possibility, and fix this issue. --- .../sftptos3connector/internal/sftp/SftpFileStreamer.kt | 7 ++++--- .../internal/sftp/SftpFileStreamerTest.kt | 8 ++++++++ .../sftptos3connector/internal/sftp/SftpServer.kt | 7 +++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamer.kt b/src/main/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamer.kt index 628f6a5..0ca1103 100644 --- a/src/main/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamer.kt +++ b/src/main/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamer.kt @@ -18,15 +18,16 @@ package br.com.guiabolso.sftptos3connector.internal.sftp import br.com.guiabolso.sftptos3connector.config.SftpConfig import org.apache.commons.vfs2.VFS +import java.net.URI internal class SftpFileStreamer(sftpConfig: SftpConfig) { - private val baseConnectionURI = sftpConfig.run { "sftp://$username:$password@$host:$port" } + private val baseConnectionURI = sftpConfig.run { URI("sftp", "$username:$password", host, port, null, null, null) } private val fileSystemManager = VFS.getManager() - + fun getSftpFile(filePath: String): SftpFile { return getInputStreamWithContentLength(filePath) } - + private fun getInputStreamWithContentLength(filePath: String): SftpFile { val remoteFile = fileSystemManager.resolveFile("$baseConnectionURI/$filePath") return SftpFile(remoteFile.content.inputStream, remoteFile.content.size) diff --git a/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamerTest.kt b/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamerTest.kt index 885e6b2..bf8d476 100644 --- a/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamerTest.kt +++ b/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpFileStreamerTest.kt @@ -41,4 +41,12 @@ class SftpFileStreamerTest : FunSpec({ fileInfo.contentLength shouldBe sftpFileContent.encodeToByteArray().size.toLong() } } + + test("Escape uri characters") { + withConfiguredSftpServer("unsafe%%,,..&") { server -> + val target = SftpFileStreamer(SftpConfig("localhost", server.port, sftpUsername, "unsafe%%,,..&")) + + target.getSftpFile(sftpFilePath) + } + } }) diff --git a/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpServer.kt b/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpServer.kt index 1f231af..8a834f3 100644 --- a/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpServer.kt +++ b/src/test/kotlin/br/com/guiabolso/sftptos3connector/internal/sftp/SftpServer.kt @@ -25,10 +25,13 @@ val sftpFilePath = "path/to/file" val sftpFileContent = "FileContent\nMoreContent" -fun withConfiguredSftpServer(block: (FakeSftpServer) -> Unit) = FakeSftpServer.withSftpServer { server -> +fun withConfiguredSftpServer( + password: String = sftpPassword, + block: (FakeSftpServer) -> Unit +) = FakeSftpServer.withSftpServer { server -> server.port = obtainRandomAvailablePort() server.putFile(sftpFilePath, sftpFileContent, Charsets.UTF_8) - server.addUser(sftpUsername, sftpPassword) + server.addUser(sftpUsername, password) block(server) }