X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=rpc%2Fdial.go;h=c098714cc0759388dd32e0d723819c4b4c598665;hb=fd97e8019e2ab166d9475ed59782c86247d8430b;hp=ef280191ef57b23ca8f03461a97af206e23ecc67;hpb=7c4e5d64e25acec7209a54a15836b4481c450416;p=safcm%2Fsafcm.git diff --git a/rpc/dial.go b/rpc/dial.go index ef28019..c098714 100644 --- a/rpc/dial.go +++ b/rpc/dial.go @@ -24,22 +24,35 @@ import ( "encoding/hex" "fmt" "io" + "io/fs" "os/exec" "strconv" "strings" "ruderich.org/simon/safcm" - "ruderich.org/simon/safcm/remote" ) -func (c *Conn) DialSSH(user, host string) error { +type SSHConfig struct { + Host string + User string // optional + SshConfig string // optional + + RemoteHelpers fs.FS +} + +func (c *Conn) DialSSH(cfg SSHConfig) error { if c.events == nil { return fmt.Errorf("cannot reuse Conn") } - remote := host - if user != "" { - remote = user + "@" + host + if cfg.RemoteHelpers == nil { + return fmt.Errorf("SSHConfig.RemoteHelpers not set") + } + c.remoteHelpers = cfg.RemoteHelpers + + remote := cfg.Host + if cfg.User != "" { + remote = cfg.User + "@" + cfg.Host } c.debugf("DialSSH: connecting to %q", remote) @@ -48,8 +61,14 @@ func (c *Conn) DialSSH(user, host string) error { // Help debugging by showing executed shell commands opts += "x" } - c.cmd = exec.Command("ssh", remote, "/bin/sh", opts) - c.remote = remote + + c.sshRemote = remote + if cfg.SshConfig != "" { + c.sshOpts = []string{"-F", cfg.SshConfig} + } + c.cmd = exec.Command("ssh", + append(append([]string{}, c.sshOpts...), + c.sshRemote, "/bin/sh", opts)...) stdin, err := c.cmd.StdinPipe() if err != nil { @@ -135,13 +154,13 @@ compat_sha512sum() { // // The target directory must no permit other users to delete our files // or symlink attacks and arbitrary code execution is possible. For - // /tmp this is guaranteed by the sticky bit. Make sure it has the - // proper permissions. + // /tmp this is guaranteed by the sticky bit. The code verifies the + // directory has the proper permissions. // // We cannot use `test -f && test -O` because this is open to TOCTOU // attacks. `stat` gives use the full file state. If the file is owned - // by us and not a symlink then it's safe to use (assuming sticky or - // directory not writable by others). + // by us and not a symlink then it's safe to use (assuming sticky + // directory or directory not writable by others). // // `test -e` is only used to prevent error messages if the file // doesn't exist. It does not guard against any races. @@ -171,7 +190,6 @@ f() { tmp="$(mktemp "$x.XXXXXX")" # Report filename for upload echo "$tmp" - # Wait for upload to complete read unused @@ -181,6 +199,8 @@ f() { rm "$tmp" # Make file executable chmod 0700 "$x" + # Some BSD create files with group wheel in /tmp + chgrp "$(id -g)" "$x" fi exec "$x" sync @@ -195,9 +215,9 @@ f return err } - // Get embedded helper binary - helper, err := remote.Helpers.ReadFile( - fmt.Sprintf("helpers/%s-%s", goos, goarch)) + // Get remote helper binary + helper, err := fs.ReadFile(c.remoteHelpers, + fmt.Sprintf("%s-%s", goos, goarch)) if err != nil { return fmt.Errorf("remote not built for GOOS/GOARCH %s/%s", goos, goarch) @@ -249,12 +269,14 @@ f path = strings.TrimSuffix(path, "\n") c.debugf("DialSSH: uploading new remote to %q at %q", - c.remote, path) + c.sshRemote, path) - cmd := exec.Command("ssh", c.remote, - fmt.Sprintf("cat > %q", path)) + cmd := exec.Command("ssh", + append(append([]string{}, c.sshOpts...), + c.sshRemote, + fmt.Sprintf("cat > %q", path))...) cmd.Stdin = bytes.NewReader(helper) - err = c.handleStderrAsEvents(cmd) + err = c.handleStderrAsEvents(cmd) // cmd.Stderr if err != nil { return err }