summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler St. Onge <tylertstonge@gmail.com>2020-08-22 01:53:25 -0400
committerTyler St. Onge <tylertstonge@gmail.com>2020-08-22 01:53:25 -0400
commita600075abf8515977c7728b35e8677d7d5f1756c (patch)
tree4a8647965fb4ce99a590cba55e9172c34d868e81
parent14fa23601c560464a19a55e1b4e530b742df301a (diff)
ability to accept files over passive connection
-rw-r--r--src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala27
-rw-r--r--src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileRetriever.scala50
-rw-r--r--src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala32
-rw-r--r--src/main/scala/com/tylerstonge/honeypot/ftp/FtpListener.scala2
4 files changed, 37 insertions, 74 deletions
diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala
index 74ca594..9f88b06 100644
--- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala
+++ b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala
@@ -1,9 +1,11 @@
package com.tylerstonge.honeypot.ftp
+import java.io.File
import java.net.InetSocketAddress
-import java.nio.file.{Files, OpenOption, Paths, StandardOpenOption}
+import java.nio.file.{Files, Paths, StandardOpenOption}
+import java.util.UUID
-import akka.actor.{Actor, Props}
+import akka.actor.{Actor, ActorRef, Props}
import akka.event.{Logging, LoggingAdapter}
import akka.io.Tcp._
import akka.io.{IO, Tcp}
@@ -11,30 +13,39 @@ import akka.util.{ByteString, ByteStringBuilder}
object FtpFileReceiver {
- def props(port: Int): Props = Props(new FtpFileReceiver(port))
+ def props(port: Int, controller: ActorRef): Props = Props(new FtpFileReceiver(port, controller))
}
-class FtpFileReceiver(port: Int) extends Actor {
+class FtpFileReceiver(port: Int, controller: ActorRef) extends Actor {
val log: LoggingAdapter = Logging(context.system, this)
- IO(Tcp)(context.system) ! Bind(self, new InetSocketAddress("localhost", port))
+ IO(Tcp)(context.system) ! Bind(self, new InetSocketAddress("127.0.0.1", port))
val fileData: ByteStringBuilder = ByteString.newBuilder
+ val name: String = UUID.randomUUID().toString
+
+ override def postStop {
+ log.debug("shutting down")
+ }
override def receive: Receive = {
case Bound(localAddress) =>
log.info("listening on {}", localAddress)
case CommandFailed(_: Bind) => context.stop(self)
case Connected(_, _) =>
- log.info("peer connected")
+ val connection = sender()
+ connection ! Register(self)
context.become {
case Received(data) =>
+ log.info("read {} bytes", data.length)
fileData.addAll(data)
case PeerClosed =>
- log.info("peer closed connection, writing file to disk")
- val out = Files.newByteChannel(Paths.get("testfile.txt"), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)
+ log.debug("peer closed connection, writing file to disk")
+ val out = Files.newByteChannel(new File("C:\\Users\\dropkick\\Documents\\dev\\honeypot\\" + this.name).toPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)
out.write(fileData.result().toByteBuffer)
out.close()
+ controller.tell(Write(ByteString.apply("226 File transferred.\n")), context.parent)
context.stop(self)
+ case msg@_ => log.warning("unknown message: {}", msg)
}
}
}
diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileRetriever.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileRetriever.scala
deleted file mode 100644
index 1e441dd..0000000
--- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileRetriever.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.tylerstonge.honeypot.ftp
-
-import java.net.InetSocketAddress
-import java.nio.file.{Files, Paths}
-
-import akka.actor.{Actor, Props}
-import akka.event.{Logging, LoggingAdapter}
-import akka.io.Tcp._
-import akka.io.{IO, Tcp}
-import akka.util.{ByteString, ByteStringBuilder}
-
-object FtpFileRetriever {
- def props(remote: InetSocketAddress): Props = Props(new FtpFileRetriever(remote))
-}
-
-class FtpFileRetriever(remote: InetSocketAddress) extends Actor {
-
- val log: LoggingAdapter = Logging(context.system, this)
- IO(Tcp)(context.system) ! Connect(remote)
- val fileData: ByteStringBuilder = ByteString.newBuilder
-
- override def preStart(): Unit = {
- super.preStart()
- log.info("started retrieving from {}:{}", remote.getHostString, remote.getPort)
- }
-
- override def receive: Receive = {
- case CommandFailed(_: Connect) =>
- context.stop(self)
- case c@Connected(_, _) =>
- val connection = sender()
- connection ! Register(self)
- context.become {
- case data: ByteString =>
- log.info("received {} bytes", data.length)
- fileData.addAll(data)
- case CommandFailed(w: Write) =>
- log.info("command failed")
- case Received(data) =>
- log.info("received {} bytes", data.length)
- fileData.addAll(data)
- case _: ConnectionClosed =>
- log.info("peer closed connection, writing file to disk")
- val out = Files.newByteChannel(Paths.get("testfile.txt"))
- out.write(fileData.result().toByteBuffer)
- out.close()
- context.stop(self)
- }
- }
-}
diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala
index 8bdb190..840ce97 100644
--- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala
+++ b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala
@@ -1,18 +1,20 @@
package com.tylerstonge.honeypot.ftp
-import java.net.InetSocketAddress
-
-import akka.actor.Actor
+import akka.actor.{Actor, ActorRef, Props}
import akka.event.{Logging, LoggingAdapter}
import akka.io.Tcp.{PeerClosed, Received, Write}
import akka.util.ByteString
-class FtpHandler extends Actor {
+object FtpHandler {
+ def props(client: ActorRef): Props = Props(new FtpHandler(client))
+}
+
+class FtpHandler(client: ActorRef) extends Actor {
val log: LoggingAdapter = Logging(context.system, this)
override def receive: Receive = {
- case Received(data) => sender() ! Write(ByteString.apply(parse(sanitize(data))))
+ case Received(data) => client ! Write(ByteString.apply(parse(sanitize(data))))
case PeerClosed =>
log.info("peer closed connection")
context.stop(self)
@@ -28,18 +30,22 @@ class FtpHandler extends Actor {
case "pwd" => "257 \"/\" is the current directory\n"
case "quit" => "221 Goodbye.\n"
case "pasv" =>
- context.actorOf(FtpFileReceiver.props(1287))
+ log.info("entering passive mode")
+ context.actorOf(FtpFileReceiver.props(1287, client), name = "passive-connection")
+ Thread.sleep(256)
"227 entering passive mode (127,0,0,1,5,7)\n"
- case "port" =>
- context.actorOf(FtpFileRetriever.props(new InetSocketAddress(getHostname(msg(1)), getPort(msg(1)))))
- "200 OK\n"
case "stor" =>
- "200 OK \n"
+ log.info("stor: {}", msg(1))
+ "150 File status okay; about to open data connection.\n"
case _ =>
log.info("unsupported command received: {}", msg.mkString(" "))
"451 Requested action aborted. Local error in processing.\n"
}
+ def sanitize(data: ByteString): Array[String] = {
+ data.utf8String.trim.toLowerCase().split(" ")
+ }
+
def getHostname(msg: String): String = {
val split = msg.split(",")
split.slice(0, 4).mkString(".")
@@ -49,8 +55,4 @@ class FtpHandler extends Actor {
val split = msg.split(",")
split(4).toInt * 256 + split(5).toInt
}
-
- def sanitize(data: ByteString): Array[String] = {
- data.utf8String.trim.toLowerCase().split(" ")
- }
-}
+} \ No newline at end of file
diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpListener.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpListener.scala
index 07557bc..b7ce337 100644
--- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpListener.scala
+++ b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpListener.scala
@@ -22,8 +22,8 @@ class FtpListener(port: Int) extends Actor {
log.info("listening on {}", localAddress)
case CommandFailed(_: Bind) => context.stop(self)
case Connected(_, _) =>
- val handler = context.actorOf(Props[FtpHandler])
val connection = sender()
+ val handler = context.actorOf(FtpHandler.props(connection), name = "handler")
connection ! Register(handler)
connection ! Write(ByteString.apply("220 (vulnFTPd 2.0.1)\n"))
}