feature (plg_backend_ftp): handle various connection strategy

This commit is contained in:
Mickael Kerjean 2022-12-01 01:11:38 +11:00
parent 1129e76ad3
commit f5df1445d2

View file

@ -80,43 +80,96 @@ func (f Ftp) Init(params map[string]string, app *App) (IBackend, error) {
} }
} }
configWithoutTLS := goftp.Config{ connectStrategy := []string{"ftp", "ftps::implicit", "ftps::explicit"}
User: params["username"], if strings.HasPrefix(params["hostname"], "ftp://") {
Password: params["password"], connectStrategy = []string{"ftp"}
ConnectionsPerHost: conn, params["hostname"] = strings.TrimPrefix(params["hostname"], "ftp://")
Timeout: 60 * time.Second, } else if strings.HasPrefix(params["hostname"], "ftps://") {
connectStrategy = []string{"ftps::implicit", "ftps::explicit"}
params["hostname"] = strings.TrimPrefix(params["hostname"], "ftps://")
} }
configWithTLS := configWithoutTLS
configWithTLS.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
ClientSessionCache: tls.NewLRUClientSessionCache(32),
}
configWithTLS.TLSMode = goftp.TLSExplicit
var backend *Ftp = nil var backend *Ftp = nil
hostname := fmt.Sprintf("%s:%s", params["hostname"], params["port"])
// Attempt to connect using FTPS cfgBuilder := func(timeout time.Duration, withTLS bool) goftp.Config {
if client, err := goftp.DialConfig(configWithTLS, fmt.Sprintf("%s:%s", strings.TrimPrefix(params["hostname"], "ftps://"), params["port"])); err == nil { cfg := goftp.Config{
if _, err := client.ReadDir("/"); err != nil { User: params["username"],
Password: params["password"],
ConnectionsPerHost: conn,
Timeout: timeout * time.Second,
}
cfg.Timeout = timeout
if withTLS {
cfg.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
ClientSessionCache: tls.NewLRUClientSessionCache(0),
SessionTicketsDisabled: false,
ServerName: hostname,
}
}
return cfg
}
for i := 0; i < len(connectStrategy); i++ {
if connectStrategy[i] == "ftp" {
client, err := goftp.DialConfig(cfgBuilder(5*time.Second, false), hostname)
if err != nil {
Log.Debug("plg_backend_ftp::ftp dial %s", err.Error())
continue
} else if _, err := client.ReadDir("/"); err != nil {
client.Close()
Log.Debug("plg_backend_ftp::ftp verify %s", err.Error())
continue
}
client.Close() client.Close()
} else { client, err = goftp.DialConfig(cfgBuilder(60*time.Second, false), hostname)
if err != nil {
continue
}
params["mode"] = connectStrategy[i]
backend = &Ftp{client, params, nil} backend = &Ftp{client, params, nil}
} break
} } else if connectStrategy[i] == "ftps::implicit" {
cfg := cfgBuilder(60*time.Second, true)
// Attempt to create an FTP connection if FTPS isn't available cfg.TLSMode = goftp.TLSImplicit
if backend == nil { client, err := goftp.DialConfig(cfg, hostname)
client, err := goftp.DialConfig(configWithoutTLS, fmt.Sprintf("%s:%s", strings.TrimPrefix(params["hostname"], "ftp://"), params["port"])) if err != nil {
if err != nil { Log.Debug("plg_backend_ftp::ftps::implicit dial %s", err.Error())
return backend, err continue
} } else if _, err := client.ReadDir("/"); err != nil {
if _, err := client.ReadDir("/"); err != nil { Log.Debug("plg_backend_ftp::ftps::implicit verify %s", err.Error())
client.Close()
continue
}
params["mode"] = connectStrategy[i]
backend = &Ftp{client, params, nil}
break
} else if connectStrategy[i] == "ftps::explicit" {
cfg := cfgBuilder(5*time.Second, true)
cfg.TLSMode = goftp.TLSExplicit
client, err := goftp.DialConfig(cfg, hostname)
if err != nil {
Log.Debug("plg_backend_ftp::ftps::explicit dial '%s'", err.Error())
continue
} else if _, err := client.ReadDir("/"); err != nil {
Log.Debug("plg_backend_ftp::ftps::explicit verify %s", err.Error())
client.Close()
continue
}
client.Close() client.Close()
return backend, ErrAuthenticationFailed cfg = cfgBuilder(60*time.Second, true)
cfg.TLSMode = goftp.TLSExplicit
client, err = goftp.DialConfig(cfg, hostname)
if err != nil {
continue
}
params["mode"] = connectStrategy[i]
backend = &Ftp{client, params, nil}
break
} }
backend = &Ftp{client, params, nil}
} }
if backend == nil {
return nil, ErrAuthenticationFailed
}
backend.wg = new(sync.WaitGroup) backend.wg = new(sync.WaitGroup)
backend.wg.Add(1) backend.wg.Add(1)
go func() { go func() {