From 7ab1d887aecf7883b1254cd97ecfee02de45b74a Mon Sep 17 00:00:00 2001 From: Idan Freiberg Date: Thu, 17 Jul 2014 14:29:23 +0300 Subject: [PATCH] libxrdp: work on TLS support --- libxrdp/libxrdp.c | 23 +++++- libxrdp/libxrdp.h | 4 +- libxrdp/xrdp_iso.c | 9 ++- libxrdp/xrdp_mcs.c | 10 ++- libxrdp/xrdp_sec.c | 15 +++- libxrdp/xrdp_tls.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 230 insertions(+), 10 deletions(-) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 6a79e8fb..44e9d775 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -143,7 +143,12 @@ libxrdp_force_read(struct trans* trans) init_stream(s, 32 * 1024); if (trans->do_tls) { - /*TLS*/ + g_writeln("libxrdp_force_read: tls data in"); + if (xrdp_tls_force_read_s(trans, s, 4) != 0) + { + return 0; + } + g_hexdump(s->data, 4); } else if (trans_force_read(trans, 4) != 0) /*TCP*/ { @@ -161,11 +166,25 @@ libxrdp_force_read(struct trans* trans) g_writeln("libxrdp_force_read: error"); return 0; } - if (trans_force_read(trans, bytes - 4) != 0) + + if (trans->do_tls) + { + g_writeln("libxrdp_force_read: tls data in"); + xrdp_tls_force_read_s(trans, s, bytes - 4); + g_hexdump(s->data, bytes); + } + else if (trans_force_read(trans, bytes - 4) != 0) /*TCP*/ { g_writeln("libxrdp_force_read: error"); return 0; } + + +// if (trans_force_read(trans, bytes - 4) != 0) +// { +// g_writeln("libxrdp_force_read: error"); +// return 0; +// } return s; } diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index c2800abf..4ce39eb3 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -312,9 +312,9 @@ xrdp_tls_disconnect(struct xrdp_tls *self); void APP_CC xrdp_tls_delete(struct xrdp_tls *self); int APP_CC -xrdp_tls_read(struct xrdp_tls *tls, unsigned char *data, int length); +xrdp_tls_force_read_s(struct trans *self, struct stream *in_s, int size); int APP_CC -xrdp_tls_write(struct xrdp_tls *tls, unsigned char *data, int length); +xrdp_tls_force_write_s(struct trans *self, struct stream *out_s); int APP_CC compress_rdp(struct xrdp_mppc_enc *enc, tui8 *srcData, int len); diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index b15be2ad..33570e19 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -416,7 +416,14 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s) out_uint8(s, ISO_PDU_DT); out_uint8(s, 0x80); - if (trans_force_write_s(self->trans, s) != 0) + if (self->trans->do_tls) + { + if (xrdp_tls_force_write_s(self->trans, s) != 0) + { + return 1; + } + } + else if (trans_force_write_s(self->trans, s) != 0) { return 1; } diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index df4f81f5..13d190d2 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -630,6 +630,7 @@ static int APP_CC xrdp_mcs_ber_out_header(struct xrdp_mcs *self, struct stream *s, int tag_val, int len) { + g_writeln("tag_val > 0xff ? %d", tag_val > 0xff); if (tag_val > 0xff) { out_uint16_be(s, tag_val); @@ -639,6 +640,7 @@ xrdp_mcs_ber_out_header(struct xrdp_mcs *self, struct stream *s, out_uint8(s, tag_val); } + g_writeln("len >= 0x80 ? %d", len >= 0x80); if (len >= 0x80) { out_uint8(s, 0x82); @@ -720,7 +722,8 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) init_stream(s, 8192); 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: 36 - tls , 38 - rdp - we should calculate that + xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, 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); @@ -750,17 +753,19 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) { DEBUG((" in xrdp_mcs_incoming")); + /* ISO */ if (xrdp_iso_incoming(self->iso_layer) != 0) { return 1; } - /* tls */ + /* TLS */ if (PROTOCOL_SSL & self->iso_layer->selectedProtocol) { g_writeln("xrdp_mcs_incoming: TLS mode!"); self->sec_layer->crypt_level = CRYPT_LEVEL_NONE; self->sec_layer->crypt_method = CRYPT_METHOD_NONE; + self->sec_layer->rsa_key_bytes = 0; if (xrdp_tls_accept(self->sec_layer->tls) != 0) { @@ -770,6 +775,7 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) g_writeln("xrdp_mcs_incoming: ssl_tls_accept done!!!!"); } + /* MCS */ if (xrdp_mcs_recv_connect_initial(self) != 0) { return 1; diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index c908c081..ef1b94f9 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -277,7 +277,8 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level, self->fastpath_layer = xrdp_fastpath_create(self, trans); self->chan_layer = xrdp_channel_create(self, self->mcs_layer); //TODO: add cert to config - self->tls = xrdp_tls_create(trans, "/opt/xrdpdev/etc/xrdp/pkey.pem", "/opt/xrdpdev/etc/xrdp/cert.pem"); + self->tls = xrdp_tls_create(trans, "/opt/xrdpdev/etc/xrdp/pkey.pem", + "/opt/xrdpdev/etc/xrdp/cert.pem"); DEBUG((" out xrdp_sec_create")); return self; } @@ -1857,7 +1858,7 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) ud_ptr = s->p; /* User Data */ out_uint16_le(s, SEC_TAG_SRV_INFO); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) + if (self->mcs_layer->iso_layer->rdpNegData) { out_uint16_le(s, 12); /* len */ } @@ -1869,7 +1870,7 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) out_uint8(s, 0); out_uint8(s, 8); out_uint8(s, 0); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) + if (self->mcs_layer->iso_layer->rdpNegData) { /* ReqeustedProtocol */ out_uint32_le(s, self->mcs_layer->iso_layer->selectedProtocol); @@ -1952,6 +1953,14 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) 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 { LLOGLN(0, ("xrdp_sec_out_mcs_data: error")); diff --git a/libxrdp/xrdp_tls.c b/libxrdp/xrdp_tls.c index d893ca3c..1f6e847e 100644 --- a/libxrdp/xrdp_tls.c +++ b/libxrdp/xrdp_tls.c @@ -237,3 +237,182 @@ xrdp_tls_write(struct xrdp_tls *tls, unsigned char *data, int length) return status; } /*****************************************************************************/ +int APP_CC +xrdp_tls_force_read_s(struct trans *self, struct stream *in_s, int size) +{ + int rcvd; + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + while (size > 0) + { + /* make sure stream has room */ + if ((in_s->end + size) > (in_s->data + in_s->size)) + { + return 1; + } + + g_writeln("xrdp_tls_force_read_s: Pending= %d", SSL_pending(self->tls->ssl)); + rcvd = xrdp_tls_read(self->tls, in_s->end, size); + + if (rcvd == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + if (!g_tcp_can_recv(self->sck, 100)) + { + /* check for term here */ + if (self->is_term != 0) + { + if (self->is_term()) + { + /* term */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + } + } + } + else + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + } + else if (rcvd == 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + else + { + in_s->end += rcvd; + size -= rcvd; + } + } + + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_tls_force_write_s(struct trans *self, struct stream *out_s) +{ + int size; + int total; + int sent; + + if (self->status != TRANS_STATUS_UP) + { + return 1; + } + + size = (int)(out_s->end - out_s->data); + g_writeln("packet size= %d", size); + total = 0; + + if (send_waiting(self, 1) != 0) + { + self->status = TRANS_STATUS_DOWN; + return 1; + } + + while (total < size) + { + sent = xrdp_tls_write(self->tls, out_s->data + total, size - total); + + if (sent == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + if (!g_tcp_can_send(self->sck, 100)) + { + /* check for term here */ + if (self->is_term != 0) + { + if (self->is_term()) + { + /* term */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + } + } + } + else + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + } + else if (sent == 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + else + { + total = total + sent; + } + } + + return 0; +} +/*****************************************************************************/ +int APP_CC +send_waiting(struct trans *self, int block) +{ + struct stream *temp_s; + int bytes; + int sent; + int timeout; + int cont; + + timeout = block ? 100 : 0; + cont = 1; + while (cont) + { + if (self->wait_s != 0) + { + temp_s = self->wait_s; + if (g_tcp_can_send(self->sck, timeout)) + { + bytes = (int) (temp_s->end - temp_s->p); + sent = xrdp_tls_write(self->tls, temp_s->p, bytes); + if (sent > 0) + { + temp_s->p += sent; + if (temp_s->p >= temp_s->end) + { + self->wait_s = (struct stream *) (temp_s->next_packet); + free_stream(temp_s); + } + } + else if (sent == 0) + { + return 1; + } + else + { + if (!g_tcp_last_error_would_block(self->sck)) + { + return 1; + } + } + } + } + else + { + break; + } + cont = block; + } + return 0; +}