Skip to content
This repository has been archived by the owner on Jul 8, 2020. It is now read-only.

Commit

Permalink
Merge branch 'phacops-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Jul 10, 2016
2 parents 08acff7 + fcd8a9c commit 2f7c01b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 21 deletions.
21 changes: 8 additions & 13 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@ func (cmd commandEpsv) RequireAuth() bool {
}

func (cmd commandEpsv) Execute(conn *Conn, param string) {
addr := conn.conn.LocalAddr()
lastIdx := strings.LastIndex(addr.String(), ":")
addr := conn.passiveListenIP()
lastIdx := strings.LastIndex(addr, ":")
if lastIdx <= 0 {
conn.writeMessage(425, "Data connection failed")
return
}

socket, err := newPassiveSocket(addr.String()[:lastIdx], conn.logger, conn.tlsConfig)
socket, err := newPassiveSocket(addr[:lastIdx], conn.PassivePort(), conn.logger, conn.tlsConfig)
if err != nil {
log.Error(err)
conn.writeMessage(425, "Data connection failed")
Expand Down Expand Up @@ -367,7 +367,9 @@ func (cmd commandList) Execute(conn *Conn, param string) {
conn.writeMessage(550, err.Error())
return
}

if !info.IsDir() {
conn.logger.Printf("%s is not a dir.\n", path)
return
}
var files []FileInfo
Expand Down Expand Up @@ -592,23 +594,16 @@ func (cmd commandPasv) RequireAuth() bool {
}

func (cmd commandPasv) Execute(conn *Conn, param string) {
addr := conn.conn.LocalAddr()
parts := strings.Split(addr.String(), ":")
if len(parts) != 2 {
conn.writeMessage(425, "Data connection failed")
return
}
socket, err := newPassiveSocket(parts[0], conn.logger, conn.tlsConfig)
listenIP := conn.passiveListenIP()
socket, err := newPassiveSocket(listenIP, conn.PassivePort(), conn.logger, conn.tlsConfig)
if err != nil {
conn.writeMessage(425, "Data connection failed")
return
}
conn.dataConn = socket
p1 := socket.Port() / 256
p2 := socket.Port() - (p1 * 256)
host := socket.Host()

quads := strings.Split(host, ".")
quads := strings.Split(listenIP, ".")
target := fmt.Sprintf("(%s,%s,%s,%s,%d,%d)", quads[0], quads[1], quads[2], quads[3], p1, p2)
msg := "Entering Passive Mode " + target
conn.writeMessage(227, msg)
Expand Down
37 changes: 34 additions & 3 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import (
"encoding/hex"
"fmt"
"io"
"log"
"net"
"path/filepath"
"strconv"
"strings"

mrand "math/rand"
)

const (
Expand Down Expand Up @@ -47,6 +50,35 @@ func (conn *Conn) IsLogin() bool {
return len(conn.user) > 0
}

func (conn *Conn) PublicIp() string {
return conn.server.PublicIp
}

func (conn *Conn) passiveListenIP() string {
if len(conn.PublicIp()) > 0 {
return conn.PublicIp()
}
return conn.conn.LocalAddr().String()
}

func (conn *Conn) PassivePort() int {
if len(conn.server.PassivePorts) > 0 {
portRange := strings.Split(conn.server.PassivePorts, "-")

if len(portRange) != 2 {
log.Println("empty port")
return 0
}

minPort, _ := strconv.Atoi(strings.TrimSpace(portRange[0]))
maxPort, _ := strconv.Atoi(strings.TrimSpace(portRange[1]))

return minPort + mrand.Intn(maxPort-minPort)
}
// let system automatically chose one port
return 0
}

// returns a random 20 char string that can be used as a unique session ID
func newSessionID() string {
hash := sha256.New()
Expand All @@ -72,11 +104,10 @@ func (conn *Conn) Serve() {
for {
line, err := conn.controlReader.ReadString('\n')
if err != nil {
if err == io.EOF {
continue
if err != io.EOF {
conn.logger.Print(fmt.Sprintln("read error:", err))
}

conn.logger.Print(fmt.Sprintln("read error:", err))
break
}
conn.receiveLine(line)
Expand Down
10 changes: 10 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ type ServerOpts struct {
// "::", which means all hostnames on ipv4 and ipv6.
Hostname string

// Public IP of the server
PublicIp string

// Passive ports
PassivePorts string

// The port that the FTP should listen on. Optional, defaults to 3000. In
// a production environment you will probably want to change this to 21.
Port int
Expand Down Expand Up @@ -58,6 +64,7 @@ type Server struct {
logger *Logger
listener net.Listener
tlsConfig *tls.Config
publicIp string
}

// serverOptsWithDefaults copies an ServerOpts struct into a new struct,
Expand Down Expand Up @@ -99,6 +106,9 @@ func serverOptsWithDefaults(opts *ServerOpts) *ServerOpts {
newOpts.CertFile = opts.CertFile
newOpts.ExplicitFTPS = opts.ExplicitFTPS

newOpts.PublicIp = opts.PublicIp
newOpts.PassivePorts = opts.PassivePorts

return &newOpts
}

Expand Down
19 changes: 14 additions & 5 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package server
import (
"crypto/tls"
"errors"
"fmt"
"net"
"strconv"
"strings"
Expand Down Expand Up @@ -33,24 +34,31 @@ type ftpActiveSocket struct {
logger *Logger
}

func newActiveSocket(host string, port int, logger *Logger) (DataSocket, error) {
connectTo := buildTCPString(host, port)
func newActiveSocket(remote string, port int, logger *Logger) (DataSocket, error) {
connectTo := buildTCPString(remote, port)

logger.Print("Opening active data connection to " + connectTo)

raddr, err := net.ResolveTCPAddr("tcp", connectTo)

if err != nil {
logger.Print(err)
return nil, err
}

tcpConn, err := net.DialTCP("tcp", nil, raddr)

if err != nil {
logger.Print(err)
return nil, err
}

socket := new(ftpActiveSocket)
socket.conn = tcpConn
socket.host = host
socket.host = remote
socket.port = port
socket.logger = logger

return socket, nil
}

Expand Down Expand Up @@ -85,12 +93,13 @@ type ftpPassiveSocket struct {
tlsConfing *tls.Config
}

func newPassiveSocket(host string, logger *Logger, tlsConfing *tls.Config) (DataSocket, error) {
func newPassiveSocket(host string, port int, logger *Logger, tlsConfing *tls.Config) (DataSocket, error) {
socket := new(ftpPassiveSocket)
socket.ingress = make(chan []byte)
socket.egress = make(chan []byte)
socket.logger = logger
socket.host = host
socket.port = port
if err := socket.GoListenAndServe(); err != nil {
return nil, err
}
Expand Down Expand Up @@ -128,7 +137,7 @@ func (socket *ftpPassiveSocket) Close() error {
}

func (socket *ftpPassiveSocket) GoListenAndServe() (err error) {
laddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
laddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("0.0.0.0:%d", socket.port))
if err != nil {
socket.logger.Print(err)
return
Expand Down

0 comments on commit 2f7c01b

Please sign in to comment.