diff options
Diffstat (limited to 'libxrdp/xrdp_sec.c')
-rw-r--r-- | libxrdp/xrdp_sec.c | 67 |
1 files changed, 59 insertions, 8 deletions
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); |