aboutsummaryrefslogtreecommitdiff
path: root/src/channels.c
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2012-12-23 23:10:29 +0100
committerAris Adamantiadis <aris@0xbadc0de.be>2012-12-23 23:10:29 +0100
commit6d61c3ce4a5bf8fa739ae6f6544a01084dbc978d (patch)
treed4bf27768b9c9a31b8021af69a5a8d046927a27e /src/channels.c
parent63c3f0e7368c7286a960c65422513850ce192124 (diff)
downloadlibssh-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.c21
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,