From 1aa8a1549bf6713926a7a3f1586b8c5a40107c3c Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Thu, 4 Jul 2019 20:27:49 -0700 Subject: [PATCH] Used fixed goutmp pty logging Signed-off-by: Russ Magee --- hkexnet/consts.go | 11 ++++++----- hkexshd/hkexshd.go | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/hkexnet/consts.go b/hkexnet/consts.go index 176b82f..0916090 100644 --- a/hkexnet/consts.go +++ b/hkexnet/consts.go @@ -37,11 +37,12 @@ type KEXAlg uint8 // Extended exit status codes - indicate comm/pty issues // rather than remote end normal UNIX exit codes const ( - CSENone = 1024 + iota - CSETruncCSO // No CSOExitStatus in payload - CSEStillOpen // Channel closed unexpectedly - CSEExecFail // cmd.Start() (exec) failed - CSEPtyExecFail // pty.Start() (exec w/pty) failed + CSENone = 1024 + iota + CSETruncCSO // No CSOExitStatus in payload + CSEStillOpen // Channel closed unexpectedly + CSEExecFail // cmd.Start() (exec) failed + CSEPtyExecFail // pty.Start() (exec w/pty) failed + CSEPtyGetNameFail // failed to obtain pty name ) // Extended (>255 UNIX exit status) codes diff --git a/hkexshd/hkexshd.go b/hkexshd/hkexshd.go index 953ec24..6584740 100755 --- a/hkexshd/hkexshd.go +++ b/hkexshd/hkexshd.go @@ -25,6 +25,7 @@ import ( "path" "sync" "syscall" + "unsafe" "blitter.com/go/goutmp" hkexsh "blitter.com/go/hkexsh" @@ -38,6 +39,22 @@ var ( Log *logger.Writer ) +func ioctl(fd, request, argp uintptr) error { + if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, fd, request, argp, 0, 0, 0); e != 0 { + return e + } + return nil +} + +func ptsName(fd uintptr) (string, error) { + var n uintptr + err := ioctl(fd, syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return "", err + } + return fmt.Sprintf("/dev/pts/%d", n), nil +} + /* -------------------------------------------------------------- */ // Perform a client->server copy func runClientToServerCopyAs(who, ttype string, conn *hkexnet.Conn, fpath string, chaffing bool) (exitStatus uint32, err error) { @@ -230,7 +247,7 @@ func runServerToClientCopyAs(who, ttype string, conn *hkexnet.Conn, srcPath stri // // Uses ptys to support commands which expect a terminal. // nolint: gocyclo -func runShellAs(who, ttype string, cmd string, interactive bool, conn *hkexnet.Conn, chaffing bool) (exitStatus uint32, err error) { +func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *hkexnet.Conn, chaffing bool) (exitStatus uint32, err error) { var wg sync.WaitGroup u, err := user.Lookup(who) if err != nil { @@ -279,6 +296,15 @@ func runShellAs(who, ttype string, cmd string, interactive bool, conn *hkexnet.C // #gv:s/label=\"runShellAs\$1\"/label=\"deferPtmxClose\"/ defer func() { _ = ptmx.Close() }() // nolint: gosec + // get pty info for system accounting (who, lastlog) + pts, pe := ptsName(ptmx.Fd()) + if pe != nil { + return hkexnet.CSEPtyGetNameFail, err + } + utmpx := goutmp.Put_utmp(who, pts, hname) + defer func() { goutmp.Unput_utmp(utmpx) }() + goutmp.Put_lastlog_entry("hkexsh", who, pts, hname) + log.Printf("[%s]\n", cmd) if err != nil { log.Printf("Command finished with error: %v", err) @@ -571,7 +597,7 @@ func main() { logger.LogNotice(fmt.Sprintf("[Generating autologin token for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck token := GenAuthToken(string(rec.Who()), string(rec.ConnHost())) tokenCmd := fmt.Sprintf("echo \"%s\" | tee -a ~/.hkexsh_id", token) - cmdStatus, runErr := runShellAs(string(rec.Who()), string(rec.TermType()), tokenCmd, false, hc, chaffEnabled) + cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), tokenCmd, false, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) @@ -586,7 +612,7 @@ func main() { addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) logger.LogNotice(fmt.Sprintf("[Running command for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck - cmdStatus, runErr := runShellAs(string(rec.Who()), string(rec.TermType()), string(rec.Cmd()), false, hc, chaffEnabled) + cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), string(rec.Cmd()), false, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) @@ -602,10 +628,7 @@ func main() { hname := goutmp.GetHost(addr.String()) logger.LogNotice(fmt.Sprintf("[Running shell for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck - utmpx := goutmp.Put_utmp(string(rec.Who()), hname) - defer func() { goutmp.Unput_utmp(utmpx) }() - goutmp.Put_lastlog_entry("hkexsh", string(rec.Who()), hname) - cmdStatus, runErr := runShellAs(string(rec.Who()), string(rec.TermType()), string(rec.Cmd()), true, hc, chaffEnabled) + cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), string(rec.Cmd()), true, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0})