196 lines
4.0 KiB
Go
196 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
l, err := net.Listen("tcp", ":8021")
|
|
if err != nil {
|
|
panic(err)
|
|
|
|
}
|
|
defer l.Close()
|
|
|
|
for {
|
|
conn, err := l.Accept()
|
|
if err != nil {
|
|
fmt.Printf(err.Error())
|
|
continue
|
|
}
|
|
go handle(conn)
|
|
}
|
|
}
|
|
|
|
func handle(c net.Conn) {
|
|
defer c.Close()
|
|
s, err := NewServer(c)
|
|
if err != nil {
|
|
fmt.Printf(err.Error())
|
|
}
|
|
s.ctrl.PrintfLine("220 %s [%s]", "go-ftp", c.LocalAddr())
|
|
for {
|
|
line, err := s.ctrl.ReadLine()
|
|
if err != nil {
|
|
fmt.Printf(err.Error())
|
|
return
|
|
}
|
|
parts := strings.Fields(line)
|
|
cmd := parts[0]
|
|
params := parts[1:]
|
|
switch cmd {
|
|
case "USER":
|
|
s.cmdServerUser(params)
|
|
case "PASS":
|
|
s.cmdServerPass(params)
|
|
case "PWD":
|
|
s.cmdServerPwd(params)
|
|
case "EPSV":
|
|
s.cmdServerEpsv(params)
|
|
case "PASV":
|
|
s.cmdServerPasv(params)
|
|
case "TYPE":
|
|
s.cmdServerType(params)
|
|
case "LIST":
|
|
s.cmdServerList(params)
|
|
case "SYST":
|
|
s.cmdServerSyst(params)
|
|
case "QUIT":
|
|
s.cmdServerQuit(params)
|
|
s.Close()
|
|
return
|
|
case "SIZE":
|
|
s.cmdServerSize(params)
|
|
case "CWD":
|
|
s.cmdServerCwd(params)
|
|
case "RETR":
|
|
s.cmdServerRetr(params)
|
|
default:
|
|
fmt.Printf("%s\n", line)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Conn) cmdServerUser(args []string) {
|
|
fmt.Printf("cmdServerUser: %s\n", args)
|
|
s.ctrl.PrintfLine("331 Password required for %s", args[0])
|
|
}
|
|
|
|
func (s *Conn) cmdServerPass(args []string) {
|
|
fmt.Printf("cmdServerPass: %s\n", args)
|
|
s.ctrl.PrintfLine("230 Logged on")
|
|
//530 Login incorrect.
|
|
}
|
|
|
|
func (s *Conn) cmdServerPwd(args []string) {
|
|
fmt.Printf("cmdServerPwd: %s\n", args)
|
|
s.ctrl.PrintfLine(`257 "/" is current directory.`)
|
|
}
|
|
|
|
func (s *Conn) cmdServerEpsv(args []string) {
|
|
fmt.Printf("cmdServerEpsv: %s\n", args)
|
|
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
|
if err != nil {
|
|
|
|
}
|
|
s.ln = ln
|
|
_, port, _ := net.SplitHostPort(ln.Addr().String())
|
|
s.ctrl.PrintfLine("229 Entering Extended Passive Mode (|||%s|)", port)
|
|
go func() {
|
|
for {
|
|
conn, err := s.ln.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
s.data = conn
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (s *Conn) cmdServerType(args []string) {
|
|
fmt.Printf("cmdServerType: %s\n", args)
|
|
switch args[0] {
|
|
default:
|
|
s.ctrl.PrintfLine("200 Type set to %s", args[0])
|
|
}
|
|
}
|
|
|
|
func (s *Conn) cmdServerList(args []string) {
|
|
fmt.Printf("cmdServerList: %s\n", args)
|
|
s.ctrl.PrintfLine(`150 Opening data channel for directory listing of "%s"`, args[0])
|
|
n, err := s.data.Write([]byte("-rw-r--r-- 1 ftp ftp 4 Apr 16 2008 TEST\n"))
|
|
if err != nil {
|
|
fmt.Printf(err.Error())
|
|
}
|
|
s.data.Close()
|
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
|
s.ctrl.PrintfLine("226 Transfer complete.")
|
|
}
|
|
|
|
func (s *Conn) cmdServerSyst(args []string) {
|
|
fmt.Printf("cmdServerSyst: %s\n", args)
|
|
s.ctrl.PrintfLine("215 UNIX Type: L8")
|
|
}
|
|
|
|
func (s *Conn) cmdServerQuit(args []string) {
|
|
if s.data != nil {
|
|
s.data.Close()
|
|
}
|
|
if s.ln != nil {
|
|
s.ln.Close()
|
|
}
|
|
if s.ctrl != nil {
|
|
s.ctrl.Close()
|
|
}
|
|
}
|
|
|
|
func (s *Conn) cmdServerPasv(args []string) {
|
|
fmt.Printf("cmdServerPasv: %s\n", args)
|
|
|
|
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
|
if err != nil {
|
|
|
|
}
|
|
s.ln = ln
|
|
host, port, _ := net.SplitHostPort(ln.Addr().String())
|
|
p0, _ := strconv.Atoi(port)
|
|
p1 := p0 / 256
|
|
p2 := p0 - p1*256
|
|
s.ctrl.PrintfLine("227 Entering Passive Mode (%s,%d,%d)", strings.Replace(host, ".", ",", -1), p1, p2)
|
|
go func() {
|
|
for {
|
|
conn, err := s.ln.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
s.data = conn
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (s *Conn) cmdServerSize(args []string) {
|
|
fmt.Printf("cmdServerSize: %s\n", args)
|
|
s.ctrl.PrintfLine("213 %d", len([]byte("test\n")))
|
|
}
|
|
|
|
func (s *Conn) cmdServerCwd(args []string) {
|
|
fmt.Printf("cmdServerCwd: %s\n", args)
|
|
s.ctrl.PrintfLine("250 Okay")
|
|
}
|
|
|
|
func (s *Conn) cmdServerRetr(args []string) {
|
|
fmt.Printf("cmdServerRetr: %s\n", args)
|
|
s.ctrl.PrintfLine(`150 Opening data channel for file contents "%s"`, args[0])
|
|
n, err := s.data.Write([]byte("test\n"))
|
|
if err != nil {
|
|
fmt.Printf(err.Error())
|
|
}
|
|
s.data.Close()
|
|
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
|
s.ctrl.PrintfLine("226 Transfer complete.")
|
|
|
|
}
|