ssh: Support multiple source-addresses, don't require IPv4 in tests.
The ssh tests currently require 127.0.0.1 to work which isn't necessarily available everywhere. To fix the source-address tests, support comma-separated source-address values per the PROTOCOL.certkeys file: Comma-separated list of source addresses from which this certificate is accepted for authentication. Addresses are specified in CIDR format (nn.nn.nn.nn/nn or hhhh::hhhh/nn). If this option is not present then certificates may be presented from any source address. Change-Id: I87536ff81ffa005c073da103021ebc0dfb12b620 Reviewed-on: https://go-review.googlesource.com/36110 Reviewed-by: Han-Wen Nienhuys <hanwen@google.com> Run-TryBot: Heschi Kreinick <heschi@google.com>
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+15
-12
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user