2018-10-16 21:23:01 +02:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2019-07-18 00:19:32 +02:00
|
|
|
"encoding/json"
|
2019-04-30 01:09:37 +02:00
|
|
|
"errors"
|
2018-10-16 21:23:01 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
2019-07-17 23:55:43 +02:00
|
|
|
"path"
|
2018-10-16 21:23:01 +02:00
|
|
|
"path/filepath"
|
2018-10-23 05:34:04 +02:00
|
|
|
"runtime"
|
2023-03-15 10:03:38 +01:00
|
|
|
"strconv"
|
2018-10-16 21:23:01 +02:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2023-01-12 19:23:50 +01:00
|
|
|
"github.com/chzyer/readline"
|
2020-09-17 22:04:33 +02:00
|
|
|
"github.com/schollz/cli/v2"
|
2021-04-17 19:33:38 +02:00
|
|
|
"github.com/schollz/croc/v9/src/comm"
|
|
|
|
"github.com/schollz/croc/v9/src/croc"
|
|
|
|
"github.com/schollz/croc/v9/src/models"
|
|
|
|
"github.com/schollz/croc/v9/src/tcp"
|
|
|
|
"github.com/schollz/croc/v9/src/utils"
|
2019-07-17 22:33:02 +02:00
|
|
|
log "github.com/schollz/logger"
|
2023-01-12 19:23:50 +01:00
|
|
|
"github.com/schollz/mnemonicode"
|
2021-04-17 18:42:11 +02:00
|
|
|
"github.com/schollz/pake/v3"
|
2018-10-16 21:23:01 +02:00
|
|
|
)
|
|
|
|
|
2019-09-07 18:46:04 +02:00
|
|
|
// Version specifies the version
|
2018-10-16 21:23:01 +02:00
|
|
|
var Version string
|
|
|
|
|
2020-09-23 12:58:00 +02:00
|
|
|
// Run will run the command line program
|
2019-04-30 01:09:37 +02:00
|
|
|
func Run() (err error) {
|
2019-05-03 22:51:27 +02:00
|
|
|
// use all of the processors
|
2018-10-23 05:34:04 +02:00
|
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
2019-05-02 22:14:09 +02:00
|
|
|
|
2018-10-16 21:23:01 +02:00
|
|
|
app := cli.NewApp()
|
|
|
|
app.Name = "croc"
|
|
|
|
if Version == "" {
|
2024-02-19 16:47:23 +01:00
|
|
|
Version = "v9.6.11"
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
app.Version = Version
|
|
|
|
app.Compiled = time.Now()
|
|
|
|
app.Usage = "easily and securely transfer stuff from one computer to another"
|
2019-11-17 22:19:27 +01:00
|
|
|
app.UsageText = `Send a file:
|
|
|
|
croc send file.txt
|
|
|
|
|
2023-09-23 03:15:27 +02:00
|
|
|
-git to respect your .gitignore
|
2021-08-29 19:16:51 +02:00
|
|
|
Send multiple files:
|
|
|
|
croc send file1.txt file2.txt file3.txt
|
|
|
|
or
|
|
|
|
croc send *.jpg
|
|
|
|
|
|
|
|
Send everything in a folder:
|
|
|
|
croc send example-folder-name
|
|
|
|
|
2019-11-17 22:19:27 +01:00
|
|
|
Send a file with a custom code:
|
2020-10-14 00:47:53 +02:00
|
|
|
croc send --code secret-code file.txt
|
|
|
|
|
|
|
|
Receive a file using code:
|
|
|
|
croc secret-code`
|
2020-09-09 17:05:57 +02:00
|
|
|
app.Commands = []*cli.Command{
|
2018-10-16 21:23:01 +02:00
|
|
|
{
|
|
|
|
Name: "send",
|
2021-08-29 19:16:51 +02:00
|
|
|
Usage: "send file(s), or folder (see options with croc send -h)",
|
|
|
|
Description: "send file(s), or folder, over the relay",
|
|
|
|
ArgsUsage: "[filename(s) or folder]",
|
2018-10-16 21:23:01 +02:00
|
|
|
Flags: []cli.Flag{
|
2022-07-07 19:32:23 +02:00
|
|
|
&cli.BoolFlag{Name: "zip", Usage: "zip folder before sending"},
|
2020-09-09 05:52:42 +02:00
|
|
|
&cli.StringFlag{Name: "code", Aliases: []string{"c"}, Usage: "codephrase used to connect to relay"},
|
2021-06-21 16:34:28 +02:00
|
|
|
&cli.StringFlag{Name: "hash", Value: "xxhash", Usage: "hash algorithm (xxhash, imohash, md5)"},
|
2020-09-09 05:52:42 +02:00
|
|
|
&cli.StringFlag{Name: "text", Aliases: []string{"t"}, Usage: "send some text"},
|
2020-09-09 17:05:57 +02:00
|
|
|
&cli.BoolFlag{Name: "no-local", Usage: "disable local relay when sending"},
|
|
|
|
&cli.BoolFlag{Name: "no-multi", Usage: "disable multiplexing"},
|
2023-09-23 03:15:27 +02:00
|
|
|
&cli.BoolFlag{Name: "git", Usage: "enable .gitignore respect / don't send ignored files"},
|
2024-02-17 19:09:53 +01:00
|
|
|
&cli.IntFlag{Name: "port", Value: 9009, Usage: "base port for the relay"},
|
|
|
|
&cli.IntFlag{Name: "transfers", Value: 4, Usage: "number of ports to use for transfers"},
|
2018-10-16 21:23:01 +02:00
|
|
|
},
|
|
|
|
HelpName: "croc send",
|
2021-10-01 23:49:21 +02:00
|
|
|
Action: send,
|
2018-10-16 21:23:01 +02:00
|
|
|
},
|
2019-04-30 06:25:30 +02:00
|
|
|
{
|
|
|
|
Name: "relay",
|
2019-11-17 22:19:27 +01:00
|
|
|
Usage: "start your own relay (optional)",
|
2019-04-30 06:25:30 +02:00
|
|
|
Description: "start relay",
|
|
|
|
HelpName: "croc relay",
|
2021-10-01 23:49:21 +02:00
|
|
|
Action: relay,
|
2019-05-01 21:48:09 +02:00
|
|
|
Flags: []cli.Flag{
|
2021-10-01 06:55:28 +02:00
|
|
|
&cli.StringFlag{Name: "host", Usage: "host of the relay"},
|
2020-09-09 17:05:57 +02:00
|
|
|
&cli.StringFlag{Name: "ports", Value: "9009,9010,9011,9012,9013", Usage: "ports of the relay"},
|
2019-05-01 21:48:09 +02:00
|
|
|
},
|
2019-04-30 06:25:30 +02:00
|
|
|
},
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
app.Flags = []cli.Flag{
|
2021-08-16 19:25:34 +02:00
|
|
|
&cli.BoolFlag{Name: "internal-dns", Usage: "use a built-in DNS stub resolver rather than the host operating system"},
|
2020-09-09 17:05:57 +02:00
|
|
|
&cli.BoolFlag{Name: "remember", Usage: "save these settings to reuse next time"},
|
|
|
|
&cli.BoolFlag{Name: "debug", Usage: "toggle debug mode"},
|
|
|
|
&cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"},
|
|
|
|
&cli.BoolFlag{Name: "stdout", Usage: "redirect file to stdout"},
|
|
|
|
&cli.BoolFlag{Name: "no-compress", Usage: "disable compression"},
|
|
|
|
&cli.BoolFlag{Name: "ask", Usage: "make sure sender and recipient are prompted"},
|
2020-10-21 19:23:12 +02:00
|
|
|
&cli.BoolFlag{Name: "local", Usage: "force to use only local connections"},
|
2021-02-01 15:58:27 +01:00
|
|
|
&cli.BoolFlag{Name: "ignore-stdin", Usage: "ignore piped stdin"},
|
2021-04-17 00:14:21 +02:00
|
|
|
&cli.BoolFlag{Name: "overwrite", Usage: "do not prompt to overwrite"},
|
2023-01-08 17:11:55 +01:00
|
|
|
&cli.BoolFlag{Name: "testing", Usage: "flag for testing purposes"},
|
2022-04-07 14:52:54 +02:00
|
|
|
&cli.StringFlag{Name: "curve", Value: "p256", Usage: "choose an encryption curve (" + strings.Join(pake.AvailableCurves(), ", ") + ")"},
|
2020-12-17 16:37:48 +01:00
|
|
|
&cli.StringFlag{Name: "ip", Value: "", Usage: "set sender ip if known e.g. 10.0.0.1:9009, [::1]:9009"},
|
2020-09-09 17:25:13 +02:00
|
|
|
&cli.StringFlag{Name: "relay", Value: models.DEFAULT_RELAY, Usage: "address of the relay", EnvVars: []string{"CROC_RELAY"}},
|
|
|
|
&cli.StringFlag{Name: "relay6", Value: models.DEFAULT_RELAY6, Usage: "ipv6 address of the relay", EnvVars: []string{"CROC_RELAY6"}},
|
2020-09-09 17:05:57 +02:00
|
|
|
&cli.StringFlag{Name: "out", Value: ".", Usage: "specify an output folder to receive the file"},
|
2020-10-22 08:37:32 +02:00
|
|
|
&cli.StringFlag{Name: "pass", Value: models.DEFAULT_PASSPHRASE, Usage: "password for the relay", EnvVars: []string{"CROC_PASS"}},
|
2020-10-14 00:47:00 +02:00
|
|
|
&cli.StringFlag{Name: "socks5", Value: "", Usage: "add a socks5 proxy", EnvVars: []string{"SOCKS5_PROXY"}},
|
2023-04-12 12:04:15 +02:00
|
|
|
&cli.StringFlag{Name: "connect", Value: "", Usage: "add a http proxy", EnvVars: []string{"HTTP_PROXY"}},
|
2021-10-19 02:46:54 +02:00
|
|
|
&cli.StringFlag{Name: "throttleUpload", Value: "", Usage: "Throttle the upload speed e.g. 500k"},
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
app.EnableBashCompletion = true
|
|
|
|
app.HideHelp = false
|
|
|
|
app.HideVersion = false
|
|
|
|
app.Action = func(c *cli.Context) error {
|
2020-09-19 17:52:32 +02:00
|
|
|
allStringsAreFiles := func(strs []string) bool {
|
|
|
|
for _, str := range strs {
|
|
|
|
if !utils.Exists(str) {
|
2020-10-05 17:30:45 +02:00
|
|
|
return false
|
2020-09-19 17:52:32 +02:00
|
|
|
}
|
|
|
|
}
|
2020-10-05 17:30:45 +02:00
|
|
|
return true
|
2020-09-19 17:52:32 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 15:08:57 +01:00
|
|
|
// if trying to send but forgot send, let the user know
|
2020-09-19 17:52:32 +02:00
|
|
|
if c.Args().Present() && allStringsAreFiles(c.Args().Slice()) {
|
|
|
|
fnames := []string{}
|
|
|
|
for _, fpath := range c.Args().Slice() {
|
|
|
|
_, basename := filepath.Split(fpath)
|
2020-10-05 17:30:45 +02:00
|
|
|
fnames = append(fnames, "'"+basename+"'")
|
2020-09-19 17:52:32 +02:00
|
|
|
}
|
2021-06-10 14:12:05 +02:00
|
|
|
promptMessage := fmt.Sprintf("Did you mean to send %s? (Y/n) ", strings.Join(fnames, ", "))
|
|
|
|
choice := strings.ToLower(utils.GetInput(promptMessage))
|
|
|
|
if choice == "" || choice == "y" || choice == "yes" {
|
2018-11-01 15:08:57 +01:00
|
|
|
return send(c)
|
|
|
|
}
|
|
|
|
}
|
2018-10-16 21:23:01 +02:00
|
|
|
return receive(c)
|
|
|
|
}
|
|
|
|
|
2019-04-30 01:09:37 +02:00
|
|
|
return app.Run(os.Args)
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
|
2019-09-20 18:20:50 +02:00
|
|
|
func setDebugLevel(c *cli.Context) {
|
2020-09-09 17:05:57 +02:00
|
|
|
if c.Bool("debug") {
|
2019-07-18 00:19:32 +02:00
|
|
|
log.SetLevel("debug")
|
|
|
|
log.Debug("debug mode on")
|
2019-07-18 15:17:15 +02:00
|
|
|
} else {
|
|
|
|
log.SetLevel("info")
|
2019-07-18 00:19:32 +02:00
|
|
|
}
|
2019-09-20 18:20:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func getConfigFile() string {
|
2022-02-03 17:34:03 +01:00
|
|
|
configFile, err := utils.GetConfigDir()
|
2019-07-18 00:19:32 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
2019-09-20 18:20:50 +02:00
|
|
|
return ""
|
2019-07-18 00:19:32 +02:00
|
|
|
}
|
2019-09-20 18:20:50 +02:00
|
|
|
return path.Join(configFile, "send.json")
|
|
|
|
}
|
2019-09-20 18:24:10 +02:00
|
|
|
|
2020-09-03 22:31:01 +02:00
|
|
|
func determinePass(c *cli.Context) (pass string) {
|
2020-09-09 17:05:57 +02:00
|
|
|
pass = c.String("pass")
|
2021-11-17 04:25:52 +01:00
|
|
|
b, err := os.ReadFile(pass)
|
2020-09-03 22:31:01 +02:00
|
|
|
if err == nil {
|
|
|
|
pass = strings.TrimSpace(string(b))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-09-20 18:20:50 +02:00
|
|
|
func send(c *cli.Context) (err error) {
|
|
|
|
setDebugLevel(c)
|
2020-10-05 17:30:45 +02:00
|
|
|
comm.Socks5Proxy = c.String("socks5")
|
2023-04-12 12:04:15 +02:00
|
|
|
comm.HttpProxy = c.String("connect")
|
2024-02-17 19:09:53 +01:00
|
|
|
|
|
|
|
portParam := c.Int("port")
|
|
|
|
if portParam == 0 {
|
|
|
|
portParam = 9009
|
|
|
|
}
|
|
|
|
transfersParam := c.Int("transfers")
|
|
|
|
if transfersParam == 0 {
|
|
|
|
transfersParam = 4
|
2022-08-12 21:00:26 +02:00
|
|
|
}
|
2024-02-17 19:09:53 +01:00
|
|
|
|
|
|
|
ports := make([]string, transfersParam+1)
|
|
|
|
for i := 0; i <= transfersParam; i++ {
|
|
|
|
ports[i] = strconv.Itoa(portParam + i)
|
|
|
|
}
|
|
|
|
|
2019-07-18 02:06:52 +02:00
|
|
|
crocOptions := croc.Options{
|
2019-11-18 16:57:12 +01:00
|
|
|
SharedSecret: c.String("code"),
|
|
|
|
IsSender: true,
|
2020-09-09 17:05:57 +02:00
|
|
|
Debug: c.Bool("debug"),
|
|
|
|
NoPrompt: c.Bool("yes"),
|
|
|
|
RelayAddress: c.String("relay"),
|
|
|
|
RelayAddress6: c.String("relay6"),
|
|
|
|
Stdout: c.Bool("stdout"),
|
2019-11-18 16:57:12 +01:00
|
|
|
DisableLocal: c.Bool("no-local"),
|
2020-10-21 19:23:12 +02:00
|
|
|
OnlyLocal: c.Bool("local"),
|
2021-02-01 15:58:27 +01:00
|
|
|
IgnoreStdin: c.Bool("ignore-stdin"),
|
2024-02-17 19:09:53 +01:00
|
|
|
RelayPorts: ports,
|
2020-09-09 17:05:57 +02:00
|
|
|
Ask: c.Bool("ask"),
|
2019-11-18 16:57:12 +01:00
|
|
|
NoMultiplexing: c.Bool("no-multi"),
|
2020-09-03 22:31:01 +02:00
|
|
|
RelayPassword: determinePass(c),
|
2020-09-03 02:24:32 +02:00
|
|
|
SendingText: c.String("text") != "",
|
2020-09-09 17:05:57 +02:00
|
|
|
NoCompress: c.Bool("no-compress"),
|
2021-04-17 00:14:21 +02:00
|
|
|
Overwrite: c.Bool("overwrite"),
|
2021-04-17 18:01:58 +02:00
|
|
|
Curve: c.String("curve"),
|
2021-06-21 16:34:28 +02:00
|
|
|
HashAlgorithm: c.String("hash"),
|
2021-10-19 02:46:54 +02:00
|
|
|
ThrottleUpload: c.String("throttleUpload"),
|
2022-07-06 15:17:34 +02:00
|
|
|
ZipFolder: c.Bool("zip"),
|
2023-09-23 03:15:27 +02:00
|
|
|
GitIgnore: c.Bool("git"),
|
2019-07-18 02:06:52 +02:00
|
|
|
}
|
2020-08-27 18:40:41 +02:00
|
|
|
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
|
|
|
|
crocOptions.RelayAddress6 = ""
|
|
|
|
} else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 {
|
|
|
|
crocOptions.RelayAddress = ""
|
|
|
|
}
|
2021-11-17 04:25:52 +01:00
|
|
|
b, errOpen := os.ReadFile(getConfigFile())
|
2020-09-09 17:05:57 +02:00
|
|
|
if errOpen == nil && !c.Bool("remember") {
|
2019-07-18 02:06:52 +02:00
|
|
|
var rememberedOptions croc.Options
|
|
|
|
err = json.Unmarshal(b, &rememberedOptions)
|
2019-07-18 01:23:50 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2019-07-18 02:06:52 +02:00
|
|
|
// update anything that isn't explicitly set
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("relay") && rememberedOptions.RelayAddress != "" {
|
2019-07-18 02:06:52 +02:00
|
|
|
crocOptions.RelayAddress = rememberedOptions.RelayAddress
|
2019-07-18 01:23:50 +02:00
|
|
|
}
|
2019-07-18 02:06:52 +02:00
|
|
|
if !c.IsSet("no-local") {
|
|
|
|
crocOptions.DisableLocal = rememberedOptions.DisableLocal
|
2019-07-18 01:23:50 +02:00
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("ports") && len(rememberedOptions.RelayPorts) > 0 {
|
2019-07-18 02:06:52 +02:00
|
|
|
crocOptions.RelayPorts = rememberedOptions.RelayPorts
|
2019-07-18 01:23:50 +02:00
|
|
|
}
|
2019-07-18 02:06:52 +02:00
|
|
|
if !c.IsSet("code") {
|
|
|
|
crocOptions.SharedSecret = rememberedOptions.SharedSecret
|
2019-07-18 01:23:50 +02:00
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("pass") && rememberedOptions.RelayPassword != "" {
|
2019-11-19 20:47:04 +01:00
|
|
|
crocOptions.RelayPassword = rememberedOptions.RelayPassword
|
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("relay6") && rememberedOptions.RelayAddress6 != "" {
|
2021-05-12 16:19:02 +02:00
|
|
|
crocOptions.RelayAddress6 = rememberedOptions.RelayAddress6
|
|
|
|
}
|
|
|
|
if !c.IsSet("overwrite") {
|
|
|
|
crocOptions.Overwrite = rememberedOptions.Overwrite
|
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("curve") && rememberedOptions.Curve != "" {
|
2021-05-12 16:19:02 +02:00
|
|
|
crocOptions.Curve = rememberedOptions.Curve
|
|
|
|
}
|
|
|
|
if !c.IsSet("local") {
|
|
|
|
crocOptions.OnlyLocal = rememberedOptions.OnlyLocal
|
|
|
|
}
|
2022-12-06 00:28:25 +01:00
|
|
|
if !c.IsSet("hash") {
|
|
|
|
crocOptions.HashAlgorithm = rememberedOptions.HashAlgorithm
|
|
|
|
}
|
2023-09-23 03:15:27 +02:00
|
|
|
if !c.IsSet("git") {
|
|
|
|
crocOptions.GitIgnore = rememberedOptions.GitIgnore
|
|
|
|
}
|
2019-07-18 01:23:50 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 01:09:37 +02:00
|
|
|
var fnames []string
|
2018-10-16 21:23:01 +02:00
|
|
|
stat, _ := os.Stdin.Stat()
|
2021-02-01 15:58:27 +01:00
|
|
|
if ((stat.Mode() & os.ModeCharDevice) == 0) && !c.Bool("ignore-stdin") {
|
2019-09-20 18:27:59 +02:00
|
|
|
fnames, err = getStdin()
|
2018-10-16 21:23:01 +02:00
|
|
|
if err != nil {
|
2019-09-20 18:27:59 +02:00
|
|
|
return
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
defer func() {
|
2021-02-01 10:34:06 +01:00
|
|
|
e := os.Remove(fnames[0])
|
|
|
|
if e != nil {
|
|
|
|
log.Error(e)
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
}()
|
2020-09-03 02:24:32 +02:00
|
|
|
} else if c.String("text") != "" {
|
|
|
|
fnames, err = makeTempFileWithString(c.String("text"))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer func() {
|
2021-02-01 10:34:06 +01:00
|
|
|
e := os.Remove(fnames[0])
|
|
|
|
if e != nil {
|
|
|
|
log.Error(e)
|
2020-09-03 02:24:32 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-10-16 21:23:01 +02:00
|
|
|
} else {
|
2020-09-19 21:48:11 +02:00
|
|
|
fnames = c.Args().Slice()
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
2019-04-30 01:09:37 +02:00
|
|
|
if len(fnames) == 0 {
|
2021-08-29 19:16:51 +02:00
|
|
|
return errors.New("must specify file: croc send [filename(s) or folder]")
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
2019-04-30 01:09:37 +02:00
|
|
|
|
2019-07-18 01:23:50 +02:00
|
|
|
if len(crocOptions.SharedSecret) == 0 {
|
2018-10-16 21:23:01 +02:00
|
|
|
// generate code phrase
|
2019-07-18 01:23:50 +02:00
|
|
|
crocOptions.SharedSecret = utils.GetRandomName()
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
2023-09-23 03:15:27 +02:00
|
|
|
minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders, err := croc.GetFilesInfo(fnames, crocOptions.ZipFolder, crocOptions.GitIgnore)
|
2019-09-20 18:24:10 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cr, err := croc.New(crocOptions)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// save the config
|
|
|
|
saveConfig(c, crocOptions)
|
|
|
|
|
2022-04-09 00:38:22 +02:00
|
|
|
err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders)
|
2019-09-20 18:24:10 +02:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-09-20 18:27:59 +02:00
|
|
|
func getStdin() (fnames []string, err error) {
|
2021-11-17 04:25:52 +01:00
|
|
|
f, err := os.CreateTemp(".", "croc-stdin-")
|
2019-09-20 18:27:59 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
_, err = io.Copy(f, os.Stdin)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = f.Close()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fnames = []string{f.Name()}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-03 02:24:32 +02:00
|
|
|
func makeTempFileWithString(s string) (fnames []string, err error) {
|
2021-11-17 04:25:52 +01:00
|
|
|
f, err := os.CreateTemp(".", "croc-stdin-")
|
2020-09-03 02:24:32 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = f.WriteString(s)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = f.Close()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fnames = []string{f.Name()}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-09-20 18:20:50 +02:00
|
|
|
func saveConfig(c *cli.Context, crocOptions croc.Options) {
|
2020-09-09 17:05:57 +02:00
|
|
|
if c.Bool("remember") {
|
2019-09-20 18:20:50 +02:00
|
|
|
configFile := getConfigFile()
|
2019-07-18 00:19:32 +02:00
|
|
|
log.Debug("saving config file")
|
|
|
|
var bConfig []byte
|
2019-07-18 01:23:50 +02:00
|
|
|
// if the code wasn't set, don't save it
|
|
|
|
if c.String("code") == "" {
|
|
|
|
crocOptions.SharedSecret = ""
|
|
|
|
}
|
2019-09-20 18:20:50 +02:00
|
|
|
bConfig, err := json.MarshalIndent(crocOptions, "", " ")
|
2019-07-18 00:19:32 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2022-12-05 20:21:04 +01:00
|
|
|
err = os.WriteFile(configFile, bConfig, 0o644)
|
2019-07-18 00:19:32 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Debugf("wrote %s", configFile)
|
|
|
|
}
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
|
2023-01-12 19:23:50 +01:00
|
|
|
type TabComplete struct{}
|
|
|
|
|
|
|
|
func (t TabComplete) Do(line []rune, pos int) ([][]rune, int) {
|
|
|
|
var words = strings.SplitAfter(string(line), "-")
|
2023-01-13 16:29:11 +01:00
|
|
|
var lastPartialWord = words[len(words)-1]
|
|
|
|
var nbCharacter = len(lastPartialWord)
|
|
|
|
if nbCharacter == 0 {
|
2023-01-12 19:23:50 +01:00
|
|
|
// No completion
|
|
|
|
return [][]rune{[]rune("")}, 0
|
|
|
|
}
|
2023-03-15 10:03:38 +01:00
|
|
|
if len(words) == 1 && nbCharacter == utils.NbPinNumbers {
|
|
|
|
// Check if word is indeed a number
|
|
|
|
_, err := strconv.Atoi(lastPartialWord)
|
|
|
|
if err == nil {
|
|
|
|
return [][]rune{[]rune("-")}, nbCharacter
|
|
|
|
}
|
|
|
|
}
|
2023-01-12 19:23:50 +01:00
|
|
|
var strArray [][]rune
|
|
|
|
for _, s := range mnemonicode.WordList {
|
2023-01-13 16:29:11 +01:00
|
|
|
if strings.HasPrefix(s, lastPartialWord) {
|
2023-03-15 10:03:38 +01:00
|
|
|
var completionCandidate = s[nbCharacter:]
|
|
|
|
if len(words) <= mnemonicode.WordsRequired(utils.NbBytesWords) {
|
|
|
|
completionCandidate += "-"
|
|
|
|
}
|
|
|
|
strArray = append(strArray, []rune(completionCandidate))
|
2023-01-12 19:23:50 +01:00
|
|
|
}
|
|
|
|
}
|
2023-01-13 16:29:11 +01:00
|
|
|
return strArray, nbCharacter
|
2023-01-12 19:23:50 +01:00
|
|
|
}
|
|
|
|
|
2019-04-30 01:09:37 +02:00
|
|
|
func receive(c *cli.Context) (err error) {
|
2020-10-05 17:30:45 +02:00
|
|
|
comm.Socks5Proxy = c.String("socks5")
|
2023-04-12 12:04:15 +02:00
|
|
|
comm.HttpProxy = c.String("connect")
|
2019-07-18 02:16:50 +02:00
|
|
|
crocOptions := croc.Options{
|
2019-11-18 17:16:19 +01:00
|
|
|
SharedSecret: c.String("code"),
|
|
|
|
IsSender: false,
|
2020-09-09 17:05:57 +02:00
|
|
|
Debug: c.Bool("debug"),
|
|
|
|
NoPrompt: c.Bool("yes"),
|
|
|
|
RelayAddress: c.String("relay"),
|
|
|
|
RelayAddress6: c.String("relay6"),
|
|
|
|
Stdout: c.Bool("stdout"),
|
|
|
|
Ask: c.Bool("ask"),
|
2020-09-03 22:31:01 +02:00
|
|
|
RelayPassword: determinePass(c),
|
2020-10-21 19:23:12 +02:00
|
|
|
OnlyLocal: c.Bool("local"),
|
2020-12-17 16:37:48 +01:00
|
|
|
IP: c.String("ip"),
|
2021-04-17 00:14:21 +02:00
|
|
|
Overwrite: c.Bool("overwrite"),
|
2021-04-17 18:01:58 +02:00
|
|
|
Curve: c.String("curve"),
|
2023-01-08 17:11:55 +01:00
|
|
|
TestFlag: c.Bool("testing"),
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
2020-08-27 18:40:41 +02:00
|
|
|
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
|
|
|
|
crocOptions.RelayAddress6 = ""
|
|
|
|
} else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 {
|
|
|
|
crocOptions.RelayAddress = ""
|
|
|
|
}
|
2020-02-18 05:26:13 +01:00
|
|
|
|
2020-09-09 17:05:57 +02:00
|
|
|
switch c.Args().Len() {
|
2020-02-18 05:26:13 +01:00
|
|
|
case 1:
|
2019-07-18 02:16:50 +02:00
|
|
|
crocOptions.SharedSecret = c.Args().First()
|
2020-02-18 05:26:13 +01:00
|
|
|
case 3:
|
|
|
|
var phrase []string
|
|
|
|
phrase = append(phrase, c.Args().First())
|
|
|
|
phrase = append(phrase, c.Args().Tail()...)
|
|
|
|
crocOptions.SharedSecret = strings.Join(phrase, "-")
|
2019-04-30 01:09:37 +02:00
|
|
|
}
|
2019-07-18 02:16:50 +02:00
|
|
|
|
|
|
|
// load options here
|
2019-09-20 18:20:50 +02:00
|
|
|
setDebugLevel(c)
|
2022-02-03 17:34:03 +01:00
|
|
|
configFile, err := utils.GetConfigDir()
|
2019-07-18 02:16:50 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
configFile = path.Join(configFile, "receive.json")
|
2021-11-17 04:25:52 +01:00
|
|
|
b, errOpen := os.ReadFile(configFile)
|
2020-09-09 17:05:57 +02:00
|
|
|
if errOpen == nil && !c.Bool("remember") {
|
2019-07-18 02:16:50 +02:00
|
|
|
var rememberedOptions croc.Options
|
|
|
|
err = json.Unmarshal(b, &rememberedOptions)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2021-11-17 19:20:32 +01:00
|
|
|
// update anything that isn't explicitly Globally set
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("relay") && rememberedOptions.RelayAddress != "" {
|
2019-07-18 02:16:50 +02:00
|
|
|
crocOptions.RelayAddress = rememberedOptions.RelayAddress
|
|
|
|
}
|
2020-09-09 17:05:57 +02:00
|
|
|
if !c.IsSet("yes") {
|
2019-07-18 15:13:11 +02:00
|
|
|
crocOptions.NoPrompt = rememberedOptions.NoPrompt
|
|
|
|
}
|
2019-07-18 02:16:50 +02:00
|
|
|
if crocOptions.SharedSecret == "" {
|
|
|
|
crocOptions.SharedSecret = rememberedOptions.SharedSecret
|
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("pass") && rememberedOptions.RelayPassword != "" {
|
2019-11-19 21:06:12 +01:00
|
|
|
crocOptions.RelayPassword = rememberedOptions.RelayPassword
|
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("relay6") && rememberedOptions.RelayAddress6 != "" {
|
2021-05-12 16:19:02 +02:00
|
|
|
crocOptions.RelayAddress6 = rememberedOptions.RelayAddress6
|
|
|
|
}
|
|
|
|
if !c.IsSet("overwrite") {
|
|
|
|
crocOptions.Overwrite = rememberedOptions.Overwrite
|
|
|
|
}
|
2021-10-02 18:12:34 +02:00
|
|
|
if !c.IsSet("curve") && rememberedOptions.Curve != "" {
|
2021-05-12 16:19:02 +02:00
|
|
|
crocOptions.Curve = rememberedOptions.Curve
|
|
|
|
}
|
|
|
|
if !c.IsSet("local") {
|
|
|
|
crocOptions.OnlyLocal = rememberedOptions.OnlyLocal
|
|
|
|
}
|
2019-07-18 02:16:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if crocOptions.SharedSecret == "" {
|
2023-01-12 19:23:50 +01:00
|
|
|
l, err := readline.NewEx(&readline.Config{
|
|
|
|
Prompt: "Enter receive code: ",
|
|
|
|
AutoComplete: TabComplete{},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
crocOptions.SharedSecret, err = l.Readline()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
2020-09-09 17:05:57 +02:00
|
|
|
if c.String("out") != "" {
|
|
|
|
if err = os.Chdir(c.String("out")); err != nil {
|
2020-08-23 01:05:00 +02:00
|
|
|
return err
|
|
|
|
}
|
2018-10-22 15:36:36 +02:00
|
|
|
}
|
2019-04-30 01:09:37 +02:00
|
|
|
|
2019-07-18 02:16:50 +02:00
|
|
|
cr, err := croc.New(crocOptions)
|
2019-04-30 01:09:37 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
2018-10-19 19:18:49 +02:00
|
|
|
}
|
2019-07-18 15:13:11 +02:00
|
|
|
|
|
|
|
// save the config
|
2020-09-09 17:05:57 +02:00
|
|
|
if c.Bool("remember") {
|
2019-07-18 15:13:11 +02:00
|
|
|
log.Debug("saving config file")
|
|
|
|
var bConfig []byte
|
|
|
|
bConfig, err = json.MarshalIndent(crocOptions, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
2022-12-05 20:21:04 +01:00
|
|
|
err = os.WriteFile(configFile, bConfig, 0o644)
|
2019-07-18 15:13:11 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Debugf("wrote %s", configFile)
|
|
|
|
}
|
|
|
|
|
2019-04-30 01:09:37 +02:00
|
|
|
err = cr.Receive()
|
|
|
|
return
|
2018-10-16 21:23:01 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 06:25:30 +02:00
|
|
|
func relay(c *cli.Context) (err error) {
|
2020-04-09 17:44:19 +02:00
|
|
|
log.Infof("starting croc relay version %v", Version)
|
2019-05-02 21:08:23 +02:00
|
|
|
debugString := "info"
|
2020-09-09 17:05:57 +02:00
|
|
|
if c.Bool("debug") {
|
2019-04-30 06:25:30 +02:00
|
|
|
debugString = "debug"
|
|
|
|
}
|
2021-10-01 06:55:28 +02:00
|
|
|
host := c.String("host")
|
2019-05-01 21:48:09 +02:00
|
|
|
ports := strings.Split(c.String("ports"), ",")
|
2019-05-01 01:19:10 +02:00
|
|
|
tcpPorts := strings.Join(ports[1:], ",")
|
2019-04-30 06:25:30 +02:00
|
|
|
for i, port := range ports {
|
|
|
|
if i == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
go func(portStr string) {
|
2022-07-17 10:40:49 +02:00
|
|
|
err := tcp.Run(debugString, host, portStr, determinePass(c))
|
2019-04-30 06:25:30 +02:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}(port)
|
|
|
|
}
|
2021-10-01 06:55:28 +02:00
|
|
|
return tcp.Run(debugString, host, ports[0], determinePass(c), tcpPorts)
|
2019-04-30 06:25:30 +02:00
|
|
|
}
|