diff options
Diffstat (limited to 'libxrdp/xrdp_sec.c')
-rw-r--r-- | libxrdp/xrdp_sec.c | 445 |
1 files changed, 182 insertions, 263 deletions
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 6ebdf715..7ac68b14 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -222,87 +222,46 @@ 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) +xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) { struct xrdp_sec *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; - 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 ; - } - - self->channel_code = channel_code; - self->multimon = multimon; - - if (self->decrypt_rc4_info != NULL) - { - g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!"); - } - - self->decrypt_rc4_info = ssl_rc4_info_create(); - - if (self->encrypt_rc4_info != NULL) - { - g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!"); - } - - 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->fastpath_layer = xrdp_fastpath_create(self, trans); - 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); - 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); +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); } /*****************************************************************************/ @@ -325,7 +284,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; @@ -1042,6 +1001,21 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { return 1; } + + /* TODO: HACK, we should recognize packets without security header + However, client info packet and license packet always have security header. */ + if (s->data[17] == 0x13) /* confirm active pdu */ + { + g_writeln("CONFIRM ACTIVE ARRIVED"); + return 0; + } + + if (s->data[17] == 0x17 || s->data[16] == 0x17) /* rdp data pdu */ + { + g_writeln("RDP DATA ARRIVED"); + return 0; + } + in_uint32_le(s, flags); DEBUG((" in xrdp_sec_recv flags $%x", flags)); @@ -1066,7 +1040,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)) { @@ -1253,7 +1227,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) @@ -1616,11 +1590,16 @@ 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; @@ -1672,9 +1651,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")); @@ -1816,156 +1795,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; - int gcc_size; - char* gcc_size_ptr; - char* ud_ptr; - - num_channels = self->mcs_layer->channel_list->count; - num_channels_even = num_channels + (num_channels & 1); - s = &(self->server_mcs_data); - init_stream(s, 8192); - 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 */ - /* GCC Response Total Length - 2 bytes , set later */ - gcc_size_ptr = s->p; /* RDPGCCUserDataResponseLength */ - out_uint8s(s, 2); - ud_ptr = s->p; /* User Data */ - - 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) - { - /* ReqeustedProtocol */ - 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); - } - } - - if (self->rsa_key_bytes == 64) - { - g_writeln("xrdp_sec_out_mcs_data: using 512 bit RSA key"); - 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); /* 0x0006 */ - out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ - out_uint32_le(s, 0x0048); /* 72 bytes modulus len */ - out_uint32_be(s, 0x00020000); /* bit len */ - out_uint32_be(s, 0x3f000000); /* data len */ - 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); /* 0x0008 */ - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ - } - else if (self->rsa_key_bytes == 256) - { - g_writeln("xrdp_sec_out_mcs_data: using 2048 bit RSA key"); - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 0x01ac); /* len is 428 */ - 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, 0x178); /* 376 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); /* 0x0006 */ - out_uint16_le(s, 0x011c); /* 284 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ - out_uint32_le(s, 0x0108); /* 264 bytes modulus len */ - out_uint32_be(s, 0x00080000); /* bit len */ - out_uint32_be(s, 0xff000000); /* data len */ - out_uint8a(s, self->pub_exp, 4); /* pub exp */ - out_uint8a(s, self->pub_mod, 256); /* pub mod */ - out_uint8s(s, 8); /* pad */ - out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ - } - else - { - LLOGLN(0, ("xrdp_sec_out_mcs_data: error")); - } - /* end certificate */ - s_mark_end(s); - - gcc_size = (int)(s->end - ud_ptr) | 0x8000; - gcc_size_ptr[0] = gcc_size >> 8; - gcc_size_ptr[1] = gcc_size; - - 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) @@ -2029,65 +1858,154 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) } /*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_rdp_security(struct xrdp_sec *self) +{ + switch (self->rdp_layer->client_info.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 ; + } + + 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]; - 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); + DEBUG((" in xrdp_sec_incoming:")); + iso = self->mcs_layer->iso_layer; - if (file_by_name_read_section(key_file, "keys", items, values) != 0) + /* negotiate security layer */ + if (xrdp_iso_incoming(iso) != 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(("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); + g_writeln("xrdp_sec_incoming: trans_set_tls_mode failed"); + return 1; } - else if (g_strcasecmp(item, "pub_mod") == 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) { - 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); + DEBUG(("xrdp_sec_incoming: xrdp_sec_init_rdp_security failed")); + return 1; } - else if (g_strcasecmp(item, "pub_sig") == 0) + + 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) { - hex_str_to_bin(value, self->pub_sig, 64); + /* 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; } - else if (g_strcasecmp(item, "pri_exp") == 0) + + for (index = 0; index < items->count; index++) { - 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); + 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; @@ -2106,6 +2024,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) { return 1; } + LLOGLN(10, ("xrdp_sec_incoming: out")); return 0; } |