mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			Merge tag 'v0.8.20' into xc-bigfile-EOF
This commit is contained in:
		
						commit
						0c1d5e036e
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
VERSION := 0.8.19
 | 
			
		||||
VERSION := 0.8.20
 | 
			
		||||
.PHONY: lint vis clean common client server passwd subpkgs install uninstall reinstall
 | 
			
		||||
 | 
			
		||||
## Tag version of binaries with build info wrt.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ Currently supported session algorithms:
 | 
			
		|||
* Twofish-128
 | 
			
		||||
* Blowfish-64
 | 
			
		||||
* CryptMTv1 (64bit) (https://eprint.iacr.org/2005/165.pdf)
 | 
			
		||||
* ChaCha20 (https://github.com/aead/chacha20)
 | 
			
		||||
 | 
			
		||||
[HMAC]
 | 
			
		||||
* HMAC-SHA256
 | 
			
		||||
| 
						 | 
				
			
			@ -183,6 +184,8 @@ xc uses a 'tarpipe' to send file data over the encrypted channel. Use the -d fla
 | 
			
		|||
 | 
			
		||||
NOTE: Renaming while copying (eg., 'cp /foo/bar/fileA ./fileB') is NOT supported. Put another way, the destination (whether local or remote) must ALWAYS be a directory.
 | 
			
		||||
 | 
			
		||||
If the 'pv' pipeview utility is available (http://www.ivarch.com/programs/pv.shtml) file transfer progress and bandwidth control will be available (suppress the former with the -q option, set the latter with -L <bytes_per_second>).
 | 
			
		||||
 | 
			
		||||
### Tunnels
 | 
			
		||||
 | 
			
		||||
Simple tunnels (client -> server, no reverse tunnels for now) are supported.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										134
									
								
								xs/xs.go
								
								
								
								
							
							
						
						
									
										134
									
								
								xs/xs.go
								
								
								
								
							| 
						 | 
				
			
			@ -240,21 +240,47 @@ func GetSize() (cols, rows int, err error) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// doCopyMode begins a secure xs local<->remote file copy operation.
 | 
			
		||||
//
 | 
			
		||||
// TODO: reduce gocyclo
 | 
			
		||||
func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, rec *xs.Session) (exitStatus uint32, err error) {
 | 
			
		||||
	if remoteDest {
 | 
			
		||||
		log.Println("local files:", files, "remote filepath:", string(rec.Cmd()))
 | 
			
		||||
func buildCmdRemoteToLocal(copyQuiet bool, copyLimitBPS uint, destPath, files string) (captureStderr bool, cmd string, args []string) {
 | 
			
		||||
	// Detect if we have 'pv'
 | 
			
		||||
	// pipeview http://www.ivarch.com/programs/pv.shtml
 | 
			
		||||
	// and use it for nice client progress display.
 | 
			
		||||
	_, pverr := os.Stat("/usr/bin/pv")
 | 
			
		||||
	if pverr != nil {
 | 
			
		||||
		_, pverr = os.Stat("/usr/local/bin/pv")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		var c *exec.Cmd
 | 
			
		||||
	if copyQuiet || pverr != nil {
 | 
			
		||||
		// copyQuiet and copyLimitBPS are not applicable in dumb copy mode
 | 
			
		||||
		captureStderr = true
 | 
			
		||||
		cmd = "/bin/tar"
 | 
			
		||||
 | 
			
		||||
		//os.Clearenv()
 | 
			
		||||
		//os.Setenv("HOME", u.HomeDir)
 | 
			
		||||
		//os.Setenv("TERM", "vt102") // TODO: server or client option?
 | 
			
		||||
		args = []string{"-xz", "-C", destPath}
 | 
			
		||||
} else {
 | 
			
		||||
		// TODO: Query remote side for total file/dir size
 | 
			
		||||
		bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d ", copyLimitBPS)
 | 
			
		||||
		displayOpts := " -f -pr "
 | 
			
		||||
		cmd = "/bin/bash"
 | 
			
		||||
		args = []string{"-c", "pv " + displayOpts + bandwidthInBytesPerSec + "| tar -xz -C " + destPath}
 | 
			
		||||
	}
 | 
			
		||||
	log.Printf("[%v %v]\n", cmd, args)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		cmdName := "/bin/tar"
 | 
			
		||||
		cmdArgs := []string{"-cz", "-f", "/dev/stdout"}
 | 
			
		||||
func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (captureStderr bool, cmd string, args []string) {
 | 
			
		||||
	// Detect if we have 'pv'
 | 
			
		||||
	// pipeview http://www.ivarch.com/programs/pv.shtml
 | 
			
		||||
	// and use it for nice client progress display.
 | 
			
		||||
	_, pverr := os.Stat("/usr/bin/pv")
 | 
			
		||||
	if pverr != nil {
 | 
			
		||||
		_, pverr = os.Stat("/usr/local/bin/pv")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if pverr != nil {
 | 
			
		||||
		// copyQuiet and copyLimitBPS are not applicable in dumb copy mode
 | 
			
		||||
 | 
			
		||||
		captureStderr = true
 | 
			
		||||
		cmd = "/bin/tar"
 | 
			
		||||
		args = []string{"-cz", "-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
 | 
			
		||||
| 
						 | 
				
			
			@ -272,22 +298,70 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, rec *xs.Session
 | 
			
		|||
			v, _ = filepath.Abs(v) // #nosec
 | 
			
		||||
			dirTmp, fileTmp := path.Split(v)
 | 
			
		||||
			if dirTmp == "" {
 | 
			
		||||
				cmdArgs = append(cmdArgs, fileTmp)
 | 
			
		||||
				args = append(args, fileTmp)
 | 
			
		||||
			} else {
 | 
			
		||||
				cmdArgs = append(cmdArgs, "-C", dirTmp, fileTmp)
 | 
			
		||||
				args = append(args, "-C", dirTmp, fileTmp)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		captureStderr = copyQuiet
 | 
			
		||||
		bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d", copyLimitBPS)
 | 
			
		||||
		displayOpts := " -f -pr "
 | 
			
		||||
		cmd = "/bin/bash"
 | 
			
		||||
		args = []string{"-c", "/bin/tar -cz -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 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) // #nosec
 | 
			
		||||
			dirTmp, fileTmp := path.Split(v)
 | 
			
		||||
			if dirTmp == "" {
 | 
			
		||||
				args[1] = args[1] + fileTmp + " "
 | 
			
		||||
			} else {
 | 
			
		||||
				args[1] = args[1] + " -C " + dirTmp + " " + fileTmp + " "
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		args[1] = args[1] + "| pv" + displayOpts + bandwidthInBytesPerSec + " -s $(du -cb " + files + " | tail -1 | cut -f 1) -c"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		log.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
 | 
			
		||||
		// (as this isn't input from a shell) (right? -rlm 20180823)
 | 
			
		||||
	log.Printf("[%v %v]\n", cmd, args)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// doCopyMode begins a secure xs local<->remote file copy operation.
 | 
			
		||||
//
 | 
			
		||||
// TODO: reduce gocyclo
 | 
			
		||||
func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, copyLimitBPS uint, rec *xs.Session) (exitStatus uint32, err error) {
 | 
			
		||||
	if remoteDest {
 | 
			
		||||
		log.Println("local files:", files, "remote filepath:", string(rec.Cmd()))
 | 
			
		||||
 | 
			
		||||
		var c *exec.Cmd
 | 
			
		||||
 | 
			
		||||
		//os.Clearenv()
 | 
			
		||||
		//os.Setenv("HOME", u.HomeDir)
 | 
			
		||||
		//os.Setenv("TERM", "vt102") // TODO: server or client option?
 | 
			
		||||
 | 
			
		||||
		captureStderr, cmdName, cmdArgs := buildCmdLocalToRemote(copyQuiet, copyLimitBPS, strings.TrimSpace(files))
 | 
			
		||||
		c = exec.Command(cmdName, cmdArgs...) // #nosec
 | 
			
		||||
		c.Dir, _ = os.Getwd()                 // #nosec
 | 
			
		||||
		log.Println("[wd:", c.Dir, "]")
 | 
			
		||||
		c.Stdout = conn
 | 
			
		||||
		stdErrBuffer := new(bytes.Buffer)
 | 
			
		||||
		c.Stderr = stdErrBuffer
 | 
			
		||||
		if captureStderr {
 | 
			
		||||
			c.Stderr = stdErrBuffer
 | 
			
		||||
		} else {
 | 
			
		||||
			c.Stderr = os.Stderr
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Start the command (no pty)
 | 
			
		||||
		err = c.Start() // returns immediately
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +394,9 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, rec *xs.Session
 | 
			
		|||
					// an ExitStatus() method with the same signature.
 | 
			
		||||
					if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
 | 
			
		||||
						exitStatus = uint32(status.ExitStatus())
 | 
			
		||||
						fmt.Print(stdErrBuffer)
 | 
			
		||||
						if captureStderr {
 | 
			
		||||
							fmt.Print(stdErrBuffer)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -353,17 +429,11 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, rec *xs.Session
 | 
			
		|||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Println("remote filepath:", string(rec.Cmd()), "local files:", files)
 | 
			
		||||
		var c *exec.Cmd
 | 
			
		||||
 | 
			
		||||
		cmdName := "/bin/tar"
 | 
			
		||||
		destPath := files
 | 
			
		||||
 | 
			
		||||
		cmdArgs := []string{"-xz", "-C", destPath}
 | 
			
		||||
		log.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
 | 
			
		||||
		// (as this isn't input from a shell) (right? -rlm 20180823)
 | 
			
		||||
		//cmdArgs := []string{"-xvz", "-C", destPath, `--xform=s#.*/\(.*\)#\1#`}
 | 
			
		||||
		_, cmdName, cmdArgs := buildCmdRemoteToLocal(copyQuiet, copyLimitBPS, destPath, strings.TrimSpace(files))
 | 
			
		||||
 | 
			
		||||
		var c *exec.Cmd
 | 
			
		||||
		c = exec.Command(cmdName, cmdArgs...) // #nosec
 | 
			
		||||
		c.Stdin = conn
 | 
			
		||||
		c.Stdout = os.Stdout
 | 
			
		||||
| 
						 | 
				
			
			@ -612,6 +682,8 @@ func main() {
 | 
			
		|||
 | 
			
		||||
	var copySrc []byte
 | 
			
		||||
	var copyDst string
 | 
			
		||||
	var copyQuiet bool
 | 
			
		||||
	var copyLimitBPS uint
 | 
			
		||||
 | 
			
		||||
	var authCookie string
 | 
			
		||||
	var chaffEnabled bool
 | 
			
		||||
| 
						 | 
				
			
			@ -649,6 +721,8 @@ func main() {
 | 
			
		|||
		shellMode = true
 | 
			
		||||
		flag.Usage = usageShell
 | 
			
		||||
	} else {
 | 
			
		||||
		flag.BoolVar(©Quiet, "q", false, "do not output progress bar during copy")
 | 
			
		||||
		flag.UintVar(©LimitBPS, "L", 8589934592, "copy max rate in bytes per sec")
 | 
			
		||||
		flag.Usage = usageCp
 | 
			
		||||
	}
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
| 
						 | 
				
			
			@ -932,7 +1006,7 @@ func main() {
 | 
			
		|||
			launchTuns(&conn, remoteHost, tunSpecStr)
 | 
			
		||||
			doShellMode(isInteractive, &conn, oldState, rec)
 | 
			
		||||
		} else { // copyMode
 | 
			
		||||
			s, _ := doCopyMode(&conn, pathIsDest, fileArgs, rec) // nolint: errcheck,gosec
 | 
			
		||||
			s, _ := doCopyMode(&conn, pathIsDest, fileArgs, copyQuiet, copyLimitBPS, rec) // nolint: errcheck,gosec
 | 
			
		||||
			rec.SetStatus(s)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue