2017-10-14 11:13:47 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-04-11 20:41:45 +00:00
|
|
|
"crypto/tls"
|
|
|
|
"crypto/x509"
|
2017-10-14 11:13:47 +00:00
|
|
|
"encoding/json"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/elisescu/tty-share/common"
|
|
|
|
logrus "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
var log = logrus.New()
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
commandName := flag.String("command", "bash", "The command to run")
|
|
|
|
commandArgs := flag.String("args", "", "The command arguments")
|
|
|
|
logFileName := flag.String("logfile", "-", "The name of the file to log")
|
2018-04-11 20:41:45 +00:00
|
|
|
useTLS := flag.Bool("useTLS", true, "Use TLS to connect to the server")
|
2017-10-14 11:13:47 +00:00
|
|
|
server := flag.String("server", "localhost:7654", "tty-proxyserver address")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
log.Level = logrus.ErrorLevel
|
|
|
|
if *logFileName != "-" {
|
|
|
|
fmt.Printf("Writing logs to: %s\n", *logFileName)
|
|
|
|
logFile, err := os.Create(*logFileName)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Can't open %s for writing logs\n", *logFileName)
|
|
|
|
}
|
|
|
|
log.Level = logrus.DebugLevel
|
|
|
|
log.Out = logFile
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: check we are running inside a tty environment, and exit if not
|
|
|
|
|
2018-04-11 20:41:45 +00:00
|
|
|
var rawConnection io.ReadWriteCloser
|
|
|
|
if *useTLS {
|
|
|
|
roots, err := x509.SystemCertPool()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Cannot connect to the server (%s): %s", *server, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rawConnection, err = tls.Dial("tcp", *server, &tls.Config{RootCAs: roots})
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Cannot connect (TLS) to the server (%s): %s", *server, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var err error
|
|
|
|
rawConnection, err = net.Dial("tcp", *server)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Cannot connect to the server (%s): %s", *server, err.Error())
|
|
|
|
return
|
|
|
|
}
|
2017-10-14 11:13:47 +00:00
|
|
|
}
|
|
|
|
|
2018-04-11 20:41:45 +00:00
|
|
|
serverConnection := common.NewTTYProtocolConn(rawConnection)
|
2017-10-14 11:13:47 +00:00
|
|
|
reply, err := serverConnection.InitSender(common.SenderSessionInfo{
|
|
|
|
Salt: "salt",
|
|
|
|
PasswordVerifierA: "PV_A",
|
|
|
|
})
|
|
|
|
|
2018-04-11 20:41:45 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Cannot initialise the protocol connection: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-10-14 11:13:47 +00:00
|
|
|
log.Infof("Web terminal: %s", reply.URLWebReadWrite)
|
|
|
|
|
|
|
|
// Display the session information to the user, before showing any output from the command.
|
|
|
|
// Wait until the user presses Enter
|
2018-05-23 21:52:31 +00:00
|
|
|
fmt.Printf("Web terminal: %s\n\n\r", reply.URLWebReadWrite)
|
2017-10-14 11:13:47 +00:00
|
|
|
//TODO: if the user on the remote side presses keys, and so messages are sent back to the
|
|
|
|
// tty_sender, they will be delivered all at once, after Enter has been pressed. Fix that.
|
|
|
|
|
|
|
|
ptyMaster := ptyMasterNew()
|
|
|
|
ptyMaster.Start(*commandName, strings.Fields(*commandArgs), func(cols, rows int) {
|
|
|
|
log.Infof("New window size: %dx%d", cols, rows)
|
|
|
|
serverConnection.SetWinSize(cols, rows)
|
|
|
|
})
|
|
|
|
|
|
|
|
if cols, rows, e := ptyMaster.GetWinSize(); e == nil {
|
|
|
|
serverConnection.SetWinSize(cols, rows)
|
|
|
|
}
|
|
|
|
|
|
|
|
allWriter := io.MultiWriter(os.Stdout, serverConnection)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
_, err := io.Copy(allWriter, ptyMaster)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("Lost connection with the server.\n")
|
|
|
|
ptyMaster.Stop()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
msg, err := serverConnection.ReadMessage()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf(" -- Finishing the server connection with error: %s", err.Error())
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if msg.Type == common.MsgIDWrite {
|
|
|
|
var msgWrite common.MsgTTYWrite
|
|
|
|
json.Unmarshal(msg.Data, &msgWrite)
|
|
|
|
ptyMaster.Write(msgWrite.Data[:msgWrite.Size])
|
|
|
|
}
|
2018-05-12 21:44:59 +00:00
|
|
|
if msg.Type == common.MsgIDSenderNewReceiverConnected {
|
|
|
|
var msgReceiverConnected common.MsgTTYSenderNewReceiverConnected
|
|
|
|
json.Unmarshal(msg.Data, &msgReceiverConnected)
|
|
|
|
|
|
|
|
ptyMaster.Refresh()
|
|
|
|
fmt.Printf("New receiver connected: %s ", msgReceiverConnected.Name)
|
|
|
|
}
|
2017-10-14 11:13:47 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
io.Copy(ptyMaster, os.Stdin)
|
|
|
|
}()
|
|
|
|
|
|
|
|
ptyMaster.Wait()
|
|
|
|
}
|