forked from fclairamb/ftpserverlib
/
transfer_pasv.go
103 lines (88 loc) · 2.65 KB
/
transfer_pasv.go
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package server
import (
"crypto/tls"
"fmt"
"net"
"strings"
"time"
)
// Active/Passive transfer connection handler
type transferHandler interface {
// Get the connection to transfer data on
Open() (net.Conn, error)
// Close the connection (and any associated resource)
Close() error
}
// Passive connection
type passiveTransferHandler struct {
listener net.Listener // TCP or SSL Listener
tcpListener *net.TCPListener // TCP Listener (only keeping it to define a deadline during the accept)
Port int // TCP Port we are listening on
connection net.Conn // TCP Connection established
}
func (c *clientHandler) handlePASV() {
addr, _ := net.ResolveTCPAddr("tcp", ":0")
tcpListener, err := net.ListenTCP("tcp", addr)
if err != nil {
fmt.Fprintf(c.daddy.debugStream, "Could not listen: %s\n", err)
return
}
// The listener will either be plain TCP or TLS
var listener net.Listener
if c.transferTls {
if tlsConfig, err := c.daddy.driver.GetTLSConfig(); err == nil {
listener = tls.NewListener(tcpListener, tlsConfig)
} else {
c.writeMessage(550, fmt.Sprintf("Cannot get a TLS config: %v", err))
return
}
} else {
listener = tcpListener
}
p := &passiveTransferHandler{
tcpListener: tcpListener,
listener: listener,
Port: tcpListener.Addr().(*net.TCPAddr).Port,
}
// We should rewrite this part
if c.command == "PASV" {
p1 := p.Port / 256
p2 := p.Port - (p1 * 256)
// Provide our external IP address so the ftp client can connect back to us
ip := c.daddy.Settings.PublicHost
// If we don't have an IP address, we can take the one that was used for the current connection
if ip == "" {
ip = strings.Split(c.conn.LocalAddr().String(), ":")[0]
}
quads := strings.Split(ip, ".")
c.writeMessage(227, fmt.Sprintf("Entering Passive Mode (%s,%s,%s,%s,%d,%d)", quads[0], quads[1], quads[2], quads[3], p1, p2))
} else {
c.writeMessage(229, fmt.Sprintf("Entering Extended Passive Mode (|||%d|)", p.Port))
}
c.transfer = p
}
func (p *passiveTransferHandler) ConnectionWait(wait time.Duration) (net.Conn, error) {
if p.connection == nil {
p.tcpListener.SetDeadline(time.Now().Add(wait))
var err error
if p.connection, err = p.listener.Accept(); err == nil {
return p.connection, nil
} else {
return nil, err
}
}
return p.connection, nil
}
func (p *passiveTransferHandler) Open() (net.Conn, error) {
return p.ConnectionWait(time.Minute)
}
// Closing only the client connection is not supported at that time
func (p *passiveTransferHandler) Close() error {
if p.tcpListener != nil {
p.tcpListener.Close()
}
if p.connection != nil {
p.connection.Close()
}
return nil
}