-
Notifications
You must be signed in to change notification settings - Fork 146
fix: indefinite hangs during TLS handshake and cipher enumeration #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -257,10 +257,12 @@ func (c *Client) EnumerateCiphers(hostname, ip, port string, options clients.Con | |||||||||||||||||||||||||||||||||
| conn := tls.Client(baseConn, baseCfg) | ||||||||||||||||||||||||||||||||||
| baseCfg.CipherSuites = []uint16{ztlsCiphers[v]} | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if err := c.tlsHandshakeWithTimeout(conn, context.TODO()); err == nil { | ||||||||||||||||||||||||||||||||||
| ctx, cancel := context.WithTimeout(context.Background(), time.Duration(c.options.Timeout)*time.Second) | ||||||||||||||||||||||||||||||||||
| if err := c.tlsHandshakeWithTimeout(conn, ctx); err == nil { | ||||||||||||||||||||||||||||||||||
| h1 := conn.GetHandshakeLog() | ||||||||||||||||||||||||||||||||||
| enumeratedCiphers = append(enumeratedCiphers, h1.ServerHello.CipherSuite.String()) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| cancel() | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+260
to
+265
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same timeout validation issue: This matches the issue in 🐛 Proposed fix to guard against zero timeout+ timeout := time.Duration(c.options.Timeout) * time.Second
+ if timeout == 0 {
+ timeout = 5 * time.Second // default timeout
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
- ctx, cancel := context.WithTimeout(context.Background(), time.Duration(c.options.Timeout)*time.Second)
if err := c.tlsHandshakeWithTimeout(conn, ctx); err == nil {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| _ = conn.Close() // also closes baseConn internally | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return enumeratedCiphers, nil | ||||||||||||||||||||||||||||||||||
|
|
@@ -323,17 +325,18 @@ func (c *Client) getConfig(hostname, ip, port string, options clients.ConnectOpt | |||||||||||||||||||||||||||||||||
| // tlsHandshakeWithCtx attempts tls handshake with given timeout | ||||||||||||||||||||||||||||||||||
| func (c *Client) tlsHandshakeWithTimeout(tlsConn *tls.Conn, ctx context.Context) error { | ||||||||||||||||||||||||||||||||||
| errChan := make(chan error, 1) | ||||||||||||||||||||||||||||||||||
| defer close(errChan) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| go func() { | ||||||||||||||||||||||||||||||||||
| errChan <- tlsConn.Handshake() | ||||||||||||||||||||||||||||||||||
| }() | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| select { | ||||||||||||||||||||||||||||||||||
| case <-ctx.Done(): | ||||||||||||||||||||||||||||||||||
| return errorutil.NewWithTag("ztls", "timeout while attempting handshake") //nolint | ||||||||||||||||||||||||||||||||||
| case errChan <- tlsConn.Handshake(): | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| err := <-errChan | ||||||||||||||||||||||||||||||||||
| if err == tls.ErrCertsOnly { | ||||||||||||||||||||||||||||||||||
| err = nil | ||||||||||||||||||||||||||||||||||
| case err := <-errChan: | ||||||||||||||||||||||||||||||||||
| if err == tls.ErrCertsOnly { | ||||||||||||||||||||||||||||||||||
| err = nil | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing timeout validation:
Timeout == 0causes immediate context expiration.Unlike
ConnectWithOptions(lines 110-113), this code does not checkc.options.Timeout != 0before creating the context. IfTimeoutis 0,context.WithTimeout(..., 0)creates an already-expired context, causing every handshake to fail immediately.🐛 Proposed fix to guard against zero timeout
Alternatively, skip the timeout wrapper when
Timeout == 0to matchConnectWithOptionsbehavior.🤖 Prompt for AI Agents