1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package com.tylerstonge.honeypot.ftp
import java.io.File
import java.net.InetSocketAddress
import java.nio.file.{Files, StandardOpenOption}
import java.util.UUID
import akka.actor.{Actor, ActorRef, Props}
import akka.event.{Logging, LoggingAdapter}
import akka.io.Tcp._
import akka.io.{IO, Tcp}
import akka.util.{ByteString, ByteStringBuilder}
import com.tylerstonge.honeypot.messages.MFoundFile
object FtpFileReceiver {
def props(port: Int, controller: ActorRef): Props = Props(new FtpFileReceiver(port, controller))
}
class FtpFileReceiver(port: Int, controller: ActorRef) extends Actor {
val path = "/tmp/files/"
val log: LoggingAdapter = Logging(context.system, this)
IO(Tcp)(context.system) ! Bind(self, new InetSocketAddress("127.0.0.1", port))
val fileData: ByteStringBuilder = ByteString.newBuilder
var 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(_, _) =>
val connection = sender()
connection ! Register(self)
context.become {
case Received(data) =>
log.debug("read {} bytes", data.length)
fileData.addAll(data)
case PeerClosed =>
log.debug("peer closed connection, writing file to disk")
val out = Files.newByteChannel(new File(this.path + 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.system.eventStream.publish(MFoundFile(this.path + this.name))
context.stop(self)
case SetName(name) =>
log.info("file accepted as {}", name)
this.name = name
case msg@_ => log.warning("unknown message: {}", msg)
}
}
}
case class Ready()
case class SetName(name: String)
|