sftp: add option to force the usage of an ssh-agent

Also adds the possibility to specify a specific key to request from the
ssh-agent.
This commit is contained in:
Fabian Möller 2019-01-03 12:25:13 +01:00
parent c1998c4efe
commit 0458b961c5
2 changed files with 57 additions and 8 deletions

View file

@ -66,7 +66,7 @@ func init() {
IsPassword: true, IsPassword: true,
}, { }, {
Name: "key_file", Name: "key_file",
Help: "Path to PEM-encoded private key file, leave blank to use ssh-agent.", Help: "Path to PEM-encoded private key file, leave blank or set key-use-agent to use ssh-agent.",
}, { }, {
Name: "key_file_pass", Name: "key_file_pass",
Help: `The passphrase to decrypt the PEM-encoded private key file. Help: `The passphrase to decrypt the PEM-encoded private key file.
@ -74,6 +74,14 @@ func init() {
Only PEM encrypted key files (old OpenSSH format) are supported. Encrypted keys Only PEM encrypted key files (old OpenSSH format) are supported. Encrypted keys
in the new OpenSSH format can't be used.`, in the new OpenSSH format can't be used.`,
IsPassword: true, IsPassword: true,
}, {
Name: "key_use_agent",
Help: `When set forces the usage of the ssh-agent.
When key-file is also set, the ".pub" file of the specified key-file is read and only the associated key is
requested from the ssh-agent. This allows to avoid ` + "`Too many authentication failures for *username*`" + ` errors
when the ssh-agent contains many keys.`,
Default: false,
}, { }, {
Name: "use_insecure_cipher", Name: "use_insecure_cipher",
Help: "Enable the use of the aes128-cbc cipher. This cipher is insecure and may allow plaintext data to be recovered by an attacker.", Help: "Enable the use of the aes128-cbc cipher. This cipher is insecure and may allow plaintext data to be recovered by an attacker.",
@ -130,6 +138,7 @@ type Options struct {
Pass string `config:"pass"` Pass string `config:"pass"`
KeyFile string `config:"key_file"` KeyFile string `config:"key_file"`
KeyFilePass string `config:"key_file_pass"` KeyFilePass string `config:"key_file_pass"`
KeyUseAgent bool `config:"key_use_agent"`
UseInsecureCipher bool `config:"use_insecure_cipher"` UseInsecureCipher bool `config:"use_insecure_cipher"`
DisableHashCheck bool `config:"disable_hashcheck"` DisableHashCheck bool `config:"disable_hashcheck"`
AskPassword bool `config:"ask_password"` AskPassword bool `config:"ask_password"`
@ -334,7 +343,7 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
} }
// Add ssh agent-auth if no password or file specified // Add ssh agent-auth if no password or file specified
if opt.Pass == "" && opt.KeyFile == "" { if (opt.Pass == "" && opt.KeyFile == "") || opt.KeyUseAgent {
sshAgentClient, _, err := sshagent.New() sshAgentClient, _, err := sshagent.New()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "couldn't connect to ssh-agent") return nil, errors.Wrap(err, "couldn't connect to ssh-agent")
@ -343,7 +352,30 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "couldn't read ssh agent signers") return nil, errors.Wrap(err, "couldn't read ssh agent signers")
} }
sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(signers...)) if opt.KeyFile != "" {
pubBytes, err := ioutil.ReadFile(opt.KeyFile + ".pub")
if err != nil {
return nil, errors.Wrap(err, "failed to read public key file")
}
pub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes)
if err != nil {
return nil, errors.Wrap(err, "failed to parse public key file")
}
pubM := pub.Marshal()
found := false
for _, s := range signers {
if bytes.Equal(pubM, s.PublicKey().Marshal()) {
sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(s))
found = true
break
}
}
if !found {
return nil, errors.New("private key not found in the ssh-agent")
}
} else {
sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(signers...))
}
} }
// Load key file if specified // Load key file if specified

View file

@ -124,11 +124,15 @@ The SFTP remote supports three authentication methods:
* Key file * Key file
* ssh-agent * ssh-agent
Key files should be unencrypted PEM-encoded private key files. For Key files should be PEM-encoded private key files. For instance `/home/$USER/.ssh/id_rsa`.
instance `/home/$USER/.ssh/id_rsa`. Only unencrypted OpenSSH or PEM encrypted files are supported.
If you don't specify `pass` or `key_file` then rclone will attempt to If you don't specify `pass` or `key_file` then rclone will attempt to contact an ssh-agent.
contact an ssh-agent.
You can also specify `key_use_agent` to force the usage of an ssh-agent. In this case
`key_file` can also be specified to force the usage of a specific key in the ssh-agent.
Using an ssh-agent is the only way to load encrypted OpenSSH keys at the moment.
If you set the `--sftp-ask-password` option, rclone will prompt for a If you set the `--sftp-ask-password` option, rclone will prompt for a
password when needed and no password has been configured. password when needed and no password has been configured.
@ -204,7 +208,7 @@ SSH password, leave blank to use ssh-agent.
#### --sftp-key-file #### --sftp-key-file
Path to PEM-encoded private key file, leave blank to use ssh-agent. Path to PEM-encoded private key file, leave blank or set key-use-agent to use ssh-agent.
- Config: key_file - Config: key_file
- Env Var: RCLONE_SFTP_KEY_FILE - Env Var: RCLONE_SFTP_KEY_FILE
@ -223,6 +227,19 @@ in the new OpenSSH format can't be used.
- Type: string - Type: string
- Default: "" - Default: ""
#### --sftp-key-use-agent
When set forces the usage of the ssh-agent.
When key-file is also set, the ".pub" file of the specified key-file is read and only the associated key is
requested from the ssh-agent. This allows to avoid `Too many authentication failures for *username*` errors
when the ssh-agent contains many keys.
- Config: key_use_agent
- Env Var: RCLONE_SFTP_KEY_USE_AGENT
- Type: bool
- Default: false
#### --sftp-use-insecure-cipher #### --sftp-use-insecure-cipher
Enable the use of the aes128-cbc cipher. This cipher is insecure and may allow plaintext data to be recovered by an attacker. Enable the use of the aes128-cbc cipher. This cipher is insecure and may allow plaintext data to be recovered by an attacker.