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
|
package com.tylerstonge.honeypot.ftp
import java.net.InetSocketAddress
import akka.actor.Actor
import akka.event.{Logging, LoggingAdapter}
import akka.io.Tcp.{PeerClosed, Received, Write}
import akka.util.ByteString
class FtpHandler extends Actor {
val log: LoggingAdapter = Logging(context.system, this)
override def receive: Receive = {
case Received(data) => sender() ! Write(ByteString.apply(parse(sanitize(data))))
case PeerClosed =>
log.info("peer closed connection")
context.stop(self)
}
def parse(msg: Array[String]): String = msg(0) match {
case "user" =>
log.info("attempted login with username: {}", msg(1))
"331 Please specify password.\n"
case "pass" =>
log.info("attempted login with password: {}", msg(1))
"230 Login successful.\n"
case "pwd" => "257 \"/\" is the current directory\n"
case "quit" => "221 Goodbye.\n"
case "pasv" =>
context.actorOf(FtpFileReceiver.props(1287))
"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"
case _ =>
log.info("unsupported command received: {}", msg.mkString(" "))
"451 Requested action aborted. Local error in processing.\n"
}
def getHostname(msg: String): String = {
val split = msg.split(",")
split.slice(0, 4).mkString(".")
}
def getPort(msg: String): Int = {
val split = msg.split(",")
split(4).toInt * 256 + split(5).toInt
}
def sanitize(data: ByteString): Array[String] = {
data.utf8String.trim.toLowerCase().split(" ")
}
}
|