1
0
mirror of https://github.com/schollz/croc.git synced 2024-11-24 08:02:33 +03:00
This commit is contained in:
Zack Scholl 2019-04-29 20:40:42 -07:00
parent 859130a988
commit c1c8e39499
3 changed files with 201 additions and 26 deletions

7
go.mod
View File

@ -4,17 +4,20 @@ require (
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
github.com/denisbrodbeck/machineid v1.0.1
github.com/fatih/color v1.7.0 // indirect
github.com/google/pprof v0.0.0-20190404155422-f8f10df84213 // indirect
github.com/gorilla/websocket v1.4.0
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pkg/errors v0.8.1
github.com/schollz/mnemonicode v1.0.1
github.com/schollz/pake v1.1.0
github.com/schollz/progressbar/v2 v2.10.0
github.com/schollz/progressbar/v2 v2.12.0
github.com/schollz/spinner v0.0.0-20180925172146-6bbc5f7804f9
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.3.0
github.com/urfave/cli v1.20.0
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c // indirect
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect
)

11
go.sum
View File

@ -7,8 +7,12 @@ github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMS
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/google/pprof v0.0.0-20190404155422-f8f10df84213 h1:y77GPNuZbqlt3/OjKA9yysnnxxqW+XwLaGY3ol9Mgmc=
github.com/google/pprof v0.0.0-20190404155422-f8f10df84213/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -28,9 +32,13 @@ github.com/schollz/pake v1.1.0 h1:+tYqsPVkuirFpmeRePjYTUhIHHKLufdmd7QfuspaXCk=
github.com/schollz/pake v1.1.0/go.mod h1:pL7Z08gnQ4OQ3G27s5e5T6TEzp6cFc5GzCwLm0f75Io=
github.com/schollz/progressbar/v2 v2.10.0 h1:AxYYUjr5fOPlA0Pcqc3R3kDBrqyLFWk2P7LRLdXb3yE=
github.com/schollz/progressbar/v2 v2.10.0/go.mod h1:l6tn6yU6ZdQoF8lwX/VoAUQ3FjhCbrcZDnl9xeWZzYw=
github.com/schollz/progressbar/v2 v2.12.0 h1:eTkmx9oWkRqi+rAzSDsreLbwGHvlrLJDR8xzmO0ccDI=
github.com/schollz/progressbar/v2 v2.12.0/go.mod h1:fBI3onORwtNtwCWJHsrXtjE3QnJOtqIZrvr3rDaF7L0=
github.com/schollz/spinner v0.0.0-20180925172146-6bbc5f7804f9 h1:y08o5oQ/slxXE/F0uh5dd8mdVvb+w4NLcNSDSq4c2F0=
github.com/schollz/spinner v0.0.0-20180925172146-6bbc5f7804f9/go.mod h1:kCMoQsqzx4MzGJWaALr6tKyCnlrY0kILGLkA1FOiLF4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -38,6 +46,8 @@ github.com/tscholl2/siec v0.0.0-20180721101609-21667da05937 h1:lhssCpSe3TjKcbvUo
github.com/tscholl2/siec v0.0.0-20180721101609-21667da05937/go.mod h1:KL9+ubr1JZdaKjgAaHr+tCytEncXBa1pR6FjbTsOJnw=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c h1:Rx/HTKi09myZ25t1SOlDHmHOy/mKxNAcu0hP1oPX9qM=
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -47,3 +57,4 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjW
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -3,9 +3,11 @@ package croc
import (
"bytes"
"crypto/elliptic"
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"math"
"os"
"path"
"path/filepath"
@ -17,6 +19,7 @@ import (
"github.com/denisbrodbeck/machineid"
"github.com/pkg/errors"
"github.com/schollz/croc/v6/src/comm"
"github.com/schollz/croc/v6/src/compress"
"github.com/schollz/croc/v6/src/crypt"
"github.com/schollz/croc/v6/src/logger"
"github.com/schollz/croc/v6/src/message"
@ -254,25 +257,35 @@ func (c *Client) transfer(options TransferOptions) (err error) {
// listen for incoming messages and process them
for {
var data []byte
var done bool
data, err = c.conn[0].Receive()
if err != nil {
return
}
err = c.processMessage(data)
done, err = c.processMessage(data)
if err != nil {
return
}
if done {
break
}
}
return
}
func (c *Client) processMessage(payload []byte) (err error) {
func (c *Client) processMessage(payload []byte) (done bool, err error) {
m, err := message.Decode(c.Key, payload)
if err != nil {
return
}
switch m.Type {
case "finished":
err = message.Send(c.conn[0], c.Key, message.Message{
Type: "finished",
})
done = true
return
case "pake":
// if // c.spinner.Suffix != " performing PAKE..." {
// // c.spinner.Stop()
@ -294,11 +307,25 @@ func (c *Client) processMessage(payload []byte) (err error) {
log.Debug("session key is verified, generating encryption")
key, err := c.Pake.SessionKey()
if err != nil {
return err
return true, err
}
c.Key, err = crypt.New(key, []byte(c.Options.SharedSecret))
if err != nil {
return err
return true, err
}
// connects to the other ports of the server for transfer
for i := 1; i < len(c.Options.RelayPorts); i++ {
c.conn[i], err = tcp.ConnectToTCPServer(
fmt.Sprintf("%s:%s", c.Options.RelayAddress, c.Options.RelayPorts[i]),
fmt.Sprintf("%s-%d", utils.SHA256(c.Options.SharedSecret)[:7], i),
)
if err != nil {
return true, err
}
if !c.Options.IsSender {
go c.receiveData(i)
}
}
c.Step1ChannelSecured = true
}
@ -306,7 +333,7 @@ func (c *Client) processMessage(payload []byte) (err error) {
// c.spinner.Stop()
fmt.Print("\r")
err = fmt.Errorf("peer error: %s", m.Message)
return err
return true, err
case "fileinfo":
var senderInfo SenderInfo
err = json.Unmarshal(m.Bytes, &senderInfo)
@ -331,7 +358,7 @@ func (c *Client) processMessage(payload []byte) (err error) {
Type: "error",
Message: "refusing files",
})
return fmt.Errorf("refused files")
return true, fmt.Errorf("refused files")
}
} else {
fmt.Fprintf(os.Stderr, "\rReceiving %s (%s) from machine '%s'\n", fname, utils.ByteCountDecimal(totalSize), senderInfo.MachineID)
@ -354,7 +381,6 @@ func (c *Client) processMessage(payload []byte) (err error) {
log.Debug("sending close-recipient")
err = message.Send(c.conn[0], c.Key, message.Message{
Type: "close-recipient",
Num: m.Num,
})
case "close-recipient":
c.Step4FileTransfer = false
@ -421,6 +447,53 @@ func (c *Client) updateState() (err error) {
// start initiating the process to receive a new file
log.Debugf("working on file %d", c.FilesToTransferCurrentNum)
// recipient sets the file
pathToFile := path.Join(
c.FilesToTransfer[c.FilesToTransferCurrentNum].FolderRemote,
c.FilesToTransfer[c.FilesToTransferCurrentNum].Name,
)
folderForFile, _ := filepath.Split(pathToFile)
os.MkdirAll(folderForFile, os.ModePerm)
var errOpen error
c.CurrentFile, errOpen = os.OpenFile(
pathToFile,
os.O_WRONLY, 0666)
truncate := false
if errOpen == nil {
stat, _ := c.CurrentFile.Stat()
truncate = stat.Size() != c.FilesToTransfer[c.FilesToTransferCurrentNum].Size
} else {
c.CurrentFile, errOpen = os.Create(pathToFile)
if errOpen != nil {
errOpen = errors.Wrap(errOpen, "could not create "+pathToFile)
log.Error(errOpen)
return errOpen
}
truncate = true
}
if truncate {
err := c.CurrentFile.Truncate(c.FilesToTransfer[c.FilesToTransferCurrentNum].Size)
if err != nil {
err = errors.Wrap(err, "could not truncate "+pathToFile)
log.Error(err)
return err
}
}
// setup the progressbar
c.bar = progressbar.NewOptions64(
c.FilesToTransfer[c.FilesToTransferCurrentNum].Size,
progressbar.OptionOnCompletion(func() {
fmt.Println(" ✔️")
}),
progressbar.OptionSetWidth(8),
progressbar.OptionSetDescription(c.FilesToTransfer[c.FilesToTransferCurrentNum].Name),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionSetBytes64(c.FilesToTransfer[c.FilesToTransferCurrentNum].Size),
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionThrottle(100*time.Millisecond),
)
// recipient requests the file and chunks (if empty, then should receive all chunks)
bRequest, _ := json.Marshal(RemoteFileRequest{
CurrentFileChunks: c.CurrentFileChunks,
@ -434,35 +507,123 @@ func (c *Client) updateState() (err error) {
return
}
c.Step3RecipientRequestFile = true
// TODO: receive
}
if c.Options.IsSender && c.Step3RecipientRequestFile && !c.Step4FileTransfer {
log.Debug("start sending data!")
// TODO: send
c.Step4FileTransfer = true
// setup the progressbar
c.bar = progressbar.NewOptions64(
c.FilesToTransfer[c.FilesToTransferCurrentNum].Size,
progressbar.OptionOnCompletion(func() {
fmt.Println(" ✔️")
}),
progressbar.OptionSetWidth(8),
progressbar.OptionSetDescription(c.FilesToTransfer[c.FilesToTransferCurrentNum].Name),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionSetBytes64(c.FilesToTransfer[c.FilesToTransferCurrentNum].Size),
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionThrottle(100*time.Millisecond),
)
for i := 1; i < len(c.Options.RelayPorts); i++ {
go c.sendData(i)
}
}
return
}
// Encode encodes the input in base64
// It can optionally zip the input before encoding
func Encode(obj interface{}) string {
b, err := json.Marshal(obj)
func (c *Client) receiveData(i int) {
for {
data, err := c.conn[i].Receive()
if err != nil {
log.Errorf("%s: %s", i, err.Error())
}
data, err = c.Key.Decrypt(data)
if err != nil {
panic(err)
}
data = compress.Decompress(data)
// get position
var position uint64
rbuf := bytes.NewReader(data[:8])
err = binary.Read(rbuf, binary.LittleEndian, &position)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
positionInt64 := int64(position)
c.mutex.Lock()
n, err := c.CurrentFile.WriteAt(data[8:], positionInt64)
c.mutex.Unlock()
if err != nil {
panic(err)
}
c.bar.Add(n)
if c.bar.State().CurrentBytes == float64(c.FilesToTransfer[c.FilesToTransferCurrentNum].Size) {
log.Debug("finished receiving!")
c.CurrentFile.Close()
log.Debug("sending close-sender")
err = message.Send(c.conn[0], c.Key, message.Message{
Type: "close-sender",
})
if err != nil {
panic(err)
}
}
}
return
}
func (c *Client) sendData(i int) {
pathToFile := path.Join(
c.FilesToTransfer[c.FilesToTransferCurrentNum].FolderSource,
c.FilesToTransfer[c.FilesToTransferCurrentNum].Name,
)
log.Debugf("opening %s to read", pathToFile)
f, err := os.Open(pathToFile)
if err != nil {
panic(err)
}
defer f.Close()
return base64.StdEncoding.EncodeToString(b)
}
pos := uint64(0)
curi := float64(0)
for {
// Read file
data := make([]byte, 1000)
n, err := f.Read(data)
if err != nil {
if err == io.EOF {
return
}
panic(err)
}
// Decode decodes the input from base64
// It can optionally unzip the input after decoding
func Decode(in string, obj interface{}) (err error) {
b, err := base64.StdEncoding.DecodeString(in)
if err != nil {
return
if math.Mod(curi, float64(len(c.Options.RelayPorts)-1))+1 == float64(i) {
posByte := make([]byte, 8)
binary.LittleEndian.PutUint64(posByte, pos)
dataToSend, err := c.Key.Encrypt(
compress.Compress(
append(posByte, data[:n]...),
),
)
if err != nil {
panic(err)
}
err = c.conn[i].Send(dataToSend)
if err != nil {
panic(err)
}
c.bar.Add(n)
}
curi++
pos += uint64(n)
}
err = json.Unmarshal(b, obj)
return
}