Skip to content

Commit

Permalink
checks in in proxy subsystem, fixes #1336
Browse files Browse the repository at this point in the history
  • Loading branch information
klizhentas authored and russjones committed Oct 2, 2017
1 parent 92bfdcd commit eb1f6ae
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 27 deletions.
66 changes: 39 additions & 27 deletions lib/srv/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,56 +59,68 @@ type proxySubsys struct {
// "proxy:@clustername" - Teleport request to connect to an auth server for cluster with name 'clustername'
// "proxy:host:22@clustername" - Teleport request to connect to host:22 on cluster 'clustername'
// "proxy:host:22@namespace@clustername"
func parseProxySubsys(name string, srv *Server) (*proxySubsys, error) {
log.Debugf("parse_proxy_subsys(%s)", name)
func parseProxySubsys(request string, srv *Server) (*proxySubsys, error) {
log.Debugf("parse_proxy_subsys(%q)", request)
var (
clusterName string
host string
port string
paramError = trace.BadParameter("invalid format for proxy request: '%v', expected 'proxy:host:port@site'", name)
clusterName string
targetHost string
targetPort string
paramMessage = fmt.Sprintf("invalid format for proxy request: %q, expected 'proxy:host:port@cluster'", request)
)
const prefix = "proxy:"
// get rid of 'proxy:' prefix:
if strings.Index(name, prefix) != 0 {
return nil, trace.Wrap(paramError)
if strings.Index(request, prefix) != 0 {
return nil, trace.BadParameter(paramMessage)
}
name = strings.TrimPrefix(name, prefix)
requestBody := strings.TrimPrefix(request, prefix)
namespace := defaults.Namespace
// find the site name in the argument:
parts := strings.Split(name, "@")
switch len(parts) {
case 2:
clusterName = strings.Join(parts[1:], "@")
name = parts[0]
case 3:
var err error
parts := strings.Split(requestBody, "@")
switch {
case len(parts) == 0: // "proxy:"
return nil, trace.BadParameter(paramMessage)
case len(parts) == 1: // "proxy:host:22"
targetHost, targetPort, err = utils.SplitHostPort(parts[0])
if err != nil {
return nil, trace.BadParameter(paramMessage)
}
case len(parts) == 2: // "proxy:@clustername" or "proxy:host:22@clustername"
if parts[0] != "" {
targetHost, targetPort, err = utils.SplitHostPort(parts[0])
if err != nil {
return nil, trace.BadParameter(paramMessage)
}
}
clusterName = parts[1]
if clusterName == "" && targetHost == "" {
return nil, trace.BadParameter("invalid format for proxy request: missing cluster name or target host in %q", request)
}
case len(parts) > 3: // "proxy:host:22@namespace@clustername"
clusterName = strings.Join(parts[2:], "@")
namespace = parts[1]
name = parts[0]
}
// find host & port in the arguments:
host, port, err := net.SplitHostPort(name)
if clusterName == "" && err != nil {
return nil, trace.Wrap(paramError)
targetHost, targetPort, err = utils.SplitHostPort(parts[0])
if err != nil {
return nil, trace.BadParameter(paramMessage)
}
}
if clusterName != "" && srv.proxyTun != nil {
_, err := srv.proxyTun.GetSite(clusterName)
if err != nil {
return nil, trace.BadParameter("unknown cluster '%s'", clusterName)
return nil, trace.BadParameter("invalid format for proxy request: unknown cluster %q in %q", clusterName, request)
}
}

return &proxySubsys{
namespace: namespace,
srv: srv,
host: host,
port: port,
host: targetHost,
port: targetPort,
siteName: clusterName,
closeC: make(chan struct{}),
}, nil
}

func (t *proxySubsys) String() string {
return fmt.Sprintf("proxySubsys(site=%s/%s, host=%s, port=%s)",
return fmt.Sprintf("proxySubsys(cluster=%s/%s, host=%s, port=%s)",
t.namespace, t.siteName, t.host, t.port)
}

Expand Down
18 changes: 18 additions & 0 deletions lib/srv/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,21 @@ func (s *ProxyTestSuite) TestParseProxyRequest(c *check.C) {
c.Assert(subsys.port, check.Equals, "100")
c.Assert(subsys.siteName, check.Equals, "moon")
}

func (s *ProxyTestSuite) TestParseBadRequests(c *check.C) {
testCases := []string{
// empty request
"proxy:",
// missing hostname
"proxy::80",
// missing hostname and missing cluster name
"proxy:@",
// just random string
"this is bad string",
}
for _, input := range testCases {
comment := check.Commentf("test case: %q", input)
_, err := parseProxySubsys(input, s.srv)
c.Assert(err, check.NotNil, comment)
}
}
12 changes: 12 additions & 0 deletions lib/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ import (
"golang.org/x/crypto/ssh"
)

// SplitHostPort splits host and port and checks that host is not empty
func SplitHostPort(hostname string) (string, string, error) {
host, port, err := net.SplitHostPort(hostname)
if err != nil {
return "", "", trace.Wrap(err)
}
if host == "" {
return "", "", trace.BadParameter("empty hostname")
}
return host, port, nil
}

type HostKeyCallback func(hostID string, remote net.Addr, key ssh.PublicKey) error

func ReadPath(path string) ([]byte, error) {
Expand Down

0 comments on commit eb1f6ae

Please sign in to comment.