summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src/packet.c')
-rw-r--r--libs/libssh2/src/packet.c608
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;
}
-