mirror of
https://github.com/rclone/rclone.git
synced 2024-11-07 09:04:52 +01:00
config: factor --password-command code into its own function #7859
This commit is contained in:
parent
71799d7efd
commit
c9c283533c
@ -78,37 +78,19 @@ func Decrypt(b io.ReadSeeker) (io.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(configKey) == 0 {
|
if len(configKey) == 0 {
|
||||||
if len(ci.PasswordCommand) != 0 {
|
pass, err := GetPasswordCommand(ctx)
|
||||||
var stdout bytes.Buffer
|
if err != nil {
|
||||||
var stderr bytes.Buffer
|
return nil, err
|
||||||
|
}
|
||||||
cmd := exec.Command(ci.PasswordCommand[0], ci.PasswordCommand[1:]...)
|
if pass != "" {
|
||||||
|
usingPasswordCommand = true
|
||||||
cmd.Stdout = &stdout
|
err = SetConfigPassword(pass)
|
||||||
cmd.Stderr = &stderr
|
if err != nil {
|
||||||
cmd.Stdin = os.Stdin
|
return nil, fmt.Errorf("incorrect password: %w", err)
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
// One does not always get the stderr returned in the wrapped error.
|
|
||||||
fs.Errorf(nil, "Using --password-command returned: %v", err)
|
|
||||||
if ers := strings.TrimSpace(stderr.String()); ers != "" {
|
|
||||||
fs.Errorf(nil, "--password-command stderr: %s", ers)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("password command failed: %w", err)
|
|
||||||
}
|
}
|
||||||
if pass := strings.Trim(stdout.String(), "\r\n"); pass != "" {
|
|
||||||
err := SetConfigPassword(pass)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("incorrect password: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("password-command returned empty string")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(configKey) == 0 {
|
if len(configKey) == 0 {
|
||||||
return nil, errors.New("unable to decrypt configuration: incorrect password")
|
return nil, errors.New("unable to decrypt configuration: incorrect password")
|
||||||
}
|
}
|
||||||
usingPasswordCommand = true
|
|
||||||
} else {
|
} else {
|
||||||
usingPasswordCommand = false
|
usingPasswordCommand = false
|
||||||
|
|
||||||
@ -183,6 +165,40 @@ func Decrypt(b io.ReadSeeker) (io.Reader, error) {
|
|||||||
return bytes.NewReader(out), nil
|
return bytes.NewReader(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPasswordCommand gets the password using the --password-command setting
|
||||||
|
//
|
||||||
|
// If the the --password-command flag was not in use it returns "", nil
|
||||||
|
func GetPasswordCommand(ctx context.Context) (pass string, err error) {
|
||||||
|
ci := fs.GetConfig(ctx)
|
||||||
|
if len(ci.PasswordCommand) == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
|
cmd := exec.Command(ci.PasswordCommand[0], ci.PasswordCommand[1:]...)
|
||||||
|
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
// One does not always get the stderr returned in the wrapped error.
|
||||||
|
fs.Errorf(nil, "Using --password-command returned: %v", err)
|
||||||
|
if ers := strings.TrimSpace(stderr.String()); ers != "" {
|
||||||
|
fs.Errorf(nil, "--password-command stderr: %s", ers)
|
||||||
|
}
|
||||||
|
return pass, fmt.Errorf("password command failed: %w", err)
|
||||||
|
}
|
||||||
|
pass = strings.Trim(stdout.String(), "\r\n")
|
||||||
|
if pass == "" {
|
||||||
|
return pass, errors.New("--password-command returned empty string")
|
||||||
|
}
|
||||||
|
return pass, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt the config file
|
// Encrypt the config file
|
||||||
func Encrypt(src io.Reader, dst io.Writer) error {
|
func Encrypt(src io.Reader, dst io.Writer) error {
|
||||||
if len(configKey) == 0 {
|
if len(configKey) == 0 {
|
||||||
|
@ -113,3 +113,29 @@ func TestConfigLoadEncryptedFailures(t *testing.T) {
|
|||||||
err = config.Data().Load()
|
err = config.Data().Load()
|
||||||
assert.Equal(t, config.ErrorConfigFileNotFound, err)
|
assert.Equal(t, config.ErrorConfigFileNotFound, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetPasswordCommand(t *testing.T) {
|
||||||
|
ctx, ci := fs.AddConfig(context.Background())
|
||||||
|
|
||||||
|
// Not configured
|
||||||
|
ci.PasswordCommand = fs.SpaceSepList{}
|
||||||
|
pass, err := config.GetPasswordCommand(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "", pass)
|
||||||
|
|
||||||
|
// With password - happy path
|
||||||
|
ci.PasswordCommand = fs.SpaceSepList{"echo", "asdf"}
|
||||||
|
pass, err = config.GetPasswordCommand(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "asdf", pass)
|
||||||
|
|
||||||
|
// Empty password returned
|
||||||
|
ci.PasswordCommand = fs.SpaceSepList{"echo", ""}
|
||||||
|
_, err = config.GetPasswordCommand(ctx)
|
||||||
|
assert.ErrorContains(t, err, "returned empty string")
|
||||||
|
|
||||||
|
// Error when running command
|
||||||
|
ci.PasswordCommand = fs.SpaceSepList{"XXX non-existent command XXX", ""}
|
||||||
|
_, err = config.GetPasswordCommand(ctx)
|
||||||
|
assert.ErrorContains(t, err, "not found")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user