From a6640c603b7a15d3531980116fdce15d1743c865 Mon Sep 17 00:00:00 2001 From: Lena Date: Wed, 1 Jul 2026 00:00:00 +0000 Subject: rsh: bound the SSH handshake ssh.Dial applies its Timeout only to the TCP connect, so a host that accepts the connection and then stalls the SSH handshake hangs the sync forever. Dial with a timeout, run the handshake under a deadline, and clear the deadline once the connection is established. --- rsh/main.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/rsh/main.go b/rsh/main.go index dfcea0b..68b6e49 100644 --- a/rsh/main.go +++ b/rsh/main.go @@ -203,7 +203,24 @@ func dial(user, host string, hostKey ssh.HostKeyCallback) (*ssh.Client, error) { Timeout: dialTimeout, } addr := net.JoinHostPort(host, strconv.Itoa(port)) - return ssh.Dial("tcp", addr, cfg) + conn, err := net.DialTimeout("tcp", addr, dialTimeout) + if err != nil { + return nil, err + } + if err := conn.SetDeadline(time.Now().Add(dialTimeout)); err != nil { + conn.Close() + return nil, err + } + clientConn, chans, reqs, err := ssh.NewClientConn(conn, addr, cfg) + if err != nil { + conn.Close() + return nil, err + } + if err := conn.SetDeadline(time.Time{}); err != nil { + clientConn.Close() + return nil, err + } + return ssh.NewClient(clientConn, chans, reqs), nil } // parseTransport extracts the user, host, and remote command from the argument -- cgit v1.2.3