0
0
Fork 0
mirror of https://github.com/schollz/croc.git synced 2025-10-11 13:21:00 +02:00

new: add flag with warning for passing shared secret on single-user systems

This commit is contained in:
Zack 2024-05-26 07:52:12 -07:00
parent ca7a5979cc
commit 63c9201938

View file

@ -27,6 +27,7 @@ import (
// Version specifies the version // Version specifies the version
var Version string var Version string
var classicInsecureMode = false
// Run will run the command line program // Run will run the command line program
func Run() (err error) { func Run() (err error) {
@ -92,6 +93,7 @@ func Run() (err error) {
} }
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
&cli.BoolFlag{Name: "internal-dns", Usage: "use a built-in DNS stub resolver rather than the host operating system"}, &cli.BoolFlag{Name: "internal-dns", Usage: "use a built-in DNS stub resolver rather than the host operating system"},
&cli.BoolFlag{Name: "classic", Usage: "toggle between the classic mode (insecure due to local attack vector) and new mode (secure)"},
&cli.BoolFlag{Name: "remember", Usage: "save these settings to reuse next time"}, &cli.BoolFlag{Name: "remember", Usage: "save these settings to reuse next time"},
&cli.BoolFlag{Name: "debug", Usage: "toggle debug mode"}, &cli.BoolFlag{Name: "debug", Usage: "toggle debug mode"},
&cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"}, &cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"},
@ -125,6 +127,63 @@ func Run() (err error) {
return true return true
} }
// check if "classic" is set
classicFile := getClassicConfigFile(true)
classicInsecureMode = utils.Exists(classicFile)
if c.Bool("classic") {
if classicInsecureMode {
// classic mode not enabled
fmt.Print(`Classic mode is currently ENABLED.
Disabling this mode will prevent the shared secret from being visible
on the host's process list when passed via the command line. On a
multi-user system, this will help ensure that other local users cannot
access the shared secret and receive the files instead of the intended
recipient.
Do you wish to continue to DISABLE the classic mode? (Y/n) `)
choice := strings.ToLower(utils.GetInput(""))
if choice == "y" || choice == "yes" {
os.Remove(classicFile)
fmt.Println("\nClassic mode DISABLED.\n")
fmt.Println(`To send and receive, export the CROC_SECRET variable with the code phrase:
Send: CROC_SECRET=*** croc send file.txt
Receive: CROC_SECRET=*** croc
`)
} else {
fmt.Println("\nClassic mode ENABLED.\n")
}
} else {
// enable classic mode
// touch the file
fmt.Print(`Classic mode is currently DISABLED.
Please note that enabling this mode will make the shared secret visible
on the host's process list when passed via the command line. On a
multi-user system, this could allow other local users to access the
shared secret and receive the files instead of the intended recipient.
Do you wish to continue to enable the classic mode? (Y/n) `)
choice := strings.ToLower(utils.GetInput(""))
if choice == "y" || choice == "yes" {
fmt.Println("\nClassic mode ENABLED.\n")
os.WriteFile(classicFile, []byte("enabled"), 0o644)
fmt.Println(`To send and receive, use the code phrase:
Send: croc send --code *** file.txt
Receive: croc ***
`)
} else {
fmt.Println("\nClassic mode DISABLED.\n")
}
}
os.Exit(0)
}
// if trying to send but forgot send, let the user know // if trying to send but forgot send, let the user know
if c.Args().Present() && allStringsAreFiles(c.Args().Slice()) { if c.Args().Present() && allStringsAreFiles(c.Args().Slice()) {
fnames := []string{} fnames := []string{}
@ -138,6 +197,7 @@ func Run() (err error) {
return send(c) return send(c)
} }
} }
return receive(c) return receive(c)
} }
@ -162,6 +222,15 @@ func getSendConfigFile(requireValidPath bool) string {
return path.Join(configFile, "send.json") return path.Join(configFile, "send.json")
} }
func getClassicConfigFile(requireValidPath bool) string {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
log.Error(err)
return ""
}
return path.Join(configFile, "classic_enabled")
}
func getReceiveConfigFile(requireValidPath bool) (string, error) { func getReceiveConfigFile(requireValidPath bool) (string, error) {
configFile, err := utils.GetConfigDir(requireValidPath) configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil { if err != nil {
@ -304,11 +373,12 @@ func send(c *cli.Context) (err error) {
return errors.New("must specify file: croc send [filename(s) or folder]") return errors.New("must specify file: croc send [filename(s) or folder]")
} }
// if operating system is UNIX, then use environmental variable to set the code if !classicInsecureMode {
if (!(runtime.GOOS == "windows") && c.IsSet("code")) || os.Getenv("CROC_SECRET") != "" { // if operating system is UNIX, then use environmental variable to set the code
crocOptions.SharedSecret = os.Getenv("CROC_SECRET") if (!(runtime.GOOS == "windows") && c.IsSet("code")) || os.Getenv("CROC_SECRET") != "" {
if crocOptions.SharedSecret == "" { crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
fmt.Printf(`On linux, to send with a custom code phrase, if crocOptions.SharedSecret == "" {
fmt.Printf(`On UNIX systems, to send with a custom code phrase,
you need to set the environmental variable CROC_SECRET: you need to set the environmental variable CROC_SECRET:
export CROC_SECRET="****" export CROC_SECRET="****"
@ -317,9 +387,14 @@ you need to set the environmental variable CROC_SECRET:
Or you can have the code phrase automaticlaly generated: Or you can have the code phrase automaticlaly generated:
croc send file.txt croc send file.txt
Or you can go back to the classic croc behavior by enabling classic mode:
croc --classic
`) `)
os.Exit(0) os.Exit(0)
}
} }
} }
@ -516,10 +591,10 @@ func receive(c *cli.Context) (err error) {
if crocOptions.SharedSecret == "" && os.Getenv("CROC_SECRET") != "" { if crocOptions.SharedSecret == "" && os.Getenv("CROC_SECRET") != "" {
crocOptions.SharedSecret = os.Getenv("CROC_SECRET") crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
} else if !(runtime.GOOS == "windows") && crocOptions.SharedSecret != "" { } else if !(runtime.GOOS == "windows") && crocOptions.SharedSecret != "" && !classicInsecureMode {
crocOptions.SharedSecret = os.Getenv("CROC_SECRET") crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
if crocOptions.SharedSecret == "" { if crocOptions.SharedSecret == "" {
fmt.Printf(`On linux, to receive with croc you either need fmt.Printf(`On UNIX systems, to receive with croc you either need
to set a code phrase using your environmental variables: to set a code phrase using your environmental variables:
export CROC_SECRET="****" export CROC_SECRET="****"
@ -530,7 +605,12 @@ declaring the secret on the command line:
croc croc
Enter receive code: **** Enter receive code: ****
`)
Or you can go back to the classic croc behavior by enabling classic mode:
croc --classic
`)
os.Exit(0) os.Exit(0)
} }
} }