From 5eb7d4d1e635cecaa21747eac6209f659eb1531a Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Sun, 29 Jul 2018 00:48:42 -0700 Subject: [PATCH 1/3] Initial (buggy) support for 'fancy arg' style ala ssh: eg user@example.org:port:path --- hkexsh/hkexsh.go | 76 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/hkexsh/hkexsh.go b/hkexsh/hkexsh.go index 4f9ca23..d68e877 100755 --- a/hkexsh/hkexsh.go +++ b/hkexsh/hkexsh.go @@ -34,7 +34,8 @@ type cmdSpec struct { } var ( - wg sync.WaitGroup + wg sync.WaitGroup + defPort = "2000" ) // Get terminal size using 'stty' command @@ -52,6 +53,53 @@ func GetSize() (cols, rows int, err error) { return } +func parseFancyEndpointArg(a []string, dp string) (user, host, port, path string) { + //TODO: Look for non-option fancyArg of syntax user@host:filespec to set -r,-t and -u + // Consider: whether fancyArg is src or dst file depends on flag.Args() index; + // fancyArg as last flag.Args() element denotes dstFile + // fancyArg as not-last flag.Args() element denotes srcFile + // * throw error if >1 fancyArgs are found in flags.Args() + var fancyUser, fancyHost, fancyPort, fancyPath string + for i, arg := range flag.Args() { + if strings.Contains(arg, ":") || strings.Contains(arg, "@") { + fancyArg := strings.Split(flag.Arg(i), "@") + var fancyHostPortPath []string + if len(fancyArg) < 2 { + //TODO: no user specified, use current + fancyUser = "[default:getUser]" + fancyHostPortPath = strings.Split(fancyArg[0], ":") + } else { + // user@.... + fancyUser = fancyArg[0] + fancyHostPortPath = strings.Split(fancyArg[1], ":") + } + + if len(fancyHostPortPath) > 2 { + // [user]@host[:port]:path + fancyPath = fancyHostPortPath[2] + } + if len(fancyHostPortPath) > 1 { + // [user]@host:port[:...] or [user]@host:path (default port) + fancyPort = fancyHostPortPath[1] + } + // [user]@host[:...[:...]] + fancyHost = fancyHostPortPath[0] + + if fancyPort == "" { + fancyPort = dp + } + + if fancyPath == "" { + fancyPath = "." + } + + fmt.Println("fancyArgs: user:", fancyUser, "host:", fancyHost, "port:", fancyPort, "path:", fancyPath) + break // ignore multiple 'fancyArgs' + } + } + return fancyUser, fancyHost, fancyPort, fancyPath +} + // Demo of a simple client that dials up to a simple test server to // send data. // @@ -90,29 +138,45 @@ func main() { flag.BoolVar(&dbg, "d", false, "debug logging") flag.StringVar(&cAlg, "c", "C_AES_256", "cipher [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\"]") flag.StringVar(&hAlg, "m", "H_SHA256", "hmac [\"H_SHA256\"]") - flag.StringVar(&server, "s", "localhost:2000", "server hostname/address[:port]") + flag.StringVar(&server, "s", "localhost:"+defPort, "server hostname/address[:port]") flag.StringVar(&altUser, "u", "", "specify alternate user") flag.StringVar(&authCookie, "a", "", "auth cookie") flag.BoolVar(&chaffEnabled, "e", true, "enabled chaff pkts (default true)") flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)") flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max (msecs)") flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)") - + // Find out what program we are (shell or copier) myPath := strings.Split(os.Args[0], string(os.PathSeparator)) - if myPath[len(myPath)-1] != "hkexcp" { + if myPath[len(myPath)-1] != "hkexcp" && myPath[len(myPath)-1] != "hkexcp.exe" { // hkexsh accepts a command (-x) but not // a srcpath (-r) or dstpath (-t) flag.StringVar(&cmdStr, "x", "", "command to run (default empty - interactive shell)") - flag.Parse() } else { // hkexcp accepts srcpath (-r) and dstpath (-t), but not // a command (-x) flag.StringVar(©Src, "r", "", "copy srcpath") flag.StringVar(©Dst, "t", "", "copy dstpath") } + flag.Parse() - if flag.NFlag() == 0 { + fancyUser, fancyHost, fancyPort, fancyPath := parseFancyEndpointArg(flag.Args(), defPort /* defPort */) + fmt.Println("fancyHost:", fancyHost) + if fancyUser != "" { + altUser = fancyUser + } + if fancyHost != "" { + server = fancyHost + ":" + fancyPort + fmt.Println("fancyHost sets server to", server) + } + if fancyPath != "" { + //TODO: srcPath or dstPath depends on other flag.Args + copyDst = fancyPath + } + + fmt.Println("server finally is:", server) + + if flag.NFlag() == 0 && server == "" { flag.Usage() os.Exit(0) } From 55cf5a9277e31af32f6a13a6515b2d979535921e Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Sun, 29 Jul 2018 12:47:44 -0700 Subject: [PATCH 2/3] Improved 'fancy arg' parsing - gathering up otherArgs (non-flag) as path src list --- hkexsh/hkexsh.go | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/hkexsh/hkexsh.go b/hkexsh/hkexsh.go index d68e877..5b93ed3 100755 --- a/hkexsh/hkexsh.go +++ b/hkexsh/hkexsh.go @@ -53,14 +53,14 @@ func GetSize() (cols, rows int, err error) { return } -func parseFancyEndpointArg(a []string, dp string) (user, host, port, path string) { +func parseNonSwitchArgs(a []string, dp string) (user, host, port, path string, isDest bool, otherArgs []string) { //TODO: Look for non-option fancyArg of syntax user@host:filespec to set -r,-t and -u // Consider: whether fancyArg is src or dst file depends on flag.Args() index; // fancyArg as last flag.Args() element denotes dstFile // fancyArg as not-last flag.Args() element denotes srcFile // * throw error if >1 fancyArgs are found in flags.Args() var fancyUser, fancyHost, fancyPort, fancyPath string - for i, arg := range flag.Args() { + for i, arg := range a { if strings.Contains(arg, ":") || strings.Contains(arg, "@") { fancyArg := strings.Split(flag.Arg(i), "@") var fancyHostPortPath []string @@ -89,15 +89,20 @@ func parseFancyEndpointArg(a []string, dp string) (user, host, port, path string fancyPort = dp } - if fancyPath == "" { - fancyPath = "." - } + //if fancyPath == "" { + // fancyPath = "." + //} - fmt.Println("fancyArgs: user:", fancyUser, "host:", fancyHost, "port:", fancyPort, "path:", fancyPath) - break // ignore multiple 'fancyArgs' + if i == len(a)-1 { + isDest = true + fmt.Println("isDest") + } + //fmt.Println("fancyArgs: user:", fancyUser, "host:", fancyHost, "port:", fancyPort, "path:", fancyPath) + } else { + otherArgs = append(otherArgs, a[i]) } } - return fancyUser, fancyHost, fancyPort, fancyPath + return fancyUser, fancyHost, fancyPort, fancyPath, isDest, otherArgs } // Demo of a simple client that dials up to a simple test server to @@ -160,21 +165,26 @@ func main() { } flag.Parse() - fancyUser, fancyHost, fancyPort, fancyPath := parseFancyEndpointArg(flag.Args(), defPort /* defPort */) - fmt.Println("fancyHost:", fancyHost) + fancyUser, fancyHost, fancyPort, fancyPath, pathIsDest, otherArgs := + parseNonSwitchArgs(flag.Args(), defPort /* defPort */) + fmt.Println("otherArgs:", otherArgs) + //fmt.Println("fancyHost:", fancyHost) if fancyUser != "" { altUser = fancyUser } if fancyHost != "" { server = fancyHost + ":" + fancyPort - fmt.Println("fancyHost sets server to", server) + //fmt.Println("fancyHost sets server to", server) } if fancyPath != "" { - //TODO: srcPath or dstPath depends on other flag.Args - copyDst = fancyPath + if pathIsDest { + copyDst = fancyPath + } else { + copySrc = fancyPath + } } - fmt.Println("server finally is:", server) + //fmt.Println("server finally is:", server) if flag.NFlag() == 0 && server == "" { flag.Usage() From c6bfa2771ba42c85053a11ed0c715b2f1fe01c33 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Sun, 29 Jul 2018 13:22:35 -0700 Subject: [PATCH 3/3] Simplified hostPortPath parsing (colons mandatory if specifying more than just host) --- hkexsh/hkexsh.go | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/hkexsh/hkexsh.go b/hkexsh/hkexsh.go index 5b93ed3..704644e 100755 --- a/hkexsh/hkexsh.go +++ b/hkexsh/hkexsh.go @@ -74,30 +74,27 @@ func parseNonSwitchArgs(a []string, dp string) (user, host, port, path string, i fancyHostPortPath = strings.Split(fancyArg[1], ":") } + // [...@]host[:port[:path]] if len(fancyHostPortPath) > 2 { - // [user]@host[:port]:path fancyPath = fancyHostPortPath[2] - } - if len(fancyHostPortPath) > 1 { - // [user]@host:port[:...] or [user]@host:path (default port) + } else if len(fancyHostPortPath) > 1 { fancyPort = fancyHostPortPath[1] } - // [user]@host[:...[:...]] fancyHost = fancyHostPortPath[0] if fancyPort == "" { fancyPort = dp } - //if fancyPath == "" { - // fancyPath = "." - //} + if fancyPath == "" { + fancyPath = "." + } if i == len(a)-1 { isDest = true fmt.Println("isDest") } - //fmt.Println("fancyArgs: user:", fancyUser, "host:", fancyHost, "port:", fancyPort, "path:", fancyPath) + fmt.Println("fancyArgs: user:", fancyUser, "host:", fancyHost, "port:", fancyPort, "path:", fancyPath) } else { otherArgs = append(otherArgs, a[i]) } @@ -126,7 +123,7 @@ func main() { var server string var cmdStr string - var copySrc string + var copySrc []byte var copyDst string var altUser string @@ -157,18 +154,19 @@ func main() { // hkexsh accepts a command (-x) but not // a srcpath (-r) or dstpath (-t) flag.StringVar(&cmdStr, "x", "", "command to run (default empty - interactive shell)") - } else { - // hkexcp accepts srcpath (-r) and dstpath (-t), but not - // a command (-x) - flag.StringVar(©Src, "r", "", "copy srcpath") - flag.StringVar(©Dst, "t", "", "copy dstpath") - } + } // else { + //// hkexcp accepts srcpath (-r) and dstpath (-t), but not + //// a command (-x) + //flag.StringVar(©Src, "r", "", "copy srcpath") + //flag.StringVar(©Dst, "t", "", "copy dstpath") + //} flag.Parse() fancyUser, fancyHost, fancyPort, fancyPath, pathIsDest, otherArgs := parseNonSwitchArgs(flag.Args(), defPort /* defPort */) fmt.Println("otherArgs:", otherArgs) //fmt.Println("fancyHost:", fancyHost) + fmt.Println("fancyPath:", fancyPath) if fancyUser != "" { altUser = fancyUser } @@ -177,10 +175,20 @@ func main() { //fmt.Println("fancyHost sets server to", server) } if fancyPath != "" { + // -if pathIsSrc && len(otherArgs) > 1 ERROR + // -else flatten otherArgs into space-delim list => copySrc if pathIsDest { + for _, v := range otherArgs { + copySrc = append(copySrc, ' ') + copySrc = append(copySrc, v...) + } + fmt.Println(">> copySrc:", string(copySrc)) copyDst = fancyPath } else { - copySrc = fancyPath + if len(otherArgs) > 1 { + log.Fatal("ERROR: cannot specify more than one dest path for copy") + } + copySrc = []byte(fancyPath) } } @@ -197,7 +205,7 @@ func main() { } if len(cmdStr) != 0 && (len(copySrc) != 0 || len(copyDst) != 0) { - log.Fatal("incompatible options -- either cmd (-x) or copy ops (-r,-t), but not both") + log.Fatal("incompatible options -- either cmd (-x) or copy ops but not both") } if dbg {