From 629a3eeca286d21311214fdb4eb67dd16792a70b Mon Sep 17 00:00:00 2001 From: Ivan Andreev Date: Fri, 9 Apr 2021 01:43:50 +0300 Subject: [PATCH] backend/ftp: fix implicit TLS after PR #4266 (#5219) PR #4266 modified ftpConnection to make ftp library into using a custom dial function which is QoS aware and takes care of TLS. However the ServerConn.Login function from the ftp library also needs TLS config passed explicitly as a trigger for sending PSBZ and PROT options to FTP server. This was not taken care of resulting in failure to connect via FTP with implicit TLS. This PR fixes that. Fixes #5210 --- backend/ftp/ftp.go | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/backend/ftp/ftp.go b/backend/ftp/ftp.go index f9401ac64..ab90c1e95 100644 --- a/backend/ftp/ftp.go +++ b/backend/ftp/ftp.go @@ -241,23 +241,6 @@ func (dl *debugLog) Write(p []byte) (n int, err error) { return len(p), nil } -type dialCtx struct { - f *Fs - ctx context.Context -} - -// dial a new connection with fshttp dialer -func (d *dialCtx) dial(network, address string) (net.Conn, error) { - conn, err := fshttp.NewDialer(d.ctx).Dial(network, address) - if err != nil { - return nil, err - } - if d.f.tlsConf != nil { - conn = tls.Client(conn, d.f.tlsConf) - } - return conn, err -} - // shouldRetry returns a boolean as to whether this err deserve to be // retried. It returns the err as a convenience func shouldRetry(ctx context.Context, err error) (bool, error) { @@ -277,9 +260,22 @@ func shouldRetry(ctx context.Context, err error) (bool, error) { // Open a new connection to the FTP server. func (f *Fs) ftpConnection(ctx context.Context) (c *ftp.ServerConn, err error) { fs.Debugf(f, "Connecting to FTP server") - dCtx := dialCtx{f, ctx} - ftpConfig := []ftp.DialOption{ftp.DialWithDialFunc(dCtx.dial)} - if f.opt.ExplicitTLS { + + // Make ftp library dial with fshttp dialer optionally using TLS + dial := func(network, address string) (conn net.Conn, err error) { + conn, err = fshttp.NewDialer(ctx).Dial(network, address) + if f.tlsConf != nil && err == nil { + conn = tls.Client(conn, f.tlsConf) + } + return + } + ftpConfig := []ftp.DialOption{ftp.DialWithDialFunc(dial)} + + if f.opt.TLS { + // Our dialer takes care of TLS but ftp library also needs tlsConf + // as a trigger for sending PSBZ and PROT options to server. + ftpConfig = append(ftpConfig, ftp.DialWithTLS(f.tlsConf)) + } else if f.opt.ExplicitTLS { ftpConfig = append(ftpConfig, ftp.DialWithExplicitTLS(f.tlsConf)) // Initial connection needs to be cleartext for explicit TLS conn, err := fshttp.NewDialer(ctx).Dial("tcp", f.dialAddr)