Beispiel #1
1
func (ctrl *Controller) terminal(ctx scope.Context, ch ssh.Channel) {
	defer ch.Close()

	lines := make(chan string)
	term := terminal.NewTerminal(ch, "> ")

	go func() {
		for ctx.Err() == nil {
			line, err := term.ReadLine()
			if err != nil {
				ctx.Terminate(err)
				return
			}
			lines <- line
		}
	}()

	for {
		var line string
		select {
		case <-ctx.Done():
			return
		case line = <-lines:
		}

		cmd := parse(line)
		fmt.Printf("[control] > %v\n", cmd)
		switch cmd[0] {
		case "":
			continue
		case "quit":
			return
		case "shutdown":
			ctrl.ctx.Terminate(fmt.Errorf("shutdown initiated from console"))
		default:
			runCommand(ctx.Fork(), ctrl, cmd[0], term, cmd[1:])
		}
	}
}
Beispiel #2
0
func startTerminal(c *config) {
	var clear, protected bool

	fmt.Println("Starting terminal mode.")
	fmt.Println("Enter h for [h]elp.")
	fmt.Println("Enter l for [l]ist of commands.")
	fmt.Println("Enter q for [q]uit.")

	termState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to set raw mode on STDIN: %v\n",
			err)
		return
	}
	n := terminal.NewTerminal(os.Stdin, "> ")
	n.SetSize(int(^uint(0)>>1), 0)

	var ln string
	for {
		if !protected {
			ln, err = n.ReadLine()
		} else {
			ln, err = n.ReadPassword(">*")
		}
		terminal.Restore(int(os.Stdin.Fd()), termState)
		if err != nil {
			break
		}

		quit := execute(&protected, c, ln, &clear)
		if quit {
			break
		}

		if clear {
			fmt.Println("Clearing history...")
			termState, err = terminal.MakeRaw(int(os.Stdin.Fd()))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Failed to set raw "+
					"mode on STDIN: %v\n", err)
				break
			}
			n = terminal.NewTerminal(os.Stdin, "> ")
			n.SetSize(int(^uint(0)>>1), 0)
			clear = false
		} else {
			termState, err = terminal.MakeRaw(int(os.Stdin.Fd()))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Failed to set raw "+
					"mode on STDIN: %v\n", err)
				break
			}
		}
	}
	fmt.Println("exiting...")
}
Beispiel #3
0
// NewCLI creates a new cliUI instance
func NewCLI(version string) UI {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err.Error())
	}

	term := terminal.NewTerminal(os.Stdin, "")
	updateTerminalSize(term)
	term.SetBracketedPasteMode(true)

	resizeChan := make(chan os.Signal)
	go func() {
		for _ = range resizeChan {
			updateTerminalSize(term)
		}
	}()
	signal.Notify(resizeChan, syscall.SIGWINCH)

	return &cliUI{
		term:      term,
		oldState:  oldState,
		terminate: make(chan bool),
		input: &input{
			term:        term,
			uidComplete: new(priorityList),
		},
		RosterEditor: RosterEditor{
			PendingRosterChan: make(chan *RosterEdit),
		},
		events:   make(chan interface{}),
		commands: make(chan interface{}, 5),
	}
}
Beispiel #4
0
// promptConfirm prompts a user to confirm (or deny) something.
//
// True is returned iff the prompt is confirmed.
// Errors are reported to the log, and return false.
//
// Valid confirmations:
// 	y, yes, true, t, aye-aye
//
// Valid denials:
//	n, no, f, false
//
// Any other prompt response will return false, and issue a warning to the
// user.
func promptConfirm(msg string) bool {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		log.Err("Could not get terminal: %s", err)
		return false
	}
	defer terminal.Restore(0, oldState)

	f := readerWriter(log.Stdin, log.Stdout)
	t := terminal.NewTerminal(f, msg+" (y/N) ")
	res, err := t.ReadLine()
	if err != nil {
		log.Err("Could not read line: %s", err)
		return false
	}
	res = strings.ToLower(res)
	switch res {
	case "yes", "y", "true", "t", "aye-aye":
		return true
	case "no", "n", "false", "f":
		return false
	}
	log.Warn("Did not understand answer %q, assuming No", res)
	return false
}
func (self *ServerMode) handleSSHRequest(connection *net.Conn, config *ssh.ServerConfig) {

	// TODO: Check if we need to close anything.

	// Before use, a handshake must be performed on the incoming net.Conn.
	_, channels, requests, err := ssh.NewServerConn(*connection, config)
	if err != nil {
		panic("failed to handshake")
	}

	// The incoming Request channel must be serviced.
	go ssh.DiscardRequests(requests)

	// Service the incoming Channel channel.
	for newChannel := range channels {
		// Channels have a type, depending on the application level protocol intended. In the case of a shell, the type is
		// "session" and ServerShell may be used to present a simple terminal interface.
		if newChannel.ChannelType() != "session" {
			newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
			continue
		}

		channel, requests, err := newChannel.Accept()
		if err != nil {
			panic("could not accept channel.")
		}

		// Sessions have out-of-band requests such as "shell", "pty-req" and "env".
		// Here we handle only the "shell" request.
		go func(in <-chan *ssh.Request) {
			for req := range in {
				ok := false
				switch req.Type {
				case "shell":
					ok = true
					if len(req.Payload) > 0 {
						// We don't accept any commands, only the default shell.
						ok = false
					}
				}
				req.Reply(ok, nil)
			}
		}(requests)

		term := terminal.NewTerminal(channel, "> ")

		go func() {
			defer channel.Close()
			for {
				line, err := term.ReadLine()
				if err != nil {
					break
				}
				// TODO: Likely we need to interpret the incoming commands in here.
				fmt.Println("INPUT-SSH:" + line)
			}
		}()
	}
}
Beispiel #6
0
func sshHandleChannel(conn net.Conn, newChannel ssh.NewChannel) {
	// Channels have a type, depending on the application level protocol
	// intended. In the case of a shell, the type is "session" and ServerShell
	// may be used to present a simple terminal interface.
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Errorln(err)
		return
	}

	// Sessions have out-of-band requests such as "shell", "pty-req" and "env".
	// Here we handle only the "shell" request.
	go func(in <-chan *ssh.Request) {
		for req := range in {
			ok := false
			switch req.Type {
			case "shell":
				ok = true
				if len(req.Payload) > 0 {
					// We don't accept any commands, only the default shell.
					ok = false
				}
			case "pty-req":
				ok = true
			}
			req.Reply(ok, nil)
		}
	}(requests)

	term := terminal.NewTerminal(channel, "> ")

	go func() {
		defer channel.Close()

		for {
			line, err := term.ReadLine()
			start := time.Now().UnixNano()
			if err != nil {
				if err != io.EOF {
					log.Errorln(err)
				}
				return
			}
			sshReportChan <- uint64(len(line))
			// just echo the message
			log.Debugln("ssh received: ", line)
			term.Write([]byte(line))
			term.Write([]byte{'\r', '\n'})

			stop := time.Now().UnixNano()
			log.Info("ssh %v %vns", conn.RemoteAddr(), uint64(stop-start))
		}
	}()
}
Beispiel #7
0
func (s *shellHandler) startTerminal(parentTomb tomb.Tomb, sshConn *ssh.ServerConn, channel ssh.Channel) error {
	defer channel.Close()

	prompt := ">>> "
	term := terminal.NewTerminal(channel, prompt)

	// // Try to make the terminal raw
	// oldState, err := terminal.MakeRaw(0)
	// if err != nil {
	//     logger.Warn("Error making terminal raw: ", err.Error())
	// }
	// defer terminal.Restore(0, oldState)

	// Get username
	username, ok := sshConn.Permissions.Extensions["username"]
	if !ok {
		username = "******"
	}

	// Write ascii text
	term.Write([]byte(fmt.Sprintf("\r\n Nice job, %s! You are connected!\r\n", username)))
	defer term.Write([]byte(fmt.Sprintf("\r\nGoodbye, %s!\r\n", username)))

	// Start REPL
	for {

		select {
		case <-parentTomb.Dying():
			return nil
		default:
			s.logger.Info("Reading line...")
			input, err := term.ReadLine()
			if err != nil {
				fmt.Errorf("Readline() error")
				return err
			}

			// Process line
			line := strings.TrimSpace(input)
			if len(line) > 0 {

				// Log input and handle exit requests
				if line == "exit" || line == "quit" {
					s.logger.Info("Closing connection")
					return nil
				}

				// Echo input
				channel.Write(term.Escape.Green)
				channel.Write([]byte(line + "\r\n"))
				channel.Write(term.Escape.Reset)
			}
		}
	}
	return nil
}
Beispiel #8
0
func newTerm(prompt string) *Term {
	term := new(Term)
	var err error
	term.s, err = terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	term.t = terminal.NewTerminal(os.Stdin, prompt)
	return term
}
Beispiel #9
0
func (i *Interactive) terminalInit() {
	var err error
	i.oldTermState, err = terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		i.fatalf("Failed to get raw terminal: %v", err)
	}

	i.term = terminal.NewTerminal(os.Stdin, i.Prompt)
	i.term.AutoCompleteCallback = i.defaultAutoComplete
}
Beispiel #10
0
func terminalInit() {
	var err error
	oldTermState, err = terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		fatalf("Failed to get raw terminal: %v", err)
	}

	term = terminal.NewTerminal(os.Stdin, prompt)
	term.AutoCompleteCallback = autoComplete
}
Beispiel #11
0
// Read a password from stdin without echoing input to stdout.
func ReadPassword(prompt string) (string, error) {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		return "", err
	}
	defer terminal.Restore(0, oldState)
	term := terminal.NewTerminal(os.Stdin, "")
	pass, err := term.ReadPassword(prompt)
	return pass, err
}
Beispiel #12
0
func (server *SshServer) handleChannel(user string, newChannel ssh.NewChannel) {
	if t := newChannel.ChannelType(); t != "session" {
		newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
		return
	}

	connection, requests, err := newChannel.Accept()
	if err != nil {
		fmt.Printf("Could not accept channel (%s)", err)
		return
	}
	defer connection.Close()

	logfile, err := os.Create(fmt.Sprintf("%s_%s", user, storyLogFilename(server.story)))
	if err != nil {
		panic(err)
	}
	defer logfile.Close()

	logger := log.New(logfile, "", log.LstdFlags)

	terminal := terminal.NewTerminal(connection, "")
	zsshterm := &gork.ZSshTerminal{Term: terminal}

	zm, err := gork.NewZMachine(server.mem, server.header, zsshterm, logger)
	if err != nil {
		fmt.Println(err)
		return
	}

	go func() {
		for req := range requests {
			switch req.Type {
			case "shell":
				if len(req.Payload) == 0 {
					req.Reply(true, nil)
				}
			case "pty-req":
				termLen := req.Payload[3]
				w, h := parseDims(req.Payload[termLen+4:])
				terminal.SetSize(w, h)
			case "window-change":
				w, h := parseDims(req.Payload)
				terminal.SetSize(w, h)
			}
		}
	}()

	defer func() {
		recover()
	}()

	zm.InterpretAll()

}
Beispiel #13
0
// Read credentials from standard input
func readCredentials() (username string, password string, err error) {
	state, err := terminal.MakeRaw(0)
	if err == nil {
		t := terminal.NewTerminal(os.Stdin, "Username: "******"Password: ")
		}
		terminal.Restore(0, state)
	}
	return username, password, nil
}
Beispiel #14
0
func handleConn(nConn net.Conn, config *ssh.ServerConfig) {
	addr := nConn.RemoteAddr().String()
	log.Printf("Connection opened from %s", addr)
	defer log.Printf("Connection closed from %s", addr)

	// Negotiate SSH.  This is where passwords are checked.
	_, chans, _, err := ssh.NewServerConn(nConn, config)
	if err != nil {
		log.Printf("Couldn't handshake %s: %s", addr, err)
	}

	// A ServerConn multiplexes several channels, which must
	// themselves be Accepted.
	for newChannel := range chans {
		// Accept reads from the connection, demultiplexes packets
		// to their corresponding channels and returns when a new
		// channel request is seen. Some goroutine must always be
		// calling Accept; otherwise no messages will be forwarded
		// to the channels.
		if newChannel.ChannelType() != "session" {
			newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
			continue
		}
		channel, _, err := newChannel.Accept()
		if err != nil {
			break
		}

		// Channels have a type, depending on the application level
		// protocol intended. In the case of a shell, the type is
		// "session" and ServerShell may be used to present a simple
		// terminal interface.
		log.Printf("Channel from %s : %s", addr, newChannel.ChannelType())

		prompt := "$ "
		term := terminal.NewTerminal(channel, prompt)
		go func() {
			defer log.Printf("Channel closed from %s", addr)
			defer channel.Close()

			// Just log every line that the attacker sends.
			for {
				line, err := term.ReadLine()
				if err != nil {
					break
				}
				log.Printf("%s > %s", addr, line)
			}
		}()
	}
}
Beispiel #15
0
func askConfig() (cfg, error) {
	stdinState, err := terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		return cfg{}, err
	}
	defer terminal.Restore(syscall.Stdin, stdinState)
	stdoutState, err := terminal.MakeRaw(syscall.Stdout)
	if err != nil {
		return cfg{}, err
	}
	defer terminal.Restore(syscall.Stdout, stdoutState)
	t := struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}

	term := terminal.NewTerminal(t, "")

	msg := "Configure git-erickson for first time use.\nErickson server URL: "
	if _, err := term.Write([]byte(msg)); err != nil {
		return cfg{}, err
	}

	url, err := term.ReadLine()
	if err != nil {
		return cfg{}, err
	}

	cmd := exec.Command("git", "config", "--global", "erickson.url", string(url))
	if err := cmd.Run(); err != nil {
		return cfg{}, err
	}

	if _, err := term.Write([]byte("Erickson username: "******"git", "config", "--global", "erickson.username", string(username))
	if err := cmd.Run(); err != nil {
		return cfg{}, err
	}

	return cfg{url: url, username: username}, nil
}
Beispiel #16
0
func runTerm(cmd *cobra.Command, args []string) {
	if len(args) != 0 {
		cmd.Usage()
		return
	}

	db := makeSQLClient()

	readWriter := struct {
		io.Reader
		io.Writer
	}{
		Reader: os.Stdin,
		Writer: os.Stdout,
	}

	// We need to switch to raw mode. Unfortunately, this masks
	// signals-from-keyboard, meaning that ctrl-C cannot be caught.
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = terminal.Restore(0, oldState)
	}()

	term := terminal.NewTerminal(readWriter, "> ")
	for {
		line, err := term.ReadLine()
		if err != nil {
			if err != io.EOF {
				fmt.Fprintf(os.Stderr, "Input error: %s\n", err)
			}
			break
		}
		if len(line) == 0 {
			continue
		}

		shouldExit, err := processOneLine(db, line, term)
		if err != nil {
			fmt.Fprintf(term, "Error: %s\n", err)
		}
		if shouldExit {
			break
		}
	}
}
Beispiel #17
0
func main() {
	if len(os.Args) > 1 {
		input := strings.Replace(strings.Join(os.Args[1:], ""), " ", "", -1)
		res, err := compute.Evaluate(input)
		if err != nil {
			fmt.Println("Error: " + err.Error())
			return
		}
		fmt.Printf("%s\n", decimalToString(res))
		return
	}

	var err error
	regularState, err = terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	defer terminal.Restore(0, regularState)

	term := terminal.NewTerminal(os.Stdin, "> ")
	term.AutoCompleteCallback = handleKey
	for {
		text, err := term.ReadLine()
		if err != nil {
			if err == io.EOF {
				// Quit without error on Ctrl^D
				fmt.Println()
				break
			}
			panic(err)
		}

		text = strings.Replace(text, " ", "", -1)
		if text == "exit" || text == "quit" {
			break
		}

		res, err := compute.Evaluate(text)
		if err != nil {
			fmt.Println("Error: " + err.Error())
			continue
		}
		fmt.Printf("%s\n", res)
	}
}
Beispiel #18
0
// NewShell returns a new Shell Adapter.
func NewShell(b bot.Bot) bot.Adapter {
	// Get terminal old state.
	state, err := t.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}

	// Create a new terminal struct.
	term := t.NewTerminal(os.Stdin, "")
	prompt := fmt.Sprintf("\033[36m%s\033[0m> ", b.Name)
	term.SetPrompt(prompt)

	return Shell{
		bot:         b,
		MessagePool: bot.NewMessagePool(),
		Terminal:    term,
		State:       state,
	}
}
Beispiel #19
0
func askCredentials(username string) (password string, err error) {
	stdinState, err := terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		return
	}
	defer terminal.Restore(syscall.Stdin, stdinState)
	stdoutState, err := terminal.MakeRaw(syscall.Stdout)
	if err != nil {
		return
	}
	defer terminal.Restore(syscall.Stdout, stdoutState)
	t := struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}
	term := terminal.NewTerminal(t, "")
	msg := fmt.Sprintf("Password for %s: ", username)
	password, err = term.ReadPassword(msg)
	return
}
Beispiel #20
0
func termechoMain() error {
	oldState, err := terminal.MakeRaw(int(syscall.Stdin))
	if err != nil {
		return err
	}
	defer terminal.Restore(int(syscall.Stdin), oldState)
	fmt.Println("enter 'q' to quit")
	t := terminal.NewTerminal(os.Stdin, "> ")
	for {
		line, err := t.ReadLine()
		if err != nil {
			return err
		}
		if line == "q" {
			break
		}
		fmt.Println(line)
	}
	return nil
}
Beispiel #21
0
func handleChannel(ch ssh.Channel) {
	term := terminal.NewTerminal(ch, "> ")
	serverTerm := &ssh.ServerTerminal{
		Term:    term,
		Channel: ch,
	}
	ch.Accept()
	defer ch.Close()
	for {
		line, err := serverTerm.ReadLine()
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Println("handleChannel readLine err:", err)
			continue
		}
		fmt.Println(line)
	}
}
Beispiel #22
0
func (fk *filterKeys) filter(keys []openpgp.Key, symmetric bool) ([]byte, error) {
	var keyid string
	var k openpgp.Key

	for keyid == "" {
		if fk.index >= len(keys) {
			return nil, io.EOF
		}

		k = keys[fk.index]
		fk.index++
		if k.PublicKey != nil {
			if keyid = k.PublicKey.KeyIdShortString(); keyid != "" {
				break
			}
		}
	}

	fd := int(os.Stdin.Fd())
	state, err := terminal.MakeRaw(fd)
	if err != nil {
		return nil, err
	}
	defer terminal.Restore(fd, state)

	t := terminal.NewTerminal(os.Stdin, "> ")
	pw, err := t.ReadPassword(fmt.Sprintf("Enter the passphrase for %v: ", keyid))
	if err != nil {
		return nil, err
	}

	if symmetric {
		return []byte(strings.TrimSpace(pw)), nil
	}
	if k.PrivateKey.Encrypted {
		if err := k.PrivateKey.Decrypt([]byte(strings.TrimSpace(pw))); err != nil {
			return nil, err
		}
	}
	return nil, nil
}
Beispiel #23
0
func (c *cliClient) Start() {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err.Error())
	}
	defer terminal.Restore(0, oldState)

	signal.Notify(make(chan os.Signal), os.Interrupt)

	wrapper, interruptChan := NewTerminalWrapper(os.Stdin)
	wrapper.SetErrorOnInterrupt(true)
	c.interrupt = interruptChan
	c.termWrapper = wrapper

	c.term = terminal.NewTerminal(wrapper, "> ")
	updateTerminalSize(c.term)

	resizeChan := make(chan os.Signal)
	go func() {
		for _ = range resizeChan {
			updateTerminalSize(c.term)
		}
	}()
	signal.Notify(resizeChan, syscall.SIGWINCH)

	c.loadUI()

	if c.writerChan != nil {
		c.save()
	}
	if c.writerChan != nil {
		close(c.writerChan)
		<-c.writerDone
	}
	if c.fetchNowChan != nil {
		close(c.fetchNowChan)
	}
	if c.stateLock != nil {
		c.stateLock.Close()
	}
}
Beispiel #24
0
func startTerminal(c *config) {
	fmt.Printf("Starting terminal mode.\n")
	fmt.Printf("Enter h for [h]elp.\n")
	fmt.Printf("Enter q for [q]uit.\n")
	done := make(chan bool)
	initState, err := terminal.GetState(0)
	protected := false
	if err != nil {
		fmt.Printf("error getting terminal state: %v\n", err.Error())
		return
	}

	go func() {
		terminal.MakeRaw(int(os.Stdin.Fd()))
		n := terminal.NewTerminal(os.Stdin, "> ")
		for {
			var ln string
			var err error
			if !protected {
				ln, err = n.ReadLine()
				if err != nil {
					done <- true
				}
			} else {
				ln, err = n.ReadPassword(">*")
				if err != nil {
					done <- true
				}
			}
			execute(done, &protected, c, ln)
		}
	}()
	select {
	case <-done:
		fmt.Printf("exiting...\n")
		terminal.Restore(0, initState)
		close(done)
	}
}
Beispiel #25
0
func (s *SSHServer) shellHandler(channel ssh.Channel) error {
	defer channel.Close()

	term := terminal.NewTerminal(channel, "# ")
	for {
		line, err := term.ReadLine()
		if err != nil {
			break
		}
		if line == "" {
			return nil
		}

		result, status, err := s.runCmd(line)
		if err != nil {
			return fmt.Errorf("failed to run command: %v", err)
		}
		if err := sendCmdResult(channel, result, status); err != nil {
			return fmt.Errorf("failed to send result: %v", err)
		}
	}
	return nil
}
Beispiel #26
0
// Make new terminal from a session channel
func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) {
	if ch.ChannelType() != "session" {
		return nil, errors.New("terminal requires session channel")
	}
	channel, requests, err := ch.Accept()
	if err != nil {
		return nil, err
	}
	term := Terminal{
		*terminal.NewTerminal(channel, "Connecting..."),
		sshConn{conn},
		channel,
	}

	go term.listen(requests)
	go func() {
		// FIXME: Is this necessary?
		conn.Wait()
		channel.Close()
	}()

	return &term, nil
}
Beispiel #27
0
// NewStartedQShell returns an initialized QShell, ready to Interact() with.
// Prints mongo startup message.
func NewStartedQShell(driver *strata.Driver, mountPath string, showSize bool, mongodPath, mongoPath string) (*QShell, error) {
	finished := false
	sh := QShell{driver: driver, mountPath: mountPath, showSize: showSize, mongodPath: mongodPath, mongoPath: mongoPath}

	// Put terminal in raw mode
	var err error
	sh.stdinFd = int(os.Stdin.Fd())
	sh.oldState, err = terminal.MakeRaw(sh.stdinFd)
	if err != nil {
		return &sh, err
	}

	// Convention seems to be that caller invokes Close() only if there is no error.
	// But we need to clean up if there is an error.
	defer func() {
		if !finished {
			sh.Close()
		}
	}()

	sh.term = terminal.NewTerminal(&readerWriter{r: os.Stdin, w: os.Stdout}, "\r> ")

	sh.mongoStateHolder, err = newMongoStateHolder(sh.mongoPath)
	if err != nil {
		return &sh, err
	}

	if err := sh.print("Wrapper around MongoDB shell with additional commands for querying backups.\n"); err != nil {
		return &sh, err
	}
	if err := sh.printMongoOutput(true); err != nil {
		return &sh, err
	}

	finished = true
	return &sh, nil
}
Beispiel #28
0
func (r *sshRunner) Run() error {
	logrus.WithFields(logrus.Fields{
		"user": r.user,
		"host": r.host,
	}).Info("ssh")

	sshHost := fmt.Sprintf("%s:%d", r.host, r.port)

	// Key Auth
	key, err := ioutil.ReadFile(r.keyPath)
	if err != nil {
		return err
	}
	privateKey, err := ssh.ParsePrivateKey(key)
	if err != nil {
		return err
	}
	if err := sshConnect(r.user, sshHost, ssh.PublicKeys(privateKey)); err != nil {
		// Password Auth if Key Auth Fails
		fd := os.Stdin.Fd()
		state, err := terminal.MakeRaw(int(fd))
		if err != nil {
			return err
		}
		defer terminal.Restore(int(fd), state)
		t := terminal.NewTerminal(os.Stdout, ">")
		password, err := t.ReadPassword("Password: ")
		if err != nil {
			return err
		}
		if err := sshConnect(r.user, sshHost, ssh.Password(string(password))); err != nil {
			return err
		}
	}
	return err

}
Beispiel #29
0
func (app *h2i) Main() error {
	cfg := &tls.Config{
		ServerName:         app.host,
		NextProtos:         strings.Split(*flagNextProto, ","),
		InsecureSkipVerify: *flagInsecure,
	}

	hostAndPort := withPort(app.host)
	log.Printf("Connecting to %s ...", hostAndPort)
	tc, err := tls.Dial("tcp", hostAndPort, cfg)
	if err != nil {
		return fmt.Errorf("Error dialing %s: %v", withPort(app.host), err)
	}
	log.Printf("Connected to %v", tc.RemoteAddr())
	defer tc.Close()

	if err := tc.Handshake(); err != nil {
		return fmt.Errorf("TLS handshake: %v", err)
	}
	if !*flagInsecure {
		if err := tc.VerifyHostname(app.host); err != nil {
			return fmt.Errorf("VerifyHostname: %v", err)
		}
	}
	state := tc.ConnectionState()
	log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
	if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
		return fmt.Errorf("Could not negotiate protocol mutually")
	}

	if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
		return err
	}

	app.framer = http2.NewFramer(tc, tc)

	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		return err
	}
	defer terminal.Restore(0, oldState)

	var screen = struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}

	app.term = terminal.NewTerminal(screen, "h2i> ")
	lastWord := regexp.MustCompile(`.+\W(\w+)$`)
	app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
		if key != '\t' {
			return
		}
		if pos != len(line) {
			// TODO: we're being lazy for now, only supporting tab completion at the end.
			return
		}
		// Auto-complete for the command itself.
		if !strings.Contains(line, " ") {
			var name string
			name, _, ok = lookupCommand(line)
			if !ok {
				return
			}
			return name, len(name), true
		}
		_, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
		if !ok || c.complete == nil {
			return
		}
		if strings.HasSuffix(line, " ") {
			app.logf("%s", strings.Join(c.complete(), " "))
			return line, pos, true
		}
		m := lastWord.FindStringSubmatch(line)
		if m == nil {
			return line, len(line), true
		}
		soFar := m[1]
		var match []string
		for _, cand := range c.complete() {
			if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
				continue
			}
			match = append(match, cand)
		}
		if len(match) == 0 {
			return
		}
		if len(match) > 1 {
			// TODO: auto-complete any common prefix
			app.logf("%s", strings.Join(match, " "))
			return line, pos, true
		}
		newLine = line[:len(line)-len(soFar)] + match[0]
		return newLine, len(newLine), true

	}

	errc := make(chan error, 2)
	go func() { errc <- app.readFrames() }()
	go func() { errc <- app.readConsole() }()
	return <-errc
}
Beispiel #30
0
func remoteShellHandler(ws *websocket.Conn) {
	var httpErr *errors.HTTP
	defer func() {
		defer ws.Close()
		if httpErr != nil {
			var msg string
			switch httpErr.Code {
			case http.StatusUnauthorized:
				msg = "no token provided or session expired, please login again\n"
			default:
				msg = httpErr.Message + "\n"
			}
			ws.Write([]byte("Error: " + msg))
		}
	}()
	r := ws.Request()
	token := context.GetAuthToken(r)
	if token == nil {
		httpErr = &errors.HTTP{
			Code:    http.StatusUnauthorized,
			Message: "no token provided",
		}
		return
	}
	appName := r.URL.Query().Get(":appname")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		if herr, ok := err.(*errors.HTTP); ok {
			httpErr = herr
		} else {
			httpErr = &errors.HTTP{
				Code:    http.StatusInternalServerError,
				Message: err.Error(),
			}
		}
		return
	}
	allowed := permission.Check(token, permission.PermAppRunShell, contextsForApp(&a)...)
	if !allowed {
		httpErr = permission.ErrUnauthorized
		return
	}
	buf := &optionalWriterCloser{}
	var term *terminal.Terminal
	unitID := r.URL.Query().Get("unit")
	width, _ := strconv.Atoi(r.URL.Query().Get("width"))
	height, _ := strconv.Atoi(r.URL.Query().Get("height"))
	clientTerm := r.URL.Query().Get("term")
	evt, err := event.New(&event.Opts{
		Target:      appTarget(appName),
		Kind:        permission.PermAppRunShell,
		Owner:       token,
		CustomData:  event.FormToCustomData(r.Form),
		Allowed:     event.Allowed(permission.PermAppReadEvents, contextsForApp(&a)...),
		DisableLock: true,
	})
	if err != nil {
		httpErr = &errors.HTTP{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		}
		return
	}
	defer func() {
		var finalErr error
		if httpErr != nil {
			finalErr = httpErr
		}
		for term != nil {
			buf.disableWrite = true
			var line string
			line, err = term.ReadLine()
			if err != nil {
				break
			}
			fmt.Fprintf(evt, "> %s\n", line)
		}
		evt.Done(finalErr)
	}()
	term = terminal.NewTerminal(buf, "")
	opts := provision.ShellOptions{
		Conn:   &cmdLogger{base: ws, term: term},
		Width:  width,
		Height: height,
		Unit:   unitID,
		Term:   clientTerm,
	}
	err = a.Shell(opts)
	if err != nil {
		httpErr = &errors.HTTP{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		}
	}
}