summaryrefslogtreecommitdiffstats
path: root/libxrdp
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp')
-rw-r--r--libxrdp/libxrdp.h9
-rw-r--r--libxrdp/libxrdpinc.h1
-rw-r--r--libxrdp/xrdp_rdp.c22
-rw-r--r--libxrdp/xrdp_sec.c67
4 files changed, 84 insertions, 15 deletions
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index b5afde0a..dd87096e 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -75,8 +75,9 @@ struct xrdp_sec
char encrypt_key[16];
char decrypt_update_key[16];
char encrypt_update_key[16];
- int rc4_key_size;
- int rc4_key_len;
+ int rc4_key_size; /* 1 = 40 bit, 2 = 128 bit */
+ int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */
+ int crypt_level; /* 1, 2, 3 = low, meduim, high */
char sign_key[16];
void* decrypt_rc4_info;
void* encrypt_rc4_info;
@@ -230,7 +231,7 @@ xrdp_mcs_disconnect(struct xrdp_mcs* self);
/* xrdp_sec.c */
struct xrdp_sec* APP_CC
-xrdp_sec_create(struct xrdp_rdp* owner, int sck);
+xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level);
void APP_CC
xrdp_sec_delete(struct xrdp_sec* self);
int APP_CC
@@ -238,7 +239,7 @@ 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, int flags);
+xrdp_sec_send(struct xrdp_sec* self, struct stream* s);
int APP_CC
xrdp_sec_incoming(struct xrdp_sec* self);
int APP_CC
diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h
index cc8f77be..74ebfda3 100644
--- a/libxrdp/libxrdpinc.h
+++ b/libxrdp/libxrdpinc.h
@@ -56,6 +56,7 @@ struct xrdp_client_info
char directory[256];
int rdp_compression;
int rdp_autologin;
+ int crypt_level; /* 1, 2, 3 = low, medium, high */
};
struct xrdp_brush
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index 39aa8896..3aebcb28 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -87,6 +87,21 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info)
client_info->use_bitmap_comp = 1;
}
}
+ else if (g_strncasecmp(item, "crypt_level", 255) == 0)
+ {
+ if (g_strncasecmp(value, "low", 255) == 0)
+ {
+ client_info->crypt_level = 1;
+ }
+ else if (g_strncasecmp(value, "medium", 255) == 0)
+ {
+ client_info->crypt_level = 2;
+ }
+ else if (g_strncasecmp(value, "high", 255) == 0)
+ {
+ client_info->crypt_level = 3;
+ }
+ }
}
list_delete(items);
list_delete(values);
@@ -104,9 +119,10 @@ xrdp_rdp_create(struct xrdp_session* session, int sck)
self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1);
self->session = session;
self->share_id = 66538;
- self->sec_layer = xrdp_sec_create(self, 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);
/* default 8 bit v1 color bitmap cache entries and size */
self->client_info.cache1_entries = 600;
self->client_info.cache1_size = 256;
@@ -221,7 +237,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) != 0)
+ if (xrdp_sec_send(self->sec_layer, s) != 0)
{
DEBUG(("out xrdp_rdp_send error\r\n"));
return 1;
@@ -250,7 +266,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) != 0)
+ if (xrdp_sec_send(self->sec_layer, s) != 0)
{
DEBUG(("out xrdp_rdp_send_data error\r\n"));
return 1;
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 47f67815..3656af6d 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -169,7 +169,7 @@ 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)
+xrdp_sec_create(struct xrdp_rdp* owner, int sck, int crypt_level)
{
struct xrdp_sec* self;
struct list* items;
@@ -181,7 +181,23 @@ xrdp_sec_create(struct xrdp_rdp* owner, int sck)
self = (struct xrdp_sec*)g_malloc(sizeof(struct xrdp_sec), 1);
self->rdp_layer = owner;
- self->rc4_key_size = 1;
+ self->rc4_key_size = 1; /* 1 = 40 bit, 2 = 128 bit */
+ self->crypt_level = 1; /* 1, 2, 3 = low, medium, high */
+ switch (crypt_level)
+ {
+ case 1:
+ self->rc4_key_size = 1;
+ self->crypt_level = 1;
+ break;
+ case 2:
+ self->rc4_key_size = 1;
+ self->crypt_level = 2;
+ break;
+ case 3:
+ self->rc4_key_size = 2;
+ self->crypt_level = 3;
+ break;
+ }
self->decrypt_rc4_info = ssl_rc4_info_create();
self->encrypt_rc4_info = ssl_rc4_info_create();
g_random(self->server_random, 32);
@@ -248,7 +264,14 @@ xrdp_sec_init(struct xrdp_sec* self, struct stream* s)
{
return 1;
}
- s_push_layer(s, sec_hdr, 4);
+ if (self->crypt_level > 1)
+ {
+ s_push_layer(s, sec_hdr, 4 + 8);
+ }
+ else
+ {
+ s_push_layer(s, sec_hdr, 4);
+ }
return 0;
}
@@ -315,6 +338,22 @@ xrdp_sec_decrypt(struct xrdp_sec* self, char* data, int len)
}
/*****************************************************************************/
+static void APP_CC
+xrdp_sec_encrypt(struct xrdp_sec* self, char* data, int len)
+{
+ if (self->encrypt_use_count == 4096)
+ {
+ xrdp_sec_update(self->encrypt_key, self->encrypt_update_key,
+ self->rc4_key_len);
+ ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key,
+ self->rc4_key_len);
+ self->encrypt_use_count = 0;
+ }
+ ssl_rc4_crypt(self->encrypt_rc4_info, data, len);
+ self->encrypt_use_count++;
+}
+
+/*****************************************************************************/
static int APP_CC
unicode_in(struct stream* s, int uni_len, char* dst, int dst_len)
{
@@ -642,13 +681,24 @@ xrdp_sec_sign(struct xrdp_sec* self, char* out, int out_len,
/*****************************************************************************/
/* returns error */
-/* TODO needs outgoing encryption */
int APP_CC
-xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int flags)
+xrdp_sec_send(struct xrdp_sec* self, struct stream* s)
{
+ int datalen;
+
DEBUG((" in xrdp_sec_send\r\n"));
s_pop_layer(s, sec_hdr);
- out_uint32_le(s, flags);
+ if (self->crypt_level > 1)
+ {
+ out_uint32_le(s, SEC_ENCRYPT);
+ datalen = (s->end - s->p) - 8;
+ xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen);
+ xrdp_sec_encrypt(self, s->p + 8, datalen);
+ }
+ else
+ {
+ out_uint32_le(s, 0);
+ }
if (xrdp_mcs_send(self->mcs_layer, s) != 0)
{
return 1;
@@ -698,8 +748,9 @@ xrdp_sec_out_mcs_data(struct xrdp_sec* self)
out_uint8(p, 0);
out_uint16_le(p, SEC_TAG_SRV_CRYPT);
out_uint16_le(p, 0x00ec); /* len is 236 */
- out_uint32_le(p, 1); /* key len 1 = 40 bit 2 = 128 bit */
- out_uint32_le(p, 1); /* crypt level 1 = low 2 = medium 3 = high */
+ 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 */
+ /* 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);