mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 16:34:30 +01:00
sftp: fix using key_use_agent and key_file together needing private key file
When using ssh-agent to hold multiple keys, it is common practice to configure openssh to use a specific key by setting the corresponding public key as the `IdentityFile`. This change makes a similar behavior possible in rclone by having it parse the `key_file` config as the public key when `key_use_agent` is `true`. rclone already attempted this behavior before this change, but it assumed that `key_file` is the private key and that the public key is specified in `${key_file}.pub`. So for parity with the openssh behavior, this change makes rclone first attempt to read the public key from `${key_file}.pub` as before (for the sake of backward compatibility), then fall back to reading it from `key_file`. Fixes #6791
This commit is contained in:
parent
e5a1bcb1ce
commit
9f8357ada7
@ -10,6 +10,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
iofs "io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -782,10 +783,32 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
|||||||
return nil, fmt.Errorf("couldn't read ssh agent signers: %w", err)
|
return nil, fmt.Errorf("couldn't read ssh agent signers: %w", err)
|
||||||
}
|
}
|
||||||
if keyFile != "" {
|
if keyFile != "" {
|
||||||
|
// If `opt.KeyUseAgent` is false, then it's expected that `opt.KeyFile` contains the private key
|
||||||
|
// and `${opt.KeyFile}.pub` contains the public key.
|
||||||
|
//
|
||||||
|
// If `opt.KeyUseAgent` is true, then it's expected that `opt.KeyFile` contains the public key.
|
||||||
|
// This is how it works with openssh; the `IdentityFile` in openssh config points to the public key.
|
||||||
|
// It's not necessary to specify the public key explicitly when using ssh-agent, since openssh and rclone
|
||||||
|
// will try all the keys they find in the ssh-agent until they find one that works. But just like
|
||||||
|
// `IdentityFile` is used in openssh config to limit the search to one specific key, so does
|
||||||
|
// `opt.KeyFile` in rclone config limit the search to that specific key.
|
||||||
|
//
|
||||||
|
// However, previous versions of rclone would always expect to find the public key in
|
||||||
|
// `${opt.KeyFile}.pub` even if `opt.KeyUseAgent` was true. So for the sake of backward compatibility
|
||||||
|
// we still first attempt to read the public key from `${opt.KeyFile}.pub`. But if it fails with
|
||||||
|
// an `fs.ErrNotExist` then we also try to read the public key from `opt.KeyFile`.
|
||||||
pubBytes, err := os.ReadFile(keyFile + ".pub")
|
pubBytes, err := os.ReadFile(keyFile + ".pub")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read public key file: %w", err)
|
if errors.Is(err, iofs.ErrNotExist) && opt.KeyUseAgent {
|
||||||
|
pubBytes, err = os.ReadFile(keyFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read public key file: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("failed to read public key file: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes)
|
pub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse public key file: %w", err)
|
return nil, fmt.Errorf("failed to parse public key file: %w", err)
|
||||||
@ -807,8 +830,8 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load key file if specified
|
// Load key file as a private key, if specified. This is only needed when not using an ssh agent.
|
||||||
if keyFile != "" || opt.KeyPem != "" {
|
if (keyFile != "" && !opt.KeyUseAgent) || opt.KeyPem != "" {
|
||||||
var key []byte
|
var key []byte
|
||||||
if opt.KeyPem == "" {
|
if opt.KeyPem == "" {
|
||||||
key, err = os.ReadFile(keyFile)
|
key, err = os.ReadFile(keyFile)
|
||||||
|
Loading…
Reference in New Issue
Block a user