Пример #1
0
/* {{{ libssh2_packet_x11_open
 * Accept a forwarded X11 connection
 */
inline int libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data, unsigned long datalen)
{
	int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */
	unsigned char *s = data + (sizeof("x11") - 1) + 5;
	unsigned long packet_len = 17 + (sizeof("X11 Forward Unavailable") - 1);
	unsigned char *p, packet[17 + (sizeof("X11 Forward Unavailable") - 1)];
					/* packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
	LIBSSH2_CHANNEL *channel;
	unsigned long sender_channel, initial_window_size, packet_size;
	unsigned char *shost;
	unsigned long sport, shost_len;

	sender_channel = libssh2_ntohu32(s);			s += 4;
	initial_window_size = libssh2_ntohu32(s);		s += 4;
	packet_size = libssh2_ntohu32(s);				s += 4;
	shost_len = libssh2_ntohu32(s);					s += 4;
	shost = s;										s += shost_len;
	sport = libssh2_ntohu32(s);						s += 4;

#ifdef LIBSSH2_DEBUG_CONNECTION
	_libssh2_debug(session, LIBSSH2_DBG_CONN, "X11 Connection Received from %s:%ld on channel %lu", shost, sport, sender_channel);
#endif
	if (session->x11) {
		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 */
			goto x11_exit;
		}
		memset(channel, 0, sizeof(LIBSSH2_CHANNEL));

		channel->session = session;
		channel->channel_type_len = sizeof("x11") - 1;
		channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1);
		if (!channel->channel_type) {
			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 */
			goto x11_exit;
		}
		memcpy(channel->channel_type, "x11", 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;

#ifdef LIBSSH2_DEBUG_CONNECTION
	_libssh2_debug(session, LIBSSH2_DBG_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);
#endif
		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 session */
		if (session->channels.tail) {
			session->channels.tail->next = channel;
			channel->prev = session->channels.tail;
		} else {
			session->channels.head = channel;
			channel->prev = NULL;
		}
		channel->next = NULL;
		session->channels.tail = channel;

		/* Pass control to the callback, they may turn right around and free the channel, or actually use it */
		LIBSSH2_X11_OPEN(channel, shost, sport);

		return 0;
	} else {
		failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
	}

 x11_exit:
	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("X11 Forward Unavailable") - 1);		p += 4;
	memcpy(s, "X11 Forward Unavailable", sizeof("X11 Forward Unavailable") - 1); p += sizeof("X11 Forward Unavailable") - 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;
}
Пример #2
0
/*
 * packet_x11_open
 *
 * Accept a forwarded X11 connection
 */
static inline int
packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
                unsigned long datalen,
                packet_x11_open_state_t * x11open_state)
{
    int failure_code = 2;       /* SSH_OPEN_CONNECT_FAILED */
    unsigned char *s = data + (sizeof("x11") - 1) + 5;
    /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
    unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
    unsigned char *p;
    LIBSSH2_CHANNEL *channel;
    int rc;

    (void) datalen;

    if (x11open_state->state == libssh2_NB_state_idle) {
        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);
        s += 4;

        _libssh2_debug(session, LIBSSH2_DBG_CONN,
                       "X11 Connection Received from %s:%ld on channel %lu",
                       x11open_state->shost, x11open_state->sport,
                       x11open_state->sender_channel);

        x11open_state->state = libssh2_NB_state_allocated;
    }

    if (session->x11) {
        if (x11open_state->state == libssh2_NB_state_allocated) {
            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 */
                goto x11_exit;
            }
            memset(channel, 0, sizeof(LIBSSH2_CHANNEL));

            channel->session = session;
            channel->channel_type_len = sizeof("x11") - 1;
            channel->channel_type = LIBSSH2_ALLOC(session,
                                                  channel->channel_type_len +
                                                  1);
            if (!channel->channel_type) {
                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 */
                goto x11_exit;
            }
            memcpy(channel->channel_type, "x11",
                   channel->channel_type_len + 1);

            channel->remote.id = x11open_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 =
                x11open_state->initial_window_size;
            channel->local.window_size = x11open_state->initial_window_size;
            channel->local.packet_size = x11open_state->packet_size;

            _libssh2_debug(session, LIBSSH2_DBG_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);
            p = x11open_state->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;

            x11open_state->state = libssh2_NB_state_created;
        }

        if (x11open_state->state == libssh2_NB_state_created) {
            rc = _libssh2_transport_write(session, x11open_state->packet, 17);
            if (rc == PACKET_EAGAIN) {
                return PACKET_EAGAIN;
            } else if (rc) {
                libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
                              "Unable to send channel open confirmation", 0);
                x11open_state->state = libssh2_NB_state_idle;
                return -1;
            }

            /* Link the channel into the session */
            if (session->channels.tail) {
                session->channels.tail->next = channel;
                channel->prev = session->channels.tail;
            } else {
                session->channels.head = channel;
                channel->prev = NULL;
            }
            channel->next = NULL;
            session->channels.tail = channel;

            /*
             * Pass control to the callback, they may turn right around and
             * free the channel, or actually use it
             */
            LIBSSH2_X11_OPEN(channel, (char *) x11open_state->shost,
                             x11open_state->sport);

            x11open_state->state = libssh2_NB_state_idle;
            return 0;
        }
    } else {
        failure_code = 4;       /* SSH_OPEN_RESOURCE_SHORTAGE */
    }

  x11_exit:
    p = x11open_state->packet;
    *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
    _libssh2_htonu32(p, x11open_state->sender_channel);
    p += 4;
    _libssh2_htonu32(p, failure_code);
    p += 4;
    _libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1);
    p += 4;
    memcpy(s, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
    p += sizeof(X11FwdUnAvil) - 1;
    _libssh2_htonu32(p, 0);

    rc = _libssh2_transport_write(session, x11open_state->packet, packet_len);
    if (rc == PACKET_EAGAIN) {
        return PACKET_EAGAIN;
    } else if (rc) {
        libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
                      "Unable to send open failure", 0);
        x11open_state->state = libssh2_NB_state_idle;
        return -1;
    }
    x11open_state->state = libssh2_NB_state_idle;
    return 0;
}