config: add --password-command to allow dynamic config password - fixes #3694
This commit is contained in:
committed by
Nick Craig-Wood
parent
0ab2693da6
commit
06df133159
+58
-9
@@ -14,6 +14,7 @@ import (
|
||||
"log"
|
||||
mathrand "math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
@@ -239,15 +240,7 @@ var errorConfigFileNotFound = errors.New("config file not found")
|
||||
// loadConfigFile will load a config file, and
|
||||
// automatically decrypt it.
|
||||
func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||
envpw := os.Getenv("RCLONE_CONFIG_PASS")
|
||||
if len(configKey) == 0 && envpw != "" {
|
||||
err := setConfigPassword(envpw)
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "Using RCLONE_CONFIG_PASS returned: %v", err)
|
||||
} else {
|
||||
fs.Debugf(nil, "Using RCLONE_CONFIG_PASS password.")
|
||||
}
|
||||
}
|
||||
var usingPasswordCommand bool
|
||||
|
||||
b, err := ioutil.ReadFile(ConfigPath)
|
||||
if err != nil {
|
||||
@@ -280,6 +273,59 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||
return goconfig.LoadFromReader(bytes.NewBuffer(b))
|
||||
}
|
||||
|
||||
if len(configKey) == 0 {
|
||||
pwc := fs.Config.PasswordCommand
|
||||
|
||||
if pwc == "" {
|
||||
pwc = os.Getenv("RCLONE_CONFIG_PASS_COMMAND")
|
||||
}
|
||||
if pwc != "" {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
args := strings.Fields(pwc)
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
// One does not always get the stderr returned in the wrapped error.
|
||||
fs.Errorf(nil, "Using RCLONE_CONFIG_PASS_COMMAND returned: %v", err)
|
||||
if ers := strings.TrimSpace(stderr.String()); ers != "" {
|
||||
fs.Errorf(nil, "--password-command stderr: %s", ers)
|
||||
}
|
||||
return nil, errors.Wrap(err, "password command failed")
|
||||
}
|
||||
if pass := strings.Trim(stdout.String(), "\r\n"); pass != "" {
|
||||
err := setConfigPassword(pass)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "incorrect password")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("password-command returned empty string")
|
||||
}
|
||||
|
||||
if len(configKey) == 0 {
|
||||
return nil, errors.New("unable to decrypt configuration: incorrect password")
|
||||
}
|
||||
usingPasswordCommand = true
|
||||
} else {
|
||||
usingPasswordCommand = false
|
||||
|
||||
envpw := os.Getenv("RCLONE_CONFIG_PASS")
|
||||
|
||||
if envpw != "" {
|
||||
err := setConfigPassword(envpw)
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "Using RCLONE_CONFIG_PASS returned: %v", err)
|
||||
} else {
|
||||
fs.Debugf(nil, "Using RCLONE_CONFIG_PASS password.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypted content is base64 encoded.
|
||||
dec := base64.NewDecoder(base64.StdEncoding, r)
|
||||
box, err := ioutil.ReadAll(dec)
|
||||
@@ -310,6 +356,9 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||
fs.Debugf(nil, "using _RCLONE_CONFIG_KEY_FILE for configKey")
|
||||
} else {
|
||||
if len(configKey) == 0 {
|
||||
if usingPasswordCommand {
|
||||
return nil, errors.New("using password command derived password, unable to decrypt configuration")
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user