diff --git a/ssh/client_auth_test.go b/ssh/client_auth_test.go index 1d9681a..e384c79 100644 --- a/ssh/client_auth_test.go +++ b/ssh/client_auth_test.go @@ -333,14 +333,14 @@ func TestClientLoginCert(t *testing.T) { } // allowed source address - cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"} + cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err != nil { t.Errorf("cert login with source-address failed: %v", err) } // disallowed source address - cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"} + cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"} cert.SignCert(rand.Reader, testSigners["ecdsa"]) if err := tryAuth(t, clientConfig); err == nil { t.Errorf("cert login with source-address succeeded") diff --git a/ssh/handshake_test.go b/ssh/handshake_test.go index 4d64376..1b83112 100644 --- a/ssh/handshake_test.go +++ b/ssh/handshake_test.go @@ -40,7 +40,7 @@ func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error // therefore is buffered (net.Pipe deadlocks if both sides start with // a write.) func netPipe() (net.Conn, net.Conn, error) { - listener, err := net.Listen("tcp", "127.0.0.1:0") + listener, err := net.Listen("tcp", ":0") if err != nil { return nil, nil, err } diff --git a/ssh/server.go b/ssh/server.go index 28b109a..77c84d1 100644 --- a/ssh/server.go +++ b/ssh/server.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net" + "strings" ) // The Permissions type holds fine-grained permissions that are @@ -231,7 +232,7 @@ func isAcceptableAlgo(algo string) bool { return false } -func checkSourceAddress(addr net.Addr, sourceAddr string) error { +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") } @@ -241,18 +242,20 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error { return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) } - if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { - if allowedIP.Equal(tcpAddr.IP) { - return nil - } - } else { - _, ipNet, err := net.ParseCIDR(sourceAddr) - if err != nil { - return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) - } + for _, sourceAddr := range strings.Split(sourceAddrs, ",") { + if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { + if allowedIP.Equal(tcpAddr.IP) { + return nil + } + } else { + _, ipNet, err := net.ParseCIDR(sourceAddr) + if err != nil { + return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) + } - if ipNet.Contains(tcpAddr.IP) { - return nil + if ipNet.Contains(tcpAddr.IP) { + return nil + } } }