Add DialWithExplicitTLS
This commit is contained in:
parent
d4caf6ffca
commit
ac1574d383
42
ftp.go
42
ftp.go
@ -50,6 +50,7 @@ type dialOptions struct {
|
|||||||
context context.Context
|
context context.Context
|
||||||
dialer net.Dialer
|
dialer net.Dialer
|
||||||
tlsConfig *tls.Config
|
tlsConfig *tls.Config
|
||||||
|
explicitTLS bool
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
disableEPSV bool
|
disableEPSV bool
|
||||||
location *time.Location
|
location *time.Location
|
||||||
@ -90,7 +91,7 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) {
|
|||||||
|
|
||||||
if do.dialFunc != nil {
|
if do.dialFunc != nil {
|
||||||
tconn, err = do.dialFunc("tcp", addr)
|
tconn, err = do.dialFunc("tcp", addr)
|
||||||
} else if do.tlsConfig != nil {
|
} else if do.tlsConfig != nil && !do.explicitTLS {
|
||||||
tconn, err = tls.DialWithDialer(&do.dialer, "tcp", addr, do.tlsConfig)
|
tconn, err = tls.DialWithDialer(&do.dialer, "tcp", addr, do.tlsConfig)
|
||||||
} else {
|
} else {
|
||||||
ctx := do.context
|
ctx := do.context
|
||||||
@ -111,15 +112,10 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) {
|
|||||||
// If we use the domain name, we might not resolve to the same IP.
|
// If we use the domain name, we might not resolve to the same IP.
|
||||||
remoteAddr := tconn.RemoteAddr().(*net.TCPAddr)
|
remoteAddr := tconn.RemoteAddr().(*net.TCPAddr)
|
||||||
|
|
||||||
var sourceConn io.ReadWriteCloser = tconn
|
|
||||||
if do.debugOutput != nil {
|
|
||||||
sourceConn = newDebugWrapper(tconn, do.debugOutput)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &ServerConn{
|
c := &ServerConn{
|
||||||
options: do,
|
options: do,
|
||||||
features: make(map[string]string),
|
features: make(map[string]string),
|
||||||
conn: textproto.NewConn(sourceConn),
|
conn: textproto.NewConn(do.wrapConn(tconn)),
|
||||||
host: remoteAddr.IP.String(),
|
host: remoteAddr.IP.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +125,15 @@ func Dial(addr string, options ...DialOption) (*ServerConn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if do.explicitTLS {
|
||||||
|
if err := c.authTLS(); err != nil {
|
||||||
|
_ = c.Quit()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tconn = tls.Client(tconn, do.tlsConfig)
|
||||||
|
c.conn = textproto.NewConn(do.wrapConn(tconn))
|
||||||
|
}
|
||||||
|
|
||||||
err = c.feat()
|
err = c.feat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Quit()
|
c.Quit()
|
||||||
@ -198,6 +203,15 @@ func DialWithTLS(tlsConfig *tls.Config) DialOption {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialWithExplicitTLS returns a DialOption that configures the ServerConn to be upgraded to TLS
|
||||||
|
// See DialWithTLS for general TLS documentation
|
||||||
|
func DialWithExplicitTLS(tlsConfig *tls.Config) DialOption {
|
||||||
|
return DialOption{func(do *dialOptions) {
|
||||||
|
do.explicitTLS = true
|
||||||
|
do.tlsConfig = tlsConfig
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
// DialWithDebugOutput returns a DialOption that configures the ServerConn to write to the Writer
|
// DialWithDebugOutput returns a DialOption that configures the ServerConn to write to the Writer
|
||||||
// everything it reads from the server
|
// everything it reads from the server
|
||||||
func DialWithDebugOutput(w io.Writer) DialOption {
|
func DialWithDebugOutput(w io.Writer) DialOption {
|
||||||
@ -218,6 +232,14 @@ func DialWithDialFunc(f func(network, address string) (net.Conn, error)) DialOpt
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *dialOptions) wrapConn(netConn net.Conn) io.ReadWriteCloser {
|
||||||
|
if o.debugOutput == nil {
|
||||||
|
return netConn
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDebugWrapper(netConn, o.debugOutput)
|
||||||
|
}
|
||||||
|
|
||||||
// Connect is an alias to Dial, for backward compatibility
|
// Connect is an alias to Dial, for backward compatibility
|
||||||
func Connect(addr string) (*ServerConn, error) {
|
func Connect(addr string) (*ServerConn, error) {
|
||||||
return Dial(addr)
|
return Dial(addr)
|
||||||
@ -269,6 +291,12 @@ func (c *ServerConn) Login(user, password string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// authTLS upgrades the connection to use TLS
|
||||||
|
func (c *ServerConn) authTLS() error {
|
||||||
|
_, _, err := c.cmd(StatusAuthOK, "AUTH TLS")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// feat issues a FEAT FTP command to list the additional commands supported by
|
// feat issues a FEAT FTP command to list the additional commands supported by
|
||||||
// the remote FTP server.
|
// the remote FTP server.
|
||||||
// FEAT is described in RFC 2389
|
// FEAT is described in RFC 2389
|
||||||
|
@ -25,6 +25,7 @@ const (
|
|||||||
StatusLoggedIn = 230
|
StatusLoggedIn = 230
|
||||||
StatusLoggedOut = 231
|
StatusLoggedOut = 231
|
||||||
StatusLogoutAck = 232
|
StatusLogoutAck = 232
|
||||||
|
StatusAuthOK = 234
|
||||||
StatusRequestedFileActionOK = 250
|
StatusRequestedFileActionOK = 250
|
||||||
StatusPathCreated = 257
|
StatusPathCreated = 257
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ var statusText = map[int]string{
|
|||||||
StatusLoggedIn: "User logged in, proceed.",
|
StatusLoggedIn: "User logged in, proceed.",
|
||||||
StatusLoggedOut: "User logged out; service terminated.",
|
StatusLoggedOut: "User logged out; service terminated.",
|
||||||
StatusLogoutAck: "Logout command noted, will complete when transfer done.",
|
StatusLogoutAck: "Logout command noted, will complete when transfer done.",
|
||||||
|
StatusAuthOK: "AUTH command OK",
|
||||||
StatusRequestedFileActionOK: "Requested file action okay, completed.",
|
StatusRequestedFileActionOK: "Requested file action okay, completed.",
|
||||||
StatusPathCreated: "Path created.",
|
StatusPathCreated: "Path created.",
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user