1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-11-02 10:53:16 +03:00

Add remote tcp/ip forwarding.

This commit is contained in:
Sara Golemon
2004-12-29 19:26:28 +00:00
parent 596b62c027
commit 2e02ad041a
6 changed files with 354 additions and 1 deletions

View File

@@ -42,6 +42,132 @@
#include <openssl/evp.h>
#include <openssl/rand.h>
/* {{{ libssh2_packet_queue_listener
* Queue a connection request for a listener
*/
inline int libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data, unsigned long datalen)
{
/* Look for a matching listener */
unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
unsigned long packet_len = 17 + (sizeof("Forward not requested") - 1);
unsigned char *p, packet[17 + (sizeof("Forward not requested") - 1)];
/* packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
LIBSSH2_LISTENER *l = session->listeners;
char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */
unsigned long sender_channel, initial_window_size, packet_size;
unsigned char *host, *shost;
unsigned long port, sport, host_len, shost_len;
sender_channel = libssh2_ntohu32(s); s += 4;
initial_window_size = libssh2_ntohu32(s); s += 4;
packet_size = libssh2_ntohu32(s); s += 4;
host_len = libssh2_ntohu32(s); s += 4;
host = s; s += host_len;
port = libssh2_ntohu32(s); s += 4;
shost_len = libssh2_ntohu32(s); s += 4;
shost = s; s += shost_len;
sport = libssh2_ntohu32(s); s += 4;
while (l) {
if ((l->port == port) &&
(strlen(l->host) == host_len) &&
(memcmp(l->host, host, host_len) == 0)) {
/* This is our listener */
LIBSSH2_CHANNEL *channel, *last_queued = l->queue;
if (l->queue_maxsize &&
(l->queue_maxsize <= l->queue_size)) {
/* Queue is full */
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
break;
}
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
break;
}
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->session = session;
channel->channel_type_len = sizeof("forwarded-tcpip") - 1;
channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1);
if (!channel) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
LIBSSH2_FREE(session, channel);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
break;
}
memcpy(channel->channel_type, "forwarded-tcpip", channel->channel_type_len + 1);
channel->remote.id = 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 = initial_window_size;
channel->local.window_size = initial_window_size;
channel->local.packet_size = packet_size;
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
libssh2_htonu32(p, channel->remote.id); p += 4;
libssh2_htonu32(p, channel->local.id); p += 4;
libssh2_htonu32(p, channel->remote.window_size_initial); p += 4;
libssh2_htonu32(p, channel->remote.packet_size); p += 4;
if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1;
}
/* Link the channel into the end of the queue list */
if (!last_queued) {
l->queue = channel;
return 0;
}
while (last_queued->next) last_queued = last_queued->next;
last_queued->next = channel;
channel->prev = last_queued;
l->queue_size++;
return 0;
}
l = l->next;
}
/* We're not listening to you */
{
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
libssh2_htonu32(p, sender_channel); p += 4;
libssh2_htonu32(p, failure_code); p += 4;
libssh2_htonu32(p, sizeof("Forward not requested") - 1); p += 4;
memcpy(s, "Forward not requested", sizeof("Forward not requested") - 1); p += sizeof("Forward not requested") - 1;
libssh2_htonu32(p, 0);
if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send open failure", 0);
return -1;
}
return 0;
}
}
/* }}} */
/* {{{ libssh2_packet_new
* Create a new packet and attach it to the brigade
*/
@@ -230,6 +356,16 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0;
}
break;
case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip")-1) == libssh2_ntohu32(data + 1)) &&
(memcmp(data + 5, "forwarded-tcpip", sizeof("forwarded-tcpip") - 1) == 0)) {
int retval = libssh2_packet_queue_listener(session, data, datalen);
LIBSSH2_FREE(session, data);
return retval;
}
break;
}
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));