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.
Этот коммит содержится в:
родитель
f4ad3e0120
Коммит
1d11d02aa9
@ -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;
|
||||||
|
|
||||||
|
393
src/packet.c
393
src/packet.c
@ -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));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user