diff options
author | jsorg71 <jsorg71> | 2006-12-28 06:15:13 +0000 |
---|---|---|
committer | jsorg71 <jsorg71> | 2006-12-28 06:15:13 +0000 |
commit | 0dc679e2dc3ddf71735585cf53c4b717ab5b11a9 (patch) | |
tree | e9598abc49d8e30e8867add6d5e7184fff1cd90e | |
parent | 1ed935186d183ad01352b8846b762fbb4ee361d8 (diff) | |
download | xrdp-proprietary-0dc679e2dc3ddf71735585cf53c4b717ab5b11a9.tar.gz xrdp-proprietary-0dc679e2dc3ddf71735585cf53c4b717ab5b11a9.zip |
added channel support
-rw-r--r-- | libxrdp/libxrdp.h | 43 | ||||
-rw-r--r-- | libxrdp/libxrdpinc.h | 2 | ||||
-rw-r--r-- | libxrdp/xrdp_channel.c | 239 | ||||
-rw-r--r-- | libxrdp/xrdp_mcs.c | 102 | ||||
-rw-r--r-- | libxrdp/xrdp_rdp.c | 11 | ||||
-rw-r--r-- | libxrdp/xrdp_sec.c | 232 |
6 files changed, 548 insertions, 81 deletions
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index dd87096e..eadb9c0e 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -48,6 +48,15 @@ struct xrdp_iso struct xrdp_tcp* tcp_layer; }; +/* used in mcs */ +struct mcs_channel_item +{ + char name[16]; + int flags; + int chanid; + struct stream* in_s; +}; + /* mcs */ struct xrdp_mcs { @@ -57,6 +66,7 @@ struct xrdp_mcs int chanid; struct stream* client_mcs_data; struct stream* server_mcs_data; + struct list* channel_list; }; /* sec */ @@ -64,6 +74,7 @@ struct xrdp_sec { struct xrdp_rdp* rdp_layer; /* owner */ struct xrdp_mcs* mcs_layer; + struct xrdp_channel* chan_layer; char server_random[32]; char client_random[64]; char client_crypt_random[72]; @@ -85,6 +96,14 @@ struct xrdp_sec char pub_mod[64]; char pub_sig[64]; char pri_exp[64]; + int channel_code; +}; + +/* channel */ +struct xrdp_channel +{ + struct xrdp_sec* sec_layer; + struct xrdp_mcs* mcs_layer; }; /* rdp */ @@ -223,7 +242,7 @@ xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s); int APP_CC xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan); int APP_CC -xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s); +xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s, int chan); int APP_CC xrdp_mcs_incoming(struct xrdp_mcs* self); int APP_CC @@ -231,7 +250,8 @@ xrdp_mcs_disconnect(struct xrdp_mcs* self); /* xrdp_sec.c */ struct xrdp_sec* APP_CC -xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level); +xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level, + int channel_code); void APP_CC xrdp_sec_delete(struct xrdp_sec* self); int APP_CC @@ -239,7 +259,11 @@ xrdp_sec_init(struct xrdp_sec* self, struct stream* s); int APP_CC xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan); int APP_CC -xrdp_sec_send(struct xrdp_sec* self, struct stream* s); +xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int chan); +int APP_CC +xrdp_sec_process_mcs_data(struct xrdp_sec* self); +int APP_CC +xrdp_sec_out_mcs_data(struct xrdp_sec* self); int APP_CC xrdp_sec_incoming(struct xrdp_sec* self); int APP_CC @@ -356,4 +380,17 @@ xrdp_bitmap_compress(char* in_data, int width, int height, int start_line, struct stream* temp, int e); +/* xrdp_channel.c */ +struct xrdp_channel* APP_CC +xrdp_channel_create(struct xrdp_sec* owner, struct xrdp_mcs* mcs_layer); +void APP_CC +xrdp_channel_delete(struct xrdp_channel* self); +int APP_CC +xrdp_channel_init(struct xrdp_channel* self, struct stream* s); +int APP_CC +xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id); +int APP_CC +xrdp_channel_process(struct xrdp_channel* self, struct stream* s, + int chanid); + #endif diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 74ebfda3..a7e8927d 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -57,6 +57,8 @@ struct xrdp_client_info int rdp_compression; int rdp_autologin; int crypt_level; /* 1, 2, 3 = low, medium, high */ + int channel_code; /* 0 = no channels 1 = channels */ + int sound_code; /* 1 = leave sound at server */ }; struct xrdp_brush diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c new file mode 100644 index 00000000..f5ddfef3 --- /dev/null +++ b/libxrdp/xrdp_channel.c @@ -0,0 +1,239 @@ +/* + 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. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2006 + + channel layer + +*/ + +#include "libxrdp.h" + +/* todo, move these to constants.h */ +//#define CHANNEL_CHUNK_LENGTH 1600 /* todo, why is this so small? */ +#define CHANNEL_CHUNK_LENGTH 8192 +#define CHANNEL_FLAG_FIRST 0x01 +#define CHANNEL_FLAG_LAST 0x02 +#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 + +/*****************************************************************************/ +/* returns pointer or nil on error */ +static struct mcs_channel_item* APP_CC +xrdp_channel_get_item(struct xrdp_channel* self, int channel_id) +{ + struct mcs_channel_item* channel; + + channel = (struct mcs_channel_item*) + list_get_item(self->mcs_layer->channel_list, channel_id); + return channel; +} + +/*****************************************************************************/ +struct xrdp_channel* APP_CC +xrdp_channel_create(struct xrdp_sec* owner, struct xrdp_mcs* mcs_layer) +{ + struct xrdp_channel* self; + + self = (struct xrdp_channel*)g_malloc(sizeof(struct xrdp_channel), 1); + self->sec_layer = owner; + self->mcs_layer = mcs_layer; + return self; +} + +/*****************************************************************************/ +/* returns error */ +void APP_CC +xrdp_channel_delete(struct xrdp_channel* self) +{ + if (self == 0) + { + return; + } + g_free(self); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_channel_init(struct xrdp_channel* self, struct stream* s) +{ + if (xrdp_sec_init(self->sec_layer, s) != 0) + { + return 1; + } + s_push_layer(s, channel_hdr, 8); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* This sends data out to the secure layer, breaking up the data to + CHANNEL_CHUNK_LENGTH as needed. This can end up sending many packets. */ +int APP_CC +xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id) +{ + int length; + int flags; + int thislength; + int remaining; + char* data; + struct mcs_channel_item* channel; + + channel = xrdp_channel_get_item(self, channel_id); + if (channel == 0) + { + return 1; + } + s_pop_layer(s, channel_hdr); + length = (int)((s->end - s->p) - 8); + thislength = MIN(length, CHANNEL_CHUNK_LENGTH); + remaining = length - thislength; + flags = (remaining == 0) ? + CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST; + if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) + { + flags |= CHANNEL_FLAG_SHOW_PROTOCOL; + } + out_uint32_le(s, length); + out_uint32_le(s, flags); + s->end = s->p + thislength; + data = s->end; + if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0) + { + return 1; + } + while (remaining > 0) + { + thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH); + remaining -= thislength; + flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0; + if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) + { + flags |= CHANNEL_FLAG_SHOW_PROTOCOL; + } + if (xrdp_sec_init(self->sec_layer, s) != 0) + { + return 1; + } + out_uint32_le(s, length); + out_uint32_le(s, flags); + /* this is copying a later part of the stream up to the front */ + out_uint8a(s, data, thislength); + s_mark_end(s); + if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0) + { + return 1; + } + data += thislength; + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* this will inform the callback, whatever it is that some channel data is + ready. the default for this is a call to xrdp_wm.c. */ +static int APP_CC +xrdp_channel_call_callback(struct xrdp_channel* self, struct stream* s, + int channel_id) +{ + struct xrdp_session* session; + int rv; + int size; + + rv = 0; + session = self->sec_layer->rdp_layer->session; + if (session != 0) + { + if (session->callback != 0) + { + size = (int)(s->end - s->p); + /* in xrdp_wm.c */ + rv = session->callback(session->id, 0x5555, channel_id, size, + (long)s->p, 0); + } + else + { + g_writeln("in xrdp_channel_process1, session->callback is nil"); + } + } + else + { + g_writeln("in xrdp_channel_process1, session is nil"); + } + return rv; +} + +/*****************************************************************************/ +/* returns error */ +/* This is called from the secure layer to process an incomming non global + channel packet. It copies the channel data to a special stream contained + in the channel struct(the one in xrdp_mcs->channel_list) untill the + whole data message is ready. + 'chanid' passed in here is the mcs channel id so it MCS_GLOBAL_CHANNEL + plus something. */ +int APP_CC +xrdp_channel_process(struct xrdp_channel* self, struct stream* s, + int chanid) +{ + int length; + int flags; + int thislength; + int rv; + int channel_id; + struct stream* in_s; + struct mcs_channel_item* channel; + + /* this assumes that the channels are in order of chanid(mcs channel id) + but they should be, see xrdp_sec_process_mcs_data_channels + the first channel should be MCS_GLOBAL_CHANNEL + 1, second + one should be MCS_GLOBAL_CHANNEL + 2, and so on */ + channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1; + channel = xrdp_channel_get_item(self, channel_id); + if (channel == 0) + { + g_writeln("xrdp_channel_process, channel not found"); + return 1; + } + rv = 0; + in_uint32_le(s, length); + in_uint32_le(s, flags); + if ((flags & CHANNEL_FLAG_FIRST) && (flags & CHANNEL_FLAG_LAST)) + { + rv = xrdp_channel_call_callback(self, s, channel_id); + } + else + { + if (channel->in_s == 0) + { + make_stream(channel->in_s); + } + in_s = channel->in_s; + if (flags & CHANNEL_FLAG_FIRST) + { + init_stream(in_s, length); + } + thislength = MIN(s->end - s->p, (in_s->data + in_s->size) - in_s->p); + out_uint8a(in_s, s->p, thislength); + if (flags & CHANNEL_FLAG_LAST) + { + in_s->end = in_s->p; + in_s->p = in_s->data; + rv = xrdp_channel_call_callback(self, in_s, channel_id); + } + } + return rv; +} diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 0c589a02..ca6660bf 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -37,6 +37,7 @@ xrdp_mcs_create(struct xrdp_sec* owner, int sck, self->client_mcs_data = client_mcs_data; self->server_mcs_data = server_mcs_data; self->iso_layer = xrdp_iso_create(self, sck); + self->channel_list = list_create(); return self; } @@ -44,10 +45,27 @@ xrdp_mcs_create(struct xrdp_sec* owner, int sck, void APP_CC xrdp_mcs_delete(struct xrdp_mcs* self) { + struct mcs_channel_item* channel_item; + int index; + int count; + if (self == 0) { return; } + /* here we have to free the channel items and anything in them */ + count = self->channel_list->count; + for (index = count - 1; index >= 0; index--) + { + channel_item = (struct mcs_channel_item*) + list_get_item(self->channel_list, index); + if (channel_item != 0) + { + free_stream(channel_item->in_s); + g_free(channel_item); + } + } + list_delete(self->channel_list); xrdp_iso_delete(self->iso_layer); g_free(self); } @@ -55,7 +73,7 @@ xrdp_mcs_delete(struct xrdp_mcs* self) /*****************************************************************************/ /* returns error */ static int APP_CC -xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid) +xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid) { struct stream* s; @@ -68,7 +86,7 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid) } out_uint8(s, (MCS_CJCF << 2) | 2); out_uint8(s, 0); - out_uint16_be(s, self->userid); + out_uint16_be(s, userid); out_uint16_be(s, chanid); out_uint16_be(s, chanid); s_mark_end(s); @@ -89,6 +107,8 @@ xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan) int appid; int opcode; int len; + int userid; + int chanid; DEBUG((" in xrdp_mcs_recv")); while (1) @@ -105,9 +125,12 @@ xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan) DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM")); return 1; } + /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { - xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE); + in_uint16_be(s, userid); + in_uint16_be(s, chanid); + xrdp_mcs_send_cjcf(self, userid, chanid); continue; } break; @@ -499,12 +522,12 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs* self) init_stream(s, 8192); data_len = self->server_mcs_data->end - self->server_mcs_data->data; xrdp_iso_init(self->iso_layer, s); - xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, 313); + xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, data_len + 38); xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1); out_uint8(s, 0); xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); out_uint8(s, 0); - xrdp_mcs_out_domain_params(self, s, 2, 2, 0, 0xffff); + xrdp_mcs_out_domain_params(self, s, 22, 3, 0, 0xfff8); xrdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len); /* mcs data */ out_uint8a(s, self->server_mcs_data->data, data_len); @@ -532,6 +555,16 @@ xrdp_mcs_incoming(struct xrdp_mcs* self) { return 1; } + /* in xrdp_sec.c */ + if (xrdp_sec_process_mcs_data(self->sec_layer) != 0) + { + return 1; + } + /* in xrdp_sec.c */ + if (xrdp_sec_out_mcs_data(self->sec_layer) != 0) + { + return 1; + } if (xrdp_mcs_send_connect_response(self) != 0) { return 1; @@ -552,7 +585,8 @@ xrdp_mcs_incoming(struct xrdp_mcs* self) { return 1; } - if (xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE) != 0) + if (xrdp_mcs_send_cjcf(self, self->userid, + self->userid + MCS_USERCHANNEL_BASE) != 0) { return 1; } @@ -560,7 +594,7 @@ xrdp_mcs_incoming(struct xrdp_mcs* self) { return 1; } - if (xrdp_mcs_send_cjcf(self, MCS_GLOBAL_CHANNEL) != 0) + if (xrdp_mcs_send_cjcf(self, self->userid, MCS_GLOBAL_CHANNEL) != 0) { return 1; } @@ -580,24 +614,74 @@ xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s) /*****************************************************************************/ /* returns error */ +/* Inform the callback that an mcs packet has been sent. This is needed so + the module can send any high priority mcs packets like audio. */ +static int APP_CC +xrdp_mcs_call_callback(struct xrdp_mcs* self) +{ + int rv; + struct xrdp_session* session; + + rv = 0; + /* if there is a callback, call it here */ + session = self->sec_layer->rdp_layer->session; + if (session != 0) + { + if (session->callback != 0) + { + /* in xrdp_wm.c */ + rv = session->callback(session->id, 0x5556, 0, 0, 0, 0); + } + else + { + g_writeln("in xrdp_mcs_send, session->callback is nil"); + } + } + else + { + g_writeln("in xrdp_mcs_send, session is nil"); + } + return rv; +} + +/*****************************************************************************/ +/* returns error */ int APP_CC -xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s) +xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s, int chan) { int len; + //static int max_len = 0; DEBUG((" in xrdp_mcs_send")); s_pop_layer(s, mcs_hdr); len = (s->end - s->p) - 8; + if (len > 8192 * 2) + { + g_writeln("error in xrdp_mcs_send, size too bog, its %d", len); + } + //if (len > max_len) + //{ + // max_len = len; + // g_printf("mcs max length is %d\r\n", max_len); + //} + //g_printf("mcs length %d max length is %d\r\n", len, max_len); + //g_printf("mcs length %d\r\n", len); len = len | 0x8000; out_uint8(s, MCS_SDIN << 2); out_uint16_be(s, self->userid); - out_uint16_be(s, MCS_GLOBAL_CHANNEL); + out_uint16_be(s, chan); out_uint8(s, 0x70); out_uint16_be(s, len); if (xrdp_iso_send(self->iso_layer, s) != 0) { return 1; } + /* todo, do we need to call this for every mcs packet, + maybe every 5 or so */ + if (chan == MCS_GLOBAL_CHANNEL) + { + xrdp_mcs_call_callback(self); + } DEBUG((" out xrdp_mcs_send")); return 0; } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 45a29d1b..2fa61eb4 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -122,7 +122,8 @@ xrdp_rdp_create(struct xrdp_session* session, int sck) /* read ini settings */ xrdp_rdp_read_config(&self->client_info); /* create sec layer */ - self->sec_layer = xrdp_sec_create(self, sck, self->client_info.crypt_level); + self->sec_layer = xrdp_sec_create(self, sck, self->client_info.crypt_level, + self->client_info.channel_code); /* default 8 bit v1 color bitmap cache entries and size */ self->client_info.cache1_entries = 600; self->client_info.cache1_size = 256; @@ -198,6 +199,10 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) } if (chan != MCS_GLOBAL_CHANNEL && chan > 0) { + if (chan > MCS_GLOBAL_CHANNEL) + { + xrdp_channel_process(self->sec_layer->chan_layer, s, chan); + } s->next_packet = 0; *code = 0; DEBUG(("out xrdp_rdp_recv")); @@ -237,7 +242,7 @@ xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type) out_uint16_le(s, len); out_uint16_le(s, 0x10 | pdu_type); out_uint16_le(s, self->mcs_channel); - if (xrdp_sec_send(self->sec_layer, s) != 0) + if (xrdp_sec_send(self->sec_layer, s, MCS_GLOBAL_CHANNEL) != 0) { DEBUG(("out xrdp_rdp_send error")); return 1; @@ -266,7 +271,7 @@ xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, out_uint8(s, data_pdu_type); out_uint8(s, 0); out_uint16_le(s, 0); - if (xrdp_sec_send(self->sec_layer, s) != 0) + if (xrdp_sec_send(self->sec_layer, s, MCS_GLOBAL_CHANNEL) != 0) { DEBUG(("out xrdp_rdp_send_data error")); return 1; diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index c80cb844..ea165c62 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -139,7 +139,7 @@ hex_to_bin(char* in, char* out) } /*****************************************************************************/ -static void +static void APP_CC hex_str_to_bin(char* in, char* out, int out_len) { int in_index; @@ -169,7 +169,8 @@ hex_str_to_bin(char* in, char* out, int out_len) /*****************************************************************************/ struct xrdp_sec* APP_CC -xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level) +xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level, + int channel_code) { struct xrdp_sec* self; struct list* items; @@ -198,6 +199,7 @@ xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level) self->crypt_level = 3; break; } + self->channel_code = channel_code; self->decrypt_rc4_info = ssl_rc4_info_create(); self->encrypt_rc4_info = ssl_rc4_info_create(); g_random(self->server_random, 32); @@ -398,6 +400,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec* self, struct stream* s) { /* must be or error */ return 1; } + if (flags & RDP_LOGON_LEAVE_AUDIO) + { + self->rdp_layer->client_info.sound_code = 1; + } if (flags & RDP_LOGON_AUTO) { self->rdp_layer->client_info.rdp_autologin = 1; @@ -451,7 +457,7 @@ xrdp_sec_send_lic_initial(struct xrdp_sec* self) } out_uint8a(s, g_lic1, 322); s_mark_end(s); - if (xrdp_mcs_send(self->mcs_layer, s) != 0) + if (xrdp_mcs_send(self->mcs_layer, s, MCS_GLOBAL_CHANNEL) != 0) { free_stream(s); return 1; @@ -476,7 +482,7 @@ xrdp_sec_send_lic_response(struct xrdp_sec* self) } out_uint8a(s, g_lic2, 20); s_mark_end(s); - if (xrdp_mcs_send(self->mcs_layer, s) != 0) + if (xrdp_mcs_send(self->mcs_layer, s, MCS_GLOBAL_CHANNEL) != 0) { free_stream(s); return 1; @@ -682,7 +688,7 @@ xrdp_sec_sign(struct xrdp_sec* self, char* out, int out_len, /*****************************************************************************/ /* returns error */ int APP_CC -xrdp_sec_send(struct xrdp_sec* self, struct stream* s) +xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int chan) { int datalen; @@ -699,7 +705,7 @@ xrdp_sec_send(struct xrdp_sec* self, struct stream* s) { out_uint32_le(s, 0); } - if (xrdp_mcs_send(self->mcs_layer, s) != 0) + if (xrdp_mcs_send(self->mcs_layer, s, chan) != 0) { return 1; } @@ -708,73 +714,168 @@ xrdp_sec_send(struct xrdp_sec* self, struct stream* s) } /*****************************************************************************/ +/* this adds the mcs channels in the list of channels to be used when + creating the server mcs data */ +static int APP_CC +xrdp_sec_process_mcs_data_channels(struct xrdp_sec* self, struct stream* s) +{ + int num_channels; + int index; + struct mcs_channel_item* channel_item; + + /* this is an option set in xrdp.ini */ + if (self->channel_code != 1) /* are channels on? */ + { + return 0; + } + in_uint32_le(s, num_channels); + for (index = 0; index < num_channels; index++) + { + channel_item = (struct mcs_channel_item*) + g_malloc(sizeof(struct mcs_channel_item), 1); + in_uint8a(s, channel_item->name, 8); + in_uint32_be(s, channel_item->flags); + channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); + list_add_item(self->mcs_layer->channel_list, (long)channel_item); + } + return 0; +} + +/*****************************************************************************/ +/* process client mcs data, we need some things in here to create the server + mcs data */ +int APP_CC +xrdp_sec_process_mcs_data(struct xrdp_sec* self) +{ + struct stream* s; + char* hold_p; + int tag; + int size; + + s = &self->client_mcs_data; + /* set p to beginning */ + s->p = s->data; + /* skip header */ + in_uint8s(s, 23); + while (s_check_rem(s, 4)) + { + hold_p = s->p; + in_uint16_le(s, tag); + in_uint16_le(s, size); + if (size < 4 || !s_check_rem(s, size - 4)) + { + g_writeln("error in xrdp_sec_process_mcs_data tag %d size %d", + tag, size); + break; + } + switch (tag) + { + case SEC_TAG_CLI_INFO: + break; + case SEC_TAG_CLI_CRYPT: + break; + case SEC_TAG_CLI_CHANNELS: + xrdp_sec_process_mcs_data_channels(self, s); + break; + case SEC_TAG_CLI_4: + break; + default: + g_writeln("error unknown xrdp_sec_process_mcs_data tag %d size %d", + tag, size); + break; + } + s->p = hold_p + size; + } + /* set p to beginning */ + s->p = s->data; + return 0; +} + +/*****************************************************************************/ /* prepare server mcs data to send in mcs layer */ -static void APP_CC +int APP_CC xrdp_sec_out_mcs_data(struct xrdp_sec* self) { - struct stream* p; - - p = &self->server_mcs_data; - init_stream(p, 512); - out_uint16_be(p, 5); - out_uint16_be(p, 0x14); - out_uint8(p, 0x7c); - out_uint16_be(p, 1); - out_uint8(p, 0x2a); - out_uint8(p, 0x14); - out_uint8(p, 0x76); - out_uint8(p, 0x0a); - out_uint8(p, 1); - out_uint8(p, 1); - out_uint8(p, 0); - out_uint16_le(p, 0xc001); - out_uint8(p, 0); - out_uint8(p, 0x4d); /* M */ - out_uint8(p, 0x63); /* c */ - out_uint8(p, 0x44); /* D */ - out_uint8(p, 0x6e); /* n */ - out_uint16_be(p, 0x80fc); - out_uint16_le(p, SEC_TAG_SRV_INFO); - out_uint16_le(p, 8); /* len */ - out_uint8(p, 4); /* 4 = rdp5 1 = rdp4 */ - out_uint8(p, 0); - out_uint8(p, 8); - out_uint8(p, 0); - out_uint16_le(p, SEC_TAG_SRV_CHANNELS); - out_uint16_le(p, 8); /* len */ - out_uint8(p, 0xeb); - out_uint8(p, 3); - out_uint8(p, 0); - out_uint8(p, 0); - out_uint16_le(p, SEC_TAG_SRV_CRYPT); - out_uint16_le(p, 0x00ec); /* len is 236 */ - out_uint32_le(p, self->rc4_key_size); /* key len 1 = 40 bit 2 = 128 bit */ - out_uint32_le(p, self->crypt_level); /* crypt level 1 = low 2 = medium */ + struct stream* s; + int num_channels_even; + int num_channels; + int index; + int channel; + + num_channels = self->mcs_layer->channel_list->count; + num_channels_even = num_channels + (num_channels & 1); + s = &self->server_mcs_data; + init_stream(s, 512); + out_uint16_be(s, 5); + out_uint16_be(s, 0x14); + out_uint8(s, 0x7c); + out_uint16_be(s, 1); + out_uint8(s, 0x2a); + out_uint8(s, 0x14); + out_uint8(s, 0x76); + out_uint8(s, 0x0a); + out_uint8(s, 1); + out_uint8(s, 1); + out_uint8(s, 0); + out_uint16_le(s, 0xc001); + out_uint8(s, 0); + out_uint8(s, 0x4d); /* M */ + out_uint8(s, 0x63); /* c */ + out_uint8(s, 0x44); /* D */ + out_uint8(s, 0x6e); /* n */ + out_uint16_be(s, 0x80fc + (num_channels_even * 2)); + out_uint16_le(s, SEC_TAG_SRV_INFO); + out_uint16_le(s, 8); /* len */ + out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ + out_uint8(s, 0); + out_uint8(s, 8); + out_uint8(s, 0); + out_uint16_le(s, SEC_TAG_SRV_CHANNELS); + out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ + out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ + out_uint16_le(s, num_channels); /* number of other channels */ + for (index = 0; index < num_channels_even; index++) + { + if (index < num_channels) + { + channel = MCS_GLOBAL_CHANNEL + (index + 1); + out_uint16_le(s, channel); + } + else + { + out_uint16_le(s, 0); + } + } + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 0x00ec); /* len is 236 */ + out_uint32_le(s, self->rc4_key_size); /* key len 1 = 40 bit 2 = 128 bit */ + out_uint32_le(s, self->crypt_level); /* crypt level 1 = low 2 = medium */ /* 3 = high */ - out_uint32_le(p, 32); /* 32 bytes random len */ - out_uint32_le(p, 0xb8); /* 184 bytes rsa info(certificate) len */ - out_uint8a(p, self->server_random, 32); + out_uint32_le(s, 32); /* 32 bytes random len */ + out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ + out_uint8a(s, self->server_random, 32); /* here to end is certificate */ /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ /* TermService\Parameters\Certificate */ - out_uint32_le(p, 1); - out_uint32_le(p, 1); - out_uint32_le(p, 1); - out_uint16_le(p, SEC_TAG_PUBKEY); - out_uint16_le(p, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(p, SEC_RSA_MAGIC); - out_uint32_le(p, 0x48); /* 72 bytes modulus len */ - out_uint32_be(p, 0x00020000); - out_uint32_be(p, 0x3f000000); - out_uint8a(p, self->pub_exp, 4); /* pub exp */ - out_uint8a(p, self->pub_mod, 64); /* pub mod */ - out_uint8s(p, 8); /* pad */ - out_uint16_le(p, SEC_TAG_KEYSIG); - out_uint16_le(p, 72); /* len */ - out_uint8a(p, self->pub_sig, 64); /* pub sig */ - out_uint8s(p, 8); /* pad */ + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint16_le(s, SEC_TAG_PUBKEY); + out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ + out_uint32_le(s, SEC_RSA_MAGIC); + out_uint32_le(s, 0x48); /* 72 bytes modulus len */ + out_uint32_be(s, 0x00020000); + out_uint32_be(s, 0x3f000000); + out_uint8a(s, self->pub_exp, 4); /* pub exp */ + out_uint8a(s, self->pub_mod, 64); /* pub mod */ + out_uint8s(s, 8); /* pad */ + out_uint16_le(s, SEC_TAG_KEYSIG); + out_uint16_le(s, 72); /* len */ + out_uint8a(s, self->pub_sig, 64); /* pub sig */ + out_uint8s(s, 8); /* pad */ /* end certificate */ - s_mark_end(p); + s_mark_end(s); + return 0; } /*****************************************************************************/ @@ -818,7 +919,6 @@ int APP_CC xrdp_sec_incoming(struct xrdp_sec* self) { DEBUG(("in xrdp_sec_incoming")); - xrdp_sec_out_mcs_data(self); if (xrdp_mcs_incoming(self->mcs_layer) != 0) { return 1; |