mirror of https://gogs.blitter.com/RLabs/xs
-Moved recCmd out of hkexsh and hkexshd into hkexsession.go (now abstract Session type)
This commit is contained in:
parent
bff56a2c61
commit
9e803ffc19
|
@ -0,0 +1,88 @@
|
||||||
|
// Session info/routines for the HKExSh
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-2018 Russell Magee
|
||||||
|
// Licensed under the terms of the MIT license (see LICENSE.mit in this
|
||||||
|
// distribution)
|
||||||
|
//
|
||||||
|
// golang implementation by Russ Magee (rmagee_at_gmail.com)
|
||||||
|
|
||||||
|
package hkexsh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
op []byte
|
||||||
|
who []byte
|
||||||
|
cmd []byte
|
||||||
|
authCookie []byte
|
||||||
|
status uint32 // exit status (0-255 is std UNIX status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output Session record as a string. Implements Stringer interface.
|
||||||
|
func (h *Session) String() string {
|
||||||
|
return fmt.Sprintf("hkexsh.Session:\nOp:%v\nWho:%v\nCmd:%v\nAuthCookie:%v\nStatus:%v",
|
||||||
|
h.op, h.who, h.cmd, h.AuthCookie(false), h.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Session) Op() []byte {
|
||||||
|
return h.op
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) SetOp(o []byte) {
|
||||||
|
h.op = o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Session) Who() []byte {
|
||||||
|
return h.who
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) SetWho(w []byte) {
|
||||||
|
h.who = w
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Session) Cmd() []byte {
|
||||||
|
return h.cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) SetCmd(c []byte) {
|
||||||
|
h.cmd = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Session) AuthCookie(reallyShow bool) []byte {
|
||||||
|
if reallyShow {
|
||||||
|
return h.authCookie
|
||||||
|
} else {
|
||||||
|
return []byte("**REDACTED**")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) SetAuthCookie(a []byte) {
|
||||||
|
h.authCookie = a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) ClearAuthCookie() {
|
||||||
|
for i := range h.authCookie {
|
||||||
|
h.authCookie[i] = 0
|
||||||
|
}
|
||||||
|
runtime.GC()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Session) Status() uint32 {
|
||||||
|
return h.status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Session) SetStatus(s uint32) {
|
||||||
|
h.status = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSession(op, who, cmd, authcookie []byte, status uint32) *Session {
|
||||||
|
return &Session{
|
||||||
|
op: op,
|
||||||
|
who: who,
|
||||||
|
cmd: cmd,
|
||||||
|
authCookie: authcookie,
|
||||||
|
status: status}
|
||||||
|
}
|
|
@ -31,14 +31,6 @@ import (
|
||||||
isatty "github.com/mattn/go-isatty"
|
isatty "github.com/mattn/go-isatty"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cmdSpec struct {
|
|
||||||
op []byte
|
|
||||||
who []byte
|
|
||||||
cmd []byte
|
|
||||||
authCookie []byte
|
|
||||||
status uint32 // exit status (0-255 is std UNIX status)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
)
|
)
|
||||||
|
@ -100,9 +92,9 @@ func parseNonSwitchArgs(a []string) (user, host, path string, isDest bool, other
|
||||||
}
|
}
|
||||||
|
|
||||||
// doCopyMode begins a secure hkexsh local<->remote file copy operation.
|
// doCopyMode begins a secure hkexsh local<->remote file copy operation.
|
||||||
func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec) (err error, exitStatus uint32) {
|
func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.Session) (err error, exitStatus uint32) {
|
||||||
if remoteDest {
|
if remoteDest {
|
||||||
log.Println("local files:", files, "remote filepath:", string(rec.cmd))
|
log.Println("local files:", files, "remote filepath:", string(rec.Cmd()))
|
||||||
|
|
||||||
var c *exec.Cmd
|
var c *exec.Cmd
|
||||||
|
|
||||||
|
@ -172,12 +164,12 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
|
||||||
//fmt.Println("*** client->server cp finished ***")
|
//fmt.Println("*** client->server cp finished ***")
|
||||||
// Signal other end transfer is complete
|
// Signal other end transfer is complete
|
||||||
s := make([]byte, 4)
|
s := make([]byte, 4)
|
||||||
binary.BigEndian.PutUint32(s, rec.status)
|
binary.BigEndian.PutUint32(s, rec.Status())
|
||||||
conn.WritePacket(s, hkexnet.CSOExitStatus)
|
conn.WritePacket(s, hkexnet.CSOExitStatus)
|
||||||
_, _ = conn.Read(nil /*ackByte*/)
|
_, _ = conn.Read(nil /*ackByte*/)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Println("remote filepath:", string(rec.cmd), "local files:", files)
|
log.Println("remote filepath:", string(rec.Cmd()), "local files:", files)
|
||||||
var c *exec.Cmd
|
var c *exec.Cmd
|
||||||
|
|
||||||
//os.Clearenv()
|
//os.Clearenv()
|
||||||
|
@ -230,7 +222,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// doShellMode begins an hkexsh shell session (one-shot command or interactive).
|
// doShellMode begins an hkexsh shell session (one-shot command or interactive).
|
||||||
func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State, rec *cmdSpec) {
|
func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State, rec *hkexsh.Session) {
|
||||||
//client reader (from server) goroutine
|
//client reader (from server) goroutine
|
||||||
//Read remote end's stdout
|
//Read remote end's stdout
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
@ -254,8 +246,8 @@ func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rec.status = uint32(conn.GetStatus())
|
rec.SetStatus(uint32(conn.GetStatus()))
|
||||||
log.Println("rec.status:", rec.status)
|
log.Println("rec.status:", rec.Status)
|
||||||
|
|
||||||
if isInteractive {
|
if isInteractive {
|
||||||
log.Println("[* Got EOF *]")
|
log.Println("[* Got EOF *]")
|
||||||
|
@ -522,28 +514,23 @@ func main() {
|
||||||
ab = nil
|
ab = nil
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
}
|
}
|
||||||
|
|
||||||
rec := &cmdSpec{
|
rec := hkexsh.NewSession(op, []byte(uname), []byte(cmdStr), []byte(authCookie),0)
|
||||||
op: op,
|
|
||||||
who: []byte(uname),
|
|
||||||
cmd: []byte(cmdStr),
|
|
||||||
authCookie: []byte(authCookie),
|
|
||||||
status: 0}
|
|
||||||
|
|
||||||
_, err = fmt.Fprintf(conn, "%d %d %d %d\n",
|
_, err = fmt.Fprintf(conn, "%d %d %d %d\n",
|
||||||
len(rec.op), len(rec.who), len(rec.cmd), len(rec.authCookie))
|
len(rec.Op()), len(rec.Who()), len(rec.Cmd()), len(rec.AuthCookie(true)))
|
||||||
|
|
||||||
_, err = conn.Write(rec.op)
|
_, err = conn.Write(rec.Op())
|
||||||
_, err = conn.Write(rec.who)
|
_, err = conn.Write(rec.Who())
|
||||||
_, err = conn.Write(rec.cmd)
|
_, err = conn.Write(rec.Cmd())
|
||||||
_, err = conn.Write(rec.authCookie)
|
_, err = conn.Write(rec.AuthCookie(true))
|
||||||
|
|
||||||
// Read auth reply from server
|
// Read auth reply from server
|
||||||
authReply := make([]byte, 1) // bool: 0 = fail, 1 = pass
|
authReply := make([]byte, 1) // bool: 0 = fail, 1 = pass
|
||||||
_, err = conn.Read(authReply)
|
_, err = conn.Read(authReply)
|
||||||
if authReply[0] == 0 {
|
if authReply[0] == 0 {
|
||||||
fmt.Fprintln(os.Stderr, rejectUserMsg())
|
fmt.Fprintln(os.Stderr, rejectUserMsg())
|
||||||
rec.status = 255
|
rec.SetStatus(255)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Set up chaffing to server
|
// Set up chaffing to server
|
||||||
|
@ -557,16 +544,17 @@ func main() {
|
||||||
if shellMode {
|
if shellMode {
|
||||||
doShellMode(isInteractive, conn, oldState, rec)
|
doShellMode(isInteractive, conn, oldState, rec)
|
||||||
} else { // copyMode
|
} else { // copyMode
|
||||||
_, rec.status = doCopyMode(conn, pathIsDest, fileArgs, rec)
|
_, s := doCopyMode(conn, pathIsDest, fileArgs, rec)
|
||||||
|
rec.SetStatus(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rec.status != 0 {
|
if rec.Status() != 0 {
|
||||||
fmt.Fprintln(os.Stderr, "Remote end exited with status:", rec.status)
|
fmt.Fprintln(os.Stderr, "Remote end exited with status:", rec.Status())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldState != nil {
|
if oldState != nil {
|
||||||
_ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // Best effort.
|
_ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // Best effort.
|
||||||
}
|
}
|
||||||
os.Exit(int(rec.status))
|
os.Exit(int(rec.Status()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -30,14 +29,6 @@ import (
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cmdSpec struct {
|
|
||||||
op []byte
|
|
||||||
who []byte
|
|
||||||
cmd []byte
|
|
||||||
authCookie []byte
|
|
||||||
status int
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
// Perform a client->server copy
|
// Perform a client->server copy
|
||||||
func runClientToServerCopyAs(who string, conn hkexnet.Conn, fpath string, chaffing bool) (err error, exitStatus uint32) {
|
func runClientToServerCopyAs(who string, conn hkexnet.Conn, fpath string, chaffing bool) (err error, exitStatus uint32) {
|
||||||
|
@ -394,138 +385,140 @@ func main() {
|
||||||
defer hc.Close()
|
defer hc.Close()
|
||||||
|
|
||||||
//We use io.ReadFull() here to guarantee we consume
|
//We use io.ReadFull() here to guarantee we consume
|
||||||
//just the data we want for the cmdSpec, and no more.
|
//just the data we want for the hkexsh.Session, and no more.
|
||||||
//Otherwise data will be sitting in the channel that isn't
|
//Otherwise data will be sitting in the channel that isn't
|
||||||
//passed down to the command handlers.
|
//passed down to the command handlers.
|
||||||
var rec cmdSpec
|
var rec hkexsh.Session
|
||||||
var len1, len2, len3, len4 uint32
|
var len1, len2, len3, len4 uint32
|
||||||
|
|
||||||
n, err := fmt.Fscanf(hc, "%d %d %d %d\n", &len1, &len2, &len3, &len4)
|
n, err := fmt.Fscanf(hc, "%d %d %d %d\n", &len1, &len2, &len3, &len4)
|
||||||
log.Printf("cmdSpec read:%d %d %d %d\n", len1, len2, len3, len4)
|
log.Printf("hkexsh.Session read:%d %d %d %d\n", len1, len2, len3, len4)
|
||||||
|
|
||||||
if err != nil || n < 4 {
|
if err != nil || n < 4 {
|
||||||
log.Println("[Bad cmdSpec fmt]")
|
log.Println("[Bad hkexsh.Session fmt]")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//fmt.Printf(" lens:%d %d %d %d\n", len1, len2, len3, len4)
|
//fmt.Printf(" lens:%d %d %d %d\n", len1, len2, len3, len4)
|
||||||
|
|
||||||
rec.op = make([]byte, len1, len1)
|
tmp := make([]byte, len1, len1)
|
||||||
_, err = io.ReadFull(hc, rec.op)
|
_, err = io.ReadFull(hc, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Bad cmdSpec.op]")
|
log.Println("[Bad hkexsh.Session.Op]")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rec.who = make([]byte, len2, len2)
|
rec.SetOp(tmp)
|
||||||
_, err = io.ReadFull(hc, rec.who)
|
|
||||||
|
tmp = make([]byte, len2, len2)
|
||||||
|
_, err = io.ReadFull(hc, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Bad cmdSpec.who]")
|
log.Println("[Bad hkexsh.Session.Who]")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rec.SetWho(tmp)
|
||||||
|
|
||||||
rec.cmd = make([]byte, len3, len3)
|
tmp = make([]byte, len3, len3)
|
||||||
_, err = io.ReadFull(hc, rec.cmd)
|
_, err = io.ReadFull(hc, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Bad cmdSpec.cmd]")
|
log.Println("[Bad hkexsh.Session.Cmd]")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rec.SetCmd(tmp)
|
||||||
|
|
||||||
rec.authCookie = make([]byte, len4, len4)
|
tmp = make([]byte, len4, len4)
|
||||||
_, err = io.ReadFull(hc, rec.authCookie)
|
_, err = io.ReadFull(hc, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Bad cmdSpec.authCookie]")
|
log.Println("[Bad hkexsh.Session.AuthCookie]")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rec.SetAuthCookie(tmp)
|
||||||
|
|
||||||
log.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:****]\n",
|
log.Printf("[hkexsh.Session: op:%c who:%s cmd:%s auth:****]\n",
|
||||||
rec.op[0], string(rec.who), string(rec.cmd))
|
rec.Op()[0], string(rec.Who()), string(rec.Cmd()))
|
||||||
|
|
||||||
valid, allowedCmds := hkexsh.AuthUser(string(rec.who), string(rec.authCookie), "/etc/hkexsh.passwd")
|
valid, allowedCmds := hkexsh.AuthUser(string(rec.Who()), string(rec.AuthCookie(true)), "/etc/hkexsh.passwd")
|
||||||
|
|
||||||
// Security scrub
|
// Security scrub
|
||||||
for i := range rec.authCookie {
|
rec.ClearAuthCookie()
|
||||||
rec.authCookie[i] = 0
|
|
||||||
}
|
|
||||||
runtime.GC()
|
|
||||||
|
|
||||||
// Tell client if auth was valid
|
// Tell client if auth was valid
|
||||||
if valid {
|
if valid {
|
||||||
hc.Write([]byte{1})
|
hc.Write([]byte{1})
|
||||||
} else {
|
} else {
|
||||||
log.Println("Invalid user", string(rec.who))
|
log.Println("Invalid user", string(rec.Who()))
|
||||||
hc.Write([]byte{0})
|
hc.Write([]byte{0}) // ? required?
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[allowedCmds:%s]\n", allowedCmds)
|
log.Printf("[allowedCmds:%s]\n", allowedCmds)
|
||||||
|
|
||||||
if rec.op[0] == 'c' {
|
if rec.Op()[0] == 'c' {
|
||||||
// Non-interactive command
|
// Non-interactive command
|
||||||
addr := hc.RemoteAddr()
|
addr := hc.RemoteAddr()
|
||||||
//hname := goutmp.GetHost(addr.String())
|
//hname := goutmp.GetHost(addr.String())
|
||||||
hname := strings.Split(addr.String(), ":")[0]
|
hname := strings.Split(addr.String(), ":")[0]
|
||||||
|
|
||||||
log.Printf("[Running command for [%s@%s]]\n", rec.who, hname)
|
log.Printf("[Running command for [%s@%s]]\n", rec.Who(), hname)
|
||||||
runErr, cmdStatus := runShellAs(string(rec.who), string(rec.cmd), false, hc, chaffEnabled)
|
runErr, cmdStatus := runShellAs(string(rec.Who()), string(rec.Cmd()), false, hc, chaffEnabled)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.SetOp([]byte{0})
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
log.Printf("[Error spawning cmd for %s@%s]\n", rec.who, hname)
|
log.Printf("[Error spawning cmd 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(cmdStatus)
|
hc.SetStatus(cmdStatus)
|
||||||
}
|
}
|
||||||
} else if rec.op[0] == 's' {
|
} else if rec.Op()[0] == 's' {
|
||||||
// Interactive session
|
// Interactive session
|
||||||
addr := hc.RemoteAddr()
|
addr := hc.RemoteAddr()
|
||||||
//hname := goutmp.GetHost(addr.String())
|
//hname := goutmp.GetHost(addr.String())
|
||||||
hname := strings.Split(addr.String(), ":")[0]
|
hname := strings.Split(addr.String(), ":")[0]
|
||||||
log.Printf("[Running shell for [%s@%s]]\n", rec.who, hname)
|
log.Printf("[Running shell for [%s@%s]]\n", rec.Who(), hname)
|
||||||
|
|
||||||
utmpx := goutmp.Put_utmp(string(rec.who), hname)
|
utmpx := goutmp.Put_utmp(string(rec.Who()), hname)
|
||||||
defer func() { goutmp.Unput_utmp(utmpx) }()
|
defer func() { goutmp.Unput_utmp(utmpx) }()
|
||||||
goutmp.Put_lastlog_entry("hkexsh", string(rec.who), hname)
|
goutmp.Put_lastlog_entry("hkexsh", string(rec.Who()), hname)
|
||||||
runErr, cmdStatus := runShellAs(string(rec.who), string(rec.cmd), true, hc, chaffEnabled)
|
runErr, cmdStatus := runShellAs(string(rec.Who()), string(rec.Cmd()), true, hc, chaffEnabled)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.SetOp([]byte{0})
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
log.Printf("[Error spawning shell for %s@%s]\n", rec.who, hname)
|
log.Printf("[Error spawning shell for %s@%s]\n", rec.Who(), hname)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[Shell completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus)
|
log.Printf("[Shell completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)
|
||||||
hc.SetStatus(cmdStatus)
|
hc.SetStatus(cmdStatus)
|
||||||
}
|
}
|
||||||
} 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")
|
||||||
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)
|
||||||
runErr, cmdStatus := runClientToServerCopyAs(string(rec.who), hc, string(rec.cmd), chaffEnabled)
|
runErr, cmdStatus := runClientToServerCopyAs(string(rec.Who()), hc, string(rec.Cmd()), chaffEnabled)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.SetOp([]byte{0})
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
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(cmdStatus)
|
hc.SetStatus(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")
|
||||||
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)
|
||||||
runErr, cmdStatus := runServerToClientCopyAs(string(rec.who), hc, string(rec.cmd), chaffEnabled)
|
runErr, cmdStatus := runServerToClientCopyAs(string(rec.Who()), hc, string(rec.Cmd()), chaffEnabled)
|
||||||
//fmt.Print("ServerToClient cmdStatus:", cmdStatus)
|
//fmt.Print("ServerToClient cmdStatus:", cmdStatus)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.op[0] = 0
|
rec.SetOp([]byte{0})
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
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(cmdStatus)
|
hc.SetStatus(cmdStatus)
|
||||||
// Signal other end transfer is complete
|
// Signal other end transfer is complete
|
||||||
|
@ -536,7 +529,7 @@ func main() {
|
||||||
_, _ = hc.Read(nil /*ackByte*/)
|
_, _ = hc.Read(nil /*ackByte*/)
|
||||||
//fmt.Println("Got remote end ack.")
|
//fmt.Println("Got remote end ack.")
|
||||||
} else {
|
} else {
|
||||||
log.Println("[Bad cmdSpec]")
|
log.Println("[Bad hkexsh.Session]")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}(conn)
|
}(conn)
|
||||||
|
|
Loading…
Reference in New Issue