hkexsh gometalinter cleanup

This commit is contained in:
Russ Magee 2018-11-22 16:49:09 -08:00
parent c6cbd8d681
commit 0b668630e7
2 changed files with 75 additions and 58 deletions

View File

@ -36,13 +36,14 @@ import (
) )
var ( var (
wg sync.WaitGroup wg sync.WaitGroup
Log *logger.Writer // reg. syslog output (no -d) // Log defaults to regular syslog output (no -d)
Log *logger.Writer
) )
// Get terminal size using 'stty' command // GetSize gets the terminal size using 'stty' command
func GetSize() (cols, rows int, err error) { func GetSize() (cols, rows int, err error) {
cmd := exec.Command("stty", "size") cmd := exec.Command("stty", "size") // #nosec
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
out, err := cmd.Output() out, err := cmd.Output()
@ -50,13 +51,22 @@ func GetSize() (cols, rows int, err error) {
log.Println(err) log.Println(err)
cols, rows = 80, 24 //failsafe cols, rows = 80, 24 //failsafe
} else { } else {
fmt.Sscanf(string(out), "%d %d\n", &rows, &cols) n, err := fmt.Sscanf(string(out), "%d %d\n", &rows, &cols)
if n < 2 ||
rows < 0 ||
cols < 0 ||
rows > 9000 ||
cols > 9000 ||
err != nil {
log.Printf("GetSize error: rows:%d cols:%d; %v\n",
rows, cols, err)
}
} }
return return
} }
// 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 *hkexsh.Session) (err error, exitStatus uint32) { func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.Session) (exitStatus uint32, err error) {
if remoteDest { if remoteDest {
log.Println("local files:", files, "remote filepath:", string(rec.Cmd())) log.Println("local files:", files, "remote filepath:", string(rec.Cmd()))
@ -82,7 +92,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.S
// files and dirs in different trees to be deposited in a single // files and dirs in different trees to be deposited in a single
// remote destDir. // remote destDir.
for _, v := range strings.Split(files, " ") { for _, v := range strings.Split(files, " ") {
v, _ = filepath.Abs(v) v, _ = filepath.Abs(v) // #nosec
dirTmp, fileTmp := path.Split(v) dirTmp, fileTmp := path.Split(v)
if dirTmp == "" { if dirTmp == "" {
cmdArgs = append(cmdArgs, fileTmp) cmdArgs = append(cmdArgs, fileTmp)
@ -96,8 +106,8 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.S
// When args are passed in exec() format, no quoting is required // When args are passed in exec() format, no quoting is required
// (as this isn't input from a shell) (right? -rlm 20180823) // (as this isn't input from a shell) (right? -rlm 20180823)
//cmdArgs := []string{"-xvz", "-C", files, `--xform=s#.*/\(.*\)#\1#`} //cmdArgs := []string{"-xvz", "-C", files, `--xform=s#.*/\(.*\)#\1#`}
c = exec.Command(cmdName, cmdArgs...) c = exec.Command(cmdName, cmdArgs...) // #nosec
c.Dir, _ = os.Getwd() c.Dir, _ = os.Getwd() // #nosec
log.Println("[wd:", c.Dir, "]") log.Println("[wd:", c.Dir, "]")
c.Stdout = conn c.Stdout = conn
stdErrBuffer := new(bytes.Buffer) stdErrBuffer := new(bytes.Buffer)
@ -143,7 +153,10 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.S
log.Println("Sending local exitStatus:", exitStatus) log.Println("Sending local exitStatus:", exitStatus)
r := make([]byte, 4) r := make([]byte, 4)
binary.BigEndian.PutUint32(r, exitStatus) binary.BigEndian.PutUint32(r, exitStatus)
conn.WritePacket(r, hkexnet.CSOExitStatus) _, we := conn.WritePacket(r, hkexnet.CSOExitStatus)
if we != nil {
fmt.Println("Error:", we)
}
// Do a final read for remote's exit status // Do a final read for remote's exit status
s := make([]byte, 4) s := make([]byte, 4)
@ -180,7 +193,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *hkexsh.S
// When args are passed in exec() format, no quoting is required // When args are passed in exec() format, no quoting is required
// (as this isn't input from a shell) (right? -rlm 20180823) // (as this isn't input from a shell) (right? -rlm 20180823)
//cmdArgs := []string{"-xvz", "-C", destPath, `--xform=s#.*/\(.*\)#\1#`} //cmdArgs := []string{"-xvz", "-C", destPath, `--xform=s#.*/\(.*\)#\1#`}
c = exec.Command(cmdName, cmdArgs...) c = exec.Command(cmdName, cmdArgs...) // #nosec
c.Stdin = conn c.Stdin = conn
c.Stdout = os.Stdout c.Stdout = os.Stdout
c.Stderr = os.Stderr c.Stderr = os.Stderr
@ -232,7 +245,7 @@ func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State,
// exit with inerr == nil // exit with inerr == nil
_, inerr := io.Copy(os.Stdout, conn) _, inerr := io.Copy(os.Stdout, conn)
if inerr != nil { if inerr != nil {
_ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // Best effort. _ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // #nosec
// Copy operations and user logging off will cause // Copy operations and user logging off will cause
// a "use of closed network connection" so handle that // a "use of closed network connection" so handle that
// gracefully here // gracefully here
@ -243,11 +256,11 @@ func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State,
} }
rec.SetStatus(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 *]")
_ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // Best effort. _ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // #nosec
} }
}() }()
@ -273,7 +286,7 @@ func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State,
if outerr != nil { if outerr != nil {
log.Println(outerr) log.Println(outerr)
fmt.Println(outerr) fmt.Println(outerr)
_ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // Best effort. _ = hkexsh.Restore(int(os.Stdin.Fd()), oldState) // #nosec
log.Println("[Hanging up]") log.Println("[Hanging up]")
os.Exit(0) os.Exit(0)
} }
@ -283,16 +296,15 @@ func doShellMode(isInteractive bool, conn *hkexnet.Conn, oldState *hkexsh.State,
// Wait until both stdin and stdout goroutines finish before returning // Wait until both stdin and stdout goroutines finish before returning
// (ensure client gets all data from server before closing) // (ensure client gets all data from server before closing)
wg.Wait() wg.Wait()
return
} }
func UsageShell() { func usageShell() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "%s [opts] [user]@server\n", os.Args[0]) fmt.Fprintf(os.Stderr, "%s [opts] [user]@server\n", os.Args[0])
flag.PrintDefaults() flag.PrintDefaults()
} }
func UsageCp() { func usageCp() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "%s [opts] srcFileOrDir [...] [user]@server[:dstpath]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "%s [opts] srcFileOrDir [...] [user]@server[:dstpath]\n", os.Args[0])
fmt.Fprintf(os.Stderr, "%s [opts] [user]@server[:srcFileOrDir] dstPath\n", os.Args[0]) fmt.Fprintf(os.Stderr, "%s [opts] [user]@server[:srcFileOrDir] dstPath\n", os.Args[0])
@ -310,10 +322,16 @@ func rejectUserMsg() string {
func reqTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) { func reqTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) {
// Write request to server so it can attempt to set up its end // Write request to server so it can attempt to set up its end
var bTmp bytes.Buffer var bTmp bytes.Buffer
binary.Write(&bTmp, binary.BigEndian, lp) if e := binary.Write(&bTmp, binary.BigEndian, lp); e != nil {
binary.Write(&bTmp, binary.BigEndian, rp) fmt.Fprintln(os.Stderr, "reqTunnel:", e)
logger.LogDebug(fmt.Sprintln("[Client sending CSOTunSetup]")) }
hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunSetup) if e := binary.Write(&bTmp, binary.BigEndian, rp); e != nil {
fmt.Fprintln(os.Stderr, "reqTunnel:", e)
}
_ = logger.LogDebug(fmt.Sprintln("[Client sending CSOTunSetup]"))
if n, e := hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunSetup); e != nil || n != len(bTmp.Bytes()) {
fmt.Fprintln(os.Stderr, "reqTunnel:", e)
}
return return
} }
@ -374,6 +392,18 @@ func launchTuns(conn *hkexnet.Conn, remoteHost string, tuns string) {
} }
} }
func sendSessionParams(conn io.Writer /* *hkexnet.Conn*/, rec *hkexsh.Session) (e error) {
_, e = fmt.Fprintf(conn, "%d %d %d %d %d %d\n",
len(rec.Op()), len(rec.Who()), len(rec.ConnHost()), len(rec.TermType()), len(rec.Cmd()), len(rec.AuthCookie(true)))
_, e = conn.Write(rec.Op())
_, e = conn.Write(rec.Who())
_, e = conn.Write(rec.ConnHost())
_, e = conn.Write(rec.TermType())
_, e = conn.Write(rec.Cmd())
_, e = conn.Write(rec.AuthCookie(true))
return
}
// hkexsh - a client for secure shell and file copy operations. // hkexsh - a client for secure shell and file copy operations.
// //
// While conforming to the basic net.Conn interface HKex.Conn has extra // While conforming to the basic net.Conn interface HKex.Conn has extra
@ -390,10 +420,10 @@ func main() {
var vopt bool var vopt bool
var gopt bool //login via password, asking server to generate authToken var gopt bool //login via password, asking server to generate authToken
var dbg bool var dbg bool
var shellMode bool // if true act as shell, else file copier var shellMode bool // if true act as shell, else file copier
var cAlg string //cipher alg var cipherAlg string //cipher alg
var hAlg string //hmac alg var hmacAlg string //hmac alg
var kAlg string //KEX/KEM alg var kexAlg string //KEX/KEM alg
var server string var server string
var port uint var port uint
var cmdStr string var cmdStr string
@ -413,9 +443,9 @@ func main() {
flag.BoolVar(&vopt, "v", false, "show version") flag.BoolVar(&vopt, "v", false, "show version")
flag.BoolVar(&dbg, "d", false, "debug logging") flag.BoolVar(&dbg, "d", false, "debug logging")
flag.StringVar(&cAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]") flag.StringVar(&cipherAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]")
flag.StringVar(&hAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\"]") flag.StringVar(&hmacAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\"]")
flag.StringVar(&kAlg, "k", "KEX_HERRADURA256", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\"]") flag.StringVar(&kexAlg, "k", "KEX_HERRADURA256", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\"]")
flag.UintVar(&port, "p", 2000, "`port`") flag.UintVar(&port, "p", 2000, "`port`")
//flag.StringVar(&authCookie, "a", "", "auth cookie") //flag.StringVar(&authCookie, "a", "", "auth cookie")
flag.BoolVar(&chaffEnabled, "e", true, "enabled chaff pkts (default true)") flag.BoolVar(&chaffEnabled, "e", true, "enabled chaff pkts (default true)")
@ -432,9 +462,9 @@ func main() {
flag.StringVar(&tunSpecStr, "T", "", "`tunnelspec` localPort:remotePort[,localPort:remotePort,...]") flag.StringVar(&tunSpecStr, "T", "", "`tunnelspec` localPort:remotePort[,localPort:remotePort,...]")
flag.BoolVar(&gopt, "g", false, "ask server to generate authtoken") flag.BoolVar(&gopt, "g", false, "ask server to generate authtoken")
shellMode = true shellMode = true
flag.Usage = UsageShell flag.Usage = usageShell
} else { } else {
flag.Usage = UsageCp flag.Usage = usageCp
} }
flag.Parse() flag.Parse()
@ -524,25 +554,16 @@ func main() {
u, _ := user.Current() u, _ := user.Current()
ab, aerr := ioutil.ReadFile(fmt.Sprintf("%s/.hkexsh_id", u.HomeDir)) ab, aerr := ioutil.ReadFile(fmt.Sprintf("%s/.hkexsh_id", u.HomeDir))
if aerr == nil { if aerr == nil {
//authCookie = string(ab)
idx := strings.Index(string(ab), remoteHost) idx := strings.Index(string(ab), remoteHost)
//fmt.Printf("auth entry idx:%d\n", idx)
if idx >= 0 { if idx >= 0 {
//fmt.Fprintln(os.Stderr, "[authtoken]")
ab = ab[idx:] ab = ab[idx:]
entries := strings.SplitN(string(ab), "\n", -1) entries := strings.SplitN(string(ab), "\n", -1)
//if len(entries) > 0 {
//fmt.Println("entries[0]:", entries[0])
authCookie = strings.TrimSpace(entries[0]) authCookie = strings.TrimSpace(entries[0])
//} else {
// fmt.Fprintln(os.Stderr, "ERROR: no matching authtoken")
// os.Exit(1)
//}
// Security scrub // Security scrub
ab = nil ab = nil
runtime.GC() runtime.GC()
} else { } else {
fmt.Fprintln(os.Stderr, "[no authtoken, use -g to request one from server]") _, _ = fmt.Fprintln(os.Stderr, "[no authtoken, use -g to request one from server]")
} }
} else { } else {
log.Printf("[cannot read %s/.hkexsh_id]\n", u.HomeDir) log.Printf("[cannot read %s/.hkexsh_id]\n", u.HomeDir)
@ -589,7 +610,7 @@ func main() {
} }
} }
conn, err := hkexnet.Dial("tcp", server, cAlg, hAlg, kAlg) conn, err := hkexnet.Dial("tcp", server, cipherAlg, hmacAlg, kexAlg)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
panic(err) panic(err)
@ -616,27 +637,19 @@ func main() {
if len(authCookie) == 0 { if len(authCookie) == 0 {
//No auth token, prompt for password //No auth token, prompt for password
fmt.Printf("Gimme cookie:") fmt.Printf("Gimme cookie:")
ab, err := hkexsh.ReadPassword(int(os.Stdin.Fd())) ab, e := hkexsh.ReadPassword(int(os.Stdin.Fd()))
fmt.Printf("\r\n") fmt.Printf("\r\n")
if err != nil { if e != nil {
panic(err) panic(e)
} }
authCookie = string(ab) authCookie = string(ab)
// Security scrub
ab = nil
runtime.GC()
} }
// Security scrub
runtime.GC()
// Set up session params and send over to server // Set up session params and send over to server
rec := hkexsh.NewSession(op, []byte(uname), []byte(remoteHost), []byte(os.Getenv("TERM")), []byte(cmdStr), []byte(authCookie), 0) rec := hkexsh.NewSession(op, []byte(uname), []byte(remoteHost), []byte(os.Getenv("TERM")), []byte(cmdStr), []byte(authCookie), 0)
_, err = fmt.Fprintf(conn, "%d %d %d %d %d %d\n", sendSessionParams(&conn, rec)
len(rec.Op()), len(rec.Who()), len(rec.ConnHost()), len(rec.TermType()), len(rec.Cmd()), len(rec.AuthCookie(true)))
_, err = conn.Write(rec.Op())
_, err = conn.Write(rec.Who())
_, err = conn.Write(rec.ConnHost())
_, err = conn.Write(rec.TermType())
_, err = conn.Write(rec.Cmd())
_, err = conn.Write(rec.AuthCookie(true))
//Security scrub //Security scrub
authCookie = "" authCookie = ""
@ -645,7 +658,10 @@ func main() {
// 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 err != nil {
fmt.Fprintln(os.Stderr, "Error reading auth reply")
rec.SetStatus(255)
} else if authReply[0] == 0 {
fmt.Fprintln(os.Stderr, rejectUserMsg()) fmt.Fprintln(os.Stderr, rejectUserMsg())
rec.SetStatus(255) rec.SetStatus(255)
} else { } else {
@ -671,7 +687,7 @@ func main() {
doShellMode(isInteractive, &conn, oldState, rec) doShellMode(isInteractive, &conn, oldState, rec)
} else { // copyMode } else { // copyMode
_, s := doCopyMode(&conn, pathIsDest, fileArgs, rec) s, _ := doCopyMode(&conn, pathIsDest, fileArgs, rec)
rec.SetStatus(s) rec.SetStatus(s)
} }

View File

@ -1,4 +1,5 @@
// +build linux // +build linux
package main package main
import ( import (