Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sftp: Allow password entry #1270

Merged
merged 2 commits into from
Sep 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions cmd/restic/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,27 @@ import (

var cleanupHandlers struct {
sync.Mutex
list []func() error
done bool
list []func() error
done bool
sigintCh chan os.Signal
}

var stderr = os.Stderr

func init() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
cleanupHandlers.sigintCh = make(chan os.Signal)
go CleanupHandler(cleanupHandlers.sigintCh)
InstallSignalHandler()
}

// InstallSignalHandler listens for SIGINT and triggers the cleanup handlers.
func InstallSignalHandler() {
signal.Notify(cleanupHandlers.sigintCh, syscall.SIGINT)
}

go CleanupHandler(c)
// SuspendSignalHandler removes the signal handler for SIGINT.
func SuspendSignalHandler() {
signal.Reset(syscall.SIGINT)
}

// AddCleanupHandler adds the function f to the list of cleanup handlers so
Expand Down
4 changes: 2 additions & 2 deletions cmd/restic/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ func open(s string, opts options.Options) (restic.Backend, error) {
case "local":
be, err = local.Open(cfg.(local.Config))
case "sftp":
be, err = sftp.Open(cfg.(sftp.Config))
be, err = sftp.Open(cfg.(sftp.Config), SuspendSignalHandler, InstallSignalHandler)
case "s3":
be, err = s3.Open(cfg.(s3.Config))
case "gs":
Expand Down Expand Up @@ -522,7 +522,7 @@ func create(s string, opts options.Options) (restic.Backend, error) {
case "local":
return local.Create(cfg.(local.Config))
case "sftp":
return sftp.Create(cfg.(sftp.Config))
return sftp.Create(cfg.(sftp.Config), SuspendSignalHandler, InstallSignalHandler)
case "s3":
return s3.Create(cfg.(s3.Config))
case "gs":
Expand Down
2 changes: 1 addition & 1 deletion internal/backend/sftp/layout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestLayout(t *testing.T) {
Command: fmt.Sprintf("%q -e", sftpServer),
Path: repo,
Layout: test.layout,
})
}, nil, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
31 changes: 19 additions & 12 deletions internal/backend/sftp/sftp.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var _ restic.Backend = &SFTP{}

const defaultLayout = "default"

func startClient(program string, args ...string) (*SFTP, error) {
func startClient(preExec, postExec func(), program string, args ...string) (*SFTP, error) {
debug.Log("start client %v %v", program, args)
// Connect to a remote host and request the sftp subsystem via the 'ssh'
// command. This assumes that passwordless login is correctly configured.
Expand All @@ -55,9 +55,6 @@ func startClient(program string, args ...string) (*SFTP, error) {
}
}()

// ignore signals sent to the parent (e.g. SIGINT)
cmd.SysProcAttr = ignoreSigIntProcAttr()

// get stdin and stdout
wr, err := cmd.StdinPipe()
if err != nil {
Expand All @@ -68,11 +65,19 @@ func startClient(program string, args ...string) (*SFTP, error) {
return nil, errors.Wrap(err, "cmd.StdoutPipe")
}

if preExec != nil {
preExec()
}

// start the process
if err := cmd.Start(); err != nil {
return nil, errors.Wrap(err, "cmd.Start")
}

if postExec != nil {
postExec()
}

// wait in a different goroutine
ch := make(chan error, 1)
go func() {
Expand Down Expand Up @@ -104,16 +109,17 @@ func (r *SFTP) clientError() error {
}

// Open opens an sftp backend as described by the config by running
// "ssh" with the appropriate arguments (or cfg.Command, if set).
func Open(cfg Config) (*SFTP, error) {
// "ssh" with the appropriate arguments (or cfg.Command, if set). The function
// preExec is run just before, postExec just after starting a program.
func Open(cfg Config, preExec, postExec func()) (*SFTP, error) {
debug.Log("open backend with config %#v", cfg)

cmd, args, err := buildSSHCommand(cfg)
if err != nil {
return nil, err
}

sftp, err := startClient(cmd, args...)
sftp, err := startClient(preExec, postExec, cmd, args...)
if err != nil {
debug.Log("unable to start program: %v", err)
return nil, err
Expand Down Expand Up @@ -225,15 +231,16 @@ func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
return cmd, args, nil
}

// Create creates an sftp backend as described by the config by running
// "ssh" with the appropriate arguments (or cfg.Command, if set).
func Create(cfg Config) (*SFTP, error) {
// Create creates an sftp backend as described by the config by running "ssh"
// with the appropriate arguments (or cfg.Command, if set). The function
// preExec is run just before, postExec just after starting a program.
func Create(cfg Config, preExec, postExec func()) (*SFTP, error) {
cmd, args, err := buildSSHCommand(cfg)
if err != nil {
return nil, err
}

sftp, err := startClient(cmd, args...)
sftp, err := startClient(preExec, postExec, cmd, args...)
if err != nil {
debug.Log("unable to start program: %v", err)
return nil, err
Expand Down Expand Up @@ -261,7 +268,7 @@ func Create(cfg Config) (*SFTP, error) {
}

// open backend
return Open(cfg)
return Open(cfg, preExec, postExec)
}

// Location returns this backend's location (the directory name).
Expand Down
4 changes: 2 additions & 2 deletions internal/backend/sftp/sftp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ func newTestSuite(t testing.TB) *test.Suite {
// CreateFn is a function that creates a temporary repository for the tests.
Create: func(config interface{}) (restic.Backend, error) {
cfg := config.(sftp.Config)
return sftp.Create(cfg)
return sftp.Create(cfg, nil, nil)
},

// OpenFn is a function that opens a previously created temporary repository.
Open: func(config interface{}) (restic.Backend, error) {
cfg := config.(sftp.Config)
return sftp.Open(cfg)
return sftp.Open(cfg, nil, nil)
},

// CleanupFn removes data created during the tests.
Expand Down
13 changes: 0 additions & 13 deletions internal/backend/sftp/sftp_unix.go

This file was deleted.

11 changes: 0 additions & 11 deletions internal/backend/sftp/sftp_windows.go

This file was deleted.