added channel support

This commit is contained in:
jsorg71 2006-12-28 06:15:13 +00:00
parent 1ed935186d
commit 0dc679e2dc
6 changed files with 548 additions and 81 deletions

View File

@ -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

View File

@ -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

239
libxrdp/xrdp_channel.c Normal file
View File

@ -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;
}

View File

@ -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;
}
@ -578,26 +612,76 @@ xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s)
return 0;
}
/*****************************************************************************/
/* 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;
}

View File

@ -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;

View File

@ -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;
}
@ -707,74 +713,169 @@ xrdp_sec_send(struct xrdp_sec* self, struct stream* s)
return 0;
}
/*****************************************************************************/
/* 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;