Steps toward getting remote cp(tar) status back to client

This commit is contained in:
Russ Magee 2018-09-05 21:58:55 -07:00
parent 963d1c8eb2
commit a6979298fd
3 changed files with 30 additions and 23 deletions

View File

@ -437,9 +437,9 @@ func (hc Conn) Read(b []byte) (n int, err error) {
} else if ctrlStatOp == CSOExitStatus { } else if ctrlStatOp == CSOExitStatus {
if len(payloadBytes) > 0 { if len(payloadBytes) > 0 {
*hc.closeStat = uint8(payloadBytes[0]) *hc.closeStat = uint8(payloadBytes[0])
// If remote end is closing (255), reply we're closing ours // If remote end is closing with an error, reply we're closing ours
if payloadBytes[0] == 255 { if payloadBytes[0] != 0 {
hc.SetStatus(255) hc.SetStatus(payloadBytes[0])
hc.Close() hc.Close()
} }
} else { } else {

View File

@ -8,6 +8,7 @@
package main package main
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -142,11 +143,8 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
c.Dir, _ = os.Getwd() c.Dir, _ = os.Getwd()
fmt.Println("[wd:", c.Dir, "]") fmt.Println("[wd:", c.Dir, "]")
c.Stdout = conn c.Stdout = conn
// Stderr sinkholing is important. Any extraneous output to tarpipe stdErrBuffer := new(bytes.Buffer)
// messes up remote side as it's expecting pure tar data. c.Stderr = stdErrBuffer
// (For example, if user specifies abs paths, tar outputs
// "Removing leading '/' from path names")
c.Stderr = nil
// Start the command (no pty) // Start the command (no pty)
err = c.Start() // returns immediately err = c.Start() // returns immediately
@ -165,12 +163,13 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
exitStatus = status.ExitStatus() exitStatus = status.ExitStatus()
log.Printf("Exit Status: %d", exitStatus) log.Printf("Exit Status: %d", exitStatus)
fmt.Print(stdErrBuffer)
} }
} }
} }
//fmt.Println("*** client->server cp finished ***") //fmt.Println("*** client->server cp finished ***")
// Signal other end transfer is complete // Signal other end transfer is complete
conn.WritePacket([]byte{byte(255)}, hkexnet.CSOExitStatus) conn.WritePacket([]byte{byte(rec.status)}, hkexnet.CSOExitStatus)
_, _ = conn.Read(nil /*ackByte*/) _, _ = conn.Read(nil /*ackByte*/)
} }
} else { } else {

View File

@ -8,6 +8,7 @@
package main package main
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -157,11 +158,14 @@ func runServerToClientCopyAs(who string, conn hkexnet.Conn, srcPath string, chaf
c.SysProcAttr = &syscall.SysProcAttr{} c.SysProcAttr = &syscall.SysProcAttr{}
c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
c.Stdout = conn c.Stdout = conn
// Stderr sinkholing is important. Any extraneous output to tarpipe // Stderr sinkholing (or buffering to something other than stdout)
// messes up remote side as it's expecting pure tar data. // is important. Any extraneous output to tarpipe messes up remote
// side as it's expecting pure tar data.
// (For example, if user specifies abs paths, tar outputs // (For example, if user specifies abs paths, tar outputs
// "Removing leading '/' from path names") // "Removing leading '/' from path names")
c.Stderr = nil stdErrBuffer := new(bytes.Buffer)
c.Stderr = stdErrBuffer
//c.Stderr = nil
if chaffing { if chaffing {
conn.EnableChaff() conn.EnableChaff()
@ -189,6 +193,11 @@ func runServerToClientCopyAs(who string, conn hkexnet.Conn, srcPath string, chaf
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
exitStatus = status.ExitStatus() exitStatus = status.ExitStatus()
log.Printf("Exit Status: %d", exitStatus) log.Printf("Exit Status: %d", exitStatus)
// TODO: send stdErrBuffer to client via specific packet
// type so it can inform user
if len(stdErrBuffer.Bytes()) > 0 {
fmt.Print("TODO: (stderrBuffer to client):", stdErrBuffer)
}
} }
} }
} }
@ -217,6 +226,7 @@ func runShellAs(who string, cmd string, interactive bool, conn hkexnet.Conn, cha
// Investigate -- rlm 2018-01-26) // Investigate -- rlm 2018-01-26)
os.Clearenv() os.Clearenv()
os.Setenv("HOME", u.HomeDir) os.Setenv("HOME", u.HomeDir)
//os.Setenv("SHELL", "/bin/bash")
os.Setenv("TERM", "vt102") // TODO: server or client option? os.Setenv("TERM", "vt102") // TODO: server or client option?
var c *exec.Cmd var c *exec.Cmd
@ -262,8 +272,9 @@ func runShellAs(who string, cmd string, interactive bool, conn hkexnet.Conn, cha
_, e := io.Copy(ptmx, conn) _, e := io.Copy(ptmx, conn)
if e != nil { if e != nil {
log.Println("** stdin->pty ended **:", e.Error()) log.Println("** stdin->pty ended **:", e.Error())
} else {
log.Println("*** stdin->pty goroutine done ***")
} }
fmt.Println("*** stdin->pty goroutine done ***")
}() }()
if chaffing { if chaffing {
@ -284,10 +295,11 @@ func runShellAs(who string, cmd string, interactive bool, conn hkexnet.Conn, cha
_, e := io.Copy(conn, ptmx) _, e := io.Copy(conn, ptmx)
if e != nil { if e != nil {
log.Println("** pty->stdout ended **:", e.Error()) log.Println("** pty->stdout ended **:", e.Error())
} else {
// The above io.Copy() will exit when the command attached
// to the pty exits
log.Println("*** pty->stdout goroutine done ***")
} }
// The above io.Copy() will exit when the command attached
// to the pty exits
fmt.Println("*** pty->stdout goroutine done ***")
}() }()
if err := c.Wait(); err != nil { if err := c.Wait(); err != nil {
@ -486,8 +498,6 @@ func main() {
} else if rec.op[0] == 'D' { } else if rec.op[0] == 'D' {
// File copy (destination) operation - client copy to server // File copy (destination) operation - client copy to server
log.Printf("[Client->Server copy]\n") log.Printf("[Client->Server copy]\n")
// TODO: call function with hc, rec.cmd, chaffEnabled etc.
// func hooks tar cmd right-half of pipe to hc Reader
addr := hc.RemoteAddr() addr := hc.RemoteAddr()
hname := strings.Split(addr.String(), ":")[0] hname := strings.Split(addr.String(), ":")[0]
log.Printf("[Running copy for [%s@%s]]\n", rec.who, hname) log.Printf("[Running copy for [%s@%s]]\n", rec.who, hname)
@ -499,13 +509,11 @@ func main() {
log.Printf("[Error spawning cp for %s@%s]\n", rec.who, hname) log.Printf("[Error spawning cp for %s@%s]\n", rec.who, hname)
} else { } else {
log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus) log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus)
hc.SetStatus(uint8(cmdStatus))
} }
hc.SetStatus(uint8(cmdStatus))
} else if rec.op[0] == 'S' { } else if rec.op[0] == 'S' {
// File copy (src) operation - server copy to client // File copy (src) operation - server copy to client
log.Printf("[Server->Client copy]\n") log.Printf("[Server->Client copy]\n")
// TODO: call function to copy rec.cmd (file list) to
// tar cmd left-half of pipeline to hc.Writer ?
addr := hc.RemoteAddr() addr := hc.RemoteAddr()
hname := strings.Split(addr.String(), ":")[0] hname := strings.Split(addr.String(), ":")[0]
log.Printf("[Running copy for [%s@%s]]\n", rec.who, hname) log.Printf("[Running copy for [%s@%s]]\n", rec.who, hname)
@ -517,10 +525,10 @@ func main() {
log.Printf("[Error spawning cp for %s@%s]\n", rec.who, hname) log.Printf("[Error spawning cp for %s@%s]\n", rec.who, hname)
} else { } else {
log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus) log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus)
hc.SetStatus(uint8(cmdStatus))
} }
hc.SetStatus(uint8(cmdStatus))
// Signal other end transfer is complete // Signal other end transfer is complete
hc.WritePacket([]byte{byte(255)}, hkexnet.CSOExitStatus) hc.WritePacket([]byte{byte(cmdStatus)}, hkexnet.CSOExitStatus)
//fmt.Println("Waiting for EOF from other end.") //fmt.Println("Waiting for EOF from other end.")
//ackByte := make([]byte, 1, 1) //ackByte := make([]byte, 1, 1)
_, _ = hc.Read(nil /*ackByte*/) _, _ = hc.Read(nil /*ackByte*/)