Skip to content

Commit

Permalink
PASV: make sure that the passive IP is valid (#236)
Browse files Browse the repository at this point in the history
PASV: make sure that the passive IP is valid

an invalid IPv4 address will cause PASV handling crashes.

Fixes #235
  • Loading branch information
drakkan authored Apr 27, 2021
1 parent 34feba4 commit 04228bd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 1 deletion.
20 changes: 19 additions & 1 deletion transfer_pasv.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ type passiveTransferHandler struct {
logger log.Logger // Logger
}

type ipValidationError struct {
error string
}

func (e *ipValidationError) Error() string {
return e.error
}

func (c *clientHandler) getCurrentIP() ([]string, error) {
// Provide our external IP address so the ftp client can connect back to us
ip := c.server.settings.PublicHost
Expand All @@ -56,7 +64,17 @@ func (c *clientHandler) getCurrentIP() ([]string, error) {
}
}

return strings.Split(ip, "."), nil
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return nil, &ipValidationError{error: fmt.Sprintf("invalid passive IP %#v", ip)}
}

parsedIP = parsedIP.To4()
if parsedIP == nil {
return nil, &ipValidationError{error: fmt.Sprintf("invalid IPv4 passive IP %#v", ip)}
}

return strings.Split(parsedIP.String(), "."), nil
}

// ErrNoAvailableListeningPort is returned when no port could be found to accept incoming connection
Expand Down
38 changes: 38 additions & 0 deletions transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,3 +822,41 @@ func TestASCIITransfersInvalidFiles(t *testing.T) {
remoteHash := ftpDownloadAndHashWithRawConnection(t, raw, "file.bin")
require.Equal(t, localHash, remoteHash)
}

func TestPASVInvalidPublicHost(t *testing.T) {
s := NewTestServer(t, true)
s.settings.PublicHost = "not an IP"

conf := goftp.Config{
User: authUser,
Password: authPass,
}

c, err := goftp.DialConfig(conf, s.Addr())
require.NoError(t, err, "Couldn't connect")

defer func() { require.NoError(t, c.Close()) }()

raw, err := c.OpenRawConn()
require.NoError(t, err, "Couldn't open raw connection")

rc, resp, err := raw.SendCommand("PASV")
require.NoError(t, err)
require.Equal(t, StatusServiceNotAvailable, rc)
require.Contains(t, resp, "invalid passive IP")

s.settings.PublicHost = "::1"
rc, resp, err = raw.SendCommand("PASV")
require.NoError(t, err)
require.Equal(t, StatusServiceNotAvailable, rc)
require.Contains(t, resp, "invalid IPv4 passive IP")

s.settings.PublicHost = ""
s.settings.PublicIPResolver = func(cc ClientContext) (string, error) {
return "127.0.0", nil
}
rc, resp, err = raw.SendCommand("PASV")
require.NoError(t, err)
require.Equal(t, StatusServiceNotAvailable, rc)
require.Contains(t, resp, "invalid passive IP")
}

0 comments on commit 04228bd

Please sign in to comment.