diff options
Diffstat (limited to 'libxrdp/xrdp_mcs.c')
-rw-r--r-- | libxrdp/xrdp_mcs.c | 288 |
1 files changed, 208 insertions, 80 deletions
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 9dcb5b51..716ad13f 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -122,14 +122,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) int len; int userid; int chanid; - DEBUG((" in xrdp_mcs_recv")); while (1) { if (xrdp_iso_recv(self->iso_layer, s) != 0) { - DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero")); + DEBUG((" out xrdp_mcs_recv, xrdp_iso_recv return non zero")); + g_writeln("xrdp_mcs_recv: xrdp_iso_recv failed"); return 1; } @@ -151,12 +151,7 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { - if (s == self->iso_layer->trans->in_s) - { - /* this should not happen */ - g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time"); - return 1; - } + if (!s_check_rem(s, 4)) { return 1; @@ -171,6 +166,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ; } + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + g_writeln("xrdp_mcs_recv: libxrdp_force_read failed"); + return 1; + } + continue; } @@ -322,30 +325,29 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) int len; struct stream *s; - make_stream(s); - init_stream(s, 16 * 1024); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -353,13 +355,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -367,13 +367,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -381,38 +379,32 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } /* mcs data can not be zero length */ if ((len <= 0) || (len > 16 * 1024)) { - free_stream(s); return 1; } if (!s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -424,12 +416,10 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (s_check_end(s)) { - free_stream(s); return 0; } else { - free_stream(s); return 1; } } @@ -443,18 +433,20 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_edrq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } - + if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -462,13 +454,11 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_EDRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -479,7 +469,6 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -487,11 +476,9 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_edrq")); return 0; } @@ -505,18 +492,20 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_aurq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -524,7 +513,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_AURQ) { - free_stream(s); return 1; } @@ -532,7 +520,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -540,11 +527,9 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_aurq")); return 0; } @@ -592,18 +577,19 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) int opcode; struct stream *s; - make_stream(s); - init_stream(s, 8192); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -611,13 +597,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_CJRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -627,7 +611,6 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint8s(s, 2); @@ -635,11 +618,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); return 0; } @@ -725,7 +706,163 @@ xrdp_mcs_out_domain_params(struct xrdp_mcs *self, struct stream *s, xrdp_mcs_ber_out_int8(self, s, 2); return 0; } +/*****************************************************************************/ +/* prepare server gcc data to send in mcs response msg */ +int APP_CC +xrdp_mcs_out_gcc_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); /* AsnBerObjectIdentifier */ + out_uint16_be(s, 0x14); + out_uint8(s, 0x7c); + out_uint16_be(s, 1); /* -- */ + out_uint8(s, 0x2a); /* ConnectPDULen */ + 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->rdpNegData) + { + 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->rdpNegData) + { + /* ReqeustedProtocol */ + out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol); + } + 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 if (self->rsa_key_bytes == 0) /* no security */ + { + g_writeln("xrdp_sec_out_mcs_data: using no security"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 12); /* len is 12 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + } + else + { + g_writeln("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; +} /*****************************************************************************/ /* returns error */ static int APP_CC @@ -737,9 +874,11 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) DEBUG((" in xrdp_mcs_send_connect_response")); make_stream(s); init_stream(s, 8192); - data_len = self->server_mcs_data->end - self->server_mcs_data->data; + data_len = (int) (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, data_len + 38); + //TODO: we should calculate the whole length include MCS_CONNECT_RESPONSE + xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, + data_len > 0x80 ? data_len + 38 : data_len + 36); 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); @@ -767,13 +906,9 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) int APP_CC xrdp_mcs_incoming(struct xrdp_mcs *self) { + int i; DEBUG((" in xrdp_mcs_incoming")); - if (xrdp_iso_incoming(self->iso_layer) != 0) - { - return 1; - } - if (xrdp_mcs_recv_connect_initial(self) != 0) { return 1; @@ -785,8 +920,7 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - /* in xrdp_sec.c */ - if (xrdp_sec_out_mcs_data(self->sec_layer) != 0) + if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0) { return 1; } @@ -811,25 +945,18 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - if (xrdp_mcs_recv_cjrq(self) != 0) - { - return 1; - } - - if (xrdp_mcs_send_cjcf(self, self->userid, - self->userid + MCS_USERCHANNEL_BASE) != 0) - { - return 1; - } - - if (xrdp_mcs_recv_cjrq(self) != 0) + for (i = 0; i < self->channel_list->count + 2; i++) { - return 1; - } + if (xrdp_mcs_recv_cjrq(self) != 0) + { + return 1; + } - if (xrdp_mcs_send_cjcf(self, self->userid, MCS_GLOBAL_CHANNEL) != 0) - { - return 1; + if (xrdp_mcs_send_cjcf(self, self->userid, + self->userid + MCS_USERCHANNEL_BASE + i) != 0) + { + return 1; + } } DEBUG((" out xrdp_mcs_incoming")); @@ -895,7 +1022,7 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) if (len > 8192 * 2) { - g_writeln("error in xrdp_mcs_send, size too bog, its %d", len); + g_writeln("error in xrdp_mcs_send, size too big, its %d", len); } //if (len > max_len) @@ -958,6 +1085,7 @@ close_rdp_socket(struct xrdp_mcs *self) { if (self->iso_layer->trans != 0) { + trans_shutdown_tls_mode(self->iso_layer->trans); g_tcp_close(self->iso_layer->trans->sck); self->iso_layer->trans->sck = 0 ; g_writeln("xrdp_mcs_disconnect - socket closed"); |