From 7b0704d475d1482ad27f912065be8590ea0a105e Mon Sep 17 00:00:00 2001 From: tgic Date: Mon, 29 Dec 2014 19:50:15 +0800 Subject: [PATCH] v0.2 add mapping username and smarter upstream_file --- sshpiperd/config.go | 6 ---- sshpiperd/sshpiperd.go | 3 ++ sshpiperd/workingdir.go | 65 ++++++++++++++++++++++++++++++------ sshpiperd/workingdir_test.go | 63 ++++++++++++++++++++++++++++++++-- ver | 2 +- 5 files changed, 119 insertions(+), 20 deletions(-) diff --git a/sshpiperd/config.go b/sshpiperd/config.go index e594e387..dc484b31 100644 --- a/sshpiperd/config.go +++ b/sshpiperd/config.go @@ -39,12 +39,6 @@ var ( versionTemplate *template.Template ) -func init() { - initConfig() - initTemplate() - initLogger() -} - func initTemplate() { configTemplate = template.Must(template.New("config").Parse(` Listening : {{.ListenAddr}}:{{.Port}} diff --git a/sshpiperd/sshpiperd.go b/sshpiperd/sshpiperd.go index 794511de..8863f53c 100644 --- a/sshpiperd/sshpiperd.go +++ b/sshpiperd/sshpiperd.go @@ -37,6 +37,9 @@ func main() { showHelpOrVersion() showVersion() + initConfig() + initTemplate() + initLogger() showConfig() // TODO make this pluggable diff --git a/sshpiperd/workingdir.go b/sshpiperd/workingdir.go index d91e327f..a9f3e4ac 100644 --- a/sshpiperd/workingdir.go +++ b/sshpiperd/workingdir.go @@ -6,13 +6,15 @@ package main import ( + "bufio" "bytes" "fmt" - "github.com/tg123/sshpiper/ssh" "io/ioutil" "net" "os" "strings" + + "github.com/tg123/sshpiper/ssh" ) type userFile string @@ -56,29 +58,72 @@ func (file userFile) checkPerm(user string) error { return nil } -func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, error) { +func parseUpstreamFile(data string) (string, string) { + + var user string + var line string + + r := bufio.NewReader(strings.NewReader(data)) + + for { + var err error + line, err = r.ReadString('\n') + if err != nil { + break + } + + line = strings.TrimSpace(line) + + if line != "" && line[0] != '#' { + break + } + } + + t := strings.SplitN(line, "@", 2) + + if len(t) > 1 { + user = t[0] + line = t[1] + } + + // test if ok + if _, _, err := net.SplitHostPort(line); err != nil && line != "" { + // test valid after concat :22 + if _, _, err := net.SplitHostPort(line + ":22"); err == nil { + line += ":22" + } + } + + return line, user +} + +func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, string, error) { user := conn.User() err := UserUpstreamFile.checkPerm(user) if err != nil { - return nil, err + return nil, "", err } - addr, err := UserUpstreamFile.read(user) + data, err := UserUpstreamFile.read(user) if err != nil { - return nil, err + return nil, "", err } - saddr := strings.TrimSpace(string(addr)) + addr, mappedUser := parseUpstreamFile(string(data)) - logger.Printf("mapping user [%s] to [%s]", user, saddr) + if addr == "" { + return nil, "", fmt.Errorf("empty addr") + } - c, err := net.Dial("tcp", saddr) + logger.Printf("mapping user [%v] to [%v@%v]", user, mappedUser, addr) + + c, err := net.Dial("tcp", addr) if err != nil { - return nil, err + return nil, "", err } - return c, nil + return c, mappedUser, nil } func mapPublicKeyFromUserfile(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.Signer, error) { diff --git a/sshpiperd/workingdir_test.go b/sshpiperd/workingdir_test.go index 2ef7dd7b..45becd46 100644 --- a/sshpiperd/workingdir_test.go +++ b/sshpiperd/workingdir_test.go @@ -124,6 +124,63 @@ func (s stubConnMetadata) ServerVersion() []byte { return nil } func (s stubConnMetadata) RemoteAddr() net.Addr { return nil } func (s stubConnMetadata) LocalAddr() net.Addr { return nil } +func TestParseUpstreamFile(t *testing.T) { + + var addr, user string + + addr, user = parseUpstreamFile(` + +a:123 + +`) + + if addr != "a:123" || user != "" { + t.Fatalf("parse failed common with port") + } + + addr, user = parseUpstreamFile(` +a:123 +b:456 +`) + + if addr != "a:123" || user != "" { + t.Fatalf("parse multi line") + } + + addr, user = parseUpstreamFile(` +host +`) + + if addr != "host:22" || user != "" { + t.Fatalf("parse no port") + } + + addr, user = parseUpstreamFile(` +user@github.com +`) + + if addr != "github.com:22" || user != "user" { + t.Fatalf("parse no port with user") + } + + addr, user = parseUpstreamFile(``) + + if addr != "" || user != "" { + t.Fatalf("empty file") + } + + addr, user = parseUpstreamFile(` + +# comment +user@github.com +test@linode.com +`) + + if addr != "github.com:22" || user != "user" { + t.Fatalf("multi line with comment") + } +} + func TestFindUpstreamFromUserfile(t *testing.T) { user := "testuser" buildWorkingDir([]string{user}, t) @@ -154,7 +211,7 @@ func TestFindUpstreamFromUserfile(t *testing.T) { } t.Logf("testing file too open") - _, err = findUpstreamFromUserfile(stubConnMetadata{user}) + _, _, err = findUpstreamFromUserfile(stubConnMetadata{user}) if err == nil { t.Fatalf("should return err when file too open") } @@ -165,7 +222,7 @@ func TestFindUpstreamFromUserfile(t *testing.T) { } t.Logf("testing conn dial to %v", addr) - conn, err := findUpstreamFromUserfile(stubConnMetadata{user}) + conn, _, err := findUpstreamFromUserfile(stubConnMetadata{user}) if err != nil { t.Fatalf("findUpstreamFromUserfile failed %v", err) } @@ -186,7 +243,7 @@ func TestFindUpstreamFromUserfile(t *testing.T) { } t.Logf("testing user not found") - _, err = findUpstreamFromUserfile(stubConnMetadata{"nosuchuser"}) + _, _, err = findUpstreamFromUserfile(stubConnMetadata{"nosuchuser"}) if err == nil { t.Fatalf("should return err when finding nosuchuser") } diff --git a/ver b/ver index 085135ec..eac24e6f 100644 --- a/ver +++ b/ver @@ -1 +1 @@ -v0.1 +v0.2.dev