diff --git a/xsd/xsd.go b/xsd/xsd.go index 5b931c3..1e9b15e 100755 --- a/xsd/xsd.go +++ b/xsd/xsd.go @@ -439,9 +439,9 @@ var ( aHMACAlgs allowedHMACAlgs ) -type allowedKEXAlgs []string -type allowedCipherAlgs []string -type allowedHMACAlgs []string +type allowedKEXAlgs []string // TODO +type allowedCipherAlgs []string // TODO +type allowedHMACAlgs []string // TODO func (a allowedKEXAlgs) allowed(k xsnet.KEXAlg) bool { for i := 0; i < len(a); i++ { @@ -527,33 +527,9 @@ func main() { flag.BoolVar(&useSystemPasswd, "s", true, "use system shadow passwds") flag.BoolVar(&dbg, "d", false, "debug logging") - flag.Var(&aKEXAlgs, "aK", `Allowed KEX algs (eg. '-aK KEXAlgA -aK KEXAlgB ...') (default: none) - KEX_all - KEX_HERRADURA256 - KEX_HERRADURA512 - KEX_HERRADURA1024 - KEX_HERRADURA2048 - KEX_KYBER512 - KEX_KYBER768 - KEX_KYBER1024 - KEX_NEWHOPE - KEX_NEWHOPE_SIMPLE - KEX_FRODOKEM_1344AES - KEX_FRODOKEM_1344SHAKE - KEX_FRODOKEM_976AES - KEX_FRODOKEM_976SHAKE`) - flag.Var(&aCipherAlgs, "aC", `Allowed ciphers (eg. '-aC CAlgA -aC CAlgB ...') (default: none) - C_all - C_AES_256 - C_TWOFISH_128 - C_BLOWFISH_64 - C_CRYPTMT1 - C_HOPSCOTCH - C_CHACHA20_12`) - flag.Var(&aHMACAlgs, "aH", `Allowed HMACs (eg. '-aH HMACAlgA -aH HMACAlgB ...') (default: none) - H_all - H_SHA256 - H_SHA512`) + flag.Var(&aKEXAlgs, "aK", `List of allowed KEX algs (eg. 'KEXAlgA KEXAlgB ... KEXAlgN') (default allow all)`) + flag.Var(&aCipherAlgs, "aC", `List of allowed ciphers (eg. 'CipherAlgA CipherAlgB ... CipherAlgN') (default allow all)`) + flag.Var(&aHMACAlgs, "aH", `List of allowed HMACs (eg. 'HMACAlgA HMACAlgB ... HMACAlgN') (default allow all)`) flag.Parse() @@ -590,17 +566,17 @@ func main() { // Set up allowed algs, if specified (default allow all) if len(aKEXAlgs) == 0 { - aKEXAlgs = []string{"none"} + aKEXAlgs = []string{"KEX_all"} } logger.LogNotice(fmt.Sprintf("Allowed KEXAlgs: %v\n", aKEXAlgs)) // nolint: gosec,errcheck if len(aCipherAlgs) == 0 { - aCipherAlgs = []string{"none"} + aCipherAlgs = []string{"C_all"} } logger.LogNotice(fmt.Sprintf("Allowed CipherAlgs: %v\n", aCipherAlgs)) // nolint: gosec,errcheck if len(aHMACAlgs) == 0 { - aHMACAlgs = []string{"none"} + aHMACAlgs = []string{"H_all"} } logger.LogNotice(fmt.Sprintf("Allowed HMACAlgs: %v\n", aHMACAlgs)) // nolint: gosec,errcheck @@ -644,235 +620,233 @@ func main() { conn, err := l.Accept() if err != nil { log.Printf("Accept() got error(%v), hanging up.\n", err) + } else if !aKEXAlgs.allowed(conn.KEX()) { + log.Printf("Accept() rejected for banned KEX alg %d, hanging up.\n", conn.KEX()) + conn.SetStatus(xsnet.CSEKEXAlgDenied) + conn.Close() + } else if !aCipherAlgs.allowed(conn.CAlg()) { + log.Printf("Accept() rejected for banned Cipher alg %d, hanging up.\n", conn.CAlg()) + conn.SetStatus(xsnet.CSECipherAlgDenied) + conn.Close() + } else if !aHMACAlgs.allowed(conn.HAlg()) { + log.Printf("Accept() rejected for banned HMAC alg %d, hanging up.\n", conn.HAlg()) + conn.SetStatus(xsnet.CSEHMACAlgDenied) + conn.Close() } else { - if !aKEXAlgs.allowed(conn.KEX()) { - log.Printf("Accept() rejected for banned KEX alg %d, hanging up.\n", conn.KEX()) - conn.SetStatus(xsnet.CSEKEXAlgDenied) - conn.Close() - } else if !aCipherAlgs.allowed(conn.CAlg()) { - log.Printf("Accept() rejected for banned Cipher alg %d, hanging up.\n", conn.CAlg()) - conn.SetStatus(xsnet.CSECipherAlgDenied) - conn.Close() - } else if !aHMACAlgs.allowed(conn.HAlg()) { - log.Printf("Accept() rejected for banned HMAC alg %d, hanging up.\n", conn.HAlg()) - conn.SetStatus(xsnet.CSEHMACAlgDenied) - conn.Close() - } else { - log.Println("Accepted client") + log.Println("Accepted client") - // Set up chaffing to client - // Will only start when runShellAs() is called - // after stdin/stdout are hooked up - conn.SetupChaff(chaffFreqMin, chaffFreqMax, chaffBytesMax) // configure server->client chaffing + // Set up chaffing to client + // Will only start when runShellAs() is called + // after stdin/stdout are hooked up + conn.SetupChaff(chaffFreqMin, chaffFreqMax, chaffBytesMax) // configure server->client chaffing - // Handle the connection in a new goroutine. - // The loop then returns to accepting, so that - // multiple connections may be served concurrently. - go func(hc *xsnet.Conn) (e error) { - defer hc.Close() // nolint: errcheck + // Handle the connection in a new goroutine. + // The loop then returns to accepting, so that + // multiple connections may be served concurrently. + go func(hc *xsnet.Conn) (e error) { + defer hc.Close() // nolint: errcheck - // Start login timeout here and disconnect if user/pass phase stalls - loginTimeout := time.AfterFunc(30*time.Second, func() { - logger.LogNotice(fmt.Sprintln("Login timed out")) // nolint: errcheck,gosec - hc.Write([]byte{0}) // nolint: gosec,errcheck - hc.Close() - }) + // Start login timeout here and disconnect if user/pass phase stalls + loginTimeout := time.AfterFunc(30*time.Second, func() { + logger.LogNotice(fmt.Sprintln("Login timed out")) // nolint: errcheck,gosec + hc.Write([]byte{0}) // nolint: gosec,errcheck + hc.Close() + }) - //We use io.ReadFull() here to guarantee we consume - //just the data we want for the xs.Session, and no more. - //Otherwise data will be sitting in the channel that isn't - //passed down to the command handlers. - var rec xs.Session - var len1, len2, len3, len4, len5, len6 uint32 + //We use io.ReadFull() here to guarantee we consume + //just the data we want for the xs.Session, and no more. + //Otherwise data will be sitting in the channel that isn't + //passed down to the command handlers. + var rec xs.Session + var len1, len2, len3, len4, len5, len6 uint32 - n, err := fmt.Fscanf(hc, "%d %d %d %d %d %d\n", &len1, &len2, &len3, &len4, &len5, &len6) - log.Printf("xs.Session read:%d %d %d %d %d %d\n", len1, len2, len3, len4, len5, len6) + n, err := fmt.Fscanf(hc, "%d %d %d %d %d %d\n", &len1, &len2, &len3, &len4, &len5, &len6) + log.Printf("xs.Session read:%d %d %d %d %d %d\n", len1, len2, len3, len4, len5, len6) - if err != nil || n < 6 { - log.Println("[Bad xs.Session fmt]") - return err - } + if err != nil || n < 6 { + log.Println("[Bad xs.Session fmt]") + return err + } - tmp := make([]byte, len1) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.Op]") - return err - } - rec.SetOp(tmp) + tmp := make([]byte, len1) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.Op]") + return err + } + rec.SetOp(tmp) - tmp = make([]byte, len2) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.Who]") - return err - } - rec.SetWho(tmp) + tmp = make([]byte, len2) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.Who]") + return err + } + rec.SetWho(tmp) - tmp = make([]byte, len3) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.ConnHost]") - return err - } - rec.SetConnHost(tmp) + tmp = make([]byte, len3) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.ConnHost]") + return err + } + rec.SetConnHost(tmp) - tmp = make([]byte, len4) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.TermType]") - return err - } - rec.SetTermType(tmp) + tmp = make([]byte, len4) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.TermType]") + return err + } + rec.SetTermType(tmp) - tmp = make([]byte, len5) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.Cmd]") - return err - } - rec.SetCmd(tmp) + tmp = make([]byte, len5) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.Cmd]") + return err + } + rec.SetCmd(tmp) - tmp = make([]byte, len6) - _, err = io.ReadFull(hc, tmp) - if err != nil { - log.Println("[Bad xs.Session.AuthCookie]") - return err - } - rec.SetAuthCookie(tmp) + tmp = make([]byte, len6) + _, err = io.ReadFull(hc, tmp) + if err != nil { + log.Println("[Bad xs.Session.AuthCookie]") + return err + } + rec.SetAuthCookie(tmp) - log.Printf("[xs.Session: op:%c who:%s connhost:%s cmd:%s auth:****]\n", - rec.Op()[0], string(rec.Who()), string(rec.ConnHost()), string(rec.Cmd())) + log.Printf("[xs.Session: op:%c who:%s connhost:%s cmd:%s auth:****]\n", + rec.Op()[0], string(rec.Who()), string(rec.ConnHost()), string(rec.Cmd())) - var valid bool - var allowedCmds string // Currently unused - if xs.AuthUserByToken(xs.NewAuthCtx(), string(rec.Who()), string(rec.ConnHost()), string(rec.AuthCookie(true))) { - valid = true + var valid bool + var allowedCmds string // Currently unused + if xs.AuthUserByToken(xs.NewAuthCtx(), string(rec.Who()), string(rec.ConnHost()), string(rec.AuthCookie(true))) { + valid = true + } else { + if useSystemPasswd { + //var passErr error + valid, _ /*passErr*/ = xs.VerifyPass(xs.NewAuthCtx(), string(rec.Who()), string(rec.AuthCookie(true))) } else { - if useSystemPasswd { - //var passErr error - valid, _ /*passErr*/ = xs.VerifyPass(xs.NewAuthCtx(), string(rec.Who()), string(rec.AuthCookie(true))) - } else { - valid, allowedCmds = xs.AuthUserByPasswd(xs.NewAuthCtx(), string(rec.Who()), string(rec.AuthCookie(true)), "/etc/xs.passwd") - } + valid, allowedCmds = xs.AuthUserByPasswd(xs.NewAuthCtx(), string(rec.Who()), string(rec.AuthCookie(true)), "/etc/xs.passwd") } + } - _ = loginTimeout.Stop() - // Security scrub - rec.ClearAuthCookie() + _ = loginTimeout.Stop() + // Security scrub + rec.ClearAuthCookie() - // Tell client if auth was valid - if valid { - hc.Write([]byte{1}) // nolint: gosec,errcheck - } else { - logger.LogNotice(fmt.Sprintln("Invalid user", string(rec.Who()))) // nolint: errcheck,gosec - hc.Write([]byte{0}) // nolint: gosec,errcheck - return - } - - log.Printf("[allowedCmds:%s]\n", allowedCmds) - - if rec.Op()[0] == 'A' { - // Generate automated login token - addr := hc.RemoteAddr() - hname := goutmp.GetHost(addr.String()) - 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 ~/.xs_id", token) - 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}) - if runErr != nil { - logger.LogErr(fmt.Sprintf("[Error generating autologin token for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - } else { - log.Printf("[Autologin token generation completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus) - hc.SetStatus(xsnet.CSOType(cmdStatus)) - } - } else if rec.Op()[0] == 'c' { - // Non-interactive command - 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()), 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}) - if runErr != nil { - logger.LogErr(fmt.Sprintf("[Error spawning cmd for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - } else { - logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck - hc.SetStatus(xsnet.CSOType(cmdStatus)) - } - } else if rec.Op()[0] == 's' { - // Interactive session - addr := hc.RemoteAddr() - hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[Running shell for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck - - 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}) - if runErr != nil { - Log.Err(fmt.Sprintf("[Error spawning shell for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - } else { - logger.LogNotice(fmt.Sprintf("[Shell completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck - hc.SetStatus(xsnet.CSOType(cmdStatus)) - } - } else if rec.Op()[0] == 'D' { - // File copy (destination) operation - client copy to server - log.Printf("[Client->Server copy]\n") - addr := hc.RemoteAddr() - hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[c->s copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - cmdStatus, runErr := runClientToServerCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) - // Returned hopefully via an EOF or exit/logout; - // Clear current op so user can enter next, or EOF - rec.SetOp([]byte{0}) - if runErr != nil { - logger.LogErr(fmt.Sprintf("[c->s copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - } else { - logger.LogNotice(fmt.Sprintf("[c->s copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck - } - // TODO: Test this with huge files.. see Bug #22 - do we need to - // sync w/sender (client) that we've gotten all data? - hc.SetStatus(xsnet.CSOType(cmdStatus)) - - // Send CSOExitStatus *before* client closes channel - s := make([]byte, 4) - binary.BigEndian.PutUint32(s, cmdStatus) - log.Printf("** cp writing closeStat %d at Close()\n", cmdStatus) - hc.WritePacket(s, xsnet.CSOExitStatus) // nolint: gosec,errcheck - } else if rec.Op()[0] == 'S' { - // File copy (src) operation - server copy to client - log.Printf("[Server->Client copy]\n") - addr := hc.RemoteAddr() - hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[s->c copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - cmdStatus, runErr := runServerToClientCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) - if runErr != nil { - logger.LogErr(fmt.Sprintf("[s->c copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck - } else { - // Returned hopefully via an EOF or exit/logout; - logger.LogNotice(fmt.Sprintf("[s->c copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck - } - // HACK: Bug #22: (xc) Need to wait for rcvr to get final data - // TODO: Await specific msg from client to inform they have gotten all data from the tarpipe - time.Sleep(time.Duration(900 * time.Millisecond)) // Let rcvr set this on setup? - - // Clear current op so user can enter next, or EOF - rec.SetOp([]byte{0}) - hc.SetStatus(xsnet.CSOType(cmdStatus)) - //fmt.Println("Waiting for EOF from other end.") - //_, _ = hc.Read(nil /*ackByte*/) - //fmt.Println("Got remote end ack.") - } else { - logger.LogErr(fmt.Sprintln("[Bad xs.Session]")) // nolint: gosec,errcheck - } + // Tell client if auth was valid + if valid { + hc.Write([]byte{1}) // nolint: gosec,errcheck + } else { + logger.LogNotice(fmt.Sprintln("Invalid user", string(rec.Who()))) // nolint: errcheck,gosec + hc.Write([]byte{0}) // nolint: gosec,errcheck return - }(&conn) // nolint: errcheck - } // algs valid and not blacklisted + } + + log.Printf("[allowedCmds:%s]\n", allowedCmds) + + if rec.Op()[0] == 'A' { + // Generate automated login token + addr := hc.RemoteAddr() + hname := goutmp.GetHost(addr.String()) + 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 ~/.xs_id", token) + 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}) + if runErr != nil { + logger.LogErr(fmt.Sprintf("[Error generating autologin token for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + } else { + log.Printf("[Autologin token generation completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus) + hc.SetStatus(xsnet.CSOType(cmdStatus)) + } + } else if rec.Op()[0] == 'c' { + // Non-interactive command + 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()), 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}) + if runErr != nil { + logger.LogErr(fmt.Sprintf("[Error spawning cmd for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + } else { + logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + hc.SetStatus(xsnet.CSOType(cmdStatus)) + } + } else if rec.Op()[0] == 's' { + // Interactive session + addr := hc.RemoteAddr() + hname := goutmp.GetHost(addr.String()) + logger.LogNotice(fmt.Sprintf("[Running shell for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck + + 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}) + if runErr != nil { + Log.Err(fmt.Sprintf("[Error spawning shell for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + } else { + logger.LogNotice(fmt.Sprintf("[Shell completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + hc.SetStatus(xsnet.CSOType(cmdStatus)) + } + } else if rec.Op()[0] == 'D' { + // File copy (destination) operation - client copy to server + log.Printf("[Client->Server copy]\n") + addr := hc.RemoteAddr() + hname := goutmp.GetHost(addr.String()) + logger.LogNotice(fmt.Sprintf("[c->s copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + cmdStatus, runErr := runClientToServerCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) + // Returned hopefully via an EOF or exit/logout; + // Clear current op so user can enter next, or EOF + rec.SetOp([]byte{0}) + if runErr != nil { + logger.LogErr(fmt.Sprintf("[c->s copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + } else { + logger.LogNotice(fmt.Sprintf("[c->s copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + } + // TODO: Test this with huge files.. see Bug #22 - do we need to + // sync w/sender (client) that we've gotten all data? + hc.SetStatus(xsnet.CSOType(cmdStatus)) + + // Send CSOExitStatus *before* client closes channel + s := make([]byte, 4) + binary.BigEndian.PutUint32(s, cmdStatus) + log.Printf("** cp writing closeStat %d at Close()\n", cmdStatus) + hc.WritePacket(s, xsnet.CSOExitStatus) // nolint: gosec,errcheck + } else if rec.Op()[0] == 'S' { + // File copy (src) operation - server copy to client + log.Printf("[Server->Client copy]\n") + addr := hc.RemoteAddr() + hname := goutmp.GetHost(addr.String()) + logger.LogNotice(fmt.Sprintf("[s->c copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + cmdStatus, runErr := runServerToClientCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) + if runErr != nil { + logger.LogErr(fmt.Sprintf("[s->c copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + } else { + // Returned hopefully via an EOF or exit/logout; + logger.LogNotice(fmt.Sprintf("[s->c copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + } + // HACK: Bug #22: (xc) Need to wait for rcvr to get final data + // TODO: Await specific msg from client to inform they have gotten all data from the tarpipe + time.Sleep(time.Duration(900 * time.Millisecond)) // Let rcvr set this on setup? + + // Clear current op so user can enter next, or EOF + rec.SetOp([]byte{0}) + hc.SetStatus(xsnet.CSOType(cmdStatus)) + //fmt.Println("Waiting for EOF from other end.") + //_, _ = hc.Read(nil /*ackByte*/) + //fmt.Println("Got remote end ack.") + } else { + logger.LogErr(fmt.Sprintln("[Bad xs.Session]")) // nolint: gosec,errcheck + } + return + }(&conn) // nolint: errcheck } // Accept() success } //endfor //logger.LogNotice(fmt.Sprintln("[Exiting]")) // nolint: gosec,errcheck diff --git a/xsnet/net.go b/xsnet/net.go index bfb002f..45191b7 100644 --- a/xsnet/net.go +++ b/xsnet/net.go @@ -25,7 +25,6 @@ package xsnet import ( "bytes" "crypto/cipher" - crand "crypto/rand" "encoding/binary" "encoding/hex" "errors" @@ -40,6 +39,7 @@ import ( "strings" "sync" "time" + crand "crypto/rand" hkex "blitter.com/go/herradurakex" "blitter.com/go/kyber" @@ -169,11 +169,11 @@ func (hc *Conn) HAlg() CSHmacAlg { } func (h *CSHmacAlg) String() string { - switch *h & 0x0FF { + switch (*h >> 8) & 0x0FF { case HmacSHA256: return "H_SHA256" case HmacSHA512: - return "H_SHA512" + return "C_SHA512" default: return "H_ERR_UNK" } @@ -296,7 +296,7 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) { case KEX_FRODOKEM_976AES: fallthrough case KEX_FRODOKEM_976SHAKE: - //log.Printf("[KEx alg %d is valid]\n", kexAlg) + log.Printf("[KEx alg %d accepted]\n", kexAlg) default: // UNREACHABLE: _getkexalgnum() guarantees a valid KEX value hc.kex = KEX_HERRADURA512 @@ -517,7 +517,7 @@ func NewHopeDialSetup(c io.ReadWriter, hc *Conn) (err error) { if err != nil { panic(err) } - + hc.r, hc.rm, err = hc.getStream(aliceSharedSecret) hc.w, hc.wm, err = hc.getStream(aliceSharedSecret) return @@ -559,7 +559,7 @@ func NewHopeSimpleDialSetup(c io.ReadWriter, hc *Conn) (err error) { if err != nil { panic(err) } - + hc.r, hc.rm, err = hc.getStream(aliceSharedSecret) hc.w, hc.wm, err = hc.getStream(aliceSharedSecret) return @@ -672,6 +672,7 @@ func FrodoKEMAcceptSetup(c *net.Conn, hc *Conn) (err error) { } pubB, secB := kem.Keygen() + // [Alice sends use a public key (na, ea) pubA_bigint := big.NewInt(0) _, err = fmt.Fscanf(*c, "0x%x\n", pubA_bigint) @@ -695,7 +696,7 @@ func FrodoKEMAcceptSetup(c *net.Conn, hc *Conn) (err error) { // (... and send cipher, connection opts) fmt.Fprintf(*c, "0x%x:0x%x\n", hc.cipheropts, hc.opts) - + // Bob, step 3: Create ctBtoA, shareB ctBtoA, shareB, err := kem.Encapsulate(pubA) if err != nil { @@ -1172,8 +1173,10 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { return Conn{}, err } + // Finally, ensure alg proposed by client is allowed by server config + //if hc.kex.String() { log.Println("[hc.Accept successful]") - return hc, err + return } /*---------------------------------------------------------------------*/