Skip to content

Commit

Permalink
ssh: Support multiple source-addresses, don't require IPv4 in tests.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Run-TryBot: Heschi Kreinick <[email protected]>
  • Loading branch information
heschi committed Feb 2, 2017
1 parent 641ab6b commit bed1280
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 15 deletions.
4 changes: 2 additions & 2 deletions ssh/client_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion ssh/handshake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
27 changes: 15 additions & 12 deletions ssh/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net"
"strings"
)

// The Permissions type holds fine-grained permissions that are
Expand Down Expand Up @@ -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")
}
Expand All @@ -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
}
}
}

Expand Down

0 comments on commit bed1280

Please sign in to comment.