Skip to content

Fix client state hostkey wait timeout handling#6

Open
precla wants to merge 2 commits into
mainfrom
fix_CLIENT_STATE_HOSTKEY_WAIT_timeout_handling
Open

Fix client state hostkey wait timeout handling#6
precla wants to merge 2 commits into
mainfrom
fix_CLIENT_STATE_HOSTKEY_WAIT_timeout_handling

Conversation

@precla

@precla precla commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

i've found one possible issue and i have a test for it to reproduce the issue. both with the help of Claude, i did double check the code and the flow to verify it

connect_timeout doesn't cover host-key verification timeout within on_hostkey()

for example if on_hostkey() takes too long for whatever reason or if accept_hostkey()/reject_hostkey() are not called (even tho the last one doesn't make sense to not call one of the two..) then the timeout of c->connect_timer is never reached since it is stopped too soon in the moment the transport handshake completes (CLIENT_STATE_CONNECTING -> CLIENT_STATE_HOSTKEY), before host-key verification begins. once the client reaches CLIENT_STATE_HOSTKEY_WAIT, no timer is armed (the auth timer only starts later)

the ssh client's connect_timeout should handle the entire "getting connected" phase. currently is basically handles only CLIENT_STATE_CONNECTING, but not CLIENT_STATE_HOSTKEY_WAIT. which happens in between when the client receives the server's host key and is waiting for on_hostkey() handler to call accept_hostkey()/reject_hostkey() (or for whatever reason do some other 'magic')

the states CLIENT_STATE_HOSTKEY_WAIT and CLIENT_STATE_HOSTKEY are checked in connect_timeout_cb() so code should time-out in that case but it never does since those states never reach the connect_timeout_cb() if on_hostkey() takes too long

static void connect_timeout_cb(uv_timer_t *timer) {
    ssh_client_ctx *c = (ssh_client_ctx *)timer->data;
    if (c == NULL)
        return;
    if (c->state == CLIENT_STATE_CONNECTING || c->state == CLIENT_STATE_HOSTKEY || c->state == CLIENT_STATE_HOSTKEY_WAIT) {
        client_fail(c, "SSH connect timeout");
    }
}

if the on_hostkey() handler never responds then the client hangs forever. on_connect() is never called

note: the timeout only survives into CLIENT_STATE_HOSTKEY_WAIT on a synchronous connect, which never occurs over a non-blocking socket

proposed fix: stop the connect timer when authentication begins in client_start_auth_timer(), not when the transport connects

test _test_hostkey_stall added

precla added 2 commits July 1, 2026 14:52
Signed-off-by: Antonio Prcela <antonio.prcela@sartura.hr>
Signed-off-by: Antonio Prcela <antonio.prcela@sartura.hr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant