From 1d11d02aa9ee61b35aa024a2ce4a39a4a65eaeb2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Nov 2010 14:56:14 +0100 Subject: [PATCH] packets: code cleanup I added size checks in several places. I fixed the code flow to be easier to read in some places. I removed unnecessary zeroing of structs. I removed unused struct fields. --- src/libssh2_priv.h | 12 +- src/packet.c | 571 +++++++++++++++++++++------------------------ 2 files changed, 275 insertions(+), 308 deletions(-) diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index d73a609..23c5ff5 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -304,18 +304,13 @@ struct _LIBSSH2_PACKET { struct list_node node; /* linked list header */ - unsigned char type; - - /* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */ + /* the raw unencrypted payload */ unsigned char *data; size_t data_len; /* Where to start reading data from, * used for channel data that's been partially consumed */ unsigned long data_head; - - /* Can the message be confirmed? */ - int mac; }; typedef struct _libssh2_channel_data @@ -745,9 +740,8 @@ struct _LIBSSH2_SESSION /* State variables used in libssh2_packet_add() */ libssh2_nonblocking_states packAdd_state; - LIBSSH2_CHANNEL *packAdd_channel; - unsigned long packAdd_data_head; - key_exchange_state_t packAdd_key_state; + LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN + states */ packet_queue_listener_state_t packAdd_Qlstn_state; packet_x11_open_state_t packAdd_x11open_state; diff --git a/src/packet.c b/src/packet.c index 04146ef..466a462 100644 --- a/src/packet.c +++ b/src/packet.c @@ -415,53 +415,33 @@ int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, size_t datalen, int macstate) { - int rc; - - if (session->packAdd_state == libssh2_NB_state_idle) { - session->packAdd_data_head = 0; - - /* Zero the whole thing out */ - memset(&session->packAdd_key_state, 0, - sizeof(session->packAdd_key_state)); - - /* Zero the whole thing out */ - memset(&session->packAdd_Qlstn_state, 0, - sizeof(session->packAdd_Qlstn_state)); - - /* Zero the whole thing out */ - memset(&session->packAdd_x11open_state, 0, - sizeof(session->packAdd_x11open_state)); + int rc = 0; + char *message=NULL; + char *language=NULL; + size_t message_len=0; + size_t language_len=0; + LIBSSH2_CHANNEL *channelp = NULL; + size_t data_head = 0; + unsigned char msg = data[0]; + switch(session->packAdd_state) { + case libssh2_NB_state_idle: _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Packet type %d received, length=%d", - (int) data[0], (int) datalen); - if (macstate == LIBSSH2_MAC_INVALID) { - if (session->macerror && - LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) { - /* Calling app has given the OK, Process it anyway */ - macstate = LIBSSH2_MAC_CONFIRMED; - } else { - if (session->ssh_msg_disconnect) { - LIBSSH2_DISCONNECT(session, SSH_DISCONNECT_MAC_ERROR, - "Invalid MAC received", - sizeof("Invalid MAC received") - 1, - "", 0); - } - LIBSSH2_FREE(session, data); - return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC, - "Invalid MAC received"); - } + (int) msg, (int) datalen); + + if ((macstate == LIBSSH2_MAC_INVALID) && + (!session->macerror || + LIBSSH2_MACERROR(session, (char *) data, datalen))) { + /* Bad MAC input, but no callback set or non-zero return from the + callback */ + + LIBSSH2_FREE(session, data); + return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC, + "Invalid MAC received"); } - session->packAdd_state = libssh2_NB_state_allocated; - } - - /* - * =============================== NOTE =============================== - * I know this is very ugly and not a really good use of "goto", but - * this case statement would be even uglier to do it any other way - */ - switch(session->packAdd_state) { + break; case libssh2_NB_state_jump1: goto libssh2_packet_add_jump_point1; case libssh2_NB_state_jump2: @@ -476,13 +456,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, break; } -/* FIXME: I've noticed that DATA is accessed without proper - * out-of-bounds checking (i.e., DATALEN) in many places - * below. --simon */ - if (session->packAdd_state == libssh2_NB_state_allocated) { /* A couple exceptions to the packet adding rule: */ - switch (data[0]) { + switch (msg) { /* byte SSH_MSG_DISCONNECT @@ -492,15 +468,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, */ case SSH_MSG_DISCONNECT: - { - char *message=NULL; - char *language=NULL; - size_t message_len=0; - size_t language_len=0; - size_t reason=0; /* RFC4253 lists no valid reason for 0 */ - if(datalen >= 5) { - reason = _libssh2_ntohu32(data + 1); + size_t reason = _libssh2_ntohu32(data + 1); if(datalen >= 9) { message_len = _libssh2_ntohu32(data + 5); @@ -522,26 +491,24 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, /* bad size, clear it */ message_len=0; } + if (session->ssh_msg_disconnect) { + LIBSSH2_DISCONNECT(session, reason, message, + message_len, language, language_len); + } + _libssh2_debug(session, LIBSSH2_TRACE_TRANS, + "Disconnect(%d): %s(%s)", reason, + message, language); } - if (session->ssh_msg_disconnect) { - LIBSSH2_DISCONNECT(session, reason, message, - message_len, language, language_len); - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Disconnect(%d): %s(%s)", reason, - message, language); + LIBSSH2_FREE(session, data); session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; session->packAdd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, "socket disconnect"); - } - break; - - /* - byte SSH_MSG_IGNORE - string data - */ + /* + byte SSH_MSG_IGNORE + string data + */ case SSH_MSG_IGNORE: if (datalen >= 2) { @@ -563,15 +530,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, */ case SSH_MSG_DEBUG: - { - int always_display=0; - char *message=NULL; - char *language=NULL; - size_t message_len=0; - size_t language_len=0; - if(datalen >= 2) { - always_display = data[1]; + int always_display=always_display = data[1]; if(datalen >= 6) { message_len = _libssh2_ntohu32(data + 2); @@ -585,11 +545,11 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, language = (char *) data + 10 + message_len; } } - } - if (session->ssh_msg_debug) { - LIBSSH2_DEBUG(session, always_display, message, - message_len, language, language_len); + if (session->ssh_msg_debug) { + LIBSSH2_DEBUG(session, always_display, message, + message_len, language, language_len); + } } /* * _libssh2_debug will actually truncate this for us so @@ -600,21 +560,18 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return 0; - } - /* - byte SSH_MSG_GLOBAL_REQUEST - string request name in US-ASCII only - boolean want reply - .... request-specific data follows - */ + /* + byte SSH_MSG_GLOBAL_REQUEST + string request name in US-ASCII only + boolean want reply + .... request-specific data follows + */ case SSH_MSG_GLOBAL_REQUEST: - { - uint32_t len =0; - unsigned char want_reply=0; - if(datalen >= 5) { + uint32_t len =0; + unsigned char want_reply=0; len = _libssh2_ntohu32(data + 1); if(datalen >= (6 + len)) { want_reply = data[5 + len]; @@ -623,32 +580,33 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, "Received global request type %.*s (wr %X)", len, data + 5, want_reply); } - } - if (want_reply) { - libssh2_packet_add_jump_point5: - session->packAdd_state = libssh2_NB_state_jump5; - data[0] = SSH_MSG_REQUEST_FAILURE; - rc = _libssh2_transport_send(session, data, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - } - break; - /* - byte SSH_MSG_CHANNEL_EXTENDED_DATA - uint32 recipient channel - uint32 data_type_code - string data - */ + if (want_reply) { + unsigned char packet = SSH_MSG_REQUEST_FAILURE; + libssh2_packet_add_jump_point5: + session->packAdd_state = libssh2_NB_state_jump5; + rc = _libssh2_transport_send(session, &packet, 1, NULL, 0); + if (rc == LIBSSH2_ERROR_EAGAIN) + return rc; + } + } + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return 0; + + /* + byte SSH_MSG_CHANNEL_EXTENDED_DATA + uint32 recipient channel + uint32 data_type_code + string data + */ case SSH_MSG_CHANNEL_EXTENDED_DATA: /* streamid(4) */ - session->packAdd_data_head += 4; + data_head += 4; + + /* fall-through */ /* byte SSH_MSG_CHANNEL_DATA @@ -658,12 +616,14 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, case SSH_MSG_CHANNEL_DATA: /* packet_type(1) + channelno(4) + datalen(4) */ - session->packAdd_data_head += 9; + data_head += 9; - session->packAdd_channel = - _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); + if(datalen >= data_head) + channelp = + _libssh2_channel_locate(session, + _libssh2_ntohu32(data + 1)); - if (!session->packAdd_channel) { + if (!channelp) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, "Packet received for unknown channel"); LIBSSH2_FREE(session, data); @@ -672,33 +632,34 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } #ifdef LIBSSH2DEBUG { - unsigned long stream_id = 0; - if (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) { + uint32_t stream_id = 0; + if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA) stream_id = _libssh2_ntohu32(data + 5); - } _libssh2_debug(session, LIBSSH2_TRACE_CONN, "%d bytes packet_add() for %lu/%lu/%lu", - (int) (datalen - session->packAdd_data_head), - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id, + (int) (datalen - data_head), + channelp->local.id, + channelp->remote.id, stream_id); } #endif - if ((session->packAdd_channel->remote.extended_data_ignore_mode == + if ((channelp->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && - (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) { + (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) { /* Pretend we didn't receive this */ LIBSSH2_FREE(session, data); _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Ignoring extended data and refunding %d bytes", (int) (datalen - 13)); + session->packAdd_channelp = channelp; + /* Adjust the window based on the block we just freed */ libssh2_packet_add_jump_point1: session->packAdd_state = libssh2_NB_state_jump1; rc = _libssh2_channel_receive_window_adjust(session-> - packAdd_channel, + packAdd_channelp, datalen - 13, 0, NULL); if (rc == LIBSSH2_ERROR_EAGAIN) @@ -712,8 +673,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * REMEMBER! remote means remote as source of data, * NOT remote window! */ - if (session->packAdd_channel->remote.packet_size < - (datalen - session->packAdd_data_head)) { + if (channelp->remote.packet_size < (datalen - data_head)) { /* * Spec says we MAY ignore bytes sent beyond * packet_size @@ -722,11 +682,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, "Packet contains more data than we offered" " to receive, truncating"); - datalen = - session->packAdd_channel->remote.packet_size + - session->packAdd_data_head; + datalen = channelp->remote.packet_size + data_head; } - if (session->packAdd_channel->remote.window_size <= 0) { + if (channelp->remote.window_size <= 0) { /* * Spec says we MAY ignore bytes sent beyond * window_size @@ -740,138 +698,147 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, return 0; } /* Reset EOF status */ - session->packAdd_channel->remote.eof = 0; + channelp->remote.eof = 0; - if ((datalen - session->packAdd_data_head) > - session->packAdd_channel->remote.window_size) { + if ((datalen - data_head) > channelp->remote.window_size) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "Remote sent more data than current " "window allows, truncating"); - datalen = - session->packAdd_channel->remote.window_size + - session->packAdd_data_head; + datalen = channelp->remote.window_size + data_head; } - else { + else /* Now that we've received it, shrink our window */ - session->packAdd_channel->remote.window_size -= - datalen - session->packAdd_data_head; - } + channelp->remote.window_size -= datalen - data_head; break; + /* + byte SSH_MSG_CHANNEL_EOF + uint32 recipient channel + */ + case SSH_MSG_CHANNEL_EOF: - session->packAdd_channel = - _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); - - if (!session->packAdd_channel) { + if(datalen >= 5) + channelp = + _libssh2_channel_locate(session, + _libssh2_ntohu32(data + 1)); + if (!channelp) /* We may have freed already, just quietly ignore this... */ - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; + ; + else { + _libssh2_debug(session, + LIBSSH2_TRACE_CONN, + "EOF received for channel %lu/%lu", + channelp->local.id, + channelp->remote.id); + channelp->remote.eof = 1; } - - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "EOF received for channel %lu/%lu", - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id); - session->packAdd_channel->remote.eof = 1; - LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return 0; + /* + byte SSH_MSG_CHANNEL_REQUEST + uint32 recipient channel + string request type in US-ASCII characters only + boolean want reply + .... type-specific data follows + */ + case SSH_MSG_CHANNEL_REQUEST: - { - uint32_t channel = _libssh2_ntohu32(data + 1); - uint32_t len = _libssh2_ntohu32(data + 5); - unsigned char want_reply = data[9 + len]; + if(datalen >= 9) { + uint32_t channel = _libssh2_ntohu32(data + 1); + uint32_t len = _libssh2_ntohu32(data + 5); + unsigned char want_reply = 0; - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply); + if(len < (datalen - 10)) + want_reply = data[9 + len]; - if (len == sizeof("exit-status") - 1 - && !memcmp("exit-status", data + 9, - sizeof("exit-status") - 1)) { + _libssh2_debug(session, + LIBSSH2_TRACE_CONN, + "Channel %d received request type %.*s (wr %X)", + channel, len, data + 9, want_reply); - /* we've got "exit-status" packet. Set the session value */ - session->packAdd_channel = - _libssh2_channel_locate(session, channel); + if (len == sizeof("exit-status") - 1 + && !memcmp("exit-status", data + 9, + sizeof("exit-status") - 1)) { - if (session->packAdd_channel) { - session->packAdd_channel->exit_status = - _libssh2_ntohu32(data + 9 + sizeof("exit-status")); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit status %lu received for " - "channel %lu/%lu", - session->packAdd_channel->exit_status, - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id); - } + /* we've got "exit-status" packet. Set the session value */ + if(datalen >= 20) + channelp = + _libssh2_channel_locate(session, channel); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - - if (len == sizeof("exit-signal") - 1 - && !memcmp("exit-signal", data + 9, - sizeof("exit-signal") - 1)) { - - /* command terminated due to signal */ - session->packAdd_channel = - _libssh2_channel_locate(session, channel); - - if (session->packAdd_channel) { - /* set signal name (without SIG prefix) */ - uint32_t namelen = _libssh2_ntohu32(data + 9 + - sizeof("exit-signal")); - session->packAdd_channel->exit_signal = - LIBSSH2_ALLOC(session, namelen + 1); - if (!session->packAdd_channel->exit_signal) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for signal name"); - } else { - memcpy(session->packAdd_channel->exit_signal, - data + 13 + sizeof("exit_signal"), namelen); - session->packAdd_channel->exit_signal[namelen] = '\0'; - /* TODO: save error message and language tag */ + if (channelp) { + channelp->exit_status = + _libssh2_ntohu32(data + 9 + sizeof("exit-status")); _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit signal %s received for " + "Exit status %lu received for " "channel %lu/%lu", - session->packAdd_channel->exit_signal, - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id); + channelp->exit_status, + channelp->local.id, + channelp->remote.id); + } + + } + else if (len == sizeof("exit-signal") - 1 + && !memcmp("exit-signal", data + 9, + sizeof("exit-signal") - 1)) { + /* command terminated due to signal */ + if(datalen >= 20) + channelp = _libssh2_channel_locate(session, channel); + + if (channelp) { + /* set signal name (without SIG prefix) */ + uint32_t namelen = + _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); + channelp->exit_signal = + LIBSSH2_ALLOC(session, namelen + 1); + if (!channelp->exit_signal) + rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "memory for signal name"); + else { + memcpy(channelp->exit_signal, + data + 13 + sizeof("exit_signal"), namelen); + channelp->exit_signal[namelen] = '\0'; + /* TODO: save error message and language tag */ + _libssh2_debug(session, LIBSSH2_TRACE_CONN, + "Exit signal %s received for " + "channel %lu/%lu", + channelp->exit_signal, + channelp->local.id, + channelp->remote.id); + } } } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - if (want_reply) { - libssh2_packet_add_jump_point4: - session->packAdd_state = libssh2_NB_state_jump4; - data[0] = SSH_MSG_CHANNEL_FAILURE; - rc = _libssh2_transport_send(session, data, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; + if (want_reply) { + unsigned char packet[5]; + libssh2_packet_add_jump_point4: + session->packAdd_state = libssh2_NB_state_jump4; + packet[0] = SSH_MSG_CHANNEL_FAILURE; + memcpy(&packet[1], data+1, 4); + rc = _libssh2_transport_send(session, packet, 5, NULL, 0); + if (rc == LIBSSH2_ERROR_EAGAIN) + return rc; + } } - break; - } + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return rc; + + /* + byte SSH_MSG_CHANNEL_CLOSE + uint32 recipient channel + */ case SSH_MSG_CHANNEL_CLOSE: - session->packAdd_channel = - _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); - - if (!session->packAdd_channel) { + if(datalen >= 5) + channelp = + _libssh2_channel_locate(session, + _libssh2_ntohu32(data + 1)); + if (!channelp) { /* We may have freed already, just quietly ignore this... */ LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; @@ -879,106 +846,117 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Close received for channel %lu/%lu", - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id); + channelp->local.id, + channelp->remote.id); - session->packAdd_channel->remote.close = 1; - session->packAdd_channel->remote.eof = 1; + channelp->remote.close = 1; + channelp->remote.eof = 1; LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return 0; + /* + byte SSH_MSG_CHANNEL_OPEN + string "session" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + */ + case SSH_MSG_CHANNEL_OPEN: - if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && - ((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1)) - && - (memcmp(data + 5, "forwarded-tcpip", - sizeof("forwarded-tcpip") - 1) == 0)) { + if(datalen < 17) + ; + else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && + ((sizeof("forwarded-tcpip") - 1) == + _libssh2_ntohu32(data + 1)) + && + (memcmp(data + 5, "forwarded-tcpip", + sizeof("forwarded-tcpip") - 1) == 0)) { + + /* init the state struct */ + memset(&session->packAdd_Qlstn_state, 0, + sizeof(session->packAdd_Qlstn_state)); libssh2_packet_add_jump_point2: session->packAdd_state = libssh2_NB_state_jump2; rc = packet_queue_listener(session, data, datalen, &session->packAdd_Qlstn_state); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return rc; } - if ((datalen >= (sizeof("x11") + 4)) && - ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && - (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { + else if ((datalen >= (sizeof("x11") + 4)) && + ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && + (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { + + /* init the state struct */ + memset(&session->packAdd_x11open_state, 0, + sizeof(session->packAdd_x11open_state)); libssh2_packet_add_jump_point3: session->packAdd_state = libssh2_NB_state_jump3; rc = packet_x11_open(session, data, datalen, &session->packAdd_x11open_state); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; + } + if (rc == LIBSSH2_ERROR_EAGAIN) return rc; - } - break; - - case SSH_MSG_CHANNEL_WINDOW_ADJUST: - { - unsigned long bytestoadd = _libssh2_ntohu32(data + 5); - session->packAdd_channel = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - - if (session->packAdd_channel && bytestoadd) { - session->packAdd_channel->local.window_size += bytestoadd; - } - if(session->packAdd_channel) - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Window adjust received for channel %lu/%lu, " - "adding %lu bytes, new window_size=%lu", - session->packAdd_channel->local.id, - session->packAdd_channel->remote.id, - bytestoadd, - session->packAdd_channel->local.window_size); - else - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Window adjust for non-existing channel!"); + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return rc; + + /* + byte SSH_MSG_CHANNEL_WINDOW_ADJUST + uint32 recipient channel + uint32 bytes to add + */ + case SSH_MSG_CHANNEL_WINDOW_ADJUST: + if(datalen < 9) + ; + else { + uint32_t bytestoadd = _libssh2_ntohu32(data + 5); + channelp = + _libssh2_channel_locate(session, + _libssh2_ntohu32(data + 1)); + if(channelp) { + channelp->local.window_size += bytestoadd; + + _libssh2_debug(session, LIBSSH2_TRACE_CONN, + "Window adjust for channel %lu/%lu, " + "adding %lu bytes, new window_size=%lu", + channelp->local.id, + channelp->remote.id, + bytestoadd, + channelp->local.window_size); + } + } LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return 0; - } - break; + default: + break; } session->packAdd_state = libssh2_NB_state_sent; } if (session->packAdd_state == libssh2_NB_state_sent) { - LIBSSH2_PACKET *packAdd_packet; - packAdd_packet = + LIBSSH2_PACKET *packetp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); - if (!packAdd_packet) { + if (!packetp) { _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for LIBSSH2_PACKET"); + "memory for packet"); session->packAdd_state = libssh2_NB_state_idle; - return -1; + return LIBSSH2_ERROR_ALLOC; } - memset(packAdd_packet, 0, sizeof(LIBSSH2_PACKET)); + packetp->data = data; + packetp->data_len = datalen; + packetp->data_head = data_head; - packAdd_packet->data = data; - packAdd_packet->data_len = datalen; - packAdd_packet->data_head = session->packAdd_data_head; - packAdd_packet->mac = macstate; - - _libssh2_list_add(&session->packets, &packAdd_packet->node); + _libssh2_list_add(&session->packets, &packetp->node); session->packAdd_state = libssh2_NB_state_sent1; } - if ((data[0] == SSH_MSG_KEXINIT && + if ((msg == SSH_MSG_KEXINIT && !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) || (session->packAdd_state == libssh2_NB_state_sent2)) { if (session->packAdd_state == libssh2_NB_state_sent1) { @@ -1003,11 +981,6 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, session->packAdd_state = libssh2_NB_state_idle; session->fullpacket_state = libssh2_NB_state_idle; - /* - * Also, don't use packAdd_key_state for key re-exchange, - * as it will be wiped out in the middle of the exchange. - * How about re-using the startup_key_state? - */ memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t)); /*