diff options
| author | Shulhan <ms@kilabit.info> | 2021-04-05 00:54:35 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-04-05 01:32:55 +0700 |
| commit | 774f7f341eee1de4dd7cf719e88bfee9bcea9570 (patch) | |
| tree | 2817ac69cf1fc90341f9ca3d73ab5fe68b7a65f6 /lib/ssh | |
| parent | a211773aba0da9fbd642c2a4a172cc90efaf02d5 (diff) | |
| download | pakakeh.go-774f7f341eee1de4dd7cf719e88bfee9bcea9570.tar.xz | |
ssh: ask for passphrase if private key is encrypted on generateSigners
In case the private key defined in IdentityFile is encrypted, prompt
for the passphrase on the screen and read it from stdin using
term.ReadPassword().
This changes also remove call to generateSigners on postConfig(),
instead invoke it from NewClient() to minimize multiple calls to
generateSigners().
Diffstat (limited to 'lib/ssh')
| -rw-r--r-- | lib/ssh/client.go | 5 | ||||
| -rw-r--r-- | lib/ssh/config_section.go | 56 |
2 files changed, 49 insertions, 12 deletions
diff --git a/lib/ssh/client.go b/lib/ssh/client.go index d3ae9af6..5e6871c0 100644 --- a/lib/ssh/client.go +++ b/lib/ssh/client.go @@ -31,6 +31,11 @@ func NewClient(cfg *ConfigSection) (cl *Client, err error) { cfg.postConfig("") + err = cfg.generateSigners() + if err != nil { + return nil, err + } + sshConfig := &ssh.ClientConfig{ User: cfg.User, Auth: []ssh.AuthMethod{ diff --git a/lib/ssh/config_section.go b/lib/ssh/config_section.go index ea7132ac..0b98419a 100644 --- a/lib/ssh/config_section.go +++ b/lib/ssh/config_section.go @@ -14,6 +14,7 @@ import ( "strings" "golang.org/x/crypto/ssh" + "golang.org/x/term" ) const ( @@ -135,24 +136,36 @@ func newConfigSection() *ConfigSection { // generateSigners convert the IdentityFile to ssh.Signer for authentication // using PublicKey. // -func (section *ConfigSection) generateSigners() { +func (section *ConfigSection) generateSigners() (err error) { + var ( + logp = "generateSigners" + pkey string + pkeyRaw []byte + signer ssh.Signer + ) + section.signers = make([]ssh.Signer, 0, len(section.IdentityFile)) - for _, pkey := range section.IdentityFile { - pkeyRaw, err := ioutil.ReadFile(pkey) + for _, pkey = range section.IdentityFile { + pkeyRaw, err = ioutil.ReadFile(pkey) if err != nil { - if !errors.Is(err, os.ErrNotExist) { - log.Printf("generateSigners %s: %s", pkey, - err.Error()) + if errors.Is(err, os.ErrNotExist) { + continue } - continue + return fmt.Errorf("%s: %w", logp, err) } - signer, err := ssh.ParsePrivateKey(pkeyRaw) + signer, err = ssh.ParsePrivateKey(pkeyRaw) if err != nil { - log.Printf("generateSigners %s: ParsePrivateKey: %s", - pkey, err.Error()) - continue + _, isMissingPass := err.(*ssh.PassphraseMissingError) + if !isMissingPass { + return fmt.Errorf("%s: %w", logp, err) + } + + signer, err = section.generateSignerWithPassphrase(pkey, pkeyRaw) + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } } if len(section.privateKeyFile) == 0 { @@ -160,6 +173,7 @@ func (section *ConfigSection) generateSigners() { } section.signers = append(section.signers, signer) } + return nil } // @@ -210,8 +224,26 @@ func (section *ConfigSection) postConfig(homeDir string) { "~", homeDir, 1) } } +} + +func (section *ConfigSection) generateSignerWithPassphrase( + pkey string, pkeyRaw []byte, +) (signer ssh.Signer, err error) { + var pass []byte + + fmt.Printf("Enter passphrase for %s:", pkey) + + pass, err = term.ReadPassword(0) + if err != nil { + return nil, err + } + + signer, err = ssh.ParsePrivateKeyWithPassphrase(pkeyRaw, pass) + if err != nil { + return nil, err + } - section.generateSigners() + return signer, nil } func (section *ConfigSection) setAddKeysToAgent(val string) (err error) { |
