From 579c0b99612f43a10cd23cf26c20328d883a02f2 Mon Sep 17 00:00:00 2001 From: Cnly Date: Wed, 8 Aug 2018 23:55:21 +0800 Subject: [PATCH] mountlib: pass configKey to child process when daemonized - fixes #2442 --- cmd/mountlib/mount.go | 6 ++++++ fs/config/config.go | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/cmd/mountlib/mount.go b/cmd/mountlib/mount.go index 5cfd1ec5f..b739e3f00 100644 --- a/cmd/mountlib/mount.go +++ b/cmd/mountlib/mount.go @@ -15,6 +15,7 @@ import ( "github.com/ncw/rclone/vfs/vfsflags" "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/ncw/rclone/fs/config" ) // Options set by command line flags @@ -216,6 +217,11 @@ be copied to the vfs cache before opening with --vfs-cache-mode full. ` + vfs.Help, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(2, 2, command, args) + + if Daemon { + config.SaveKeyToEnv = true + } + fdst := cmd.NewFsDir(args) // Show stats if the user has specifically requested them diff --git a/fs/config/config.go b/fs/config/config.go index fc60d6b24..40b632d3a 100644 --- a/fs/config/config.go +++ b/fs/config/config.go @@ -79,6 +79,12 @@ var ( // output of prompt for password PasswordPromptOutput = os.Stderr + + // Whether to set the environment variable `_RCLONE_CONFIG_KEY` to the configKey (base64 encoded) when + // it is calculated from the password. If `_RCLONE_CONFIG_KEY` is present, password prompt is skipped and `RCLONE_CONFIG_PASS` ignored. + // For security reasons, the `_RCLONE_CONFIG_KEY` is unset once the configKey is successfully loaded. + // This can be used to pass the configKey to a child process. + SaveKeyToEnv = false ) func init() { @@ -249,19 +255,28 @@ func loadConfigFile() (*goconfig.ConfigFile, error) { var out []byte for { - if len(configKey) == 0 && envpw != "" { - err := setConfigPassword(envpw) + if envkey := os.Getenv("_RCLONE_CONFIG_KEY"); len(envkey) > 0 { + configKey, err = base64.StdEncoding.DecodeString(envkey) if err != nil { - fmt.Println("Using RCLONE_CONFIG_PASS returned:", err) - } else { - fs.Debugf(nil, "Using RCLONE_CONFIG_PASS password.") + log.Fatalf("unable to decode configKey from environment variable _RCLONE_CONFIG_KEY: %v", err) } - } - if len(configKey) == 0 { - if !fs.Config.AskPassword { - return nil, errors.New("unable to decrypt configuration and not allowed to ask for password - set RCLONE_CONFIG_PASS to your configuration password") + fs.Debugf(nil, "decoded configKey from environment variable _RCLONE_CONFIG_KEY") + os.Unsetenv("_RCLONE_CONFIG_KEY") + } else { + if len(configKey) == 0 && envpw != "" { + err := setConfigPassword(envpw) + if err != nil { + fmt.Println("Using RCLONE_CONFIG_PASS returned:", err) + } else { + fs.Debugf(nil, "Using RCLONE_CONFIG_PASS password.") + } + } + if len(configKey) == 0 { + if !fs.Config.AskPassword { + return nil, errors.New("unable to decrypt configuration and not allowed to ask for password - set RCLONE_CONFIG_PASS to your configuration password") + } + getConfigPassword("Enter configuration password:") } - getConfigPassword("Enter configuration password:") } // Nonce is first 24 bytes of the ciphertext @@ -362,6 +377,10 @@ func setConfigPassword(password string) error { return err } configKey = sha.Sum(nil) + if SaveKeyToEnv { + fs.Debugf(nil, "saving configKey to environment variable _RCLONE_CONFIG_KEY") + os.Setenv("_RCLONE_CONFIG_KEY", base64.StdEncoding.EncodeToString(configKey)) + } return nil }