FTPD: make sure that the passive ip, if provided, is valid

The server will refuse to start if the provided passive ip is not a
valid IPv4 address.

Fixes #376
This commit is contained in:
Nicola Murino 2021-04-16 15:08:10 +02:00
parent 683ba6cd5b
commit 124c471a2b
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
5 changed files with 46 additions and 1 deletions

View file

@ -109,7 +109,7 @@ The configuration file contains the following sections:
- `address`, string. Leave blank to listen on all available network interfaces. Default: "".
- `apply_proxy_config`, boolean. If enabled the common proxy configuration, if any, will be applied. Default `true`.
- `tls_mode`, integer. 0 means accept both cleartext and encrypted sessions. 1 means TLS is required for both control and data connection. 2 means implicit TLS. Do not enable this blindly, please check that a proper TLS config is in place if you set `tls_mode` is different from 0.
- `force_passive_ip`, ip address. External IP address to expose for passive connections. Leavy empty to autodetect. Defaut: "".
- `force_passive_ip`, ip address. External IP address to expose for passive connections. Leavy empty to autodetect. If not empty, it must be a valid IPv4 address. Defaut: "".
- `client_auth_type`, integer. Set to `1` to require a client certificate and verify it. Set to `2` to request a client certificate during the TLS handshake and verify it if given, in this mode the client is allowed not to send a certificate. At least one certification authority must be defined in order to verify client certificates. If no certification authority is defined, this setting is ignored. Default: 0.
- `tls_cipher_suites`, list of strings. List of supported cipher suites for TLS version 1.2. If empty, a default list of secure cipher suites is used, with a preference order based on hardware performance. Note that TLS 1.3 ciphersuites are not configurable. The supported ciphersuites names are defined [here](https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L52). Any invalid name will be silently ignored. The order matters, the ciphers listed first will be the preferred ones. Default: empty.
- `bind_port`, integer. Deprecated, please use `bindings`

View file

@ -3,6 +3,7 @@ package ftpd
import (
"fmt"
"net"
"path/filepath"
ftpserver "github.com/fclairamb/ftpserverlib"
@ -74,6 +75,21 @@ func (b *Binding) IsValid() bool {
return b.Port > 0
}
func (b *Binding) checkPassiveIP() error {
if b.ForcePassiveIP != "" {
ip := net.ParseIP(b.ForcePassiveIP)
if ip == nil {
return fmt.Errorf("the provided passive IP %#v is not valid", b.ForcePassiveIP)
}
ip = ip.To4()
if ip == nil {
return fmt.Errorf("the provided passive IP %#v is not a valid IPv4 address", b.ForcePassiveIP)
}
b.ForcePassiveIP = ip.String()
}
return nil
}
// HasProxy returns true if the proxy protocol is active for this binding
func (b *Binding) HasProxy() bool {
return b.ApplyProxyConfig && common.Config.ProxyProtocol > 0

View file

@ -454,6 +454,11 @@ func TestInitializationFailure(t *testing.T) {
ftpdConf.CACertificates = []string{caCrtPath}
ftpdConf.CARevocationLists = []string{caCRLPath}
ftpdConf.Bindings[1].ForcePassiveIP = "127001"
err = ftpdConf.Initialize(configDir)
require.Error(t, err)
require.Contains(t, err.Error(), "the provided passive IP \"127001\" is not valid")
ftpdConf.Bindings[1].ForcePassiveIP = ""
err = ftpdConf.Initialize(configDir)
require.Error(t, err)
}

View file

@ -387,6 +387,27 @@ func TestInitialization(t *testing.T) {
_, err = server.GetSettings()
assert.Error(t, err)
binding = Binding{
Port: 2121,
ForcePassiveIP: "192.168.1",
}
server = NewServer(c, configDir, binding, 0)
_, err = server.GetSettings()
if assert.Error(t, err) {
assert.Contains(t, err.Error(), "is not valid")
}
binding.ForcePassiveIP = "::ffff:192.168.89.9"
err = binding.checkPassiveIP()
assert.NoError(t, err)
assert.Equal(t, "192.168.89.9", binding.ForcePassiveIP)
binding.ForcePassiveIP = "::1"
err = binding.checkPassiveIP()
if assert.Error(t, err) {
assert.Contains(t, err.Error(), "is not a valid IPv4 address")
}
err = ReloadCertificateMgr()
assert.NoError(t, err)

View file

@ -83,6 +83,9 @@ func (s *Server) cleanTLSConnVerification(id uint32) {
// GetSettings returns FTP server settings
func (s *Server) GetSettings() (*ftpserver.Settings, error) {
if err := s.binding.checkPassiveIP(); err != nil {
return nil, err
}
var portRange *ftpserver.PortRange
if s.config.PassivePortRange.Start > 0 && s.config.PassivePortRange.End > s.config.PassivePortRange.Start {
portRange = &ftpserver.PortRange{