diff --git a/src/cli/cli.go b/src/cli/cli.go index 6d66546..b12b77b 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -80,6 +80,7 @@ func Run() (err error) { cli.BoolFlag{Name: "ask", Usage: "make sure sender and recipient are prompted"}, cli.StringFlag{Name: "relay", Value: models.DEFAULT_RELAY, Usage: "address of the relay"}, cli.StringFlag{Name: "out", Value: ".", Usage: "specify an output folder to receive the file"}, + cli.StringFlag{Name: "pass", Value: "pass123", Usage: "password for the relay"}, } app.EnableBashCompletion = true app.HideHelp = false @@ -147,6 +148,7 @@ func send(c *cli.Context) (err error) { RelayPorts: strings.Split(c.String("ports"), ","), Ask: c.GlobalBool("ask"), NoMultiplexing: c.Bool("no-multi"), + RelayPassword: c.GlobalString("pass"), } b, errOpen := ioutil.ReadFile(getConfigFile()) if errOpen == nil && !c.GlobalBool("remember") { @@ -290,13 +292,14 @@ func saveConfig(c *cli.Context, crocOptions croc.Options) { func receive(c *cli.Context) (err error) { crocOptions := croc.Options{ - SharedSecret: c.String("code"), - IsSender: false, - Debug: c.GlobalBool("debug"), - NoPrompt: c.GlobalBool("yes"), - RelayAddress: c.GlobalString("relay"), - Stdout: c.GlobalBool("stdout"), - Ask: c.GlobalBool("ask"), + SharedSecret: c.String("code"), + IsSender: false, + Debug: c.GlobalBool("debug"), + NoPrompt: c.GlobalBool("yes"), + RelayAddress: c.GlobalString("relay"), + Stdout: c.GlobalBool("stdout"), + Ask: c.GlobalBool("ask"), + RelayPassword: c.GlobalString("pass"), } if c.Args().First() != "" { crocOptions.SharedSecret = c.Args().First() @@ -375,11 +378,11 @@ func relay(c *cli.Context) (err error) { continue } go func(portStr string) { - err = tcp.Run(debugString, portStr) + err = tcp.Run(debugString, portStr, c.GlobalString("pass")) if err != nil { panic(err) } }(port) } - return tcp.Run(debugString, ports[0], tcpPorts) + return tcp.Run(debugString, ports[0], c.GlobalString("pass"), tcpPorts) } diff --git a/src/croc/croc.go b/src/croc/croc.go index 64c6b13..c7aa569 100644 --- a/src/croc/croc.go +++ b/src/croc/croc.go @@ -53,6 +53,7 @@ type Options struct { Debug bool RelayAddress string RelayPorts []string + RelayPassword string Stdout bool NoPrompt bool NoMultiplexing bool @@ -241,7 +242,7 @@ func (c *Client) setupLocalRelay() { if c.Options.Debug { debugString = "debug" } - err := tcp.Run(debugString, portStr, strings.Join(c.Options.RelayPorts[1:], ",")) + err := tcp.Run(debugString, portStr, c.Options.RelayPassword, strings.Join(c.Options.RelayPorts[1:], ",")) if err != nil { panic(err) } @@ -268,7 +269,7 @@ func (c *Client) transferOverLocalRelay(options TransferOptions, errchan chan<- time.Sleep(500 * time.Millisecond) log.Debug("establishing connection") var banner string - conn, banner, ipaddr, err := tcp.ConnectToTCPServer("localhost:"+c.Options.RelayPorts[0], c.Options.SharedSecret) + conn, banner, ipaddr, err := tcp.ConnectToTCPServer("localhost:"+c.Options.RelayPorts[0], c.Options.RelayPassword, c.Options.SharedSecret) log.Debugf("banner: %s", banner) if err != nil { err = errors.Wrap(err, fmt.Sprintf("could not connect to localhost:%s", c.Options.RelayPorts[0])) @@ -328,7 +329,7 @@ func (c *Client) Send(options TransferOptions) (err error) { go func() { log.Debugf("establishing connection to %s", c.Options.RelayAddress) var banner string - conn, banner, ipaddr, err := tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.SharedSecret, 5*time.Second) + conn, banner, ipaddr, err := tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.RelayPassword, c.Options.SharedSecret, 5*time.Second) log.Debugf("banner: %s", banner) if err != nil { err = errors.Wrap(err, fmt.Sprintf("could not connect to %s", c.Options.RelayAddress)) @@ -427,7 +428,7 @@ func (c *Client) Receive() (err error) { log.Debug("establishing connection") } var banner string - c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.SharedSecret) + c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.RelayPassword, c.Options.SharedSecret) log.Debugf("banner: %s", banner) if err != nil { err = errors.Wrap(err, fmt.Sprintf("could not connect to %s", c.Options.RelayAddress)) @@ -452,7 +453,7 @@ func (c *Client) Receive() (err error) { ips = ips[1:] for _, ip := range ips { serverTry := fmt.Sprintf("%s:%s", ip, port) - conn, banner2, externalIP, errConn := tcp.ConnectToTCPServer(serverTry, c.Options.SharedSecret, 50*time.Millisecond) + conn, banner2, externalIP, errConn := tcp.ConnectToTCPServer(serverTry, c.Options.RelayPassword, c.Options.SharedSecret, 50*time.Millisecond) if errConn != nil { log.Debugf("could not connect to " + serverTry) continue @@ -624,6 +625,7 @@ func (c *Client) procesMesssagePake(m message.Message) (err error) { log.Debugf("connecting to %s", server) c.conn[j+1], _, _, err = tcp.ConnectToTCPServer( server, + c.Options.RelayPassword, fmt.Sprintf("%s-%d", utils.SHA256(c.Options.SharedSecret)[:7], j), ) if err != nil { diff --git a/src/tcp/tcp.go b/src/tcp/tcp.go index 473ed26..f60f0e3 100644 --- a/src/tcp/tcp.go +++ b/src/tcp/tcp.go @@ -18,6 +18,7 @@ type server struct { port string debugLevel string banner string + password string rooms roomMap } @@ -36,9 +37,10 @@ type roomMap struct { var timeToRoomDeletion = 10 * time.Minute // Run starts a tcp listener, run async -func Run(debugLevel, port string, banner ...string) (err error) { +func Run(debugLevel, port, password string, banner ...string) (err error) { s := new(server) s.port = port + s.password = password s.debugLevel = debugLevel if len(banner) > 0 { s.banner = banner[0] @@ -48,6 +50,7 @@ func Run(debugLevel, port string, banner ...string) (err error) { func (s *server) start() (err error) { log.SetLevel(s.debugLevel) + log.Debugf("starting with password '%s'", s.password) s.rooms.Lock() s.rooms.rooms = make(map[string]roomInfo) s.rooms.Unlock() @@ -102,6 +105,17 @@ func (s *server) run() (err error) { } func (s *server) clientCommuncation(port string, c *comm.Comm) (err error) { + log.Debugf("waiting for password") + passwordBytes, err := c.Receive() + if err != nil { + return + } + if strings.TrimSpace(string(passwordBytes)) != s.password { + err = fmt.Errorf("bad password") + c.Send([]byte(err.Error())) + return + } + // send ok to tell client they are connected banner := s.banner if len(banner) == 0 { @@ -255,7 +269,7 @@ func pipe(conn1 net.Conn, conn2 net.Conn) { // ConnectToTCPServer will initiate a new connection // to the specified address, room with optional time limit -func ConnectToTCPServer(address, room string, timelimit ...time.Duration) (c *comm.Comm, banner string, ipaddr string, err error) { +func ConnectToTCPServer(address, password, room string, timelimit ...time.Duration) (c *comm.Comm, banner string, ipaddr string, err error) { if len(timelimit) > 0 { c, err = comm.NewConnection(address, timelimit[0]) } else { @@ -264,11 +278,20 @@ func ConnectToTCPServer(address, room string, timelimit ...time.Duration) (c *co if err != nil { return } + log.Debug("sending password") + err = c.Send([]byte(password)) + if err != nil { + return + } log.Debug("waiting for first ok") data, err := c.Receive() if err != nil { return } + if !strings.Contains(string(data), "|||") { + err = fmt.Errorf("bad response: %s", string(data)) + return + } banner = strings.Split(string(data), "|||")[0] ipaddr = strings.Split(string(data), "|||")[1] log.Debug("sending room")