1
1
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.
Этот коммит содержится в:
Daniel Stenberg 2010-11-10 14:56:14 +01:00
родитель f4ad3e0120
Коммит 1d11d02aa9
2 изменённых файлов: 275 добавлений и 308 удалений

Просмотреть файл

@ -304,18 +304,13 @@ struct _LIBSSH2_PACKET
{ {
struct list_node node; /* linked list header */ struct list_node node; /* linked list header */
unsigned char type; /* the raw unencrypted payload */
/* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
unsigned char *data; unsigned char *data;
size_t data_len; size_t data_len;
/* Where to start reading data from, /* Where to start reading data from,
* used for channel data that's been partially consumed */ * used for channel data that's been partially consumed */
unsigned long data_head; unsigned long data_head;
/* Can the message be confirmed? */
int mac;
}; };
typedef struct _libssh2_channel_data typedef struct _libssh2_channel_data
@ -745,9 +740,8 @@ struct _LIBSSH2_SESSION
/* State variables used in libssh2_packet_add() */ /* State variables used in libssh2_packet_add() */
libssh2_nonblocking_states packAdd_state; libssh2_nonblocking_states packAdd_state;
LIBSSH2_CHANNEL *packAdd_channel; LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN
unsigned long packAdd_data_head; states */
key_exchange_state_t packAdd_key_state;
packet_queue_listener_state_t packAdd_Qlstn_state; packet_queue_listener_state_t packAdd_Qlstn_state;
packet_x11_open_state_t packAdd_x11open_state; packet_x11_open_state_t packAdd_x11open_state;

Просмотреть файл

@ -415,53 +415,33 @@ int
_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate) size_t datalen, int macstate)
{ {
int rc; int rc = 0;
char *message=NULL;
if (session->packAdd_state == libssh2_NB_state_idle) { char *language=NULL;
session->packAdd_data_head = 0; size_t message_len=0;
size_t language_len=0;
/* Zero the whole thing out */ LIBSSH2_CHANNEL *channelp = NULL;
memset(&session->packAdd_key_state, 0, size_t data_head = 0;
sizeof(session->packAdd_key_state)); unsigned char msg = data[0];
/* 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));
switch(session->packAdd_state) {
case libssh2_NB_state_idle:
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Packet type %d received, length=%d", "Packet type %d received, length=%d",
(int) data[0], (int) datalen); (int) msg, (int) datalen);
if (macstate == LIBSSH2_MAC_INVALID) {
if (session->macerror && if ((macstate == LIBSSH2_MAC_INVALID) &&
LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) { (!session->macerror ||
/* Calling app has given the OK, Process it anyway */ LIBSSH2_MACERROR(session, (char *) data, datalen))) {
macstate = LIBSSH2_MAC_CONFIRMED; /* Bad MAC input, but no callback set or non-zero return from the
} else { callback */
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); LIBSSH2_FREE(session, data);
return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC, return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
"Invalid MAC received"); "Invalid MAC received");
} }
}
session->packAdd_state = libssh2_NB_state_allocated; session->packAdd_state = libssh2_NB_state_allocated;
} break;
/*
* =============================== 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) {
case libssh2_NB_state_jump1: case libssh2_NB_state_jump1:
goto libssh2_packet_add_jump_point1; goto libssh2_packet_add_jump_point1;
case libssh2_NB_state_jump2: case libssh2_NB_state_jump2:
@ -476,13 +456,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
break; 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) { if (session->packAdd_state == libssh2_NB_state_allocated) {
/* A couple exceptions to the packet adding rule: */ /* A couple exceptions to the packet adding rule: */
switch (data[0]) { switch (msg) {
/* /*
byte SSH_MSG_DISCONNECT byte SSH_MSG_DISCONNECT
@ -492,15 +468,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/ */
case SSH_MSG_DISCONNECT: 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) { if(datalen >= 5) {
reason = _libssh2_ntohu32(data + 1); size_t reason = _libssh2_ntohu32(data + 1);
if(datalen >= 9) { if(datalen >= 9) {
message_len = _libssh2_ntohu32(data + 5); message_len = _libssh2_ntohu32(data + 5);
@ -522,7 +491,6 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* bad size, clear it */ /* bad size, clear it */
message_len=0; message_len=0;
} }
}
if (session->ssh_msg_disconnect) { if (session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, reason, message, LIBSSH2_DISCONNECT(session, reason, message,
message_len, language, language_len); message_len, language, language_len);
@ -530,14 +498,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnect(%d): %s(%s)", reason, "Disconnect(%d): %s(%s)", reason,
message, language); message, language);
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"socket disconnect"); "socket disconnect");
}
break;
/* /*
byte SSH_MSG_IGNORE byte SSH_MSG_IGNORE
string data string data
@ -563,15 +530,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/ */
case SSH_MSG_DEBUG: 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) { if(datalen >= 2) {
always_display = data[1]; int always_display=always_display = data[1];
if(datalen >= 6) { if(datalen >= 6) {
message_len = _libssh2_ntohu32(data + 2); message_len = _libssh2_ntohu32(data + 2);
@ -585,12 +545,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
language = (char *) data + 10 + message_len; language = (char *) data + 10 + message_len;
} }
} }
}
if (session->ssh_msg_debug) { if (session->ssh_msg_debug) {
LIBSSH2_DEBUG(session, always_display, message, LIBSSH2_DEBUG(session, always_display, message,
message_len, language, language_len); message_len, language, language_len);
} }
}
/* /*
* _libssh2_debug will actually truncate this for us so * _libssh2_debug will actually truncate this for us so
* that it's not an inordinate about of data * that it's not an inordinate about of data
@ -600,7 +560,6 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
}
/* /*
byte SSH_MSG_GLOBAL_REQUEST byte SSH_MSG_GLOBAL_REQUEST
@ -610,11 +569,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/ */
case SSH_MSG_GLOBAL_REQUEST: case SSH_MSG_GLOBAL_REQUEST:
{ if(datalen >= 5) {
uint32_t len =0; uint32_t len =0;
unsigned char want_reply=0; unsigned char want_reply=0;
if(datalen >= 5) {
len = _libssh2_ntohu32(data + 1); len = _libssh2_ntohu32(data + 1);
if(datalen >= (6 + len)) { if(datalen >= (6 + len)) {
want_reply = data[5 + len]; want_reply = data[5 + len];
@ -623,21 +580,20 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"Received global request type %.*s (wr %X)", "Received global request type %.*s (wr %X)",
len, data + 5, want_reply); len, data + 5, want_reply);
} }
}
if (want_reply) { if (want_reply) {
unsigned char packet = SSH_MSG_REQUEST_FAILURE;
libssh2_packet_add_jump_point5: libssh2_packet_add_jump_point5:
session->packAdd_state = libssh2_NB_state_jump5; session->packAdd_state = libssh2_NB_state_jump5;
data[0] = SSH_MSG_REQUEST_FAILURE; rc = _libssh2_transport_send(session, &packet, 1, NULL, 0);
rc = _libssh2_transport_send(session, data, 1, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) if (rc == LIBSSH2_ERROR_EAGAIN)
return rc; return rc;
}
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
}
}
break;
/* /*
byte SSH_MSG_CHANNEL_EXTENDED_DATA byte SSH_MSG_CHANNEL_EXTENDED_DATA
@ -648,7 +604,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_CHANNEL_EXTENDED_DATA: case SSH_MSG_CHANNEL_EXTENDED_DATA:
/* streamid(4) */ /* streamid(4) */
session->packAdd_data_head += 4; data_head += 4;
/* fall-through */
/* /*
byte SSH_MSG_CHANNEL_DATA byte SSH_MSG_CHANNEL_DATA
@ -658,12 +616,14 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_CHANNEL_DATA: case SSH_MSG_CHANNEL_DATA:
/* packet_type(1) + channelno(4) + datalen(4) */ /* packet_type(1) + channelno(4) + datalen(4) */
session->packAdd_data_head += 9; data_head += 9;
session->packAdd_channel = if(datalen >= data_head)
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); channelp =
_libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1));
if (!session->packAdd_channel) { if (!channelp) {
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
"Packet received for unknown channel"); "Packet received for unknown channel");
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@ -672,33 +632,34 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
} }
#ifdef LIBSSH2DEBUG #ifdef LIBSSH2DEBUG
{ {
unsigned long stream_id = 0; uint32_t stream_id = 0;
if (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) { if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)
stream_id = _libssh2_ntohu32(data + 5); stream_id = _libssh2_ntohu32(data + 5);
}
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"%d bytes packet_add() for %lu/%lu/%lu", "%d bytes packet_add() for %lu/%lu/%lu",
(int) (datalen - session->packAdd_data_head), (int) (datalen - data_head),
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id, channelp->remote.id,
stream_id); stream_id);
} }
#endif #endif
if ((session->packAdd_channel->remote.extended_data_ignore_mode == if ((channelp->remote.extended_data_ignore_mode ==
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) &&
(data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) { (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
/* Pretend we didn't receive this */ /* Pretend we didn't receive this */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Ignoring extended data and refunding %d bytes", "Ignoring extended data and refunding %d bytes",
(int) (datalen - 13)); (int) (datalen - 13));
session->packAdd_channelp = channelp;
/* Adjust the window based on the block we just freed */ /* Adjust the window based on the block we just freed */
libssh2_packet_add_jump_point1: libssh2_packet_add_jump_point1:
session->packAdd_state = libssh2_NB_state_jump1; session->packAdd_state = libssh2_NB_state_jump1;
rc = _libssh2_channel_receive_window_adjust(session-> rc = _libssh2_channel_receive_window_adjust(session->
packAdd_channel, packAdd_channelp,
datalen - 13, datalen - 13,
0, NULL); 0, NULL);
if (rc == LIBSSH2_ERROR_EAGAIN) 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, * REMEMBER! remote means remote as source of data,
* NOT remote window! * NOT remote window!
*/ */
if (session->packAdd_channel->remote.packet_size < if (channelp->remote.packet_size < (datalen - data_head)) {
(datalen - session->packAdd_data_head)) {
/* /*
* Spec says we MAY ignore bytes sent beyond * Spec says we MAY ignore bytes sent beyond
* packet_size * packet_size
@ -722,11 +682,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
"Packet contains more data than we offered" "Packet contains more data than we offered"
" to receive, truncating"); " to receive, truncating");
datalen = datalen = channelp->remote.packet_size + data_head;
session->packAdd_channel->remote.packet_size +
session->packAdd_data_head;
} }
if (session->packAdd_channel->remote.window_size <= 0) { if (channelp->remote.window_size <= 0) {
/* /*
* Spec says we MAY ignore bytes sent beyond * Spec says we MAY ignore bytes sent beyond
* window_size * window_size
@ -740,53 +698,62 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
return 0; return 0;
} }
/* Reset EOF status */ /* Reset EOF status */
session->packAdd_channel->remote.eof = 0; channelp->remote.eof = 0;
if ((datalen - session->packAdd_data_head) > if ((datalen - data_head) > channelp->remote.window_size) {
session->packAdd_channel->remote.window_size) {
_libssh2_error(session, _libssh2_error(session,
LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
"Remote sent more data than current " "Remote sent more data than current "
"window allows, truncating"); "window allows, truncating");
datalen = datalen = channelp->remote.window_size + data_head;
session->packAdd_channel->remote.window_size +
session->packAdd_data_head;
} }
else { else
/* Now that we've received it, shrink our window */ /* Now that we've received it, shrink our window */
session->packAdd_channel->remote.window_size -= channelp->remote.window_size -= datalen - data_head;
datalen - session->packAdd_data_head;
}
break; break;
/*
byte SSH_MSG_CHANNEL_EOF
uint32 recipient channel
*/
case SSH_MSG_CHANNEL_EOF: case SSH_MSG_CHANNEL_EOF:
session->packAdd_channel = if(datalen >= 5)
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); channelp =
_libssh2_channel_locate(session,
if (!session->packAdd_channel) { _libssh2_ntohu32(data + 1));
if (!channelp)
/* We may have freed already, just quietly ignore this... */ /* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data); ;
session->packAdd_state = libssh2_NB_state_idle; else {
return 0;
}
_libssh2_debug(session, _libssh2_debug(session,
LIBSSH2_TRACE_CONN, LIBSSH2_TRACE_CONN,
"EOF received for channel %lu/%lu", "EOF received for channel %lu/%lu",
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id); channelp->remote.id);
session->packAdd_channel->remote.eof = 1; channelp->remote.eof = 1;
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; 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: case SSH_MSG_CHANNEL_REQUEST:
{ if(datalen >= 9) {
uint32_t channel = _libssh2_ntohu32(data + 1); uint32_t channel = _libssh2_ntohu32(data + 1);
uint32_t len = _libssh2_ntohu32(data + 5); uint32_t len = _libssh2_ntohu32(data + 5);
unsigned char want_reply = data[9 + len]; unsigned char want_reply = 0;
if(len < (datalen - 10))
want_reply = data[9 + len];
_libssh2_debug(session, _libssh2_debug(session,
LIBSSH2_TRACE_CONN, LIBSSH2_TRACE_CONN,
@ -798,80 +765,80 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
sizeof("exit-status") - 1)) { sizeof("exit-status") - 1)) {
/* we've got "exit-status" packet. Set the session value */ /* we've got "exit-status" packet. Set the session value */
session->packAdd_channel = if(datalen >= 20)
channelp =
_libssh2_channel_locate(session, channel); _libssh2_channel_locate(session, channel);
if (session->packAdd_channel) { if (channelp) {
session->packAdd_channel->exit_status = channelp->exit_status =
_libssh2_ntohu32(data + 9 + sizeof("exit-status")); _libssh2_ntohu32(data + 9 + sizeof("exit-status"));
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Exit status %lu received for " "Exit status %lu received for "
"channel %lu/%lu", "channel %lu/%lu",
session->packAdd_channel->exit_status, channelp->exit_status,
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id); channelp->remote.id);
} }
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
} }
else if (len == sizeof("exit-signal") - 1
if (len == sizeof("exit-signal") - 1
&& !memcmp("exit-signal", data + 9, && !memcmp("exit-signal", data + 9,
sizeof("exit-signal") - 1)) { sizeof("exit-signal") - 1)) {
/* command terminated due to signal */ /* command terminated due to signal */
session->packAdd_channel = if(datalen >= 20)
_libssh2_channel_locate(session, channel); channelp = _libssh2_channel_locate(session, channel);
if (session->packAdd_channel) { if (channelp) {
/* set signal name (without SIG prefix) */ /* set signal name (without SIG prefix) */
uint32_t namelen = _libssh2_ntohu32(data + 9 + uint32_t namelen =
sizeof("exit-signal")); _libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
session->packAdd_channel->exit_signal = channelp->exit_signal =
LIBSSH2_ALLOC(session, namelen + 1); LIBSSH2_ALLOC(session, namelen + 1);
if (!session->packAdd_channel->exit_signal) { if (!channelp->exit_signal)
_libssh2_error(session, LIBSSH2_ERROR_ALLOC, rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for signal name"); "memory for signal name");
} else { else {
memcpy(session->packAdd_channel->exit_signal, memcpy(channelp->exit_signal,
data + 13 + sizeof("exit_signal"), namelen); data + 13 + sizeof("exit_signal"), namelen);
session->packAdd_channel->exit_signal[namelen] = '\0'; channelp->exit_signal[namelen] = '\0';
/* TODO: save error message and language tag */ /* TODO: save error message and language tag */
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Exit signal %s received for " "Exit signal %s received for "
"channel %lu/%lu", "channel %lu/%lu",
session->packAdd_channel->exit_signal, channelp->exit_signal,
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id); channelp->remote.id);
}
} }
} }
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
return 0;
}
if (want_reply) { if (want_reply) {
unsigned char packet[5];
libssh2_packet_add_jump_point4: libssh2_packet_add_jump_point4:
session->packAdd_state = libssh2_NB_state_jump4; session->packAdd_state = libssh2_NB_state_jump4;
data[0] = SSH_MSG_CHANNEL_FAILURE; packet[0] = SSH_MSG_CHANNEL_FAILURE;
rc = _libssh2_transport_send(session, data, 5, NULL, 0); memcpy(&packet[1], data+1, 4);
rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
if (rc == LIBSSH2_ERROR_EAGAIN) if (rc == LIBSSH2_ERROR_EAGAIN)
return rc; return rc;
}
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return rc;
}
break; /*
} byte SSH_MSG_CHANNEL_CLOSE
uint32 recipient channel
*/
case SSH_MSG_CHANNEL_CLOSE: case SSH_MSG_CHANNEL_CLOSE:
session->packAdd_channel = if(datalen >= 5)
_libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); channelp =
_libssh2_channel_locate(session,
if (!session->packAdd_channel) { _libssh2_ntohu32(data + 1));
if (!channelp) {
/* We may have freed already, just quietly ignore this... */ /* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
@ -879,77 +846,92 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
} }
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Close received for channel %lu/%lu", "Close received for channel %lu/%lu",
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id); channelp->remote.id);
session->packAdd_channel->remote.close = 1; channelp->remote.close = 1;
session->packAdd_channel->remote.eof = 1; channelp->remote.eof = 1;
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; 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: case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && if(datalen < 17)
((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1)) ;
else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip") - 1) ==
_libssh2_ntohu32(data + 1))
&& &&
(memcmp(data + 5, "forwarded-tcpip", (memcmp(data + 5, "forwarded-tcpip",
sizeof("forwarded-tcpip") - 1) == 0)) { 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: libssh2_packet_add_jump_point2:
session->packAdd_state = libssh2_NB_state_jump2; session->packAdd_state = libssh2_NB_state_jump2;
rc = packet_queue_listener(session, data, datalen, rc = packet_queue_listener(session, data, datalen,
&session->packAdd_Qlstn_state); &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)) && else if ((datalen >= (sizeof("x11") + 4)) &&
((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) &&
(memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { (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: libssh2_packet_add_jump_point3:
session->packAdd_state = libssh2_NB_state_jump3; session->packAdd_state = libssh2_NB_state_jump3;
rc = packet_x11_open(session, data, datalen, rc = packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state); &session->packAdd_x11open_state);
}
if (rc == LIBSSH2_ERROR_EAGAIN) if (rc == LIBSSH2_ERROR_EAGAIN)
return rc; return rc;
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return rc; return rc;
}
break;
/*
byte SSH_MSG_CHANNEL_WINDOW_ADJUST
uint32 recipient channel
uint32 bytes to add
*/
case SSH_MSG_CHANNEL_WINDOW_ADJUST: case SSH_MSG_CHANNEL_WINDOW_ADJUST:
{ if(datalen < 9)
unsigned long bytestoadd = _libssh2_ntohu32(data + 5); ;
session->packAdd_channel = else {
uint32_t bytestoadd = _libssh2_ntohu32(data + 5);
channelp =
_libssh2_channel_locate(session, _libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1)); _libssh2_ntohu32(data + 1));
if(channelp) {
channelp->local.window_size += bytestoadd;
if (session->packAdd_channel && bytestoadd) {
session->packAdd_channel->local.window_size += bytestoadd;
}
if(session->packAdd_channel)
_libssh2_debug(session, LIBSSH2_TRACE_CONN, _libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Window adjust received for channel %lu/%lu, " "Window adjust for channel %lu/%lu, "
"adding %lu bytes, new window_size=%lu", "adding %lu bytes, new window_size=%lu",
session->packAdd_channel->local.id, channelp->local.id,
session->packAdd_channel->remote.id, channelp->remote.id,
bytestoadd, bytestoadd,
session->packAdd_channel->local.window_size); channelp->local.window_size);
else }
_libssh2_debug(session, LIBSSH2_TRACE_CONN, }
"Window adjust for non-existing channel!");
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
return 0; return 0;
} default:
break; break;
} }
@ -957,28 +939,24 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
} }
if (session->packAdd_state == libssh2_NB_state_sent) { if (session->packAdd_state == libssh2_NB_state_sent) {
LIBSSH2_PACKET *packAdd_packet; LIBSSH2_PACKET *packetp =
packAdd_packet =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packAdd_packet) { if (!packetp) {
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC, _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for LIBSSH2_PACKET"); "memory for packet");
session->packAdd_state = libssh2_NB_state_idle; 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; _libssh2_list_add(&session->packets, &packetp->node);
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);
session->packAdd_state = libssh2_NB_state_sent1; 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->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
(session->packAdd_state == libssh2_NB_state_sent2)) { (session->packAdd_state == libssh2_NB_state_sent2)) {
if (session->packAdd_state == libssh2_NB_state_sent1) { 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->packAdd_state = libssh2_NB_state_idle;
session->fullpacket_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)); memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
/* /*