Skip to content

Commit c7e4856

Browse files
author
tanl
committed
add support for implicit FPTS
1 parent b78a846 commit c7e4856

File tree

2 files changed

+64
-20
lines changed

2 files changed

+64
-20
lines changed

starttls/ftp.go

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,41 +24,81 @@ import (
2424
"strconv"
2525
)
2626

27-
func dumpTLSConnStateFromFTP(dialer Dialer, address string, config *tls.Config) (*tls.ConnectionState, error) {
28-
c, err := dialer.Dial("tcp", address)
27+
type FTPCtx struct {
28+
tcpConn *net.TCPConn
29+
tlsConn *tls.Conn
30+
dialFunc func(dialer Dialer, address string) (net.Conn, error)
31+
}
32+
33+
func dumpTLSConnStateFromFTP(dialer Dialer, address string, config *tls.Config, explicitTLS bool) (*tls.ConnectionState, error) {
34+
35+
ctx := FTPCtx{}
36+
37+
if explicitTLS {
38+
ctx.dialFunc = func(dialer Dialer, address string) (net.Conn, error) {
39+
return dialer.Dial("tcp", address)
40+
}
41+
} else {
42+
ctx.dialFunc = func(dialer Dialer, address string) (net.Conn, error) {
43+
tlsDialer := &tls.Dialer{
44+
NetDialer: dialer.(*net.Dialer),
45+
Config: config,
46+
}
47+
return tlsDialer.Dial("tcp", address)
48+
}
49+
}
50+
51+
c, err := ctx.dialFunc(dialer, address)
2952
if err != nil {
3053
return nil, err
3154
}
3255

33-
conn := c.(*net.TCPConn)
56+
if _, err = checkServiceReady(c); err != nil {
57+
return nil, err
58+
}
59+
60+
if explicitTLS {
61+
ctx.tcpConn = c.(*net.TCPConn)
62+
} else {
63+
ctx.tlsConn = c.(*tls.Conn)
64+
}
65+
66+
if explicitTLS {
67+
if _, err := authTLS(ctx.tcpConn); err != nil {
68+
return nil, err
69+
}
70+
ctx.tlsConn = tls.Client(ctx.tcpConn, config)
71+
ctx.tlsConn.Handshake()
72+
}
73+
74+
state := ctx.tlsConn.ConnectionState()
75+
return &state, nil
76+
}
77+
78+
func checkServiceReady(conn net.Conn) (int, error) {
3479
status, err := readFTP(conn)
3580
if err != nil {
36-
return nil, err
81+
return status, err
3782
}
3883
if status != 220 {
39-
return nil, fmt.Errorf("FTP server responded with status %d, was expecting 220", status)
84+
return status, fmt.Errorf("FTP server responded with status %d, was expecting 220", status)
4085
}
86+
return status, nil
87+
}
4188

89+
func authTLS(conn *net.TCPConn) (int, error) {
4290
fmt.Fprintf(conn, "AUTH TLS\r\n")
43-
status, err = readFTP(conn)
91+
status, err := readFTP(conn)
4492
if err != nil {
45-
return nil, err
93+
return status, err
4694
}
4795
if status != 234 {
48-
return nil, fmt.Errorf("FTP server responded with status %d, was expecting 234", status)
96+
return status, fmt.Errorf("FTP server responded with status %d, was expecting 234", status)
4997
}
50-
51-
tlsConn := tls.Client(conn, config)
52-
err = tlsConn.Handshake()
53-
if err != nil {
54-
return nil, err
55-
}
56-
57-
state := tlsConn.ConnectionState()
58-
return &state, nil
98+
return status, nil
5999
}
60100

61-
func readFTP(conn *net.TCPConn) (int, error) {
101+
func readFTP(conn net.Conn) (int, error) {
62102
reader := bufio.NewReader(conn)
63103
response, err := reader.ReadString('\n')
64104
if err != nil {

starttls/starttls.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
)
3434

3535
// Protocols are the names of supported protocols
36-
var Protocols = []string{"mysql", "postgres", "psql", "smtp", "ldap", "ftp", "imap"}
36+
var Protocols = []string{"mysql", "postgres", "psql", "smtp", "ldap", "ftp", "ftps", "imap"}
3737

3838
type connectResult struct {
3939
state *tls.ConnectionState
@@ -230,7 +230,11 @@ func GetConnectionState(startTLSType, connectName, connectTo, identity, clientCe
230230
res <- connectResult{&state, nil}
231231
case "ftp":
232232
addr := withDefaultPort(connectTo, 21)
233-
state, err = dumpTLSConnStateFromFTP(dialer, addr, tlsConfig)
233+
state, err = dumpTLSConnStateFromFTP(dialer, addr, tlsConfig, true)
234+
res <- connectResult{state, err}
235+
case "ftps":
236+
addr := withDefaultPort(connectTo, 990)
237+
state, err = dumpTLSConnStateFromFTP(dialer, addr, tlsConfig, false)
234238
res <- connectResult{state, err}
235239
case "imap":
236240
addr := withDefaultPort(connectTo, 143)

0 commit comments

Comments
 (0)