ssh: document and test source-address behavior for non-IP transports
The source-address critical option is a comma-separated list of IP addresses and CIDR blocks, so it can never match a connection whose remote address is not IP-based, such as a Unix domain socket. Change-Id: I45e09fe5c8c13922cb0735278acf33320857322c Reviewed-on: https://go-review.googlesource.com/c/crypto/+/797042 Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Reviewed-by: Junyang Shao <shaojunyang@google.com>
This commit is contained in:
+10
-2
@@ -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, ",") {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user