diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2012-12-23 23:10:29 +0100 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2012-12-23 23:10:29 +0100 |
commit | 6d61c3ce4a5bf8fa739ae6f6544a01084dbc978d (patch) | |
tree | d4bf27768b9c9a31b8021af69a5a8d046927a27e /src/channels.c | |
parent | 63c3f0e7368c7286a960c65422513850ce192124 (diff) | |
download | libssh-6d61c3ce4a5bf8fa739ae6f6544a01084dbc978d.tar.gz libssh-6d61c3ce4a5bf8fa739ae6f6544a01084dbc978d.tar.xz libssh-6d61c3ce4a5bf8fa739ae6f6544a01084dbc978d.zip |
Fix channel_write to wait during key reexchanges
Diffstat (limited to 'src/channels.c')
-rw-r--r-- | src/channels.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/src/channels.c b/src/channels.c index 13d6d302..b51ff574 100644 --- a/src/channels.c +++ b/src/channels.c @@ -1198,6 +1198,20 @@ static int ssh_channel_waitwindow_termination(void *c){ return 0; } +/* This termination function waits until the session is not in blocked status + * anymore, e.g. because of a key re-exchange. + */ +static int ssh_waitsession_unblocked(void *s){ + ssh_session session = (ssh_session)s; + switch (session->session_state){ + case SSH_SESSION_STATE_DH: + case SSH_SESSION_STATE_INITIAL_KEX: + case SSH_SESSION_STATE_KEXINIT_RECEIVED: + return 0; + default: + return 1; + } +} /** * @internal * @brief Flushes a channel (and its session) until the output buffer @@ -1264,7 +1278,12 @@ int channel_write_common(ssh_channel channel, const void *data, return rc; } #endif - + if (ssh_waitsession_unblocked(session) == 0){ + rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, + ssh_waitsession_unblocked, session); + if (rc == SSH_ERROR || !ssh_waitsession_unblocked(session)) + goto out; + } while (len > 0) { if (channel->remote_window < len) { ssh_log(session, SSH_LOG_PROTOCOL, |