From 52ea229118f324c82b79c04edff9091e283b4c87 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Sat, 1 Sep 2018 10:20:33 -0700 Subject: [PATCH] Fixed errors in copy scatter/gather logic. Added block-chunking to hc.Write() to allow writes of larger data blocks TODO: copies of files > hc.Read() block size fails w/incomplete tarfile (last partial block likely incorrectly written or client exits before data is flushed?) --- hkexnet/hkexnet.go | 18 ++++++++++-------- hkexsh/hkexsh.go | 19 +++++++++++++++---- hkexshd/hkexshd.go | 4 ++-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/hkexnet/hkexnet.go b/hkexnet/hkexnet.go index 302835c..04ae9ab 100644 --- a/hkexnet/hkexnet.go +++ b/hkexnet/hkexnet.go @@ -394,7 +394,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { } } - if payloadLen > 16384 { + if payloadLen > 8192 { log.Printf("[Insane payloadLen:%v]\n", payloadLen) hc.Close() return 1, errors.New("Insane payloadLen") @@ -499,13 +499,15 @@ func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) { // Would be nice to determine if the mutex scope // could be tightened. hc.m.Lock() - { - log.Printf(" :>ptext:\r\n%s\r\n", hex.Dump(b)) - + for uint32(len(b)) > 0 { payloadLen = uint32(len(b)) + if payloadLen > 8192 { + payloadLen = 8192 + } + log.Printf(" :>ptext:\r\n%s\r\n", hex.Dump(b[0:payloadLen])) // Calculate hmac on payload - hc.wm.Write(b) + hc.wm.Write(b[0:payloadLen]) hmacOut = hc.wm.Sum(nil)[0:4] log.Printf(" (%04x> HMAC(o):%s\r\n", payloadLen, hex.EncodeToString(hmacOut)) @@ -514,14 +516,13 @@ func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) { // The StreamWriter acts like a pipe, forwarding whatever is // written to it through the cipher, encrypting as it goes ws := &cipher.StreamWriter{S: hc.w, W: &wb} - _, err = ws.Write(b) + _, err = ws.Write(b[0:payloadLen]) if err != nil { panic(err) } log.Printf(" ->ctext:\r\n%s\r\n", hex.Dump(wb.Bytes())) - + ctrlStatOp := op - err = binary.Write(hc.c, binary.BigEndian, &ctrlStatOp) if err == nil { // Write hmac LSB, payloadLen followed by payload @@ -533,6 +534,7 @@ func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) { } } } + b = b[payloadLen:] } hc.m.Unlock() diff --git a/hkexsh/hkexsh.go b/hkexsh/hkexsh.go index 0e37a1e..dcf08fc 100755 --- a/hkexsh/hkexsh.go +++ b/hkexsh/hkexsh.go @@ -17,6 +17,7 @@ import ( "os/exec" "os/user" "path" + "path/filepath" "runtime" "strings" "sync" @@ -107,19 +108,29 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec) //os.Setenv("TERM", "vt102") // TODO: server or client option? cmdName := "/bin/tar" - cmdArgs := []string{"-cz", "-f", "/dev/stdout"} + cmdArgs := []string{"-c", "-f", "/dev/stdout"} files = strings.TrimSpace(files) // Awesome fact: tar actually can take multiple -C args, and // changes to the dest dir *as it sees each one*. This enables // its use below, where clients can send scattered sets of source - // files and dirs to be extraced to a single dest dir server-side, + // files and dirs to be extracted to a single dest dir server-side, // whilst preserving the subtrees of dirs on the other side. :) // Eg., tar -c -f /dev/stdout -C /dirA fileInA -C /some/where/dirB fileInB /foo/dirC // packages fileInA, fileInB, and dirC at a single toplevel in the tar. // The tar authors are/were real smarties :) + // + // This is the 'scatter/gather' logic to allow specification of + // files and dirs in different trees to be deposited in a single + // remote destDir. for _, v := range strings.Split(files, " ") { + v, _ = filepath.Abs(v) dirTmp, fileTmp := path.Split(v) - cmdArgs = append(cmdArgs, "-C", dirTmp, fileTmp) + if dirTmp == "" { + cmdArgs = append(cmdArgs, fileTmp) + } else { + cmdArgs = append(cmdArgs, "-C", dirTmp, fileTmp) + } + //cmdArgs = append(cmdArgs, v) } @@ -171,7 +182,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec) cmdName := "/bin/tar" destPath := files - cmdArgs := []string{"-xz", "-C", destPath} + cmdArgs := []string{"-x", "-C", destPath} fmt.Printf("[%v %v]\n", cmdName, cmdArgs) // NOTE the lack of quotes around --xform option's sed expression. // When args are passed in exec() format, no quoting is required diff --git a/hkexshd/hkexshd.go b/hkexshd/hkexshd.go index a0874c9..eb11dc8 100755 --- a/hkexshd/hkexshd.go +++ b/hkexshd/hkexshd.go @@ -67,7 +67,7 @@ func runClientToServerCopyAs(who string, conn hkexnet.Conn, fpath string, chaffi destDir = path.Join(u.HomeDir, fpath) } - cmdArgs := []string{"-xz", "-C", destDir} + cmdArgs := []string{"-x", "-C", destDir} // NOTE the lack of quotes around --xform option's sed expression. // When args are passed in exec() format, no quoting is required @@ -146,7 +146,7 @@ func runServerToClientCopyAs(who string, conn hkexnet.Conn, srcPath string, chaf } srcDir, srcBase := path.Split(srcPath) - cmdArgs := []string{"-cz", "-C", srcDir, "-f", "-", srcBase} + cmdArgs := []string{"-c", "-C", srcDir, "-f", "-", srcBase} c = exec.Command(cmdName, cmdArgs...)