diff options
Diffstat (limited to 'libs/libssh2/src/packet.c')
-rw-r--r-- | libs/libssh2/src/packet.c | 608 |
1 files changed, 441 insertions, 167 deletions
diff --git a/libs/libssh2/src/packet.c b/libs/libssh2/src/packet.c index 38ab62944a..e3ccf814d4 100644 --- a/libs/libssh2/src/packet.c +++ b/libs/libssh2/src/packet.c @@ -1,7 +1,7 @@ -/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2009-2014 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +/* Copyright (C) Sara Golemon <sarag@libssh2.org> + * Copyright (C) Mikhail Gusarov + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,31 +36,23 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" -#include <errno.h> -#include <fcntl.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif - -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif - #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif - /* Needed for struct iovec on some platforms */ #ifdef HAVE_SYS_UIO_H #include <sys/uio.h> #endif -#include <sys/types.h> - #include "transport.h" #include "channel.h" #include "packet.h" @@ -72,48 +64,71 @@ */ static inline int packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, + size_t datalen, packet_queue_listener_state_t *listen_state) { /* * Look for a matching listener */ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1); + size_t packet_len = 17 + (sizeof(FwdNotReq) - 1); unsigned char *p; LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners); char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; int rc; - (void) datalen; - if(listen_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5; - listen_state->sender_channel = _libssh2_ntohu32(s); - s += 4; + size_t offset = (sizeof("forwarded-tcpip") - 1) + 5; + size_t temp_len = 0; + struct string_buf buf; + buf.data = data; + buf.dataptr = buf.data; + buf.len = datalen; + + if(datalen < offset) { + return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Unexpected packet size"); + } - listen_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - listen_state->packet_size = _libssh2_ntohu32(s); - s += 4; + buf.dataptr += offset; - listen_state->host_len = _libssh2_ntohu32(s); - s += 4; - listen_state->host = s; - s += listen_state->host_len; - listen_state->port = _libssh2_ntohu32(s); - s += 4; + if(_libssh2_get_u32(&buf, &(listen_state->sender_channel))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting channel"); + } + if(_libssh2_get_u32(&buf, &(listen_state->initial_window_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting window size"); + } + if(_libssh2_get_u32(&buf, &(listen_state->packet_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting packet"); + } + if(_libssh2_get_string(&buf, &(listen_state->host), &temp_len)) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting host"); + } + listen_state->host_len = (uint32_t)temp_len; - listen_state->shost_len = _libssh2_ntohu32(s); - s += 4; - listen_state->shost = s; - s += listen_state->shost_len; - listen_state->sport = _libssh2_ntohu32(s); + if(_libssh2_get_u32(&buf, &(listen_state->port))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting port"); + } + if(_libssh2_get_string(&buf, &(listen_state->shost), &temp_len)) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting shost"); + } + listen_state->shost_len = (uint32_t)temp_len; + + if(_libssh2_get_u32(&buf, &(listen_state->sport))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting sport"); + } - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Remote received connection from %s:%ld to %s:%ld", listen_state->shost, listen_state->sport, - listen_state->host, listen_state->port); + listen_state->host, listen_state->port)); listen_state->state = libssh2_NB_state_allocated; } @@ -133,8 +148,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, (listn->queue_maxsize <= listn->queue_size)) { /* Queue is full */ failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Listener queue full, ignoring"); + _libssh2_debug((session, LIBSSH2_TRACE_CONN, + "Listener queue full, ignoring")); listen_state->state = libssh2_NB_state_sent; break; } @@ -183,14 +198,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, listen_state->initial_window_size; channel->local.packet_size = listen_state->packet_size; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Connection queued: channel %lu/%lu " "win %lu/%lu packet %lu/%lu", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, channel->local.packet_size, - channel->remote.packet_size); + channel->remote.packet_size)); p = listen_state->packet; *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; @@ -262,36 +277,71 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, */ static inline int packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, + size_t datalen, packet_x11_open_state_t *x11open_state) { int failure_code = SSH_OPEN_CONNECT_FAILED; /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); unsigned char *p; LIBSSH2_CHANNEL *channel = x11open_state->channel; int rc; - (void) datalen; - if(x11open_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("x11") - 1) + 5; - x11open_state->sender_channel = _libssh2_ntohu32(s); - s += 4; - x11open_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - x11open_state->packet_size = _libssh2_ntohu32(s); - s += 4; - x11open_state->shost_len = _libssh2_ntohu32(s); - s += 4; - x11open_state->shost = s; - s += x11open_state->shost_len; - x11open_state->sport = _libssh2_ntohu32(s); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + size_t offset = (sizeof("x11") - 1) + 5; + size_t temp_len = 0; + struct string_buf buf; + buf.data = data; + buf.dataptr = buf.data; + buf.len = datalen; + + if(datalen < offset) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected data length"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + + buf.dataptr += offset; + + if(_libssh2_get_u32(&buf, &(x11open_state->sender_channel))) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected sender channel size"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + if(_libssh2_get_u32(&buf, &(x11open_state->initial_window_size))) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected window size"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + if(_libssh2_get_u32(&buf, &(x11open_state->packet_size))) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected window size"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + if(_libssh2_get_string(&buf, &(x11open_state->shost), &temp_len)) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected host size"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + x11open_state->shost_len = (uint32_t)temp_len; + + if(_libssh2_get_u32(&buf, &(x11open_state->sport))) { + _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "unexpected port size"); + failure_code = SSH_OPEN_CONNECT_FAILED; + goto x11_exit; + } + + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "X11 Connection Received from %s:%ld on channel %lu", x11open_state->shost, x11open_state->sport, - x11open_state->sender_channel); + x11open_state->sender_channel)); x11open_state->state = libssh2_NB_state_allocated; } @@ -333,14 +383,14 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, channel->local.window_size = x11open_state->initial_window_size; channel->local.packet_size = x11open_state->packet_size; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "X11 Connection established: channel %lu/%lu " "win %lu/%lu packet %lu/%lu", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, channel->local.packet_size, - channel->remote.packet_size); + channel->remote.packet_size)); p = x11open_state->packet; *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; _libssh2_store_u32(&p, channel->remote.id); @@ -381,7 +431,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, else failure_code = SSH_OPEN_RESOURCE_SHORTAGE; /* fall-trough */ - x11_exit: +x11_exit: p = x11open_state->packet; *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; _libssh2_store_u32(&p, x11open_state->sender_channel); @@ -403,6 +453,154 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } /* + * packet_authagent_open + * + * Open a connection to authentication agent + */ +static inline int +packet_authagent_open(LIBSSH2_SESSION * session, + unsigned char *data, size_t datalen, + packet_authagent_state_t *authagent_state) +{ + int failure_code = SSH_OPEN_CONNECT_FAILED; + /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ + size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + unsigned char *p; + LIBSSH2_CHANNEL *channel = authagent_state->channel; + int rc; + + (void)datalen; + + if(authagent_state->state == libssh2_NB_state_idle) { + unsigned char *s = data + (sizeof("auth-agent@openssh.org") - 1) + 5; + authagent_state->sender_channel = _libssh2_ntohu32(s); + s += 4; + authagent_state->initial_window_size = _libssh2_ntohu32(s); + s += 4; + authagent_state->packet_size = _libssh2_ntohu32(s); + + _libssh2_debug((session, LIBSSH2_TRACE_CONN, + "Auth Agent Connection Received on channel %lu", + authagent_state->sender_channel)); + + authagent_state->state = libssh2_NB_state_allocated; + } + + if(session->authagent) { + if(authagent_state->state == libssh2_NB_state_allocated) { + channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL)); + authagent_state->channel = channel; + + if(!channel) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "allocate a channel for new connection"); + failure_code = SSH_OPEN_RESOURCE_SHORTAGE; + goto authagent_exit; + } + memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); + + channel->session = session; + channel->channel_type_len = sizeof("auth agent") - 1; + channel->channel_type = LIBSSH2_ALLOC(session, + channel->channel_type_len + + 1); + if(!channel->channel_type) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "allocate a channel for new connection"); + LIBSSH2_FREE(session, channel); + failure_code = SSH_OPEN_RESOURCE_SHORTAGE; + goto authagent_exit; + } + memcpy(channel->channel_type, "auth agent", + channel->channel_type_len + 1); + + channel->remote.id = authagent_state->sender_channel; + channel->remote.window_size_initial = + LIBSSH2_CHANNEL_WINDOW_DEFAULT; + channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT; + channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT; + + channel->local.id = _libssh2_channel_nextid(session); + channel->local.window_size_initial = + authagent_state->initial_window_size; + channel->local.window_size = authagent_state->initial_window_size; + channel->local.packet_size = authagent_state->packet_size; + + _libssh2_debug((session, LIBSSH2_TRACE_CONN, + "Auth Agent Connection established: channel " + "%lu/%lu win %lu/%lu packet %lu/%lu", + channel->local.id, channel->remote.id, + channel->local.window_size, + channel->remote.window_size, + channel->local.packet_size, + channel->remote.packet_size)); + + p = authagent_state->packet; + *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; + _libssh2_store_u32(&p, channel->remote.id); + _libssh2_store_u32(&p, channel->local.id); + _libssh2_store_u32(&p, channel->remote.window_size_initial); + _libssh2_store_u32(&p, channel->remote.packet_size); + + authagent_state->state = libssh2_NB_state_created; + } + + if(authagent_state->state == libssh2_NB_state_created) { + rc = _libssh2_transport_send(session, authagent_state->packet, 17, + NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + authagent_state->state = libssh2_NB_state_idle; + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, + "Unable to send channel open " + "confirmation"); + } + + /* Link the channel into the session */ + _libssh2_list_add(&session->channels, &channel->node); + + /* mess with stuff so we don't keep reading the same packet + over and over */ + session->packet.total_num = 0; + session->fullpacket_state = libssh2_NB_state_idle; + + /* Pass control to the callback, they may turn right around and + and free the channel, or actually use it */ + + LIBSSH2_AUTHAGENT(channel); + + authagent_state->state = libssh2_NB_state_idle; + return 0; + } + } + else + failure_code = SSH_OPEN_RESOURCE_SHORTAGE; + + /* fall-through */ +authagent_exit: + p = authagent_state->packet; + *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; + _libssh2_store_u32(&p, authagent_state->sender_channel); + _libssh2_store_u32(&p, failure_code); + _libssh2_store_str(&p, AuthAgentUnavail, sizeof(AuthAgentUnavail) - 1); + _libssh2_htonu32(p, 0); + + rc = _libssh2_transport_send(session, authagent_state->packet, packet_len, + NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + authagent_state->state = libssh2_NB_state_idle; + return _libssh2_error(session, rc, "Unable to send open failure"); + } + authagent_state->state = libssh2_NB_state_idle; + return 0; +} + +/* * _libssh2_packet_add * * Create a new packet and attach it to the brigade. Called from the transport @@ -419,8 +617,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, size_t datalen, int macstate) { int rc = 0; - char *message = NULL; - char *language = NULL; + unsigned char *message = NULL; + unsigned char *language = NULL; size_t message_len = 0; size_t language_len = 0; LIBSSH2_CHANNEL *channelp = NULL; @@ -429,9 +627,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, 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", - (int) msg, (int) datalen); + (int) msg, (int) datalen)); if((macstate == LIBSSH2_MAC_INVALID) && (!session->macerror || @@ -455,6 +653,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, goto libssh2_packet_add_jump_point4; case libssh2_NB_state_jump5: goto libssh2_packet_add_jump_point5; + case libssh2_NB_state_jumpauthagent: + goto libssh2_packet_add_jump_authagent; default: /* nothing to do */ break; } @@ -472,36 +672,26 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, case SSH_MSG_DISCONNECT: if(datalen >= 5) { - size_t reason = _libssh2_ntohu32(data + 1); - - if(datalen >= 9) { - message_len = _libssh2_ntohu32(data + 5); + uint32_t reason = 0; + struct string_buf buf; + buf.data = (unsigned char *)data; + buf.dataptr = buf.data; + buf.len = datalen; + buf.dataptr++; /* advance past type */ - if(message_len < datalen-13) { - /* 9 = packet_type(1) + reason(4) + message_len(4) */ - message = (char *) data + 9; + _libssh2_get_u32(&buf, &reason); + _libssh2_get_string(&buf, &message, &message_len); + _libssh2_get_string(&buf, &language, &language_len); - language_len = - _libssh2_ntohu32(data + 9 + message_len); - language = (char *) data + 9 + message_len + 4; - - if(language_len > (datalen-13-message_len)) { - /* bad input, clear info */ - language = message = NULL; - language_len = message_len = 0; - } - } - else - /* bad size, clear it */ - message_len = 0; - } if(session->ssh_msg_disconnect) { - LIBSSH2_DISCONNECT(session, reason, message, - message_len, language, language_len); + LIBSSH2_DISCONNECT(session, reason, (const char *)message, + message_len, (const char *)language, + language_len); } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, + + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Disconnect(%d): %s(%s)", reason, - message, language); + message, language)); } LIBSSH2_FREE(session, data); @@ -539,35 +729,104 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, int always_display = data[1]; if(datalen >= 6) { - message_len = _libssh2_ntohu32(data + 2); - - if(message_len <= (datalen - 10)) { - /* 6 = packet_type(1) + display(1) + message_len(4) */ - message = (char *) data + 6; - language_len = _libssh2_ntohu32(data + 6 + - message_len); - - if(language_len <= (datalen - 10 - message_len)) - language = (char *) data + 10 + message_len; - } + struct string_buf buf; + buf.data = (unsigned char *)data; + buf.dataptr = buf.data; + buf.len = datalen; + buf.dataptr += 2; /* advance past type & always display */ + + _libssh2_get_string(&buf, &message, &message_len); + _libssh2_get_string(&buf, &language, &language_len); } if(session->ssh_msg_debug) { - LIBSSH2_DEBUG(session, always_display, message, - message_len, language, language_len); + LIBSSH2_DEBUG(session, always_display, + (const char *)message, + message_len, (const char *)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 */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Debug Packet: %s", message); + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, + "Debug Packet: %s", message)); LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return 0; /* + byte SSH_MSG_EXT_INFO + uint32 nr-extensions + [repeat "nr-extensions" times] + string extension-name [RFC8308] + string extension-value (binary) + */ + + case SSH_MSG_EXT_INFO: + if(datalen >= 5) { + uint32_t nr_extensions = 0; + struct string_buf buf; + buf.data = (unsigned char *)data; + buf.dataptr = buf.data; + buf.len = datalen; + buf.dataptr += 1; /* advance past type */ + + if(_libssh2_get_u32(&buf, &nr_extensions) != 0) { + rc = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid extension info received"); + } + + while(rc == 0 && nr_extensions > 0) { + + size_t name_len = 0; + size_t value_len = 0; + unsigned char *name = NULL; + unsigned char *value = NULL; + + nr_extensions -= 1; + + _libssh2_get_string(&buf, &name, &name_len); + _libssh2_get_string(&buf, &value, &value_len); + + if(name && value) { + _libssh2_debug((session, + LIBSSH2_TRACE_KEX, + "Server to Client extension %.*s: %.*s", + name_len, name, value_len, value)); + } + + if(name_len == 15 && + memcmp(name, "server-sig-algs", 15) == 0) { + if(session->server_sign_algorithms) { + LIBSSH2_FREE(session, + session->server_sign_algorithms); + } + + session->server_sign_algorithms = + LIBSSH2_ALLOC(session, + value_len + 1); + + if(session->server_sign_algorithms) { + memcpy(session->server_sign_algorithms, + value, value_len); + session->server_sign_algorithms[value_len] = '\0'; + } + else { + rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "memory for server sign algo"); + } + } + } + } + + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return rc; + + /* byte SSH_MSG_GLOBAL_REQUEST string request name in US-ASCII only boolean want reply @@ -579,19 +838,19 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, uint32_t len = 0; unsigned char want_reply = 0; len = _libssh2_ntohu32(data + 1); - if(datalen >= (6 + len)) { + if((len <= (UINT_MAX - 6)) && (datalen >= (6 + len))) { want_reply = data[5 + len]; - _libssh2_debug(session, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Received global request type %.*s (wr %X)", - len, data + 5, want_reply); + len, data + 5, want_reply)); } if(want_reply) { static const unsigned char packet = SSH_MSG_REQUEST_FAILURE; - libssh2_packet_add_jump_point5: +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) @@ -643,12 +902,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(msg == SSH_MSG_CHANNEL_EXTENDED_DATA) 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", (int) (datalen - data_head), channelp->local.id, channelp->remote.id, - stream_id); + stream_id)); } #endif if((channelp->remote.extended_data_ignore_mode == @@ -657,30 +916,31 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, /* Pretend we didn't receive this */ LIBSSH2_FREE(session, data); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Ignoring extended data and refunding %d bytes", - (int) (datalen - 13)); + (int) (datalen - 13))); if(channelp->read_avail + datalen - data_head >= channelp->remote.window_size) datalen = channelp->remote.window_size - channelp->read_avail + data_head; - channelp->remote.window_size -= datalen - data_head; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + channelp->remote.window_size -= (uint32_t)(datalen - + data_head); + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "shrinking window size by %lu bytes to %lu, " "read_avail %lu", datalen - data_head, channelp->remote.window_size, - channelp->read_avail); + channelp->read_avail)); session->packAdd_channelp = channelp; /* 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; rc = _libssh2_channel_receive_window_adjust(session-> packAdd_channelp, - datalen - 13, + (uint32_t)(datalen - 13), 1, NULL); if(rc == LIBSSH2_ERROR_EAGAIN) return rc; @@ -698,8 +958,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * Spec says we MAY ignore bytes sent beyond * packet_size */ - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, + _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, "Packet contains more data than we offered" " to receive, truncating"); datalen = channelp->remote.packet_size + data_head; @@ -709,8 +968,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * Spec says we MAY ignore bytes sent beyond * window_size */ - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, + _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "The current receive window is full," " data ignored"); LIBSSH2_FREE(session, data); @@ -722,8 +980,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(channelp->read_avail + datalen - data_head > channelp->remote.window_size) { - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, + _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "Remote sent more data than current " "window allows, truncating"); datalen = channelp->remote.window_size - @@ -735,11 +992,11 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * from an upper layer */ channelp->read_avail += datalen - data_head; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "increasing read_avail by %lu bytes to %lu/%lu", (long)(datalen - data_head), (long)channelp->read_avail, - (long)channelp->remote.window_size); + (long)channelp->remote.window_size)); break; @@ -757,11 +1014,11 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, /* We may have freed already, just quietly ignore this... */ ; else { - _libssh2_debug(session, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "EOF received for channel %lu/%lu", channelp->local.id, - channelp->remote.id); + channelp->remote.id)); channelp->remote.eof = 1; } LIBSSH2_FREE(session, data); @@ -785,10 +1042,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if((len + 9) < datalen) want_reply = data[len + 9]; - _libssh2_debug(session, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply); + channel, len, data + 9, want_reply)); if(len == sizeof("exit-status") - 1 && (sizeof("exit-status") - 1 + 9) <= datalen @@ -803,12 +1060,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(channelp && (sizeof("exit-status") + 13) <= datalen) { channelp->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 " "channel %lu/%lu", channelp->exit_status, channelp->local.id, - channelp->remote.id); + channelp->remote.id)); } } @@ -842,12 +1099,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, data + 13 + sizeof("exit-signal"), namelen); channelp->exit_signal[namelen] = '\0'; /* TODO: save error message and language tag */ - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Exit signal %s received for " "channel %lu/%lu", channelp->exit_signal, channelp->local.id, - channelp->remote.id); + channelp->remote.id)); } } } @@ -855,7 +1112,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(want_reply) { unsigned char packet[5]; - libssh2_packet_add_jump_point4: +libssh2_packet_add_jump_point4: session->packAdd_state = libssh2_NB_state_jump4; packet[0] = SSH_MSG_CHANNEL_FAILURE; memcpy(&packet[1], data + 1, 4); @@ -884,10 +1141,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, session->packAdd_state = libssh2_NB_state_idle; return 0; } - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Close received for channel %lu/%lu", channelp->local.id, - channelp->remote.id); + channelp->remote.id)); channelp->remote.close = 1; channelp->remote.eof = 1; @@ -918,7 +1175,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, 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; rc = packet_queue_listener(session, data, datalen, &session->packAdd_Qlstn_state); @@ -931,11 +1188,26 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, 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; rc = packet_x11_open(session, data, datalen, &session->packAdd_x11open_state); } + else if((datalen >= (sizeof("auth-agent@openssh.com") + 4)) && + ((sizeof("auth-agent@openssh.com") - 1) == + _libssh2_ntohu32(data + 1)) && + (memcmp(data + 5, "auth-agent@openssh.com", + sizeof("auth-agent@openssh.com") - 1) == 0)) { + + /* init the state struct */ + memset(&session->packAdd_authagent_state, 0, + sizeof(session->packAdd_authagent_state)); + +libssh2_packet_add_jump_authagent: + session->packAdd_state = libssh2_NB_state_jumpauthagent; + rc = packet_authagent_open(session, data, datalen, + &session->packAdd_authagent_state); + } if(rc == LIBSSH2_ERROR_EAGAIN) return rc; @@ -959,13 +1231,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(channelp) { channelp->local.window_size += bytestoadd; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, + _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); + channelp->local.window_size)); } } LIBSSH2_FREE(session, data); @@ -982,8 +1254,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, LIBSSH2_PACKET *packetp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); if(!packetp) { - _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, - "memory for packet"); + _libssh2_debug((session, LIBSSH2_ERROR_ALLOC, + "memory for packet")); LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; return LIBSSH2_ERROR_ALLOC; @@ -1006,7 +1278,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * Well, it's already in the brigade, * let's just call back into ourselves */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys"); + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, + "Renegotiating Keys")); session->packAdd_state = libssh2_NB_state_sent2; } @@ -1051,8 +1324,8 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, { LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Looking for packet of type: %d", (int) packet_type); + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, + "Looking for packet of type: %d", (int) packet_type)); while(packet) { if(packet->data[0] == packet_type @@ -1089,12 +1362,12 @@ _libssh2_packet_askv(LIBSSH2_SESSION * session, const unsigned char *match_buf, size_t match_len) { - int i, packet_types_len = strlen((char *) packet_types); + size_t i, packet_types_len = strlen((const char *) packet_types); for(i = 0; i < packet_types_len; i++) { - if(0 == _libssh2_packet_ask(session, packet_types[i], data, - data_len, match_ofs, - match_buf, match_len)) { + if(_libssh2_packet_ask(session, packet_types[i], data, + data_len, match_ofs, + match_buf, match_len) == 0) { return 0; } } @@ -1121,8 +1394,8 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, { if(state->start == 0) { if(_libssh2_packet_ask(session, packet_type, data, data_len, - match_ofs, match_buf, - match_len) == 0) { + match_ofs, match_buf, + match_len) == 0) { /* A packet was available in the packet brigade */ return 0; } @@ -1148,8 +1421,8 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, } else if(ret == 0) { /* nothing available, wait until data arrives or we time out */ - long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - - state->start); + long left = session->packet_read_timeout - (long)(time(NULL) - + state->start); if(left <= 0) { state->start = 0; @@ -1186,15 +1459,15 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session, all_packets[254] = 0; if(_libssh2_packet_askv(session, all_packets, &data, &data_len, 0, - NULL, 0) == 0) { + NULL, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ LIBSSH2_FREE(session, data); return i; } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Blocking until packet becomes available to burn"); + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, + "Blocking until packet becomes available to burn")); *state = libssh2_NB_state_created; } @@ -1215,7 +1488,7 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session, /* Be lazy, let packet_ask pull it out of the brigade */ if(0 == _libssh2_packet_ask(session, (unsigned char)ret, - &data, &data_len, 0, NULL, 0)) { + &data, &data_len, 0, NULL, 0)) { /* Smoke 'em if you got 'em */ LIBSSH2_FREE(session, data); *state = libssh2_NB_state_idle; @@ -1244,7 +1517,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session, packet_requirev_state_t * state) { if(_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, - match_buf, match_len) == 0) { + match_buf, match_len) == 0) { /* One of the packets listed was available in the packet brigade */ state->start = 0; return 0; @@ -1261,7 +1534,7 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session, return ret; } if(ret <= 0) { - long left = LIBSSH2_READ_TIMEOUT - + long left = session->packet_read_timeout - (long)(time(NULL) - state->start); if(left <= 0) { @@ -1275,9 +1548,11 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session, if(strchr((char *) packet_types, ret)) { /* Be lazy, let packet_ask pull it out of the brigade */ - return _libssh2_packet_askv(session, packet_types, data, - data_len, match_ofs, match_buf, - match_len); + ret = _libssh2_packet_askv(session, packet_types, data, + data_len, match_ofs, match_buf, + match_len); + state->start = 0; + return ret; } } @@ -1285,4 +1560,3 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session, state->start = 0; return LIBSSH2_ERROR_SOCKET_DISCONNECT; } - |