From 12ed9b1002fea166e6622ff0a5669bdfd9b3bbf0 Mon Sep 17 00:00:00 2001 From: jsorg71 Date: Sun, 25 Jul 2004 03:42:40 +0000 Subject: [PATCH] added xrdp_mcs.c --- xrdp/xrdp_mcs.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 xrdp/xrdp_mcs.c diff --git a/xrdp/xrdp_mcs.c b/xrdp/xrdp_mcs.c new file mode 100644 index 00000000..366f4b46 --- /dev/null +++ b/xrdp/xrdp_mcs.c @@ -0,0 +1,401 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Copyright (C) Jay Sorg 2004 + + mcs layer + +*/ + +#include "xrdp.h" + +/*****************************************************************************/ +struct xrdp_mcs* xrdp_mcs_create(struct xrdp_sec* owner) +{ + struct xrdp_mcs* self; + + self = (struct xrdp_mcs*)g_malloc(sizeof(struct xrdp_mcs), 1); + self->owner = owner; + self->in_s = owner->in_s; + self->out_s = owner->out_s; + self->userid = 1; + self->chanid = 1001; + self->client_mcs_data = &owner->client_mcs_data; + self->server_mcs_data = &owner->server_mcs_data; + self->iso_layer = xrdp_iso_create(self); + return self; +} + +/*****************************************************************************/ +void xrdp_mcs_delete(struct xrdp_mcs* self) +{ + xrdp_iso_delete(self->iso_layer); + g_free(self); +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_recv(struct xrdp_mcs* self) +{ + int appid; + int opcode; + int len; + + if (xrdp_iso_recv(self->iso_layer) != 0) + return 1; + in_uint8(self->in_s, opcode); + appid = opcode >> 2; + if (appid != MCS_SDRQ) + return 1; + in_uint8s(self->in_s, 5); + in_uint8(self->in_s, len); + if (len & 0x80) + in_uint8s(self->in_s, 1); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_ber_parse_header(struct xrdp_mcs* self, int tag_val, int* len) +{ + int tag; + int l; + + if (tag_val > 0xff) + { + in_uint16_be(self->in_s, tag); + } + else + { + in_uint8(self->in_s, tag); + } + if (tag != tag_val) + return 1; + in_uint8(self->in_s, l); + if (l & 0x80) + { + l = l & ~0x80; + *len = 0; + while (l > 0) + { + next_be(self->in_s, *len); + l--; + } + } + else + *len = l; + if (s_check(self->in_s)) + return 0; + else + return 1; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_parse_domain_params(struct xrdp_mcs* self) +{ + int len; + + if (xrdp_mcs_ber_parse_header(self, MCS_TAG_DOMAIN_PARAMS, &len) != 0) + return 1; + in_uint8s(self->in_s, len); + if (s_check(self->in_s)) + return 0; + else + return 1; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_recv_connect_initial(struct xrdp_mcs* self) +{ + int len; + + if (xrdp_iso_recv(self->iso_layer) != 0) + return 1; + if (xrdp_mcs_ber_parse_header(self, MCS_CONNECT_INITIAL, &len) != 0) + return 1; + if (xrdp_mcs_ber_parse_header(self, BER_TAG_OCTET_STRING, &len) != 0) + return 1; + in_uint8s(self->in_s, len); + if (xrdp_mcs_ber_parse_header(self, BER_TAG_OCTET_STRING, &len) != 0) + return 1; + in_uint8s(self->in_s, len); + if (xrdp_mcs_ber_parse_header(self, BER_TAG_BOOLEAN, &len) != 0) + return 1; + in_uint8s(self->in_s, len); + if (xrdp_mcs_parse_domain_params(self) != 0) + return 1; + if (xrdp_mcs_parse_domain_params(self) != 0) + return 1; + if (xrdp_mcs_parse_domain_params(self) != 0) + return 1; + if (xrdp_mcs_ber_parse_header(self, BER_TAG_OCTET_STRING, &len) != 0) + return 1; + /* make a copy of client mcs data */ + init_stream(self->client_mcs_data, len); + out_uint8a(self->client_mcs_data, self->in_s->p, len); + in_uint8s(self->in_s, len); + s_mark_end(self->client_mcs_data); + if (s_check_end(self->in_s)) + return 0; + else + return 1; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_recv_edrq(struct xrdp_mcs* self) +{ + int opcode; + + if (xrdp_iso_recv(self->iso_layer) != 0) + return 1; + in_uint8(self->in_s, opcode); + if ((opcode >> 2) != MCS_EDRQ) + return 1; + in_uint8s(self->in_s, 2); + in_uint8s(self->in_s, 2); + if (opcode & 2) + { + in_uint16_be(self->in_s, self->userid); + } + if (!(s_check_end(self->in_s))) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_recv_aurq(struct xrdp_mcs* self) +{ + int opcode; + + if (xrdp_iso_recv(self->iso_layer) != 0) + return 1; + in_uint8(self->in_s, opcode); + if ((opcode >> 2) != MCS_AURQ) + return 1; + if (opcode & 2) + { + in_uint16_be(self->in_s, self->userid); + } + if (!(s_check_end(self->in_s))) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_send_aucf(struct xrdp_mcs* self) +{ + if (xrdp_iso_init(self->iso_layer, 4) != 0) + return 1; + out_uint8(self->out_s, (MCS_AUCF << 2) | 2); + out_uint8s(self->out_s, 1); + out_uint16_be(self->out_s, self->userid); + s_mark_end(self->out_s); + if (xrdp_iso_send(self->iso_layer) != 0) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_recv_cjrq(struct xrdp_mcs* self) +{ + int opcode; + + if (xrdp_iso_recv(self->iso_layer) != 0) + return 1; + in_uint8(self->in_s, opcode); + if ((opcode >> 2) != MCS_CJRQ) + return 1; + in_uint8s(self->in_s, 4); + if (opcode & 2) + { + in_uint8s(self->in_s, 2); + } + if (!(s_check_end(self->in_s))) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid) +{ + if (xrdp_iso_init(self->iso_layer, 8) != 0) + return 1; + out_uint8(self->out_s, (MCS_CJCF << 2) | 2); + out_uint8(self->out_s, 0); + out_uint16_be(self->out_s, self->userid); + out_uint16_be(self->out_s, chanid); + out_uint16_be(self->out_s, chanid); + s_mark_end(self->out_s); + if (xrdp_iso_send(self->iso_layer) != 0) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_ber_out_header(struct xrdp_mcs* self, int tag_val, int len) +{ + if (tag_val > 0xff) + { + out_uint16_be(self->out_s, tag_val); + } + else + { + out_uint8(self->out_s, tag_val); + } + if (len >= 0x80) + { + out_uint8(self->out_s, 0x82); + out_uint16_be(self->out_s, len); + } + else + { + out_uint8(self->out_s, len); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_ber_out_int8(struct xrdp_mcs* self, int value) +{ + xrdp_mcs_ber_out_header(self, BER_TAG_INTEGER, 1); + out_uint8(self->out_s, value); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_ber_out_int16(struct xrdp_mcs* self, int value) +{ + xrdp_mcs_ber_out_header(self, BER_TAG_INTEGER, 2); + out_uint8(self->out_s, value >> 8); + out_uint8(self->out_s, value); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_ber_out_int24(struct xrdp_mcs* self, int value) +{ + xrdp_mcs_ber_out_header(self, BER_TAG_INTEGER, 3); + out_uint8(self->out_s, value >> 16); + out_uint8(self->out_s, value >> 8); + out_uint8(self->out_s, value); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_out_domain_params(struct xrdp_mcs* self, int max_channels, + int max_users, int max_tokens, + int max_pdu_size) +{ + xrdp_mcs_ber_out_header(self, MCS_TAG_DOMAIN_PARAMS, 26); + xrdp_mcs_ber_out_int8(self, max_channels); + xrdp_mcs_ber_out_int8(self, max_users); + xrdp_mcs_ber_out_int8(self, max_tokens); + xrdp_mcs_ber_out_int8(self, 1); + xrdp_mcs_ber_out_int8(self, 0); + xrdp_mcs_ber_out_int8(self, 1); + xrdp_mcs_ber_out_int24(self, max_pdu_size); + xrdp_mcs_ber_out_int8(self, 2); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_send_connect_response(struct xrdp_mcs* self) +{ + int data_len; + + data_len = self->server_mcs_data->end - self->server_mcs_data->data; + xrdp_iso_init(self->iso_layer, 512); + xrdp_mcs_ber_out_header(self, MCS_CONNECT_RESPONSE, 313); + xrdp_mcs_ber_out_header(self, BER_TAG_RESULT, 1); + out_uint8(self->out_s, 0); + xrdp_mcs_ber_out_header(self, BER_TAG_INTEGER, 1); + out_uint8(self->out_s, 0); + xrdp_mcs_out_domain_params(self, 2, 2, 0, 0xffff); + xrdp_mcs_ber_out_header(self, BER_TAG_OCTET_STRING, data_len); + /* mcs data */ + out_uint8a(self->out_s, self->server_mcs_data->data, data_len); + s_mark_end(self->out_s); + if (xrdp_iso_send(self->iso_layer) != 0) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_incoming(struct xrdp_mcs* self) +{ + if (xrdp_iso_incoming(self->iso_layer) != 0) + return 1; + if (xrdp_mcs_recv_connect_initial(self) != 0) + return 1; + if (xrdp_mcs_send_connect_response(self) != 0) + return 1; + if (xrdp_mcs_recv_edrq(self) != 0) + return 1; + if (xrdp_mcs_recv_aurq(self) != 0) + return 1; + if (xrdp_mcs_send_aucf(self) != 0) + return 1; + if (xrdp_mcs_recv_cjrq(self) != 0) + return 1; + if (xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE) != 0) + return 1; + if (xrdp_mcs_recv_cjrq(self) != 0) + return 1; + if (xrdp_mcs_send_cjcf(self, MCS_GLOBAL_CHANNEL) != 0) + return 1; + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_init(struct xrdp_mcs* self, int len) +{ + xrdp_iso_init(self->iso_layer, len + 8); + s_push_layer(self->out_s, mcs_hdr, 8); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int xrdp_mcs_send(struct xrdp_mcs* self) +{ + int len; + + s_pop_layer(self->out_s, mcs_hdr); + len = (self->out_s->end - self->out_s->p) - 8; + len = len | 0x8000; + out_uint8(self->out_s, MCS_SDIN << 2); + out_uint16_be(self->out_s, self->userid); + out_uint16_be(self->out_s, MCS_GLOBAL_CHANNEL); + out_uint8(self->out_s, 0x70); + out_uint16_be(self->out_s, len); + if (xrdp_iso_send(self->iso_layer) != 0) + return 1; + return 0; +}