summaryrefslogtreecommitdiffstats
path: root/libxrdp/xrdp_sec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp/xrdp_sec.c')
-rw-r--r--libxrdp/xrdp_sec.c836
1 files changed, 612 insertions, 224 deletions
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index a4fe8c5a..63957a45 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -26,6 +26,8 @@
do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0)
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0)
+#define LHEXDUMP(_level, _args) \
+ do { if (_level < LOG_LEVEL) { g_hexdump _args ; } } while (0)
/* some compilers need unsigned char to avoid warnings */
static tui8 g_pad_54[40] =
@@ -183,6 +185,8 @@ static const tui8 g_fips_ivec[8] =
0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF
};
+static int is_security_header_present = 1; /* next packet should contain security header? */
+
/*****************************************************************************/
static void APP_CC
hex_str_to_bin(char *in, char *out, int out_len)
@@ -219,85 +223,251 @@ hex_str_to_bin(char *in, char *out, int out_len)
}
/*****************************************************************************/
-struct xrdp_sec *APP_CC
-xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level,
- int channel_code, int multimon)
+static void APP_CC
+xrdp_load_keyboard_layout(struct xrdp_client_info *client_info)
{
- struct xrdp_sec *self;
+ int fd;
+ int index = 0;
+ int bytes;
+ struct list *names = (struct list *)NULL;
+ struct list *items = (struct list *)NULL;
+ struct list *values = (struct list *)NULL;
+ char *item = (char *)NULL;
+ char *value = (char *)NULL;
+ char *q = (char *)NULL;
+ char keyboard_cfg_file[256] = { 0 };
+ char rdp_layout[256] = { 0 };
+
+ LLOGLN(0, ("xrdp_load_keyboard_layout:"));
+ /* infer model/variant */
+ /* TODO specify different X11 keyboard models/variants */
+ g_memset(client_info->model, 0, sizeof(client_info->model));
+ g_memset(client_info->variant, 0, sizeof(client_info->variant));
+ g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1);
+ if (client_info->keyboard_subtype == 3)
+ {
+ /* macintosh keyboard */
+ bytes = sizeof(client_info->variant);
+ g_strncpy(client_info->variant, "mac", bytes - 1);
+ }
+ else if (client_info->keyboard_subtype == 0)
+ {
+ /* default - standard subtype */
+ client_info->keyboard_subtype = 1;
+ }
+
+ g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH);
+ LLOGLN(10, ("keyboard_cfg_file %s", keyboard_cfg_file));
+
+ fd = g_file_open(keyboard_cfg_file);
+
+ if (fd > 0)
+ {
+ int section_found = -1;
+ char section_rdp_layouts[256] = { 0 };
+ char section_layouts_map[256] = { 0 };
+
+ names = list_create();
+ names->auto_free = 1;
+ items = list_create();
+ items->auto_free = 1;
+ values = list_create();
+ values->auto_free = 1;
+
+ file_read_sections(fd, names);
+ for (index = 0; index < names->count; index++)
+ {
+ q = (char *)list_get_item(names, index);
+ if (g_strncasecmp("default", q, 8) != 0)
+ {
+ int i;
- DEBUG((" in xrdp_sec_create"));
- self = (struct xrdp_sec *)g_malloc(sizeof(struct xrdp_sec), 1);
- self->rdp_layer = owner;
- self->crypt_method = CRYPT_METHOD_NONE;
- self->crypt_level = CRYPT_LEVEL_NONE;
- switch (crypt_level)
- {
- case 1: /* low */
- self->crypt_method = CRYPT_METHOD_40BIT;
- self->crypt_level = CRYPT_LEVEL_LOW;
- break;
- case 2: /* medium */
- self->crypt_method = CRYPT_METHOD_40BIT;
- self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE;
- break;
- case 3: /* high */
- self->crypt_method = CRYPT_METHOD_128BIT;
- self->crypt_level = CRYPT_LEVEL_HIGH;
- break;
- case 4: /* fips */
- self->crypt_method = CRYPT_METHOD_FIPS;
- self->crypt_level = CRYPT_LEVEL_FIPS;
- break;
- default:
- g_writeln("Fatal : Illegal crypt_level");
- break ;
- }
+ file_read_section(fd, q, items, values);
- self->channel_code = channel_code;
- self->multimon = multimon;
+ for (i = 0; i < items->count; i++)
+ {
+ item = (char *)list_get_item(items, i);
+ value = (char *)list_get_item(values, i);
+ LLOGLN(10, ("xrdp_load_keyboard_layout: item %s value %s",
+ item, value));
+ if (g_strcasecmp(item, "keyboard_type") == 0)
+ {
+ int v = g_atoi(value);
+ if (v == client_info->keyboard_type)
+ {
+ section_found = index;
+ }
+ }
+ else if (g_strcasecmp(item, "keyboard_subtype") == 0)
+ {
+ int v = g_atoi(value);
+ if (v != client_info->keyboard_subtype &&
+ section_found == index)
+ {
+ section_found = -1;
+ break;
+ }
+ }
+ else if (g_strcasecmp(item, "rdp_layouts") == 0)
+ {
+ if (section_found != -1 && section_found == index)
+ {
+ g_strncpy(section_rdp_layouts, value, 255);
+ }
+ }
+ else if (g_strcasecmp(item, "layouts_map") == 0)
+ {
+ if (section_found != -1 && section_found == index)
+ {
+ g_strncpy(section_layouts_map, value, 255);
+ }
+ }
+ else if (g_strcasecmp(item, "model") == 0)
+ {
+ if (section_found != -1 && section_found == index)
+ {
+ bytes = sizeof(client_info->model);
+ g_memset(client_info->model, 0, bytes);
+ g_strncpy(client_info->model, value, bytes - 1);
+ }
+ }
+ else if (g_strcasecmp(item, "variant") == 0)
+ {
+ if (section_found != -1 && section_found == index)
+ {
+ bytes = sizeof(client_info->variant);
+ g_memset(client_info->variant, 0, bytes);
+ g_strncpy(client_info->variant, value, bytes - 1);
+ }
+ }
+ else
+ {
+ /*
+ * mixing items from different sections will result in
+ * skipping over current section.
+ */
+ LLOGLN(10, ("xrdp_load_keyboard_layout: skipping "
+ "configuration item - %s, continuing to next "
+ "section", item));
+ break;
+ }
+ }
- if (self->decrypt_rc4_info != NULL)
- {
- g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!");
- }
+ list_clear(items);
+ list_clear(values);
+ }
+ }
+
+ if (section_found == -1)
+ {
+ g_memset(section_rdp_layouts, 0, sizeof(char) * 256);
+ g_memset(section_layouts_map, 0, sizeof(char) * 256);
+ // read default section
+ file_read_section(fd, "default", items, values);
+ for (index = 0; index < items->count; index++)
+ {
+ item = (char *)list_get_item(items, index);
+ value = (char *)list_get_item(values, index);
+ if (g_strcasecmp(item, "rdp_layouts") == 0)
+ {
+ g_strncpy(section_rdp_layouts, value, 255);
+ }
+ else if (g_strcasecmp(item, "layouts_map") == 0)
+ {
+ g_strncpy(section_layouts_map, value, 255);
+ }
+ }
+ list_clear(items);
+ list_clear(values);
+ }
- self->decrypt_rc4_info = ssl_rc4_info_create();
+ /* load the map */
+ file_read_section(fd, section_rdp_layouts, items, values);
+ for (index = 0; index < items->count; index++)
+ {
+ int rdp_layout_id;
+ item = (char *)list_get_item(items, index);
+ value = (char *)list_get_item(values, index);
+ rdp_layout_id = g_htoi(value);
+ if (rdp_layout_id == client_info->keylayout)
+ {
+ g_strncpy(rdp_layout, item, 255);
+ break;
+ }
+ }
+ list_clear(items);
+ list_clear(values);
+ file_read_section(fd, section_layouts_map, items, values);
+ for (index = 0; index < items->count; index++)
+ {
+ item = (char *)list_get_item(items, index);
+ value = (char *)list_get_item(values, index);
+ if (g_strcasecmp(item, rdp_layout) == 0)
+ {
+ bytes = sizeof(client_info->layout);
+ g_strncpy(client_info->layout, value, bytes - 1);
+ break;
+ }
+ }
- if (self->encrypt_rc4_info != NULL)
+ list_delete(names);
+ list_delete(items);
+ list_delete(values);
+
+ LLOGLN(0, ("xrdp_load_keyboard_layout: model [%s] variant [%s] "
+ "layout [%s]", client_info->model, client_info->variant,
+ client_info->layout));
+ g_file_close(fd);
+ }
+ else
{
- g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!");
+ LLOGLN(0, ("xrdp_load_keyboard_layout: error opening %d",
+ keyboard_cfg_file));
}
+}
+
+/*****************************************************************************/
+struct xrdp_sec *APP_CC
+xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans)
+{
+ struct xrdp_sec *self;
- self->encrypt_rc4_info = ssl_rc4_info_create();
- self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data,
- &self->server_mcs_data);
- self->chan_layer = xrdp_channel_create(self, self->mcs_layer);
- DEBUG((" out xrdp_sec_create"));
- return self;
+ DEBUG((" in xrdp_sec_create"));
+ self = (struct xrdp_sec *) g_malloc(sizeof(struct xrdp_sec), 1);
+ self->rdp_layer = owner;
+ self->crypt_method = CRYPT_METHOD_NONE; /* set later */
+ self->crypt_level = CRYPT_LEVEL_NONE;
+ self->mcs_layer = xrdp_mcs_create(self, trans, &(self->client_mcs_data),
+ &(self->server_mcs_data));
+ self->fastpath_layer = xrdp_fastpath_create(self, trans);
+ self->chan_layer = xrdp_channel_create(self, self->mcs_layer);
+ DEBUG((" out xrdp_sec_create"));
+
+ return self;
}
/*****************************************************************************/
void APP_CC
-xrdp_sec_delete(struct xrdp_sec *self)
-{
- if (self == 0)
- {
- g_writeln("xrdp_sec_delete: indata is null");
- return;
- }
-
- xrdp_channel_delete(self->chan_layer);
- xrdp_mcs_delete(self->mcs_layer);
- ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */
- ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
- ssl_des3_info_delete(self->decrypt_fips_info);
- ssl_des3_info_delete(self->encrypt_fips_info);
- ssl_hmac_info_delete(self->sign_fips_info);
- g_free(self->client_mcs_data.data);
- g_free(self->server_mcs_data.data);
- /* Crypto information must always be cleared */
- g_memset(self, 0, sizeof(struct xrdp_sec));
- g_free(self);
+xrdp_sec_delete(struct xrdp_sec *self) {
+
+ if (self == 0) {
+ g_writeln("xrdp_sec_delete: indata is null");
+ return;
+ }
+
+ xrdp_channel_delete(self->chan_layer);
+ xrdp_mcs_delete(self->mcs_layer);
+ xrdp_fastpath_delete(self->fastpath_layer);
+ ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */
+ ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
+ ssl_des3_info_delete(self->decrypt_fips_info);
+ ssl_des3_info_delete(self->encrypt_fips_info);
+ ssl_hmac_info_delete(self->sign_fips_info);
+ g_free(self->client_mcs_data.data);
+ g_free(self->server_mcs_data.data);
+ /* Crypto information must always be cleared */
+ g_memset(self, 0, sizeof(struct xrdp_sec));
+ g_free(self);
}
/*****************************************************************************/
@@ -320,7 +490,7 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s)
}
else
{
- s_push_layer(s, sec_hdr, 4);
+// s_push_layer(s, sec_hdr, 4);
}
return 0;
@@ -766,9 +936,12 @@ xrdp_sec_send_media_lic_response(struct xrdp_sec *self)
/*****************************************************************************/
static void APP_CC
-xrdp_sec_rsa_op(char *out, char *in, char *mod, char *exp)
+xrdp_sec_rsa_op(struct xrdp_sec *self, char *out, char *in, int in_bytes,
+ char *mod, char *exp)
{
- ssl_mod_exp(out, 64, in, 64, mod, 64, exp, 64);
+ ssl_mod_exp(out, self->rsa_key_bytes, in, in_bytes,
+ mod, self->rsa_key_bytes,
+ exp, self->rsa_key_bytes);
}
/*****************************************************************************/
@@ -952,6 +1125,68 @@ xrdp_sec_establish_keys(struct xrdp_sec *self)
/*****************************************************************************/
/* returns error */
int APP_CC
+xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s)
+{
+ int ver;
+ int len;
+ int pad;
+
+ LLOGLN(10, ("xrdp_sec_recv_fastpath:"));
+ if (xrdp_fastpath_recv(self->fastpath_layer, s) != 0)
+ {
+ return 1;
+ }
+
+ if (self->fastpath_layer->secFlags & FASTPATH_INPUT_ENCRYPTED)
+ {
+ if (self->crypt_level == CRYPT_LEVEL_FIPS)
+ {
+ if (!s_check_rem(s, 12))
+ {
+ return 1;
+ }
+ in_uint16_le(s, len);
+ in_uint8(s, ver); /* length (2 bytes) */
+ if (len != 0x10) /* length MUST set to 0x10 */
+ {
+ return 1;
+ }
+ in_uint8(s, pad);
+ LLOGLN(10, ("xrdp_sec_recv_fastpath: len %d ver %d pad %d", len, ver, pad));
+ in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */
+ LLOGLN(10, ("xrdp_sec_recv_fastpath: data len %d", (int)(s->end - s->p)));
+ xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p));
+ s->end -= pad;
+ }
+ else
+ {
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
+ in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */
+ xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p));
+ }
+ }
+
+ if (self->fastpath_layer->numEvents == 0)
+ {
+ /**
+ * If numberEvents is not provided in fpInputHeader, it will be provided
+ * as one additional byte here.
+ */
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
+ in_uint8(s, self->fastpath_layer->numEvents); /* numEvents (1 byte) (optional) */
+ }
+
+ return 0;
+}
+/*****************************************************************************/
+/* returns error */
+int APP_CC
xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
{
int flags;
@@ -963,7 +1198,8 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0)
{
- DEBUG((" out xrdp_sec_recv error"));
+ DEBUG((" out xrdp_sec_recv : error"));
+ g_writeln("xrdp_sec_recv: xrdp_mcs_recv failed");
return 1;
}
@@ -971,6 +1207,13 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
{
return 1;
}
+
+
+ if (!is_security_header_present)
+ {
+ return 0;
+ }
+
in_uint32_le(s, flags);
DEBUG((" in xrdp_sec_recv flags $%x", flags));
@@ -995,7 +1238,7 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p));
s->end -= pad;
}
- else
+ else if (self->crypt_level > CRYPT_LEVEL_NONE)
{
if (!s_check_rem(s, 8))
{
@@ -1008,19 +1251,31 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
{
- if (!s_check_rem(s, 4 + 64))
+ if (!s_check_rem(s, 4))
{
return 1;
}
in_uint32_le(s, len);
- in_uint8a(s, self->client_crypt_random, 64);
- xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
- self->pub_mod, self->pri_exp);
+ /* 512, 2048 bit */
+ if ((len != 64 + 8) && (len != 256 + 8))
+ {
+ return 1;
+ }
+ if (!s_check_rem(s, len - 8))
+ {
+ return 1;
+ }
+ in_uint8a(s, self->client_crypt_random, len - 8);
+ xrdp_sec_rsa_op(self, self->client_random, self->client_crypt_random,
+ len - 8, self->pub_mod, self->pri_exp);
+ LLOGLN(10, ("xrdp_sec_recv: client random - len %d", len));
+ LHEXDUMP(10, (self->client_random, 256));
+ LHEXDUMP(10, (self->client_crypt_random, len - 8));
if (self->crypt_level == CRYPT_LEVEL_FIPS)
{
xrdp_sec_fips_establish_keys(self);
}
- else
+ else if (self->crypt_method != CRYPT_METHOD_NONE)
{
xrdp_sec_establish_keys(self);
}
@@ -1068,6 +1323,12 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
return 1;
}
+ if (self->crypt_level == CRYPT_LEVEL_NONE
+ && self->crypt_method == CRYPT_METHOD_NONE)
+ {
+ is_security_header_present = 0; /* in tls mode, no more security header from now on */
+ }
+
DEBUG((" out xrdp_sec_recv"));
return -1; /* special error that means send demand active */
}
@@ -1170,7 +1431,7 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
}
else
{
- out_uint32_le(s, 0);
+// out_uint32_le(s, 0);
}
if (xrdp_mcs_send(self->mcs_layer, s, chan) != 0)
@@ -1183,6 +1444,120 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
}
/*****************************************************************************/
+/* returns the fastpath sec byte count */
+int APP_CC
+xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self)
+{
+ if (self->crypt_level == CRYPT_LEVEL_FIPS)
+ {
+ return 3 + 4 + 8;
+ }
+ else if (self->crypt_level > CRYPT_LEVEL_LOW)
+ {
+ return 3 + 8;
+ }
+ return 3;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s)
+{
+ if (xrdp_fastpath_init(self->fastpath_layer, s) != 0)
+ {
+ return 1;
+ }
+ if (self->crypt_level == CRYPT_LEVEL_FIPS)
+ {
+ s_push_layer(s, sec_hdr, 3 + 4 + 8);
+ }
+ else if (self->crypt_level > CRYPT_LEVEL_LOW)
+ {
+ s_push_layer(s, sec_hdr, 3 + 8);
+ }
+ else
+ {
+ s_push_layer(s, sec_hdr, 3);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* 2.2.9.1.2 Server Fast-Path Update PDU (TS_FP_UPDATE_PDU)
+ * http://msdn.microsoft.com/en-us/library/cc240621.aspx */
+int APP_CC
+xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s)
+{
+ int secFlags;
+ int fpOutputHeader;
+ int datalen;
+ int pdulen;
+ int pad;
+ int error;
+ char save[8];
+
+ LLOGLN(10, ("xrdp_sec_send_fastpath:"));
+ error = 0;
+ s_pop_layer(s, sec_hdr);
+ if (self->crypt_level == CRYPT_LEVEL_FIPS)
+ {
+ LLOGLN(10, ("xrdp_sec_send_fastpath: fips"));
+ pdulen = (int)(s->end - s->p);
+ datalen = pdulen - 15;
+ pad = (8 - (datalen % 8)) & 7;
+ secFlags = 0x2;
+ fpOutputHeader = secFlags << 6;
+ out_uint8(s, fpOutputHeader);
+ pdulen += pad;
+ pdulen |= 0x8000;
+ out_uint16_be(s, pdulen);
+ out_uint16_le(s, 16); /* crypto header size */
+ out_uint8(s, 1); /* fips version */
+ s->end += pad;
+ out_uint8(s, pad); /* fips pad */
+ xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen);
+ g_memcpy(save, s->p + 8 + datalen, pad);
+ g_memset(s->p + 8 + datalen, 0, pad);
+ xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad);
+ error = xrdp_fastpath_send(self->fastpath_layer, s);
+ g_memcpy(s->p + 8 + datalen, save, pad);
+ }
+ else if (self->crypt_level > CRYPT_LEVEL_LOW)
+ {
+ LLOGLN(10, ("xrdp_sec_send_fastpath: crypt"));
+ pdulen = (int)(s->end - s->p);
+ datalen = pdulen - 11;
+ secFlags = 0x2;
+ fpOutputHeader = secFlags << 6;
+ out_uint8(s, fpOutputHeader);
+ pdulen |= 0x8000;
+ out_uint16_be(s, pdulen);
+ xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen);
+ xrdp_sec_encrypt(self, s->p + 8, datalen);
+ error = xrdp_fastpath_send(self->fastpath_layer, s);
+ }
+ else
+ {
+ LLOGLN(10, ("xrdp_sec_send_fastpath: no crypt"));
+ pdulen = (int)(s->end - s->p);
+ LLOGLN(10, ("xrdp_sec_send_fastpath: pdulen %d", pdulen));
+ secFlags = 0x0;
+ fpOutputHeader = secFlags << 6;
+ out_uint8(s, fpOutputHeader);
+ pdulen |= 0x8000;
+ out_uint16_be(s, pdulen);
+ error = xrdp_fastpath_send(self->fastpath_layer, s);
+ }
+ if (error != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
/* http://msdn.microsoft.com/en-us/library/cc240510.aspx
2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */
static int APP_CC
@@ -1404,10 +1779,23 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s)
found = 1;
}
}
- if (found == 0)
+ if ((found == 0) &&
+ (self->crypt_level == CRYPT_LEVEL_NONE))
{
- g_writeln(" no security");
+ if (crypt_method == CRYPT_METHOD_NONE)
+ {
+ g_writeln(" client and server support none crypt, using "
+ "none crypt");
+ self->crypt_method = CRYPT_METHOD_NONE;
+ self->crypt_level = CRYPT_LEVEL_NONE;
+ found = 1;
+ }
}
+// if (found == 0)
+// {
+// g_writeln(" can not find client / server agreed encryption method");
+// return 1;
+// }
return 0;
}
@@ -1420,11 +1808,15 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
int num_channels;
int index;
struct mcs_channel_item *channel_item;
+ struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL;
+
+ client_info = &(self->rdp_layer->client_info);
+
- DEBUG(("processing channels, channel_code is %d", self->channel_code));
+ DEBUG(("processing channels, channel_code is %d", client_info->channel_code));
/* this is an option set in xrdp.ini */
- if (self->channel_code != 1) /* are channels on? */
+ if (client_info->channel_code != 1) /* are channels on? */
{
g_writeln("Processing channel data from client - The channel is off");
return 0;
@@ -1444,16 +1836,19 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
for (index = 0; index < num_channels; index++)
{
+ struct mcs_channel_item *channel_item;
+
channel_item = (struct mcs_channel_item *)
g_malloc(sizeof(struct mcs_channel_item), 1);
if (!s_check_rem(s, 12))
{
+ g_free(channel_item);
return 1;
}
in_uint8a(s, channel_item->name, 8);
in_uint32_le(s, channel_item->flags);
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
- list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item);
+ list_add_item(self->mcs_layer->channel_list, (tintptr) channel_item);
DEBUG(("got channel flags %8.8x name %s", channel_item->flags,
channel_item->name));
}
@@ -1473,9 +1868,9 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s)
client_info = &(self->rdp_layer->client_info);
- DEBUG(("processing monitors data, allow_multimon is %d", self->multimon));
+ DEBUG(("processing monitors data, allow_multimon is %d", client_info->multimon));
/* this is an option set in xrdp.ini */
- if (self->multimon != 1) /* are multi-monitors allowed ? */
+ if (client_info->multimon != 1) /* are multi-monitors allowed ? */
{
DEBUG(("[INFO] xrdp_sec_process_mcs_data_monitors: multimon is not "
"allowed, skipping"));
@@ -1617,113 +2012,6 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
}
/*****************************************************************************/
-/* prepare server mcs data to send in mcs layer */
-int APP_CC
-xrdp_sec_out_mcs_data(struct xrdp_sec *self)
-{
- 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 */
- if (self->mcs_layer->iso_layer->selectedProtocol != -1)
- { // Check for RDPNEGDATA availability
- out_uint16_be(s, 0x80fc + (num_channels_even * 2) + 4);
- }
- else
- {
- out_uint16_be(s, 0x80fc + (num_channels_even * 2));
- }
- out_uint16_le(s, SEC_TAG_SRV_INFO);
- if (self->mcs_layer->iso_layer->selectedProtocol != -1)
- {
- out_uint16_le(s, 12); /* len */
- }
- else
- {
- 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);
- if (self->mcs_layer->iso_layer->selectedProtocol != -1)
- {
- /* clientReqeustedProtocol */
- out_uint32_le(s, self->mcs_layer->iso_layer->selectedProtocol);
- }
- 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->crypt_method);
- out_uint32_le(s, self->crypt_level);
- 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(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(s);
- return 0;
-}
-
-/*****************************************************************************/
/* process the mcs client data we received from the mcs layer */
static int APP_CC
xrdp_sec_in_mcs_data(struct xrdp_sec *self)
@@ -1782,67 +2070,166 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
in_uint8s(s, 79);
in_uint32_le(s, client_info->keyboard_type);
in_uint32_le(s, client_info->keyboard_subtype);
+ xrdp_load_keyboard_layout(client_info);
s->p = s->data;
return 0;
}
/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_sec_init_rdp_security(struct xrdp_sec *self)
+{
+ switch (self->rdp_layer->client_info.crypt_level)
+ {
+ case 0: /* none */
+ self->crypt_method = CRYPT_METHOD_NONE;
+ self->crypt_level = CRYPT_LEVEL_NONE;
+ break;
+ case 1: /* low */
+ self->crypt_method = CRYPT_METHOD_40BIT;
+ self->crypt_level = CRYPT_LEVEL_LOW;
+ break;
+ case 2: /* medium */
+ self->crypt_method = CRYPT_METHOD_40BIT;
+ self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE;
+ break;
+ case 3: /* high */
+ self->crypt_method = CRYPT_METHOD_128BIT;
+ self->crypt_level = CRYPT_LEVEL_HIGH;
+ break;
+ case 4: /* fips */
+ self->crypt_method = CRYPT_METHOD_FIPS;
+ self->crypt_level = CRYPT_LEVEL_FIPS;
+ break;
+ default:
+ g_writeln("Fatal : Illegal crypt_level");
+ break ;
+ }
+
+ if (self->decrypt_rc4_info != NULL)
+ {
+ g_writeln("xrdp_sec_init_rdp_security: decrypt_rc4_info already created !!!");
+ }
+ else
+ {
+ self->decrypt_rc4_info = ssl_rc4_info_create();
+ }
+
+ if (self->encrypt_rc4_info != NULL)
+ {
+ g_writeln("xrdp_sec_init_rdp_security: encrypt_rc4_info already created !!!");
+ }
+ else
+ {
+ self->encrypt_rc4_info = ssl_rc4_info_create();
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
int APP_CC
xrdp_sec_incoming(struct xrdp_sec *self)
{
struct list *items = NULL;
struct list *values = NULL;
+ struct xrdp_iso *iso;
int index = 0;
char *item = NULL;
char *value = NULL;
char key_file[256];
- LLOGLN(10, ("xrdp_sec_incoming:"));
- g_memset(key_file, 0, sizeof(char) * 256);
- DEBUG((" in xrdp_sec_incoming"));
- g_random(self->server_random, 32);
- items = list_create();
- items->auto_free = 1;
- values = list_create();
- values->auto_free = 1;
- g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH);
-
- if (file_by_name_read_section(key_file, "keys", items, values) != 0)
- {
- /* this is a show stopper */
- log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s "
- "(check permissions)", key_file);
- list_delete(items);
- list_delete(values);
+ DEBUG((" in xrdp_sec_incoming:"));
+ iso = self->mcs_layer->iso_layer;
+
+ /* negotiate security layer */
+ if (xrdp_iso_incoming(iso) != 0)
+ {
+ DEBUG(("xrdp_sec_incoming: xrdp_iso_incoming failed"));
return 1;
}
- for (index = 0; index < items->count; index++)
+ /* initialize selected security layer */
+ if (iso->requestedProtocol > PROTOCOL_RDP)
{
- item = (char *)list_get_item(items, index);
- value = (char *)list_get_item(values, index);
+ /* init tls security */
+ DEBUG((" in xrdp_sec_incoming: init tls security"));
- if (g_strcasecmp(item, "pub_exp") == 0)
+ if (trans_set_tls_mode(self->mcs_layer->iso_layer->trans,
+ self->rdp_layer->client_info.key_file,
+ self->rdp_layer->client_info.certificate) != 0)
{
- hex_str_to_bin(value, self->pub_exp, 4);
- }
- else if (g_strcasecmp(item, "pub_mod") == 0)
- {
- hex_str_to_bin(value, self->pub_mod, 64);
+ g_writeln("xrdp_sec_incoming: trans_set_tls_mode failed");
+ return 1;
}
- else if (g_strcasecmp(item, "pub_sig") == 0)
+
+ self->crypt_level = CRYPT_LEVEL_NONE;
+ self->crypt_method = CRYPT_METHOD_NONE;
+ self->rsa_key_bytes = 0;
+
+ }
+ else
+ {
+ /* init rdp security */
+ DEBUG((" in xrdp_sec_incoming: init rdp security"));
+ if (xrdp_sec_init_rdp_security(self) != 0)
{
- hex_str_to_bin(value, self->pub_sig, 64);
+ DEBUG(("xrdp_sec_incoming: xrdp_sec_init_rdp_security failed"));
+ return 1;
}
- else if (g_strcasecmp(item, "pri_exp") == 0)
+ if (self->crypt_method != CRYPT_METHOD_NONE)
{
- hex_str_to_bin(value, self->pri_exp, 64);
+ g_memset(key_file, 0, sizeof(char) * 256);
+ g_random(self->server_random, 32);
+ items = list_create();
+ items->auto_free = 1;
+ values = list_create();
+ values->auto_free = 1;
+ g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH);
+
+ if (file_by_name_read_section(key_file, "keys", items, values) != 0)
+ {
+ /* this is a show stopper */
+ log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s "
+ "(check permissions)", key_file);
+ list_delete(items);
+ list_delete(values);
+ return 1;
+ }
+
+ for (index = 0; index < items->count; index++)
+ {
+ item = (char *)list_get_item(items, index);
+ value = (char *)list_get_item(values, index);
+
+ if (g_strcasecmp(item, "pub_exp") == 0)
+ {
+ hex_str_to_bin(value, self->pub_exp, 4);
+ }
+ else if (g_strcasecmp(item, "pub_mod") == 0)
+ {
+ self->rsa_key_bytes = (g_strlen(value) + 1) / 5;
+ g_writeln("pub_mod bytes %d", self->rsa_key_bytes);
+ hex_str_to_bin(value, self->pub_mod, self->rsa_key_bytes);
+ }
+ else if (g_strcasecmp(item, "pub_sig") == 0)
+ {
+ hex_str_to_bin(value, self->pub_sig, 64);
+ }
+ else if (g_strcasecmp(item, "pri_exp") == 0)
+ {
+ self->rsa_key_bytes = (g_strlen(value) + 1) / 5;
+ g_writeln("pri_exp %d", self->rsa_key_bytes);
+ hex_str_to_bin(value, self->pri_exp, self->rsa_key_bytes);
+ }
+ }
+ list_delete(items);
+ list_delete(values);
}
}
- list_delete(items);
- list_delete(values);
-
+ /* negotiate mcs layer */
if (xrdp_mcs_incoming(self->mcs_layer) != 0)
{
return 1;
@@ -1861,6 +2248,7 @@ xrdp_sec_incoming(struct xrdp_sec *self)
{
return 1;
}
+
LLOGLN(10, ("xrdp_sec_incoming: out"));
return 0;
}