mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			Added -u (user), -x (exec cmd) options, -d (dbg) for logging; detection of "-x -" for
stdin/pipeline commands.
This commit is contained in:
		
							parent
							
								
									39a0890346
								
							
						
					
					
						commit
						6fd8ac1519
					
				| 
						 | 
					@ -7,6 +7,8 @@ import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"os/user"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hkex "blitter.com/herradurakex"
 | 
						hkex "blitter.com/herradurakex"
 | 
				
			||||||
| 
						 | 
					@ -37,18 +39,27 @@ type cmdSpec struct {
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	var wg sync.WaitGroup
 | 
						var wg sync.WaitGroup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dbg bool
 | 
				
			||||||
	var cAlg string
 | 
						var cAlg string
 | 
				
			||||||
	var hAlg string
 | 
						var hAlg string
 | 
				
			||||||
	var server string
 | 
						var server string
 | 
				
			||||||
 | 
						var cmdStr string
 | 
				
			||||||
 | 
						var altUser string
 | 
				
			||||||
	isInteractive := false
 | 
						isInteractive := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.StringVar(&cAlg, "c", "C_AES_256", "cipher [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\"]")
 | 
						flag.StringVar(&cAlg, "c", "C_AES_256", "cipher [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\"]")
 | 
				
			||||||
	flag.StringVar(&hAlg, "h", "H_SHA256", "hmac [\"H_SHA256\"]")
 | 
						flag.StringVar(&hAlg, "h", "H_SHA256", "hmac [\"H_SHA256\"]")
 | 
				
			||||||
	flag.StringVar(&server, "s", "localhost:2000", "server hostname/address[:port]")
 | 
						flag.StringVar(&server, "s", "localhost:2000", "server hostname/address[:port]")
 | 
				
			||||||
 | 
						flag.StringVar(&cmdStr, "x", "", "command to run (default empty - interactive shell)")
 | 
				
			||||||
 | 
						flag.StringVar(&altUser, "u", "", "specify alternate user")
 | 
				
			||||||
 | 
						flag.BoolVar(&dbg, "d", false, "debug logging")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//log.SetOutput(os.Stdout)
 | 
						if dbg {
 | 
				
			||||||
 | 
							log.SetOutput(os.Stdout)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		log.SetOutput(ioutil.Discard)
 | 
							log.SetOutput(ioutil.Discard)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conn, err := hkex.Dial("tcp", server, cAlg, hAlg)
 | 
						conn, err := hkex.Dial("tcp", server, cAlg, hAlg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -58,8 +69,9 @@ func main() {
 | 
				
			||||||
	defer conn.Close()
 | 
						defer conn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set stdin in raw mode if it's an interactive session
 | 
						// Set stdin in raw mode if it's an interactive session
 | 
				
			||||||
 | 
						// TODO: send flag to server side indicating this
 | 
				
			||||||
 | 
						//  affects shell command used
 | 
				
			||||||
	if isatty.IsTerminal(os.Stdin.Fd()) {
 | 
						if isatty.IsTerminal(os.Stdin.Fd()) {
 | 
				
			||||||
		isInteractive = true
 | 
					 | 
				
			||||||
		oldState, err := MakeRaw(int(os.Stdin.Fd()))
 | 
							oldState, err := MakeRaw(int(os.Stdin.Fd()))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic(err)
 | 
								panic(err)
 | 
				
			||||||
| 
						 | 
					@ -69,9 +81,33 @@ func main() {
 | 
				
			||||||
		fmt.Println("NOT A TTY")
 | 
							fmt.Println("NOT A TTY")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rec := &cmdSpec{op: []byte{'s'},
 | 
						var uname string
 | 
				
			||||||
		who:        []byte("ABCD"),
 | 
						if len(altUser) == 0 {
 | 
				
			||||||
		cmd:        []byte("EFGH"),
 | 
							u, _ := user.Current()
 | 
				
			||||||
 | 
							uname = u.Username
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							uname = altUser
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var op []byte
 | 
				
			||||||
 | 
						if len(cmdStr) == 0 {
 | 
				
			||||||
 | 
							op = []byte{'s'}
 | 
				
			||||||
 | 
							isInteractive = true
 | 
				
			||||||
 | 
						} else if cmdStr == "-" {
 | 
				
			||||||
 | 
							op = []byte{'c'}
 | 
				
			||||||
 | 
							cmdStdin, err := ioutil.ReadAll(os.Stdin)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cmdStr = strings.Trim(string(cmdStdin), "\r\n")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							op = []byte{'c'}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rec := &cmdSpec{
 | 
				
			||||||
 | 
							op:         op,
 | 
				
			||||||
 | 
							who:        []byte(uname),
 | 
				
			||||||
 | 
							cmd:        []byte(cmdStr),
 | 
				
			||||||
		authCookie: []byte("99"),
 | 
							authCookie: []byte("99"),
 | 
				
			||||||
		status:     0}
 | 
							status:     0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +145,7 @@ func main() {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isInteractive {
 | 
				
			||||||
		// client writer (to server) goroutine
 | 
							// client writer (to server) goroutine
 | 
				
			||||||
		wg.Add(1)
 | 
							wg.Add(1)
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
| 
						 | 
					@ -126,6 +163,7 @@ func main() {
 | 
				
			||||||
			log.Println("[Sent EOF]")
 | 
								log.Println("[Sent EOF]")
 | 
				
			||||||
			wg.Done() // client hung up, close WaitGroup to exit client
 | 
								wg.Done() // client hung up, close WaitGroup to exit client
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Wait until both stdin and stdout goroutines finish
 | 
						// Wait until both stdin and stdout goroutines finish
 | 
				
			||||||
	wg.Wait()
 | 
						wg.Wait()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import (
 | 
				
			||||||
	"flag"
 | 
						"flag"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
| 
						 | 
					@ -15,24 +16,6 @@ import (
 | 
				
			||||||
	"github.com/kr/pty"
 | 
						"github.com/kr/pty"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Unused, probably obsolete. Once interactive session
 | 
					 | 
				
			||||||
// and piped I/O one-shot commands are working reconsider
 | 
					 | 
				
			||||||
// how Op might be used
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	OpR   = 'r' // read(file) (binary mode)
 | 
					 | 
				
			||||||
	OpW   = 'w' // (over)write
 | 
					 | 
				
			||||||
	OpA   = 'a' // append
 | 
					 | 
				
			||||||
	OpRm  = 'd' // rm
 | 
					 | 
				
			||||||
	OpRmD = 'D' // rmdir (rm -rf)
 | 
					 | 
				
			||||||
	OpM   = 'm' // mkdir (-p)
 | 
					 | 
				
			||||||
	OpN   = 'n' // re(n)ame (mv)
 | 
					 | 
				
			||||||
	OpCm  = 'c' // chmod
 | 
					 | 
				
			||||||
	OpCo  = 'C' // chown
 | 
					 | 
				
			||||||
	OpX   = 'x' // exec
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//type Op uint8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type cmdSpec struct {
 | 
					type cmdSpec struct {
 | 
				
			||||||
	op         []byte
 | 
						op         []byte
 | 
				
			||||||
	who        []byte
 | 
						who        []byte
 | 
				
			||||||
| 
						 | 
					@ -89,12 +72,18 @@ func runCmdAs(who string, cmd string, conn hkex.Conn) (err error) {
 | 
				
			||||||
// Listener and Conns. The KEx and encrypt/decrypt is done within the type.
 | 
					// Listener and Conns. The KEx and encrypt/decrypt is done within the type.
 | 
				
			||||||
// Compare to 'serverp.go' in this directory to see the equivalence.
 | 
					// Compare to 'serverp.go' in this directory to see the equivalence.
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
 | 
						var dbg bool
 | 
				
			||||||
	var laddr string
 | 
						var laddr string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen")
 | 
						flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen")
 | 
				
			||||||
 | 
						flag.BoolVar(&dbg, "d", false, "debug logging")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.SetOutput(os.Stdout /*ioutil.Discard*/)
 | 
						if dbg {
 | 
				
			||||||
 | 
							log.SetOutput(os.Stdout)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.SetOutput(ioutil.Discard)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Listen on TCP port 2000 on all available unicast and
 | 
						// Listen on TCP port 2000 on all available unicast and
 | 
				
			||||||
	// anycast IP addresses of the local system.
 | 
						// anycast IP addresses of the local system.
 | 
				
			||||||
| 
						 | 
					@ -163,9 +152,17 @@ func main() {
 | 
				
			||||||
			fmt.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:%s]\n",
 | 
								fmt.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:%s]\n",
 | 
				
			||||||
				rec.op[0], string(rec.who), string(rec.cmd), string(rec.authCookie))
 | 
									rec.op[0], string(rec.who), string(rec.cmd), string(rec.authCookie))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if rec.op[0] == 's' {
 | 
								if rec.op[0] == 'c' {
 | 
				
			||||||
 | 
									// Non-interactive command
 | 
				
			||||||
 | 
									fmt.Println("[Running command]")
 | 
				
			||||||
 | 
									runCmdAs(string(rec.who), string(rec.cmd), conn)
 | 
				
			||||||
 | 
									// Returned hopefully via an EOF or exit/logout;
 | 
				
			||||||
 | 
									// Clear current op so user can enter next, or EOF
 | 
				
			||||||
 | 
									rec.op[0] = 0
 | 
				
			||||||
 | 
									fmt.Println("[Command complete]")
 | 
				
			||||||
 | 
								} else if rec.op[0] == 's' {
 | 
				
			||||||
				fmt.Println("[Running shell]")
 | 
									fmt.Println("[Running shell]")
 | 
				
			||||||
				runCmdAs("larissa", "bash -l -i", conn)
 | 
									runCmdAs(string(rec.who), "bash -l -i", conn)
 | 
				
			||||||
				// Returned hopefully via an EOF or exit/logout;
 | 
									// Returned hopefully via an EOF or exit/logout;
 | 
				
			||||||
				// Clear current op so user can enter next, or EOF
 | 
									// Clear current op so user can enter next, or EOF
 | 
				
			||||||
				rec.op[0] = 0
 | 
									rec.op[0] = 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue