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?)
This commit is contained in:
Russ Magee 2018-09-01 10:20:33 -07:00
parent 022db4956c
commit 52ea229118
3 changed files with 27 additions and 14 deletions

View File

@ -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) log.Printf("[Insane payloadLen:%v]\n", payloadLen)
hc.Close() hc.Close()
return 1, errors.New("Insane payloadLen") 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 // Would be nice to determine if the mutex scope
// could be tightened. // could be tightened.
hc.m.Lock() hc.m.Lock()
{ for uint32(len(b)) > 0 {
log.Printf(" :>ptext:\r\n%s\r\n", hex.Dump(b))
payloadLen = uint32(len(b)) 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 // Calculate hmac on payload
hc.wm.Write(b) hc.wm.Write(b[0:payloadLen])
hmacOut = hc.wm.Sum(nil)[0:4] hmacOut = hc.wm.Sum(nil)[0:4]
log.Printf(" (%04x> HMAC(o):%s\r\n", payloadLen, hex.EncodeToString(hmacOut)) 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 // The StreamWriter acts like a pipe, forwarding whatever is
// written to it through the cipher, encrypting as it goes // written to it through the cipher, encrypting as it goes
ws := &cipher.StreamWriter{S: hc.w, W: &wb} ws := &cipher.StreamWriter{S: hc.w, W: &wb}
_, err = ws.Write(b) _, err = ws.Write(b[0:payloadLen])
if err != nil { if err != nil {
panic(err) panic(err)
} }
log.Printf(" ->ctext:\r\n%s\r\n", hex.Dump(wb.Bytes())) log.Printf(" ->ctext:\r\n%s\r\n", hex.Dump(wb.Bytes()))
ctrlStatOp := op ctrlStatOp := op
err = binary.Write(hc.c, binary.BigEndian, &ctrlStatOp) err = binary.Write(hc.c, binary.BigEndian, &ctrlStatOp)
if err == nil { if err == nil {
// Write hmac LSB, payloadLen followed by payload // 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() hc.m.Unlock()

View File

@ -17,6 +17,7 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path" "path"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
"sync" "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? //os.Setenv("TERM", "vt102") // TODO: server or client option?
cmdName := "/bin/tar" cmdName := "/bin/tar"
cmdArgs := []string{"-cz", "-f", "/dev/stdout"} cmdArgs := []string{"-c", "-f", "/dev/stdout"}
files = strings.TrimSpace(files) files = strings.TrimSpace(files)
// Awesome fact: tar actually can take multiple -C args, and // Awesome fact: tar actually can take multiple -C args, and
// changes to the dest dir *as it sees each one*. This enables // changes to the dest dir *as it sees each one*. This enables
// its use below, where clients can send scattered sets of source // 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. :) // 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 // 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. // packages fileInA, fileInB, and dirC at a single toplevel in the tar.
// The tar authors are/were real smarties :) // 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, " ") { for _, v := range strings.Split(files, " ") {
v, _ = filepath.Abs(v)
dirTmp, fileTmp := path.Split(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) //cmdArgs = append(cmdArgs, v)
} }
@ -171,7 +182,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
cmdName := "/bin/tar" cmdName := "/bin/tar"
destPath := files destPath := files
cmdArgs := []string{"-xz", "-C", destPath} cmdArgs := []string{"-x", "-C", destPath}
fmt.Printf("[%v %v]\n", cmdName, cmdArgs) fmt.Printf("[%v %v]\n", cmdName, cmdArgs)
// NOTE the lack of quotes around --xform option's sed expression. // NOTE the lack of quotes around --xform option's sed expression.
// When args are passed in exec() format, no quoting is required // When args are passed in exec() format, no quoting is required

View File

@ -67,7 +67,7 @@ func runClientToServerCopyAs(who string, conn hkexnet.Conn, fpath string, chaffi
destDir = path.Join(u.HomeDir, fpath) 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. // NOTE the lack of quotes around --xform option's sed expression.
// When args are passed in exec() format, no quoting is required // 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) srcDir, srcBase := path.Split(srcPath)
cmdArgs := []string{"-cz", "-C", srcDir, "-f", "-", srcBase} cmdArgs := []string{"-c", "-C", srcDir, "-f", "-", srcBase}
c = exec.Command(cmdName, cmdArgs...) c = exec.Command(cmdName, cmdArgs...)