From db453ee4c9c7fc69c7a4440bc37061370c483bb4 Mon Sep 17 00:00:00 2001 From: Palapeli <26661008+mkwcat@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:04:03 -0400 Subject: [PATCH] NAS: Fix a few issues with TLS 1.0 for Wii --- nas/listener.go | 16 +++++++--------- nas/tls.go | 26 +++++++++++++------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/nas/listener.go b/nas/listener.go index 3c94fb4..71fcfcd 100644 --- a/nas/listener.go +++ b/nas/listener.go @@ -2,7 +2,6 @@ package nas import ( "bufio" - "bytes" "errors" "io" "net" @@ -135,22 +134,21 @@ func filterDuplicateHost(w *io.PipeWriter, r *bufio.Reader) error { } // Iterate through the HTTP headers and remove any duplicate Host headers - var headers bytes.Buffer hostSeen := false - for { - headerLine, err := r.ReadString('\n') - _, wErr := w.Write([]byte(headerLine)) - if err != nil || wErr != nil || headerLine == "\r\n" || headerLine == "\n" { - headers.WriteString(headerLine) + for errPipe == nil { + line, err = r.ReadString('\n') + if err != nil || line == "\r\n" || line == "\n" { + _, errPipe = w.Write([]byte(line)) break } - if strings.HasPrefix(strings.ToLower(headerLine), "host:") { + + if strings.HasPrefix(strings.ToLower(line), "host:") { if hostSeen { continue } hostSeen = true } - headers.WriteString(headerLine) + _, errPipe = w.Write([]byte(line)) } return errPipe } diff --git a/nas/tls.go b/nas/tls.go index 9481091..4df7338 100644 --- a/nas/tls.go +++ b/nas/tls.go @@ -274,13 +274,14 @@ var ( // handleTLSHandshake handles the TLS request from the Wii or the DS, and creates tlsConn for further communication. // It may call handleRealTLS if the request is from a modern web browser. -func (c *tlsConnection) handleTLSHandshake() error { +func (c *tlsConnection) handleTLSHandshake() (err error) { moduleName := "NAS-TLS:" + c.Conn.RemoteAddr().String() // Recover from panics. TODO: is this really necessary? defer func() { if r := recover(); r != nil { logging.Error(moduleName, "Panic:", r) + err = errors.New("panic occurred during TLS handshake") } }() @@ -292,7 +293,6 @@ func (c *tlsConnection) handleTLSHandshake() error { // Read client hello var peekMatchWii, peekMatchDS bool consumed := []byte{} - var err error if rsaKeyDS != nil { consumed, err = readBytes(c.Conn, dsClientHelloPrefix, consumed) peekMatchDS = err == nil @@ -338,6 +338,7 @@ func (c *tlsConnection) handleTLSHandshake() error { Cipher: cipher, ClientCipher: clientCipher, Version: version, + Seq: 1, } c.handshake = true return nil @@ -368,7 +369,7 @@ type consoleTLSConn struct { Cipher *rc4.Cipher ClientCipher *rc4.Cipher Version uint16 - seq uint64 + Seq uint64 decodedBuffer bytes.Buffer encodedBuffer bytes.Buffer } @@ -379,7 +380,7 @@ func (c *consoleTLSConn) Read(b []byte) (n int, err error) { } recordLength := uint16(0) - for c.encodedBuffer.Len() < int(recordLength)+5 { + for { for c.encodedBuffer.Len() < int(recordLength)+5 { readBuf := make([]byte, 1024) n, err = c.Conn.Read(readBuf) @@ -402,10 +403,14 @@ func (c *consoleTLSConn) Read(b []byte) (n int, err error) { if recordLength < 17 || (recordLength+5) > 0x1000 { return 0, errors.New("invalid record length") } + + if c.encodedBuffer.Len() >= int(recordLength)+5 { + break + } } - // Decrypt content buf := c.encodedBuffer.Bytes() + // Decrypt content c.ClientCipher.XORKeyStream(buf[5:5+recordLength], buf[5:5+recordLength]) if buf[0] != 0x17 { @@ -419,7 +424,7 @@ func (c *consoleTLSConn) Read(b []byte) (n int, err error) { return 0, errors.New("non-application data received") } // Write the decrypted content to the buffer - if int(recordLength-16) > len(b) { + if int(recordLength-5-16) > len(b) { c.decodedBuffer.Write(buf[5+len(b) : 5+recordLength-16]) } c.encodedBuffer.Next(5 + int(recordLength)) @@ -429,12 +434,12 @@ func (c *consoleTLSConn) Read(b []byte) (n int, err error) { func (c *consoleTLSConn) Write(b []byte) (n int, err error) { var record []byte - record, c.seq = encryptTLS(c.MacFn, c.Cipher, b, c.seq, []byte{0x17, 0x03, 0x01, byte(len(b) >> 8), byte(len(b))}) + record, c.Seq = encryptTLS(c.MacFn, c.Cipher, b, c.Seq, []byte{0x17, 0x03, 0x01, byte(len(b) >> 8), byte(len(b))}) return c.Conn.Write(record) } func handleWiiTLSHandshake(moduleName string, conn io.ReadWriter) (macFn macFunction, cipher *rc4.Cipher, clientCipher *rc4.Cipher, err error) { - clientHello := append(wiiClientHelloPrefix, make([]byte, 0x2-len(wiiClientHelloPrefix))...) + clientHello := append(wiiClientHelloPrefix, make([]byte, 0x2D-len(wiiClientHelloPrefix))...) _, err = io.ReadFull(conn, clientHello[len(wiiClientHelloPrefix):]) if err != nil { logging.Error(moduleName, "Failed to read client hello:", err) @@ -479,7 +484,6 @@ func handleWiiTLSHandshake(moduleName string, conn io.ReadWriter) (macFn macFunc return } - // fmt.Printf("Client key exchange:\n") buf := make([]byte, 0x1000) index := 0 // Read client key exchange (+ change cipher spec + finished) @@ -538,8 +542,6 @@ func handleWiiTLSHandshake(moduleName string, conn io.ReadWriter) (macFn macFunc return } - // fmt.Printf("Pre master secret:\n% X\n", preMasterSecret) - if len(preMasterSecret) != 48 { logging.Error(moduleName, "Invalid pre master secret length:", aurora.BrightCyan(len(preMasterSecret))) err = errors.New("invalid pre master secret length") @@ -699,8 +701,6 @@ func handleDSSSLHandshake(moduleName string, conn io.ReadWriter) (macFn macFunct return } - // fmt.Printf("Pre master secret:\n% X\n", preMasterSecret) - if len(preMasterSecret) != 48 { logging.Error(moduleName, "Invalid pre master secret length:", aurora.BrightCyan(len(preMasterSecret))) err = errors.New("invalid pre master secret length")