2018-09-23 21:34:29 +02:00
|
|
|
package tcp
|
|
|
|
|
|
|
|
import (
|
2019-04-30 00:24:22 +02:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2018-09-23 21:34:29 +02:00
|
|
|
"net"
|
2019-05-02 01:10:02 +02:00
|
|
|
"strings"
|
2018-09-23 21:34:29 +02:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2021-04-23 22:48:19 +02:00
|
|
|
"filippo.io/age"
|
2020-08-23 01:05:00 +02:00
|
|
|
log "github.com/schollz/logger"
|
2021-04-23 23:10:54 +02:00
|
|
|
"golang.org/x/crypto/bcrypt"
|
2020-08-23 01:05:00 +02:00
|
|
|
|
2021-04-17 19:33:38 +02:00
|
|
|
"github.com/schollz/croc/v9/src/comm"
|
|
|
|
"github.com/schollz/croc/v9/src/crypt"
|
|
|
|
"github.com/schollz/croc/v9/src/models"
|
2018-09-23 21:34:29 +02:00
|
|
|
)
|
|
|
|
|
2019-04-30 01:29:36 +02:00
|
|
|
type server struct {
|
2019-04-30 01:38:49 +02:00
|
|
|
port string
|
2021-04-23 22:48:19 +02:00
|
|
|
keyPrivate string
|
|
|
|
keyPublic string
|
2019-04-30 01:38:49 +02:00
|
|
|
debugLevel string
|
2019-05-01 01:05:19 +02:00
|
|
|
banner string
|
2019-11-18 17:16:19 +01:00
|
|
|
password string
|
2019-04-30 01:38:49 +02:00
|
|
|
rooms roomMap
|
2019-04-30 01:29:36 +02:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:34:29 +02:00
|
|
|
type roomInfo struct {
|
2019-04-29 22:06:18 +02:00
|
|
|
first *comm.Comm
|
|
|
|
second *comm.Comm
|
2019-04-27 18:20:03 +02:00
|
|
|
opened time.Time
|
|
|
|
full bool
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type roomMap struct {
|
|
|
|
rooms map[string]roomInfo
|
|
|
|
sync.Mutex
|
|
|
|
}
|
|
|
|
|
2019-09-08 15:12:16 +02:00
|
|
|
var timeToRoomDeletion = 10 * time.Minute
|
2020-10-22 19:09:04 +02:00
|
|
|
var pingRoom = "pinglkasjdlfjsaldjf"
|
2019-09-08 15:12:16 +02:00
|
|
|
|
2018-09-23 21:34:29 +02:00
|
|
|
// Run starts a tcp listener, run async
|
2021-04-23 22:48:19 +02:00
|
|
|
func Run(debugLevel, port, password string, keyPublic string, keyPrivate string, banner ...string) (err error) {
|
2019-04-30 01:38:49 +02:00
|
|
|
s := new(server)
|
2019-04-30 01:29:36 +02:00
|
|
|
s.port = port
|
2021-04-23 22:48:19 +02:00
|
|
|
s.keyPrivate = keyPrivate
|
|
|
|
s.keyPublic = keyPublic
|
2019-11-18 17:16:19 +01:00
|
|
|
s.password = password
|
2019-04-30 01:29:36 +02:00
|
|
|
s.debugLevel = debugLevel
|
2019-05-01 01:05:19 +02:00
|
|
|
if len(banner) > 0 {
|
|
|
|
s.banner = banner[0]
|
|
|
|
}
|
2019-04-30 06:25:30 +02:00
|
|
|
return s.start()
|
2019-04-30 01:29:36 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 06:25:30 +02:00
|
|
|
func (s *server) start() (err error) {
|
2019-05-08 23:03:54 +02:00
|
|
|
log.SetLevel(s.debugLevel)
|
2019-11-18 17:16:19 +01:00
|
|
|
log.Debugf("starting with password '%s'", s.password)
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Lock()
|
|
|
|
s.rooms.rooms = make(map[string]roomInfo)
|
|
|
|
s.rooms.Unlock()
|
2018-10-13 15:13:50 +02:00
|
|
|
|
|
|
|
// delete old rooms
|
|
|
|
go func() {
|
|
|
|
for {
|
2019-09-08 15:12:16 +02:00
|
|
|
time.Sleep(timeToRoomDeletion)
|
2020-08-23 01:05:00 +02:00
|
|
|
var roomsToDelete []string
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Lock()
|
|
|
|
for room := range s.rooms.rooms {
|
|
|
|
if time.Since(s.rooms.rooms[room].opened) > 3*time.Hour {
|
2019-05-03 22:51:27 +02:00
|
|
|
roomsToDelete = append(roomsToDelete, room)
|
2018-10-13 15:13:50 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Unlock()
|
2019-05-03 05:57:55 +02:00
|
|
|
|
|
|
|
for _, room := range roomsToDelete {
|
|
|
|
s.deleteRoom(room)
|
|
|
|
}
|
2018-10-13 15:13:50 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2019-04-30 06:25:30 +02:00
|
|
|
err = s.run()
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
2019-05-01 01:05:19 +02:00
|
|
|
}
|
|
|
|
return
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 01:29:36 +02:00
|
|
|
func (s *server) run() (err error) {
|
2021-04-24 01:59:28 +02:00
|
|
|
log.Debugf("starting TCP server on " + s.port)
|
2019-04-30 06:33:13 +02:00
|
|
|
server, err := net.Listen("tcp", ":"+s.port)
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
2020-08-23 01:05:00 +02:00
|
|
|
return fmt.Errorf("error listening on %s: %w", s.port, err)
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
defer server.Close()
|
|
|
|
// spawn a new goroutine whenever a client connects
|
|
|
|
for {
|
2018-09-26 19:43:38 +02:00
|
|
|
connection, err := server.Accept()
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
2020-08-27 17:10:44 +02:00
|
|
|
return fmt.Errorf("problem accepting connection: %w", err)
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
log.Debugf("client %s connected", connection.RemoteAddr().String())
|
2018-09-26 19:43:38 +02:00
|
|
|
go func(port string, connection net.Conn) {
|
2019-11-18 22:09:17 +01:00
|
|
|
c := comm.New(connection)
|
2020-08-23 01:05:00 +02:00
|
|
|
room, errCommunication := s.clientCommunication(port, c)
|
2020-10-22 19:09:04 +02:00
|
|
|
log.Debugf("room: %+v", room)
|
|
|
|
log.Debugf("err: %+v", errCommunication)
|
2018-09-23 21:34:29 +02:00
|
|
|
if errCommunication != nil {
|
2020-04-09 18:52:58 +02:00
|
|
|
log.Debugf("relay-%s: %s", connection.RemoteAddr().String(), errCommunication.Error())
|
2020-10-22 19:09:04 +02:00
|
|
|
connection.Close()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if room == pingRoom {
|
|
|
|
log.Debugf("got ping")
|
|
|
|
connection.Close()
|
2020-10-22 18:59:55 +02:00
|
|
|
return
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
2019-11-18 22:09:17 +01:00
|
|
|
for {
|
|
|
|
// check connection
|
|
|
|
log.Debugf("checking connection of room %s for %+v", room, c)
|
|
|
|
deleteIt := false
|
|
|
|
s.rooms.Lock()
|
|
|
|
if _, ok := s.rooms.rooms[room]; !ok {
|
|
|
|
log.Debug("room is gone")
|
|
|
|
s.rooms.Unlock()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Debugf("room: %+v", s.rooms.rooms[room])
|
|
|
|
if s.rooms.rooms[room].first != nil && s.rooms.rooms[room].second != nil {
|
|
|
|
log.Debug("rooms ready")
|
|
|
|
s.rooms.Unlock()
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
if s.rooms.rooms[room].first != nil {
|
|
|
|
errSend := s.rooms.rooms[room].first.Send([]byte{1})
|
|
|
|
if errSend != nil {
|
|
|
|
log.Debug(errSend)
|
|
|
|
deleteIt = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s.rooms.Unlock()
|
|
|
|
if deleteIt {
|
|
|
|
s.deleteRoom(room)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
}
|
2019-04-30 01:38:49 +02:00
|
|
|
}(s.port, connection)
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-28 20:59:56 +01:00
|
|
|
var weakKey = []byte{1, 2, 3}
|
|
|
|
|
2020-08-23 01:05:00 +02:00
|
|
|
func (s *server) clientCommunication(port string, c *comm.Comm) (room string, err error) {
|
2021-04-23 22:48:19 +02:00
|
|
|
// get public key of the connecting client
|
|
|
|
retBytesEnc, err := c.Receive()
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 23:10:54 +02:00
|
|
|
if bytes.Equal(retBytesEnc, []byte("ping")) {
|
|
|
|
room = pingRoom
|
|
|
|
c.Send([]byte("pong"))
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
retBytes, err := crypt.DecryptAge(retBytesEnc, s.keyPrivate)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
// check whether we have a valid public key from client
|
2021-04-23 23:10:54 +02:00
|
|
|
foo := bytes.Split(retBytes, []byte("--"))
|
|
|
|
keyPublic := string(foo[0])
|
|
|
|
hashedPassword := foo[1]
|
|
|
|
|
|
|
|
err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(s.password))
|
|
|
|
if err != nil {
|
|
|
|
err = fmt.Errorf("bad password")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:50:12 +02:00
|
|
|
_, err = age.ParseX25519Recipient(keyPublic)
|
2019-11-18 17:16:19 +01:00
|
|
|
if err != nil {
|
2021-04-23 22:50:12 +02:00
|
|
|
err = fmt.Errorf("bad public key: %s", keyPublic)
|
2019-11-18 17:16:19 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:34:29 +02:00
|
|
|
// send ok to tell client they are connected
|
2019-05-02 01:10:02 +02:00
|
|
|
banner := s.banner
|
|
|
|
if len(banner) == 0 {
|
|
|
|
banner = "ok"
|
2019-05-01 20:20:02 +02:00
|
|
|
}
|
2019-05-02 01:10:02 +02:00
|
|
|
log.Debugf("sending '%s'", banner)
|
2021-04-23 22:48:19 +02:00
|
|
|
bSend, err := crypt.EncryptAge([]byte(banner+"|||"+c.Connection().RemoteAddr().String()), keyPublic)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send(bSend)
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// wait for client to tell me which room they want
|
2018-10-13 15:09:55 +02:00
|
|
|
log.Debug("waiting for answer")
|
2020-02-28 20:59:56 +01:00
|
|
|
enc, err := c.Receive()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
roomBytes, err := crypt.DecryptAge(enc, s.keyPrivate)
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2019-11-18 22:09:17 +01:00
|
|
|
room = string(roomBytes)
|
2018-09-23 21:34:29 +02:00
|
|
|
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Lock()
|
2019-04-27 18:20:03 +02:00
|
|
|
// create the room if it is new
|
2019-04-30 01:29:36 +02:00
|
|
|
if _, ok := s.rooms.rooms[room]; !ok {
|
|
|
|
s.rooms.rooms[room] = roomInfo{
|
2019-04-27 18:20:03 +02:00
|
|
|
first: c,
|
|
|
|
opened: time.Now(),
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Unlock()
|
2018-09-23 21:34:29 +02:00
|
|
|
// tell the client that they got the room
|
2020-02-28 20:59:56 +01:00
|
|
|
|
2021-04-23 22:48:19 +02:00
|
|
|
bSend, err = crypt.EncryptAge([]byte("ok"), keyPublic)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send(bSend)
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
2018-10-13 15:09:55 +02:00
|
|
|
log.Error(err)
|
2019-05-01 20:11:20 +02:00
|
|
|
s.deleteRoom(room)
|
2018-09-23 21:34:29 +02:00
|
|
|
return
|
|
|
|
}
|
2019-04-27 18:20:03 +02:00
|
|
|
log.Debugf("room %s has 1", room)
|
2019-11-18 22:09:17 +01:00
|
|
|
return
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
2019-04-30 01:29:36 +02:00
|
|
|
if s.rooms.rooms[room].full {
|
|
|
|
s.rooms.Unlock()
|
2021-04-23 22:48:19 +02:00
|
|
|
bSend, err = crypt.EncryptAge([]byte("room full"), keyPublic)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send(bSend)
|
2019-04-27 18:20:03 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2019-11-18 22:09:17 +01:00
|
|
|
return
|
2019-04-27 18:20:03 +02:00
|
|
|
}
|
|
|
|
log.Debugf("room %s has 2", room)
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.rooms[room] = roomInfo{
|
|
|
|
first: s.rooms.rooms[room].first,
|
2019-04-27 18:20:03 +02:00
|
|
|
second: c,
|
2019-04-30 01:29:36 +02:00
|
|
|
opened: s.rooms.rooms[room].opened,
|
2019-04-27 18:20:03 +02:00
|
|
|
full: true,
|
|
|
|
}
|
2019-04-30 01:29:36 +02:00
|
|
|
otherConnection := s.rooms.rooms[room].first
|
|
|
|
s.rooms.Unlock()
|
2018-09-23 21:34:29 +02:00
|
|
|
|
|
|
|
// second connection is the sender, time to staple connections
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(1)
|
|
|
|
|
|
|
|
// start piping
|
2019-04-29 22:06:18 +02:00
|
|
|
go func(com1, com2 *comm.Comm, wg *sync.WaitGroup) {
|
2018-09-23 21:34:29 +02:00
|
|
|
log.Debug("starting pipes")
|
|
|
|
pipe(com1.Connection(), com2.Connection())
|
|
|
|
wg.Done()
|
|
|
|
log.Debug("done piping")
|
2019-04-27 18:20:03 +02:00
|
|
|
}(otherConnection, c, &wg)
|
2018-09-23 21:34:29 +02:00
|
|
|
|
|
|
|
// tell the sender everything is ready
|
2021-04-23 22:50:12 +02:00
|
|
|
bSend, err = crypt.EncryptAge([]byte("ok"), keyPublic)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send(bSend)
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
2019-05-01 20:11:20 +02:00
|
|
|
s.deleteRoom(room)
|
2018-09-23 21:34:29 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
// delete room
|
2019-05-01 20:11:20 +02:00
|
|
|
s.deleteRoom(room)
|
2019-11-18 22:09:17 +01:00
|
|
|
return
|
2019-05-01 20:11:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *server) deleteRoom(room string) {
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.Lock()
|
2019-05-01 20:11:20 +02:00
|
|
|
defer s.rooms.Unlock()
|
|
|
|
if _, ok := s.rooms.rooms[room]; !ok {
|
|
|
|
return
|
|
|
|
}
|
2018-09-23 21:34:29 +02:00
|
|
|
log.Debugf("deleting room: %s", room)
|
2019-05-06 23:56:17 +02:00
|
|
|
if s.rooms.rooms[room].first != nil {
|
|
|
|
s.rooms.rooms[room].first.Close()
|
|
|
|
}
|
|
|
|
if s.rooms.rooms[room].second != nil {
|
|
|
|
s.rooms.rooms[room].second.Close()
|
|
|
|
}
|
2019-04-30 01:29:36 +02:00
|
|
|
s.rooms.rooms[room] = roomInfo{first: nil, second: nil}
|
|
|
|
delete(s.rooms.rooms, room)
|
2019-05-01 20:11:20 +02:00
|
|
|
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// chanFromConn creates a channel from a Conn object, and sends everything it
|
|
|
|
// Read()s from the socket to the channel.
|
2018-09-26 19:43:38 +02:00
|
|
|
func chanFromConn(conn net.Conn) chan []byte {
|
2019-04-29 23:46:40 +02:00
|
|
|
c := make(chan []byte, 1)
|
2020-08-23 01:05:00 +02:00
|
|
|
if err := conn.SetReadDeadline(time.Now().Add(3 * time.Hour)); err != nil {
|
|
|
|
log.Warnf("can't set read deadline: %v", err)
|
|
|
|
}
|
2018-09-23 21:34:29 +02:00
|
|
|
|
|
|
|
go func() {
|
2019-04-30 15:57:45 +02:00
|
|
|
b := make([]byte, models.TCP_BUFFER_SIZE)
|
2018-09-23 21:34:29 +02:00
|
|
|
for {
|
2018-09-26 18:55:14 +02:00
|
|
|
n, err := conn.Read(b)
|
2018-09-26 15:36:47 +02:00
|
|
|
if n > 0 {
|
2018-09-26 18:14:24 +02:00
|
|
|
res := make([]byte, n)
|
|
|
|
// Copy the buffer so it doesn't get changed while read by the recipient.
|
|
|
|
copy(res, b[:n])
|
|
|
|
c <- res
|
2018-09-26 15:36:47 +02:00
|
|
|
}
|
2018-09-23 21:34:29 +02:00
|
|
|
if err != nil {
|
2018-10-13 15:09:55 +02:00
|
|
|
log.Debug(err)
|
2018-09-23 21:34:29 +02:00
|
|
|
c <- nil
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2019-04-29 23:46:40 +02:00
|
|
|
log.Debug("exiting")
|
2018-09-23 21:34:29 +02:00
|
|
|
}()
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// pipe creates a full-duplex pipe between the two sockets and
|
|
|
|
// transfers data from one to the other.
|
2018-09-26 19:43:38 +02:00
|
|
|
func pipe(conn1 net.Conn, conn2 net.Conn) {
|
2018-09-23 21:34:29 +02:00
|
|
|
chan1 := chanFromConn(conn1)
|
2018-09-26 23:31:45 +02:00
|
|
|
chan2 := chanFromConn(conn2)
|
2018-09-23 21:34:29 +02:00
|
|
|
|
|
|
|
for {
|
2018-09-26 23:31:45 +02:00
|
|
|
select {
|
|
|
|
case b1 := <-chan1:
|
|
|
|
if b1 == nil {
|
|
|
|
return
|
|
|
|
}
|
2020-08-23 01:05:00 +02:00
|
|
|
if _, err := conn2.Write(b1); err != nil {
|
|
|
|
log.Errorf("write error on channel 1: %v", err)
|
|
|
|
}
|
2018-09-26 18:41:12 +02:00
|
|
|
|
2018-09-26 23:31:45 +02:00
|
|
|
case b2 := <-chan2:
|
|
|
|
if b2 == nil {
|
|
|
|
return
|
|
|
|
}
|
2020-08-23 01:05:00 +02:00
|
|
|
if _, err := conn1.Write(b2); err != nil {
|
|
|
|
log.Errorf("write error on channel 2: %v", err)
|
|
|
|
}
|
2018-09-26 23:31:45 +02:00
|
|
|
}
|
2018-09-23 21:34:29 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-30 04:20:03 +02:00
|
|
|
|
2020-10-22 19:09:04 +02:00
|
|
|
func PingServer(address string) (err error) {
|
|
|
|
c, err := comm.NewConnection(address, 200*time.Millisecond)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send([]byte("ping"))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
b, err := c.Receive()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if bytes.Equal(b, []byte("pong")) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return fmt.Errorf("no pong")
|
|
|
|
}
|
|
|
|
|
2019-09-07 18:46:04 +02:00
|
|
|
// ConnectToTCPServer will initiate a new connection
|
|
|
|
// to the specified address, room with optional time limit
|
2021-04-23 23:10:54 +02:00
|
|
|
func ConnectToTCPServer(address, password, keyPublicRelay, room string, timelimit ...time.Duration) (c *comm.Comm, banner string, ipaddr string, err error) {
|
2019-05-03 22:51:27 +02:00
|
|
|
if len(timelimit) > 0 {
|
|
|
|
c, err = comm.NewConnection(address, timelimit[0])
|
|
|
|
} else {
|
|
|
|
c, err = comm.NewConnection(address)
|
|
|
|
}
|
2019-04-30 00:24:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-02-28 20:59:56 +01:00
|
|
|
|
2021-04-23 22:48:19 +02:00
|
|
|
// generate ephermeral key
|
|
|
|
keyPublic, keyPrivate, err := crypt.NewAge()
|
2020-02-28 20:59:56 +01:00
|
|
|
|
2021-04-23 23:10:54 +02:00
|
|
|
// send epheremal public key + bcrypted password, encrypted using the server's public key
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 10)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-02-28 20:59:56 +01:00
|
|
|
|
2021-04-23 23:10:54 +02:00
|
|
|
sendBytesEnc, err := crypt.EncryptAge(append([]byte(keyPublic+"--"), hashedPassword...), keyPublicRelay)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
|
|
|
|
err = c.Send(sendBytesEnc)
|
2019-11-18 17:16:19 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
retBytesEnc, err := c.Receive()
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
retBytes, err := crypt.DecryptAge(retBytesEnc, keyPrivate)
|
2019-04-30 00:24:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
if !strings.Contains(string(retBytes), "|||") {
|
|
|
|
err = fmt.Errorf("bad response: %s", string(retBytes))
|
2019-11-18 17:16:19 +01:00
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:48:19 +02:00
|
|
|
banner = strings.Split(string(retBytes), "|||")[0]
|
|
|
|
ipaddr = strings.Split(string(retBytes), "|||")[1]
|
|
|
|
|
2019-05-01 19:45:13 +02:00
|
|
|
log.Debug("sending room")
|
2021-04-23 22:50:12 +02:00
|
|
|
bSend, err := crypt.EncryptAge([]byte(room), keyPublicRelay)
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = c.Send(bSend)
|
2019-04-30 00:24:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2019-05-01 19:45:13 +02:00
|
|
|
log.Debug("waiting for room confirmation")
|
2021-04-23 22:50:12 +02:00
|
|
|
enc, err := c.Receive()
|
2020-02-28 20:59:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-04-23 22:50:12 +02:00
|
|
|
data, err := crypt.DecryptAge(enc, keyPrivate)
|
2019-04-30 00:24:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !bytes.Equal(data, []byte("ok")) {
|
|
|
|
err = fmt.Errorf("got bad response: %s", data)
|
|
|
|
return
|
|
|
|
}
|
2019-05-01 19:45:13 +02:00
|
|
|
log.Debug("all set")
|
2019-04-30 00:24:22 +02:00
|
|
|
return
|
|
|
|
}
|