diff --git a/ssh/server.go b/ssh/server.go index 480eb6b..d1a798a 100644 --- a/ssh/server.go +++ b/ssh/server.go @@ -28,7 +28,11 @@ type Permissions struct { // the given address). The SSH package currently only enforces // the "source-address" critical option: it is validated against // the client's remote address whenever it is present in the - // Permissions returned by any authentication callback. It is up + // Permissions returned by any authentication callback. Its value + // is a comma-separated list of IP addresses and CIDR blocks; + // consistently with OpenSSH, a connection whose remote address is + // not an IP address, such as a Unix domain socket, never matches + // the list and is rejected when the option is present. It is up // to server implementations to enforce other critical options, // such as "force-command", by checking them after the SSH // handshake is successful. In general, SSH servers should reject @@ -444,6 +448,10 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) return perms, err } +// checkSourceAddress matches addr against sourceAddrs, a comma-separated list +// of IP addresses and CIDR blocks. Consistently with OpenSSH, a remote address +// that is not IP-based, such as a Unix domain socket, never matches the list +// and is rejected. func checkSourceAddress(addr net.Addr, sourceAddrs string) error { if addr == nil { return errors.New("ssh: no address known for client, but source-address match required") @@ -451,7 +459,7 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { tcpAddr, ok := addr.(*net.TCPAddr) if !ok { - return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) + return fmt.Errorf("ssh: remote address %v is not a TCP address when checking source-address match", addr) } for _, sourceAddr := range strings.Split(sourceAddrs, ",") { diff --git a/ssh/server_test.go b/ssh/server_test.go index 81ebd1e..0f84616 100644 --- a/ssh/server_test.go +++ b/ssh/server_test.go @@ -849,6 +849,18 @@ func TestAuthCallbacksSourceAddress(t *testing.T) { } } +func TestCheckSourceAddressNonIP(t *testing.T) { + for _, addr := range []net.Addr{ + &net.UnixAddr{Name: "/run/test.sock", Net: "unix"}, + &net.UnixAddr{}, + nil, + } { + if err := checkSourceAddress(addr, "127.0.0.0/8,::1/128"); err == nil { + t.Errorf("source-address check succeeded for non-IP remote address %v", addr) + } + } +} + func TestVerifiedPublicCallbackPartialSuccessBadUsage(t *testing.T) { c1, c2, err := netPipe() if err != nil {