fix(tsconnect/wasm): close conn on upgradeTLS configuration errors too
Previously only a handshake failure closed the underlying conn; configuration errors (malformed caCerts PEM, bad cert/key pair) returned with the conn still open, while the JS wrapper treats every upgradeTLS rejection as fatal and marks the conn closed — leaking a live Go conn that could no longer be closed from JS. Close on every error path so the JS contract (any rejection after validation is fatal) holds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
This commit was merged in pull request #14.
This commit is contained in:
@@ -1482,9 +1482,11 @@ func wrapConn(conn net.Conn) map[string]any {
|
|||||||
}),
|
}),
|
||||||
// upgradeTLS wraps the conn in TLS in place (STARTTLS-style) and
|
// upgradeTLS wraps the conn in TLS in place (STARTTLS-style) and
|
||||||
// returns a new wrapped conn sharing the same underlying net.Conn;
|
// returns a new wrapped conn sharing the same underlying net.Conn;
|
||||||
// the old handle must not be used afterward. On handshake failure
|
// the old handle must not be used afterward. On any failure —
|
||||||
// the underlying conn is closed. With isServer, certPem and keyPem
|
// configuration or handshake — the underlying conn is closed, so
|
||||||
// are required; otherwise client options as in dialTLS apply.
|
// callers can treat every rejection as fatal to the connection.
|
||||||
|
// With isServer, certPem and keyPem are required; otherwise client
|
||||||
|
// options as in dialTLS apply.
|
||||||
"upgradeTLS": js.FuncOf(func(this js.Value, args []js.Value) any {
|
"upgradeTLS": js.FuncOf(func(this js.Value, args []js.Value) any {
|
||||||
opts := js.Undefined()
|
opts := js.Undefined()
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
@@ -1497,16 +1499,19 @@ func wrapConn(conn net.Conn) map[string]any {
|
|||||||
certPem := opts.Get("certPem")
|
certPem := opts.Get("certPem")
|
||||||
keyPem := opts.Get("keyPem")
|
keyPem := opts.Get("keyPem")
|
||||||
if certPem.Type() != js.TypeString || keyPem.Type() != js.TypeString {
|
if certPem.Type() != js.TypeString || keyPem.Type() != js.TypeString {
|
||||||
|
conn.Close()
|
||||||
return nil, fmt.Errorf("upgradeTLS: certPem and keyPem are required when isServer is set")
|
return nil, fmt.Errorf("upgradeTLS: certPem and keyPem are required when isServer is set")
|
||||||
}
|
}
|
||||||
cert, err := tls.X509KeyPair([]byte(certPem.String()), []byte(keyPem.String()))
|
cert, err := tls.X509KeyPair([]byte(certPem.String()), []byte(keyPem.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
return nil, fmt.Errorf("upgradeTLS: parsing cert/key: %w", err)
|
return nil, fmt.Errorf("upgradeTLS: parsing cert/key: %w", err)
|
||||||
}
|
}
|
||||||
tlsConn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}})
|
tlsConn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}})
|
||||||
} else {
|
} else {
|
||||||
cfg, err := tlsClientConfigFromJS("", opts)
|
cfg, err := tlsClientConfigFromJS("", opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tlsConn = tls.Client(conn, cfg)
|
tlsConn = tls.Client(conn, cfg)
|
||||||
|
|||||||
Reference in New Issue
Block a user