mirror of https://github.com/neutrinolabs/xrdp
added channel support
This commit is contained in:
parent
1ed935186d
commit
0dc679e2dc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue