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

Commit 2f7c01b

Browse files
committed
Merge branch 'phacops-master'
2 parents 08acff7 + fcd8a9c commit 2f7c01b

File tree

4 files changed

+66
-21
lines changed

4 files changed

+66
-21
lines changed

cmd.go

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,14 @@ func (cmd commandEpsv) RequireAuth() bool {
310310
}
311311

312312
func (cmd commandEpsv) Execute(conn *Conn, param string) {
313-
addr := conn.conn.LocalAddr()
314-
lastIdx := strings.LastIndex(addr.String(), ":")
313+
addr := conn.passiveListenIP()
314+
lastIdx := strings.LastIndex(addr, ":")
315315
if lastIdx <= 0 {
316316
conn.writeMessage(425, "Data connection failed")
317317
return
318318
}
319319

320-
socket, err := newPassiveSocket(addr.String()[:lastIdx], conn.logger, conn.tlsConfig)
320+
socket, err := newPassiveSocket(addr[:lastIdx], conn.PassivePort(), conn.logger, conn.tlsConfig)
321321
if err != nil {
322322
log.Error(err)
323323
conn.writeMessage(425, "Data connection failed")
@@ -367,7 +367,9 @@ func (cmd commandList) Execute(conn *Conn, param string) {
367367
conn.writeMessage(550, err.Error())
368368
return
369369
}
370+
370371
if !info.IsDir() {
372+
conn.logger.Printf("%s is not a dir.\n", path)
371373
return
372374
}
373375
var files []FileInfo
@@ -592,23 +594,16 @@ func (cmd commandPasv) RequireAuth() bool {
592594
}
593595

594596
func (cmd commandPasv) Execute(conn *Conn, param string) {
595-
addr := conn.conn.LocalAddr()
596-
parts := strings.Split(addr.String(), ":")
597-
if len(parts) != 2 {
598-
conn.writeMessage(425, "Data connection failed")
599-
return
600-
}
601-
socket, err := newPassiveSocket(parts[0], conn.logger, conn.tlsConfig)
597+
listenIP := conn.passiveListenIP()
598+
socket, err := newPassiveSocket(listenIP, conn.PassivePort(), conn.logger, conn.tlsConfig)
602599
if err != nil {
603600
conn.writeMessage(425, "Data connection failed")
604601
return
605602
}
606603
conn.dataConn = socket
607604
p1 := socket.Port() / 256
608605
p2 := socket.Port() - (p1 * 256)
609-
host := socket.Host()
610-
611-
quads := strings.Split(host, ".")
606+
quads := strings.Split(listenIP, ".")
612607
target := fmt.Sprintf("(%s,%s,%s,%s,%d,%d)", quads[0], quads[1], quads[2], quads[3], p1, p2)
613608
msg := "Entering Passive Mode " + target
614609
conn.writeMessage(227, msg)

conn.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import (
88
"encoding/hex"
99
"fmt"
1010
"io"
11+
"log"
1112
"net"
1213
"path/filepath"
1314
"strconv"
1415
"strings"
16+
17+
mrand "math/rand"
1518
)
1619

1720
const (
@@ -47,6 +50,35 @@ func (conn *Conn) IsLogin() bool {
4750
return len(conn.user) > 0
4851
}
4952

53+
func (conn *Conn) PublicIp() string {
54+
return conn.server.PublicIp
55+
}
56+
57+
func (conn *Conn) passiveListenIP() string {
58+
if len(conn.PublicIp()) > 0 {
59+
return conn.PublicIp()
60+
}
61+
return conn.conn.LocalAddr().String()
62+
}
63+
64+
func (conn *Conn) PassivePort() int {
65+
if len(conn.server.PassivePorts) > 0 {
66+
portRange := strings.Split(conn.server.PassivePorts, "-")
67+
68+
if len(portRange) != 2 {
69+
log.Println("empty port")
70+
return 0
71+
}
72+
73+
minPort, _ := strconv.Atoi(strings.TrimSpace(portRange[0]))
74+
maxPort, _ := strconv.Atoi(strings.TrimSpace(portRange[1]))
75+
76+
return minPort + mrand.Intn(maxPort-minPort)
77+
}
78+
// let system automatically chose one port
79+
return 0
80+
}
81+
5082
// returns a random 20 char string that can be used as a unique session ID
5183
func newSessionID() string {
5284
hash := sha256.New()
@@ -72,11 +104,10 @@ func (conn *Conn) Serve() {
72104
for {
73105
line, err := conn.controlReader.ReadString('\n')
74106
if err != nil {
75-
if err == io.EOF {
76-
continue
107+
if err != io.EOF {
108+
conn.logger.Print(fmt.Sprintln("read error:", err))
77109
}
78110

79-
conn.logger.Print(fmt.Sprintln("read error:", err))
80111
break
81112
}
82113
conn.receiveLine(line)

server.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ type ServerOpts struct {
2727
// "::", which means all hostnames on ipv4 and ipv6.
2828
Hostname string
2929

30+
// Public IP of the server
31+
PublicIp string
32+
33+
// Passive ports
34+
PassivePorts string
35+
3036
// The port that the FTP should listen on. Optional, defaults to 3000. In
3137
// a production environment you will probably want to change this to 21.
3238
Port int
@@ -58,6 +64,7 @@ type Server struct {
5864
logger *Logger
5965
listener net.Listener
6066
tlsConfig *tls.Config
67+
publicIp string
6168
}
6269

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

109+
newOpts.PublicIp = opts.PublicIp
110+
newOpts.PassivePorts = opts.PassivePorts
111+
102112
return &newOpts
103113
}
104114

socket.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package server
33
import (
44
"crypto/tls"
55
"errors"
6+
"fmt"
67
"net"
78
"strconv"
89
"strings"
@@ -33,24 +34,31 @@ type ftpActiveSocket struct {
3334
logger *Logger
3435
}
3536

36-
func newActiveSocket(host string, port int, logger *Logger) (DataSocket, error) {
37-
connectTo := buildTCPString(host, port)
37+
func newActiveSocket(remote string, port int, logger *Logger) (DataSocket, error) {
38+
connectTo := buildTCPString(remote, port)
39+
3840
logger.Print("Opening active data connection to " + connectTo)
41+
3942
raddr, err := net.ResolveTCPAddr("tcp", connectTo)
43+
4044
if err != nil {
4145
logger.Print(err)
4246
return nil, err
4347
}
48+
4449
tcpConn, err := net.DialTCP("tcp", nil, raddr)
50+
4551
if err != nil {
4652
logger.Print(err)
4753
return nil, err
4854
}
55+
4956
socket := new(ftpActiveSocket)
5057
socket.conn = tcpConn
51-
socket.host = host
58+
socket.host = remote
5259
socket.port = port
5360
socket.logger = logger
61+
5462
return socket, nil
5563
}
5664

@@ -85,12 +93,13 @@ type ftpPassiveSocket struct {
8593
tlsConfing *tls.Config
8694
}
8795

88-
func newPassiveSocket(host string, logger *Logger, tlsConfing *tls.Config) (DataSocket, error) {
96+
func newPassiveSocket(host string, port int, logger *Logger, tlsConfing *tls.Config) (DataSocket, error) {
8997
socket := new(ftpPassiveSocket)
9098
socket.ingress = make(chan []byte)
9199
socket.egress = make(chan []byte)
92100
socket.logger = logger
93101
socket.host = host
102+
socket.port = port
94103
if err := socket.GoListenAndServe(); err != nil {
95104
return nil, err
96105
}
@@ -128,7 +137,7 @@ func (socket *ftpPassiveSocket) Close() error {
128137
}
129138

130139
func (socket *ftpPassiveSocket) GoListenAndServe() (err error) {
131-
laddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
140+
laddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("0.0.0.0:%d", socket.port))
132141
if err != nil {
133142
socket.logger.Print(err)
134143
return

0 commit comments

Comments
 (0)