diff options
author | Marc-André Moreau <marcandre.moreau@gmail.com> | 2011-06-29 04:35:30 +0400 |
---|---|---|
committer | Marc-André Moreau <marcandre.moreau@gmail.com> | 2011-06-29 04:35:30 +0400 |
commit | 2b95558d55cc08e240b8ef64f4e6b441711bbea8 (patch) | |
tree | 1874b9912658888c7eeea3b08e0e587ff0c5ef0c | |
parent | 7c3facc4d18745350b7151e2402c92131b802cd4 (diff) |
libfreerdp-core: started network abstraction layer, started decoupling secure.c from the rest
-rw-r--r-- | dbg.txt | 0 | ||||
-rw-r--r-- | libfreerdp-core/Makefile.am | 1 | ||||
-rw-r--r-- | libfreerdp-core/asn1.c | 2 | ||||
-rw-r--r-- | libfreerdp-core/chan.c | 10 | ||||
-rw-r--r-- | libfreerdp-core/chan.h | 1 | ||||
-rw-r--r-- | libfreerdp-core/credssp.c | 12 | ||||
-rw-r--r-- | libfreerdp-core/credssp.h | 8 | ||||
-rw-r--r-- | libfreerdp-core/freerdp.c | 10 | ||||
-rw-r--r-- | libfreerdp-core/iso.c | 44 | ||||
-rw-r--r-- | libfreerdp-core/iso.h | 7 | ||||
-rw-r--r-- | libfreerdp-core/license.c | 26 | ||||
-rw-r--r-- | libfreerdp-core/license.h | 5 | ||||
-rw-r--r-- | libfreerdp-core/mcs.c | 39 | ||||
-rw-r--r-- | libfreerdp-core/mcs.h | 5 | ||||
-rw-r--r-- | libfreerdp-core/network.c | 286 | ||||
-rw-r--r-- | libfreerdp-core/network.h | 69 | ||||
-rw-r--r-- | libfreerdp-core/rdp.c | 20 | ||||
-rw-r--r-- | libfreerdp-core/rdp.h | 5 | ||||
-rw-r--r-- | libfreerdp-core/secure.c | 183 | ||||
-rw-r--r-- | libfreerdp-core/secure.h | 11 | ||||
-rw-r--r-- | libfreerdp-core/tcp.c | 127 | ||||
-rw-r--r-- | libfreerdp-core/tcp.h | 9 |
22 files changed, 527 insertions, 353 deletions
diff --git a/libfreerdp-core/Makefile.am b/libfreerdp-core/Makefile.am index c443f53..b8ba907 100644 --- a/libfreerdp-core/Makefile.am +++ b/libfreerdp-core/Makefile.am @@ -23,6 +23,7 @@ libfreerdp_core_la_SOURCES = \ rail.c rail.h \ rdp.c rdp.h \ secure.c secure.h \ + network.c network.h \ crypto.h \ tcp.c tcp.h \ nego.c nego.h \ diff --git a/libfreerdp-core/asn1.c b/libfreerdp-core/asn1.c index 58a953c..e1896d6 100644 --- a/libfreerdp-core/asn1.c +++ b/libfreerdp-core/asn1.c @@ -42,7 +42,7 @@ ber_parse_header(rdpMcs * mcs, STREAM s, int tagval, int *length) if (tag != tagval) { - ui_error(mcs->sec->rdp->inst, "expected tag %d, got %d\n", tagval, tag); + ui_error(mcs->net->rdp->inst, "expected tag %d, got %d\n", tagval, tag); return False; } diff --git a/libfreerdp-core/chan.c b/libfreerdp-core/chan.c index a0bbec4..5e94bdd 100644 --- a/libfreerdp-core/chan.c +++ b/libfreerdp-core/chan.c @@ -38,11 +38,11 @@ vchan_send(rdpChannels * chan, int mcs_id, char * data, int total_length) rdpSet * settings; struct rdp_chan * channel; - settings = chan->mcs->sec->rdp->settings; + settings = chan->mcs->net->rdp->settings; chan_index = (mcs_id - MCS_GLOBAL_CHANNEL) - 1; if ((chan_index < 0) || (chan_index >= settings->num_channels)) { - ui_error(chan->mcs->sec->rdp->inst, "error\n"); + ui_error(chan->mcs->net->rdp->inst, "error\n"); return 0; } channel = &(settings->channels[chan_index]); @@ -61,12 +61,12 @@ vchan_send(rdpChannels * chan, int mcs_id, char * data, int total_length) { chan_flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } - s = sec_init(chan->mcs->sec, sec_flags, length + 8); + s = sec_init(chan->mcs->net->sec, sec_flags, length + 8); out_uint32_le(s, total_length); out_uint32_le(s, chan_flags); out_uint8p(s, data + sent, length); s_mark_end(s); - sec_send_to_channel(chan->mcs->sec, s, sec_flags, mcs_id); + sec_send_to_channel(chan->mcs->net->sec, s, sec_flags, mcs_id); sent += length; chan_flags = 0; } @@ -86,7 +86,7 @@ vchan_process(rdpChannels * chan, STREAM s, int mcs_id) length = (int) (s->end - s->p); data = (char *) (s->p); s->p += length; - ui_channel_data(chan->mcs->sec->rdp->inst, mcs_id, data, length, flags, total_length); + ui_channel_data(chan->mcs->net->sec->rdp->inst, mcs_id, data, length, flags, total_length); } rdpChannels * diff --git a/libfreerdp-core/chan.h b/libfreerdp-core/chan.h index 867b7b3..e2391e2 100644 --- a/libfreerdp-core/chan.h +++ b/libfreerdp-core/chan.h @@ -21,6 +21,7 @@ #define __CHAN_H #include "mcs.h" +#include "network.h" struct rdp_channels { diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index 86e60d5..0e627ec 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -58,7 +58,7 @@ asn1_write(const void *buffer, size_t size, void *fd) void credssp_ntlmssp_init(rdpCredssp *credssp) { NTLMSSP *ntlmssp = credssp->ntlmssp; - rdpSet *settings = credssp->sec->rdp->settings; + rdpSet *settings = credssp->net->rdp->settings; ntlmssp_set_password(ntlmssp, settings->password); ntlmssp_set_username(ntlmssp, settings->username); @@ -92,7 +92,7 @@ int credssp_get_public_key(rdpCredssp *credssp) CryptoCert cert; int ret; - cert = tls_get_certificate(credssp->sec->tls); + cert = tls_get_certificate(credssp->net->tls); if (cert == NULL) { printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n"); @@ -396,7 +396,7 @@ void credssp_send(rdpCredssp *credssp, DATABLOB *negoToken, DATABLOB *pubKeyAuth if (enc_rval.encoded != -1) { - tls_write(credssp->sec->tls, buffer, size); + tls_write(credssp->net->tls, buffer, size); } asn_DEF_TSRequest.free_struct(&asn_DEF_TSRequest, ts_request, 0); @@ -422,7 +422,7 @@ int credssp_recv(rdpCredssp *credssp, DATABLOB *negoToken, DATABLOB *pubKeyAuth, TSRequest_t *ts_request = 0; recv_buffer = xmalloc(size); - bytes_read = tls_read(credssp->sec->tls, recv_buffer, size); + bytes_read = tls_read(credssp->net->tls, recv_buffer, size); if (bytes_read < 0) return -1; @@ -503,7 +503,7 @@ void credssp_current_time(uint8* timestamp) */ rdpCredssp * -credssp_new(struct rdp_sec * sec) +credssp_new(struct rdp_network * net) { rdpCredssp * self; @@ -511,7 +511,7 @@ credssp_new(struct rdp_sec * sec) if (self != NULL) { memset(self, 0, sizeof(rdpCredssp)); - self->sec = sec; + self->net = net; self->send_seq_num = 0; self->ntlmssp = ntlmssp_new(); } diff --git a/libfreerdp-core/credssp.h b/libfreerdp-core/credssp.h index 2ed888e..8d8b6e4 100644 --- a/libfreerdp-core/credssp.h +++ b/libfreerdp-core/credssp.h @@ -20,7 +20,7 @@ #ifndef __CREDSSP_H #define __CREDSSP_H -#include "secure.h" +#include "network.h" #include "ntlmssp.h" struct rdp_credssp @@ -33,7 +33,7 @@ struct rdp_credssp DATABLOB ts_credentials; CryptoRc4 rc4_seal_state; struct _NTLMSSP *ntlmssp; - struct rdp_sec * sec; + struct rdp_network * net; }; typedef struct rdp_credssp rdpCredssp; @@ -50,7 +50,7 @@ void credssp_encode_ts_credentials(rdpCredssp *credssp); void credssp_current_time(uint8* timestamp); void credssp_rc4k(uint8* key, int length, uint8* plaintext, uint8* ciphertext); -rdpCredssp* credssp_new(rdpSec *sec); +rdpCredssp* credssp_new(struct rdp_network * net); void credssp_free(rdpCredssp *credssp); -#endif // __CREDSSP_H +#endif /* __CREDSSP_H */ diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c index 8f4ef3d..0ee77a6 100644 --- a/libfreerdp-core/freerdp.c +++ b/libfreerdp-core/freerdp.c @@ -450,9 +450,9 @@ l_rdp_get_fds(rdpInst * inst, void ** read_fds, int * read_count, rdp = RDP_FROM_INST(inst); #ifdef _WIN32 - read_fds[*read_count] = (void *) (rdp->sec->mcs->iso->tcp->wsa_event); + read_fds[*read_count] = (void *) (rdp->net->tcp->wsa_event); #else - read_fds[*read_count] = (void *)(long) (rdp->sec->mcs->iso->tcp->sock); + read_fds[*read_count] = (void *)(long) (rdp->net->tcp->sock); #endif (*read_count)++; return 0; @@ -468,10 +468,10 @@ l_rdp_check_fds(rdpInst * inst) rdp = RDP_FROM_INST(inst); #ifdef _WIN32 - WSAResetEvent(rdp->sec->mcs->iso->tcp->wsa_event); + WSAResetEvent(rdp->net->tcp->wsa_event); #endif rv = 0; - if (tcp_can_recv(rdp->sec->mcs->iso->tcp->sock, 0)) + if (tcp_can_recv(rdp->net->tcp->sock, 0)) { if (!rdp_loop(rdp, &deactivated)) { @@ -532,7 +532,7 @@ l_rdp_channel_data(rdpInst * inst, int chan_id, char * data, int data_size) rdpChannels * chan; rdp = RDP_FROM_INST(inst); - chan = rdp->sec->mcs->chan; + chan = rdp->net->mcs->chan; return vchan_send(chan, chan_id, data, data_size); } diff --git a/libfreerdp-core/iso.c b/libfreerdp-core/iso.c index 238b80c..9cd8f73 100644 --- a/libfreerdp-core/iso.c +++ b/libfreerdp-core/iso.c @@ -80,7 +80,7 @@ x224_send_dst_src_class(rdpIso * iso, uint8 code) out_uint8(s, 0); /* class */ s_mark_end(s); - tcp_send(iso->tcp, s); + network_send(iso->net, s); } /* Output and send X.224 Connection Request TPDU with routing for username */ @@ -93,9 +93,9 @@ x224_send_connection_request(rdpIso * iso) cookie_length = strlen(iso->cookie); - if (iso->mcs->sec->rdp->redirect_routingtoken) + if (iso->net->rdp->redirect_routingtoken) /* routingToken */ - length += iso->mcs->sec->rdp->redirect_routingtoken_len; + length += iso->net->rdp->redirect_routingtoken_len; else /* cookie */ length += 19 + cookie_length; @@ -115,10 +115,10 @@ x224_send_connection_request(rdpIso * iso) out_uint16_le(s, 0); /* src_ref */ out_uint8(s, 0); /* class */ - if (iso->mcs->sec->rdp->redirect_routingtoken) + if (iso->net->rdp->redirect_routingtoken) { /* routingToken */ - out_uint8p(s, iso->mcs->sec->rdp->redirect_routingtoken, iso->mcs->sec->rdp->redirect_routingtoken_len); + out_uint8p(s, iso->net->rdp->redirect_routingtoken, iso->net->rdp->redirect_routingtoken_len); } else { @@ -138,7 +138,7 @@ x224_send_connection_request(rdpIso * iso) } s_mark_end(s); - tcp_send(iso->tcp, s); + network_send(iso->net, s); } /* Receive an X.224 TPDU */ @@ -149,7 +149,7 @@ x224_recv(rdpIso * iso, STREAM s, int length, uint8 * pcode) uint8 code; uint8 subcode; - s = tcp_recv(iso->tcp, s, length - 4); + s = network_recv(iso->net, s, length - 4); if (s == NULL) return NULL; @@ -217,7 +217,7 @@ tpkt_recv(rdpIso * iso, uint8 * pcode, isoRecvType * ptype) STREAM s; int length; - s = tcp_recv(iso->tcp, NULL, 4); + s = network_recv(iso->net, NULL, 4); if (s == NULL) return NULL; @@ -250,7 +250,7 @@ tpkt_recv(rdpIso * iso, uint8 * pcode, isoRecvType * ptype) next_be(s, length); } - s = tcp_recv(iso->tcp, s, length - 4); + s = network_recv(iso->net, s, length - 4); return s; } return NULL; /* Fast-Path not allowed */ @@ -300,7 +300,7 @@ iso_send(rdpIso * iso, STREAM s) out_uint8(s, X224_TPDU_DATA); /* code */ out_uint8(s, 0x80); /* eot */ - tcp_send(iso->tcp, s); + network_send(iso->net, s); } /* Send an fast path data PDU */ @@ -335,7 +335,7 @@ iso_fp_send(rdpIso * iso, STREAM s, uint32 flags) out_uint8(s, len); } - tcp_send(iso->tcp, s); + network_send(iso->net, s); } /* Receive ISO transport data packet @@ -355,7 +355,7 @@ iso_recv(rdpIso * iso, isoRecvType * ptype) (*ptype == ISO_RECV_X224) && (code != X224_TPDU_DATA)) { - ui_error(iso->mcs->sec->rdp->inst, "expected X224_TPDU_DATA, got 0x%x\n", code); + ui_error(iso->net->rdp->inst, "expected X224_TPDU_DATA, got 0x%x\n", code); return NULL; } @@ -366,8 +366,14 @@ iso_recv(rdpIso * iso, isoRecvType * ptype) RD_BOOL iso_connect(rdpIso * iso, char *server, char *username, int port) { - if (strlen(iso->mcs->sec->rdp->settings->domain) > 0) - iso->cookie = iso->mcs->sec->rdp->settings->domain; + if (iso->net == NULL) + printf("iso->net\n"); + + if (iso->net->rdp == NULL) + printf("iso->net->rdp\n"); + + if (strlen(iso->net->rdp->settings->domain) > 0) + iso->cookie = iso->net->rdp->settings->domain; else iso->cookie = username; @@ -376,6 +382,7 @@ iso_connect(rdpIso * iso, char *server, char *username, int port) iso->nego->tcp_connected = 0; nego_init(iso->nego); + if (nego_connect(iso->nego) > 0) { return True; @@ -393,14 +400,14 @@ iso_disconnect(rdpIso * iso) { x224_send_dst_src_class(iso, X224_TPDU_DISCONNECT_REQUEST); #ifndef DISABLE_TLS - if (iso->mcs->sec->tls) - tls_disconnect(iso->mcs->sec->tls); + if (iso->net->tls) + tls_disconnect(iso->net->tls); #endif tcp_disconnect(iso->tcp); } rdpIso * -iso_new(struct rdp_mcs *mcs) +iso_new(struct rdp_network * net) { rdpIso *self; @@ -409,7 +416,8 @@ iso_new(struct rdp_mcs *mcs) if (self != NULL) { memset(self, 0, sizeof(rdpIso)); - self->mcs = mcs; + self->net = net; + self->mcs = net->mcs; self->tcp = tcp_new(self); self->nego = nego_new(self); } diff --git a/libfreerdp-core/iso.h b/libfreerdp-core/iso.h index 148b687..ac52c8a 100644 --- a/libfreerdp-core/iso.h +++ b/libfreerdp-core/iso.h @@ -18,6 +18,8 @@ */ #include <freerdp/types/ui.h> + +#include "network.h" #include "stream.h" #include "nego.h" @@ -28,8 +30,9 @@ struct rdp_iso { char* cookie; struct _NEGO * nego; - struct rdp_mcs * mcs; struct rdp_tcp * tcp; + struct rdp_mcs * mcs; + struct rdp_network * net; }; typedef struct rdp_iso rdpIso; @@ -60,7 +63,7 @@ iso_connect(rdpIso * iso, char * server, char * username, int port); void iso_disconnect(rdpIso * iso); rdpIso * -iso_new(struct rdp_mcs * mcs); +iso_new(struct rdp_network * net); void iso_free(rdpIso * iso); diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 2863757..20ce159 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -49,7 +49,7 @@ static void license_generate_hwid(rdpLicense * license, uint8 * hwid) { buf_out_uint32(hwid, 2); - strncpy((char *) (hwid + 4), license->sec->rdp->settings->hostname, LICENSE_HWID_SIZE - 4); + strncpy((char *) (hwid + 4), license->net->rdp->settings->hostname, LICENSE_HWID_SIZE - 4); } /* Send a Licensing packet with Client License Information */ @@ -63,7 +63,7 @@ license_present(rdpLicense * license, uint8 * client_random, uint8 * rsa_data, license_size + LICENSE_HWID_SIZE + LICENSE_SIGNATURE_SIZE; STREAM s; - s = sec_init(license->sec, sec_flags, length + 4); + s = sec_init(license->net->sec, sec_flags, length + 4); /* Licensing Preamble (LICENSE_PREAMBLE) */ out_uint8(s, LICENSE_INFO); /* bMsgType LICENSE_INFO */ @@ -96,7 +96,7 @@ license_present(rdpLicense * license, uint8 * client_random, uint8 * rsa_data, out_uint8p(s, signature, LICENSE_SIGNATURE_SIZE); /* MACData */ s_mark_end(s); - sec_send(license->sec, s, sec_flags); + sec_send(license->net->sec, s, sec_flags); } /* Send a Licensing packet with Client New License Request */ @@ -109,7 +109,7 @@ license_send_request(rdpLicense * license, uint8 * client_random, uint8 * rsa_da uint16 length = 128 + userlen + hostlen; STREAM s; - s = sec_init(license->sec, sec_flags, length + 2); + s = sec_init(license->net->sec, sec_flags, length + 2); /* Licensing Preamble (LICENSE_PREAMBLE) */ out_uint8(s, NEW_LICENSE_REQUEST); /* NEW_LICENSE_REQUEST */ @@ -139,7 +139,7 @@ license_send_request(rdpLicense * license, uint8 * client_random, uint8 * rsa_da out_uint8p(s, host, hostlen); s_mark_end(s); - sec_send(license->sec, s, sec_flags); + sec_send(license->net->sec, s, sec_flags); } /* Process a Server License Request packet */ @@ -208,8 +208,8 @@ license_process_request(rdpLicense * license, STREAM s) } license_send_request(license, null_data, null_data, - license->sec->rdp->settings->username, - license->sec->rdp->settings->hostname); + license->net->rdp->settings->username, + license->net->rdp->settings->hostname); } /* Send a Licensing packet with Platform Challenge Response */ @@ -220,7 +220,7 @@ license_send_authresp(rdpLicense * license, uint8 * token, uint8 * crypt_hwid, u uint16 length = 58; STREAM s; - s = sec_init(license->sec, sec_flags, length + 2); + s = sec_init(license->net->sec, sec_flags, length + 2); /* Licensing Preamble (LICENSE_PREAMBLE) */ out_uint8(s, PLATFORM_CHALLENGE_RESPONSE); /* PLATFORM_CHALLENGE_RESPONSE */ @@ -240,7 +240,7 @@ license_send_authresp(rdpLicense * license, uint8 * token, uint8 * crypt_hwid, u out_uint8p(s, signature, LICENSE_SIGNATURE_SIZE); /* MACData */ s_mark_end(s); - sec_send(license->sec, s, sec_flags); + sec_send(license->net->sec, s, sec_flags); } /* Parse a Server Platform Challenge packet */ @@ -256,7 +256,7 @@ license_parse_authreq(rdpLicense * license, STREAM s, uint8 ** token, uint8 ** s in_uint16_le(s, tokenlen); /* wBlobLen */ if (tokenlen != LICENSE_TOKEN_SIZE) { - ui_error(license->sec->rdp->inst, "token len %d\n", tokenlen); + ui_error(license->net->rdp->inst, "token len %d\n", tokenlen); return False; } in_uint8p(s, *token, tokenlen); /* RC4-encrypted challenge data */ @@ -396,14 +396,14 @@ license_process(rdpLicense * license, STREAM s) break; default: - ui_unimpl(license->sec->rdp->inst, "Unknown license tag 0x%x", tag); + ui_unimpl(license->net->rdp->inst, "Unknown license tag 0x%x", tag); } s->p = license_start + wMsgSize; /* FIXME: Shouldn't be necessary if parsed properly */ ASSERT(s->p <= s->end); } rdpLicense * -license_new(struct rdp_sec *sec) +license_new(struct rdp_network * net) { rdpLicense *self; @@ -411,7 +411,7 @@ license_new(struct rdp_sec *sec) if (self != NULL) { memset(self, 0, sizeof(rdpLicense)); - self->sec = sec; + self->net = net; } return self; } diff --git a/libfreerdp-core/license.h b/libfreerdp-core/license.h index 3b2e525..35df3f0 100644 --- a/libfreerdp-core/license.h +++ b/libfreerdp-core/license.h @@ -21,12 +21,13 @@ #define __LICENSE_H #include "stream.h" +#include "network.h" #include <freerdp/types/ui.h> #include <freerdp/utils/debug.h> struct rdp_license { - struct rdp_sec * sec; + struct rdp_network * net; uint8 license_key[16]; uint8 license_sign_key[16]; RD_BOOL license_issued; @@ -36,7 +37,7 @@ typedef struct rdp_license rdpLicense; void license_process(rdpLicense * license, STREAM s); rdpLicense * -license_new(struct rdp_sec * secure); +license_new(struct rdp_network * net); void license_free(rdpLicense * license); diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index f1a2715..fb49173 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -69,7 +69,7 @@ mcs_send_connect_initial(rdpMcs * mcs) gccCCrq.p = gccCCrq.data = (uint8 *) xmalloc(gccCCrq.size); gccCCrq.end = gccCCrq.data + gccCCrq.size; - sec_out_gcc_conference_create_request(mcs->sec, &gccCCrq); + sec_out_gcc_conference_create_request(mcs->net->sec, &gccCCrq); gccCCrq_length = gccCCrq.end - gccCCrq.data; length = 9 + 3 * 34 + 4 + gccCCrq_length; @@ -115,7 +115,7 @@ mcs_recv_connect_response(rdpMcs * mcs) in_uint8(s, result); if (result != 0) { - ui_error(mcs->sec->rdp->inst, "MCS connect: %d\n", result); + ui_error(mcs->net->rdp->inst, "MCS connect: %d\n", result); return False; } @@ -125,7 +125,7 @@ mcs_recv_connect_response(rdpMcs * mcs) ber_parse_header(mcs, s, BER_TAG_OCTET_STRING, &length); - sec_process_mcs_data(mcs->sec, s); + sec_process_mcs_data(mcs->net->sec, s); return s_check_end(s); } @@ -173,14 +173,14 @@ mcs_recv_aucf(rdpMcs * mcs, uint16 * mcs_userid) in_uint8(s, opcode); if ((opcode >> 2) != T125_DOMAINMCSPDU_AttachUserConfirm) { - ui_error(mcs->sec->rdp->inst, "expected AUcf, got %d\n", opcode); + ui_error(mcs->net->rdp->inst, "expected AUcf, got %d\n", opcode); return False; } in_uint8(s, result); if (result != 0) { - ui_error(mcs->sec->rdp->inst, "AUrq: %d\n", result); + ui_error(mcs->net->rdp->inst, "AUrq: %d\n", result); return False; } @@ -222,14 +222,14 @@ mcs_recv_cjcf(rdpMcs * mcs) in_uint8(s, opcode); if ((opcode >> 2) != T125_DOMAINMCSPDU_ChannelJoinConfirm) { - ui_error(mcs->sec->rdp->inst, "expected CJcf, got %d\n", opcode); + ui_error(mcs->net->rdp->inst, "expected CJcf, got %d\n", opcode); return False; } in_uint8(s, result); if (result != 0) { - ui_error(mcs->sec->rdp->inst, "CJrq: %d\n", result); + ui_error(mcs->net->rdp->inst, "CJrq: %d\n", result); return False; } @@ -321,7 +321,7 @@ mcs_recv(rdpMcs * mcs, isoRecvType * ptype, uint16 * channel) { if (pduType != T125_DOMAINMCSPDU_DisconnectProviderUltimatum) { - ui_error(mcs->sec->rdp->inst, "expected data, got %d\n", pduType); + ui_error(mcs->net->rdp->inst, "expected data, got %d\n", pduType); } return NULL; } @@ -356,7 +356,7 @@ mcs_connect(rdpMcs * mcs) mcs_send_connect_initial(mcs); if (!mcs_recv_connect_response(mcs)) { - ui_error(mcs->sec->rdp->inst, "invalid mcs_recv_connect_response\n"); + ui_error(mcs->net->rdp->inst, "invalid mcs_recv_connect_response\n"); goto error; } @@ -365,7 +365,7 @@ mcs_connect(rdpMcs * mcs) mcs_send_aurq(mcs); if (!mcs_recv_aucf(mcs, &(mcs->mcs_userid))) { - ui_error(mcs->sec->rdp->inst, "invalid mcs_recv_aucf\n"); + ui_error(mcs->net->rdp->inst, "invalid mcs_recv_aucf\n"); goto error; } @@ -373,29 +373,29 @@ mcs_connect(rdpMcs * mcs) if (!mcs_recv_cjcf(mcs)) { - ui_error(mcs->sec->rdp->inst, "invalid mcs_recv_cjcf\n"); + ui_error(mcs->net->rdp->inst, "invalid mcs_recv_cjcf\n"); goto error; } mcs_send_cjrq(mcs, MCS_GLOBAL_CHANNEL); if (!mcs_recv_cjcf(mcs)) { - ui_error(mcs->sec->rdp->inst, "invalid mcs_recv_cjcf\n"); + ui_error(mcs->net->rdp->inst, "invalid mcs_recv_cjcf\n"); goto error; } - settings = mcs->sec->rdp->settings; + settings = mcs->net->rdp->settings; for (i = 0; i < settings->num_channels; i++) { mcs_id = settings->channels[i].chan_id; if (mcs_id >= mcs->mcs_userid + MCS_USERCHANNEL_BASE) { - ui_warning(mcs->sec->rdp->inst, "channel %d got id %d >= %d\n", i, mcs_id, mcs->mcs_userid + MCS_USERCHANNEL_BASE); + ui_warning(mcs->net->rdp->inst, "channel %d got id %d >= %d\n", i, mcs_id, mcs->mcs_userid + MCS_USERCHANNEL_BASE); } mcs_send_cjrq(mcs, mcs_id); if (!mcs_recv_cjcf(mcs)) { - ui_error(mcs->sec->rdp->inst, "channel %d id %d invalid mcs_recv_cjcf\n", i, mcs_id); + ui_error(mcs->net->rdp->inst, "channel %d id %d invalid mcs_recv_cjcf\n", i, mcs_id); goto error; } } @@ -414,18 +414,21 @@ mcs_disconnect(rdpMcs * mcs) } rdpMcs * -mcs_new(struct rdp_sec * sec) +mcs_new(struct rdp_network * net) { rdpMcs * self; self = (rdpMcs *) xmalloc(sizeof(rdpMcs)); + if (self != NULL) { memset(self, 0, sizeof(rdpMcs)); - self->sec = sec; - self->iso = iso_new(self); + self->net = net; + self->iso = iso_new(net); self->chan = vchan_new(self); + self->net->iso = self->iso; } + return self; } diff --git a/libfreerdp-core/mcs.h b/libfreerdp-core/mcs.h index 79dc6f5..8313035 100644 --- a/libfreerdp-core/mcs.h +++ b/libfreerdp-core/mcs.h @@ -21,13 +21,14 @@ #define __MCS_H #include "iso.h" +#include "network.h" #include <freerdp/utils/debug.h> struct rdp_mcs { - struct rdp_sec * sec; uint16 mcs_userid; struct rdp_iso * iso; + struct rdp_network * net; struct rdp_channels * chan; }; typedef struct rdp_mcs rdpMcs; @@ -49,7 +50,7 @@ mcs_connect(rdpMcs * mcs); void mcs_disconnect(rdpMcs * mcs); rdpMcs * -mcs_new(struct rdp_sec * secure); +mcs_new(struct rdp_network * net); void mcs_free(rdpMcs * mcs); diff --git a/libfreerdp-core/network.c b/libfreerdp-core/network.c new file mode 100644 index 0000000..abb873c --- /dev/null +++ b/libfreerdp-core/network.c @@ -0,0 +1,286 @@ +/* + FreeRDP: A Remote Desktop Protocol client. + Network Transport Abstraction Layer + + Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include <freerdp/utils/memory.h> + +#include "network.h" + +#ifndef DISABLE_TLS + +/* verify SSL/TLS connection integrity. 2 checks are carried out. First make sure that the + * certificate is assigned to the server we're connected to, and second make sure that the + * certificate is signed by a trusted certification authority + */ + +RD_BOOL +network_verify_tls(rdpNetwork * net) +{ + char * issuer; + char * subject; + char * fingerprint; + CryptoCert cert; + RD_BOOL verified = False; + +#ifdef _WIN32 + /* + * TODO: FIX ME! This is really bad, I know... + * There appears to be a buffer overflow only + * on Windows that affects this part of the code. + * Skipping it is a workaround, but it's obviously + * not a permanent "solution". + */ + return True; +#endif + + cert = tls_get_certificate(net->tls); + + if (!cert) + { + goto exit; + } + + subject = crypto_cert_get_subject(cert); + issuer = crypto_cert_get_issuer(cert); + fingerprint = crypto_cert_get_fingerprint(cert); + + verified = tls_verify(net->tls, net->server); + + if (verified != False) + verified = crypto_cert_verify_peer_identity(cert, net->server); + + verified = ui_check_certificate(net->rdp->inst, fingerprint, subject, issuer, verified); + + xfree(fingerprint); + xfree(subject); + xfree(issuer); + +exit: + if (cert) + { + crypto_cert_free(cert); + cert = NULL; + } + + return verified; +} +#endif + +RD_BOOL +network_connect(rdpNetwork * net, char* server, char* username, int port) +{ + NEGO *nego = net->iso->nego; + + net->port = port; + net->server = server; + net->username = username; + net->license->license_issued = 0; + + if (net->rdp->settings->nla_security) + nego->enabled_protocols[PROTOCOL_NLA] = 1; + if (net->rdp->settings->tls_security) + nego->enabled_protocols[PROTOCOL_TLS] = 1; + if (net->rdp->settings->rdp_security) + nego->enabled_protocols[PROTOCOL_RDP] = 1; + + if (!iso_connect(net->iso, net->server, net->username, net->port)) + return False; + +#ifndef DISABLE_TLS + if(nego->selected_protocol & PROTOCOL_NLA) + { + /* TLS with NLA was successfully negotiated */ + + RD_BOOL status = 1; + printf("TLS encryption with NLA negotiated\n"); + net->tls = tls_new(); + + if (!tls_connect(net->tls, net->tcp->sock)) + return False; + + if (!network_verify_tls(net)) + return False; + + net->sec->tls_connected = 1; + net->rdp->settings->encryption = 0; + + if (!net->rdp->settings->autologin) + if (!ui_authenticate(net->rdp->inst)) + return False; + + net->credssp = credssp_new(net); + + if (credssp_authenticate(net->credssp) < 0) + { + printf("Authentication failure, check credentials.\n" + "If credentials are valid, the NTLMSSP implementation may be to blame.\n"); + credssp_free(net->credssp); + return 0; + } + + credssp_free(net->credssp); + + status = mcs_connect(net->mcs); + return status; + } + else if(nego->selected_protocol & PROTOCOL_TLS) + { + /* TLS without NLA was successfully negotiated */ + RD_BOOL success; + printf("TLS encryption negotiated\n"); + net->tls = tls_new(); + + if (!tls_connect(net->tls, net->tcp->sock)) + return False; + + if (!network_verify_tls(net)) + return False; + + net->sec->tls_connected = 1; + net->rdp->settings->encryption = 0; + + success = mcs_connect(net->mcs); + + return success; + } + else +#endif + { + RD_BOOL success; + + printf("Standard RDP encryption negotiated\n"); + + success = mcs_connect(net->mcs); + + if (success && net->rdp->settings->encryption) + sec_establish_key(net->sec); + + return success; + } + + return 0; +} + +void +network_send(rdpNetwork * net, STREAM s) +{ +#ifndef DISABLE_TLS + if (net->sec->tls_connected) + { + tls_write(net->tls, (char*) s->data, s->end - s->data); + } + else +#endif + { + tcp_write(net->tcp, s); + } +} + +STREAM +network_recv(rdpNetwork * net, STREAM s, uint32 length) +{ + int rcvd = 0; + uint32 p_offset; + uint32 new_length; + uint32 end_offset; + + if (s == NULL) + { + /* read into "new" stream */ + if (length > net->in.size) + { + net->in.data = (uint8 *) xrealloc(net->in.data, length); + net->in.size = length; + } + + net->in.end = net->in.p = net->in.data; + s = &(net->in); + } + else + { + /* append to existing stream */ + new_length = (s->end - s->data) + length; + if (new_length > s->size) + { + p_offset = s->p - s->data; + end_offset = s->end - s->data; + s->data = (uint8 *) xrealloc(s->data, new_length); + s->size = new_length; + s->p = s->data + p_offset; + s->end = s->data + end_offset; + } + } + + while (length > 0) + { +#ifndef DISABLE_TLS + if (net->sec->tls_connected) + { + rcvd = tls_read(net->tls, (char*) s->end, length); + + if (rcvd < 0) + return NULL; + } + else +#endif + { + rcvd = tcp_read(net->tcp, (char*) s->end, length); + } + + s->end += rcvd; + length -= rcvd; + } + + return s; +} + +rdpNetwork* +network_new(rdpRdp * rdp) +{ + rdpNetwork * self; + + self = (rdpNetwork *) xmalloc(sizeof(rdpNetwork)); + + if (self != NULL) + { + memset(self, 0, sizeof(rdpNetwork)); + self->rdp = rdp; + self->mcs = mcs_new(self); + self->iso = iso_new(self); + self->license = license_new(self); + + self->in.size = 4096; + self->in.data = (uint8 *) xmalloc(self->in.size); + + self->out.size = 4096; + self->out.data = (uint8 *) xmalloc(self->out.size); + } + + return self; +} + +void +network_free(rdpNetwork * net) +{ + if (net != NULL) + { + xfree(net->in.data); + xfree(net->out.data); + xfree(net); + } +} diff --git a/libfreerdp-core/network.h b/libfreerdp-core/network.h new file mode 100644 index 0000000..52fbf7c --- /dev/null +++ b/libfreerdp-core/network.h @@ -0,0 +1,69 @@ +/* + FreeRDP: A Remote Desktop Protocol client. + Network Transport Abstraction Layer + + Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef __NETWORK_H +#define __NETWORK_H + +#include <freerdp/freerdp.h> +#include <freerdp/types/ui.h> + +#include "tcp.h" +#include "tls.h" +#include "iso.h" +#include "mcs.h" +#include "rdp.h" +#include "secure.h" +#include "stream.h" +#include "credssp.h" +#include "license.h" + +struct rdp_network +{ + int port; + char* server; + char* username; + struct stream in; + struct stream out; + struct rdp_rdp * rdp; + struct rdp_tcp * tcp; + struct rdp_sec * sec; + struct rdp_tls * tls; + struct rdp_iso * iso; + struct rdp_mcs * mcs; + struct rdp_credssp * credssp; + struct rdp_license * license; +}; +typedef struct rdp_network rdpNetwork; + +RD_BOOL +network_connect(rdpNetwork * net, char* server, char* username, int port); + +void +network_send(rdpNetwork * net, STREAM s); + +STREAM +network_recv(rdpNetwork * net, STREAM s, uint32 length); + +rdpNetwork* +network_new(rdpRdp * rdp); + +void +network_free(rdpNetwork * net); + +#endif /* __NETWORK_H */ diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 47b9738..e8c9949 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -35,6 +35,7 @@ #include "bitmap.h" #include "ext.h" #include "surface.h" +#include "network.h" #include <freerdp/freerdp.h> #include <freerdp/utils/hexdump.h> @@ -186,7 +187,7 @@ rdp_send_data(rdpRdp * rdp, STREAM s, uint8 data_pdu_type) /* Share Control Header */ out_uint16_le(s, length); /* totalLength */ out_uint16_le(s, (RDP_PDU_DATA | 0x10)); /* pduType */ - out_uint16_le(s, (rdp->sec->mcs->mcs_userid + 1001)); /* PDUSource */ + out_uint16_le(s, (rdp->net->mcs->mcs_userid + 1001)); /* PDUSource */ /* Share Data Header */ out_uint32_le(s, rdp->rdp_shareid); /* shareId */ @@ -352,7 +353,7 @@ rdp_send_client_info(rdpRdp * rdp, uint32 flags, char *domain_name, userName = freerdp_uniconv_out(rdp->uniconv, username, &cbUserName); alternateShell = freerdp_uniconv_out(rdp->uniconv, shell, &cbAlternateShell); workingDir = freerdp_uniconv_out(rdp->uniconv, dir, &cbWorkingDir); - clientAddress = freerdp_uniconv_out(rdp->uniconv, tcp_get_address(rdp->sec->mcs->iso->tcp), &cbClientAddress); + clientAddress = freerdp_uniconv_out(rdp->uniconv, tcp_get_address(rdp->net->tcp), &cbClientAddress); clientDir = freerdp_uniconv_out(rdp->uniconv, dll, &cbClientDir); /* client working directory OR binary name */ length = 8 + (5 * 4) + cbDomain + cbUserName + cbPassword + cbAlternateShell + cbWorkingDir; @@ -775,7 +776,7 @@ rdp_send_confirm_active(rdpRdp * rdp) /* share control header */ out_uint16_le(s, length); out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */ - out_uint16_le(s, (rdp->sec->mcs->mcs_userid + 1001)); + out_uint16_le(s, (rdp->net->mcs->mcs_userid + 1001)); out_uint32_le(s, rdp->rdp_shareid); /* sharedId */ /* originatorId must be set to the server channel ID @@ -1672,7 +1673,7 @@ rdp_connect(rdpRdp * rdp) connect_flags |= INFO_REMOTECONSOLEAUDIO; } - if (!sec_connect(rdp->sec, rdp->settings->server, rdp->settings->username, rdp->settings->tcp_port_rdp)) + if (!network_connect(rdp->net, rdp->settings->server, rdp->settings->username, rdp->settings->tcp_port_rdp)) return False; password_encoded = freerdp_uniconv_out(rdp->uniconv, rdp->settings->password, &password_encoded_len); @@ -1702,7 +1703,8 @@ rdp_reconnect(rdpRdp * rdp) sec_disconnect(rdp->sec); sec_free(rdp->sec); rdp->sec = sec_new(rdp); - if (!sec_connect(rdp->sec, server, username, rdp->settings->tcp_port_rdp)) + + if (!network_connect(rdp->net, server, username, rdp->settings->tcp_port_rdp)) return False; domain = rdp->redirect_domain ? rdp->redirect_domain : rdp->settings->domain; @@ -1714,11 +1716,14 @@ rdp_reconnect(rdpRdp * rdp) } else password = freerdp_uniconv_out(rdp->uniconv, rdp->settings->password, &password_len); + rdp_send_client_info(rdp, INFO_NORMALLOGON | INFO_AUTOLOGON, domain, username, password, password_len, rdp->settings->shell, rdp->settings->directory); + if (!rdp->redirect_password) xfree(password); + return True; } @@ -1745,11 +1750,16 @@ rdp_new(struct rdp_set *settings, struct rdp_inst *inst) self->buffer_size = 2048; self->buffer = xmalloc(self->buffer_size); memset(self->buffer, 0, self->buffer_size); + self->net = network_new(self); self->sec = sec_new(self); self->orders = orders_new(self); self->pcache = pcache_new(self); self->cache = cache_new(self); self->ext = ext_new(self); + + self->net->rdp = self; + self->net->sec = self->sec; + self->net->tcp = self->net->iso->tcp; } return self; } diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 6ce5cad..1596776 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -65,11 +65,12 @@ struct rdp_rdp UNICONV *uniconv; RDPCOMP mppc_dict; struct rdp_sec * sec; - struct rdp_set * settings; // RDP settings + struct rdp_network * net; + struct rdp_set * settings; struct rdp_orders * orders; struct rdp_pcache * pcache; struct rdp_cache * cache; - struct rdp_app * app; // RemoteApp + struct rdp_app * app; struct rdp_ext * ext; /* Session Directory redirection */ int redirect; diff --git a/libfreerdp-core/secure.c b/libfreerdp-core/secure.c index 7be5cdc..06e1e3e 100644 --- a/libfreerdp-core/secure.c +++ b/libfreerdp-core/secure.c @@ -283,7 +283,7 @@ sec_init(rdpSec * sec, uint32 flags, int maxlen) if (flags) { - if (!(sec->license->license_issued)) + if (!(sec->net->license->license_issued)) hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4; else hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0; @@ -291,7 +291,7 @@ sec_init(rdpSec * sec, uint32 flags, int maxlen) else hdrlen = 0; - s = mcs_init(sec->mcs, maxlen + hdrlen); + s = mcs_init(sec->net->mcs, maxlen + hdrlen); s_push_layer(s, sec_hdr, hdrlen); return s; @@ -305,7 +305,7 @@ sec_fp_init(rdpSec * sec, uint32 flags, int maxlen) int hdrlen; hdrlen = (flags & SEC_ENCRYPT) ? 8 : 0; - s = mcs_fp_init(sec->mcs, maxlen + hdrlen); + s = mcs_fp_init(sec->net->mcs, maxlen + hdrlen); s_push_layer(s, sec_hdr, hdrlen); return s; @@ -321,7 +321,7 @@ sec_send_to_channel(rdpSec * sec, STREAM s, uint32 flags, uint16 channel) if (flags) { /* Basic Security Header */ - if (!(sec->license->license_issued) || (flags & SEC_ENCRYPT)) + if (!(sec->net->license->license_issued) || (flags & SEC_ENCRYPT)) out_uint32_le(s, flags); /* flags */ if (flags & SEC_ENCRYPT) @@ -339,7 +339,7 @@ sec_send_to_channel(rdpSec * sec, STREAM s, uint32 flags, uint16 channel) } } - mcs_send_to_channel(sec->mcs, s, channel); + mcs_send_to_channel(sec->net->mcs, s, channel); } /* Transmit secure transport packet */ @@ -362,11 +362,11 @@ sec_fp_send(rdpSec * sec, STREAM s, uint32 flags) sec_sign(s->p, 8, sec->sec_sign_key, sec->rc4_key_len, s->p + 8, datalen); sec_encrypt(sec, s->p + 8, datalen); } - mcs_fp_send(sec->mcs, s, flags); + mcs_fp_send(sec->net->mcs, s, flags); } /* Transfer the client random to the server */ -static void +void sec_establish_key(rdpSec * sec) { uint32 length = sec->server_public_key_len + SEC_PADDING_SIZE; @@ -451,7 +451,7 @@ sec_out_client_core_data(rdpSec * sec, rdpSet * settings, STREAM s) is set in earlyCapabilityFlags */ out_uint8(s, con_type); out_uint8(s, 0); /* pad1octet */ - out_uint32_le(s, sec->mcs->iso->nego->selected_protocol); /* serverSelectedProtocol */ + out_uint32_le(s, sec->net->iso->nego->selected_protocol); /* serverSelectedProtocol */ } static void @@ -950,7 +950,7 @@ sec_recv(rdpSec * sec, secRecvType * type) uint32 sec_flags; isoRecvType iso_type; - while ((s = mcs_recv(sec->mcs, &iso_type, &channel)) != NULL) + while ((s = mcs_recv(sec->net->mcs, &iso_type, &channel)) != NULL) { if ((iso_type == ISO_RECV_FAST_PATH) || (iso_type == ISO_RECV_FAST_PATH_ENCRYPTED)) @@ -968,7 +968,7 @@ sec_recv(rdpSec * sec, secRecvType * type) ui_error(sec->rdp->inst, "expected ISO_RECV_X224, got %d\n", iso_type); return NULL; } - if (sec->rdp->settings->encryption || !sec->license->license_issued) + if (sec->rdp->settings->encryption || !sec->net->license->license_issued) { /* basicSecurityHeader: */ in_uint32_le(s, sec_flags); @@ -982,7 +982,7 @@ sec_recv(rdpSec * sec, secRecvType * type) if (sec_flags & SEC_LICENSE_PKT) { *type = SEC_RECV_LICENSE; - license_process(sec->license, s); + license_process(sec->net->license, s); continue; } @@ -995,7 +995,7 @@ sec_recv(rdpSec * sec, secRecvType * type) if (channel != MCS_GLOBAL_CHANNEL) { - vchan_process(sec->mcs->chan, s, channel); + vchan_process(sec->net->mcs->chan, s, channel); *type = SEC_RECV_IOCHANNEL; return s; } @@ -1006,161 +1006,11 @@ sec_recv(rdpSec * sec, secRecvType * type) return NULL; } -#ifndef DISABLE_TLS - -/* verify SSL/TLS connection integrity. 2 checks are carried out. First make sure that the - * certificate is assigned to the server we're connected to, and second make sure that the - * certificate is signed by a trusted certification authority - */ - -static RD_BOOL -sec_verify_tls(rdpSec * sec, const char * server) -{ - char * issuer; - char * subject; - char * fingerprint; - CryptoCert cert; - RD_BOOL verified = False; - -#ifdef _WIN32 - /* - * TODO: FIX ME! This is really bad, I know... - * There appears to be a buffer overflow only - * on Windows that affects this part of the code. - * Skipping it is a workaround, but it's obviously - * not a permanent "solution". - */ - return True; -#endif - - cert = tls_get_certificate(sec->tls); - - if (!cert) - { - goto exit; - } - - subject = crypto_cert_get_subject(cert); - issuer = crypto_cert_get_issuer(cert); - fingerprint = crypto_cert_get_fingerprint(cert); - - verified = tls_verify(sec->tls, server); - - if (verified != False) - verified = crypto_cert_verify_peer_identity(cert, server); - - verified = ui_check_certificate(sec->rdp->inst, fingerprint, subject, issuer, verified); - - xfree(fingerprint); - xfree(subject); - xfree(issuer); - -exit: - if (cert) - { - crypto_cert_free(cert); - cert = NULL; - } - - return verified; -} -#endif - -/* Establish a secure connection */ -RD_BOOL -sec_connect(rdpSec * sec, char *server, char *username, int port) -{ - NEGO *nego = sec->mcs->iso->nego; - - sec->license->license_issued = 0; - if (sec->rdp->settings->nla_security) - nego->enabled_protocols[PROTOCOL_NLA] = 1; - if (sec->rdp->settings->tls_security) - nego->enabled_protocols[PROTOCOL_TLS] = 1; - if (sec->rdp->settings->rdp_security) - nego->enabled_protocols[PROTOCOL_RDP] = 1; - - if (!iso_connect(sec->mcs->iso, server, username, port)) - return False; - -#ifndef DISABLE_TLS - if(nego->selected_protocol & PROTOCOL_NLA) - { - /* TLS with NLA was successfully negotiated */ - RD_BOOL status = 1; - printf("TLS encryption with NLA negotiated\n"); - sec->tls = tls_new(); - if (!tls_connect(sec->tls, sec->mcs->iso->tcp->sock)) - return False; - if (!sec_verify_tls(sec, server)) - return False; - sec->tls_connected = 1; - sec->rdp->settings->encryption = 0; - - if (!sec->rdp->settings->autologin) - if (!ui_authenticate(sec->rdp->inst)) - return False; - - sec->credssp = credssp_new(sec); - - if (credssp_authenticate(sec->credssp) < 0) - { - printf("Authentication failure, check credentials.\n" - "If credentials are valid, the NTLMSSP implementation may be to blame.\n"); - credssp_free(sec->credssp); - return 0; - } - - credssp_free(sec->credssp); - - status = mcs_connect(sec->mcs); - return status; - } - else if(nego->selected_protocol & PROTOCOL_TLS) - { - /* TLS without NLA was successfully negotiated */ - RD_BOOL success; - printf("TLS encryption negotiated\n"); - sec->tls = tls_new(); - if (!tls_connect(sec->tls, sec->mcs->iso->tcp->sock)) - return False; - if (!sec_verify_tls(sec, server)) - return False; - sec->tls_connected = 1; - sec->rdp->settings->encryption = 0; - success = mcs_connect(sec->mcs); - return success; - } - else -#endif - { - RD_BOOL success; - - printf("Standard RDP encryption negotiated\n"); - - success = mcs_connect(sec->mcs); - - if (success && sec->rdp->settings->encryption) - sec_establish_key(sec); - - return success; - } - - return 0; -} - /* Disconnect a connection */ void sec_disconnect(rdpSec * sec) { - mcs_disconnect(sec->mcs); - -#ifndef DISABLE_TLS - if (sec->tls) - tls_free(sec->tls); - sec->tls = NULL; - sec->tls_connected = 0; -#endif + mcs_disconnect(sec->net->mcs); if (sec->rc4_decrypt_key) crypto_rc4_free(sec->rc4_decrypt_key); @@ -1180,10 +1030,9 @@ sec_new(struct rdp_rdp * rdp) { memset(self, 0, sizeof(rdpSec)); self->rdp = rdp; - self->mcs = mcs_new(self); - self->license = license_new(self); self->rc4_decrypt_key = NULL; self->rc4_encrypt_key = NULL; + self->net = rdp->net; } return self; } @@ -1193,8 +1042,8 @@ sec_free(rdpSec * sec) { if (sec != NULL) { - license_free(sec->license); - mcs_free(sec->mcs); + license_free(sec->net->license); + mcs_free(sec->net->mcs); xfree(sec); } } diff --git a/libfreerdp-core/secure.h b/libfreerdp-core/secure.h index d5973cf..5a44da1 100644 --- a/libfreerdp-core/secure.h +++ b/libfreerdp-core/secure.h @@ -51,13 +51,8 @@ struct rdp_sec /* These values must be available to reset state - Session Directory */ int sec_encrypt_use_count; int sec_decrypt_use_count; - struct rdp_mcs * mcs; - struct rdp_license * license; int tls_connected; -#ifndef DISABLE_TLS - struct rdp_tls * tls; - struct rdp_credssp * credssp; -#endif + struct rdp_network * net; }; enum sec_recv_type @@ -95,8 +90,10 @@ STREAM sec_recv(rdpSec * sec, secRecvType * type); void sec_out_gcc_conference_create_request(rdpSec * sec, STREAM s); +void +sec_establish_key(rdpSec * sec); RD_BOOL -sec_connect(rdpSec * sec, char *server, char *username, int port); +sec_verify_tls(rdpSec * sec, const char * server); void sec_disconnect(rdpSec * sec); rdpSec * diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c index 035b2c4..2f6ea62 100644 --- a/libfreerdp-core/tcp.c +++ b/libfreerdp-core/tcp.c @@ -35,6 +35,7 @@ #include "secure.h" #include "rdp.h" #include <freerdp/utils/memory.h> +#include <freerdp/utils/hexdump.h> #include "tcp.h" @@ -141,128 +142,66 @@ tcp_init(rdpTcp * tcp, uint32 minsize) return result; } -/* Send data from stream to tcp socket. - * Will block until all data has been sent. */ void -tcp_send(rdpTcp * tcp, STREAM s) +tcp_write(rdpTcp * tcp, STREAM s) { int sent = 0; int total = 0; int length = s->end - s->data; -#ifndef DISABLE_TLS - if (tcp->iso->mcs->sec->tls_connected) - { - tls_write(tcp->iso->mcs->sec->tls, (char*) s->data, length); - } - else -#endif + while (total < length) { while (total < length) { - while (total < length) + sent = send(tcp->sock, s->data + total, length - total, MSG_NOSIGNAL); + if (sent <= 0) { - sent = send(tcp->sock, s->data + total, length - total, MSG_NOSIGNAL); - if (sent <= 0) + if (sent == -1 && TCP_BLOCKS) { - if (sent == -1 && TCP_BLOCKS) - { - tcp_can_send(tcp->sock, 100); - sent = 0; - } - else - { - ui_error(tcp->iso->mcs->sec->rdp->inst, "send: %s\n", TCP_STRERROR); - return; - } + tcp_can_send(tcp->sock, 100); + sent = 0; + } + else + { + ui_error(tcp->iso->net->rdp->inst, "send: %s\n", TCP_STRERROR); + return; } - total += sent; } + total += sent; } } } -/* Read length bytes from tcp socket to stream and return it. - * Appends to stream s if specified, otherwise it uses stream from tcp layer. - * Will block until data available. - * Returns NULL on error. */ -STREAM -tcp_recv(rdpTcp * tcp, STREAM s, uint32 length) +int +tcp_read(rdpTcp * tcp, char* b, int length) { int rcvd = 0; - uint32 p_offset; - uint32 new_length; - uint32 end_offset; - if (s == NULL) - { - /* read into "new" stream */ - if (length > tcp->in.size) - { - tcp->in.data = (uint8 *) xrealloc(tcp->in.data, length); - tcp->in.size = length; - } + if (!ui_select(tcp->iso->mcs->net->sec->rdp->inst, tcp->sock)) + return -1; /* user quit */ - tcp->in.end = tcp->in.p = tcp->in.data; - s = &(tcp->in); - } - else - { - /* append to existing stream */ - new_length = (s->end - s->data) + length; - if (new_length > s->size) - { - p_offset = s->p - s->data; - end_offset = s->end - s->data; - s->data = (uint8 *) xrealloc(s->data, new_length); - s->size = new_length; - s->p = s->data + p_offset; - s->end = s->data + end_offset; - } - } + rcvd = recv(tcp->sock, b, length, 0); - while (length > 0) + if (rcvd < 0) { -#ifndef DISABLE_TLS - if (tcp->iso->mcs->sec->tls_connected) + if (rcvd == -1 && TCP_BLOCKS) { - rcvd = tls_read(tcp->iso->mcs->sec->tls, (char*) s->end, length); - - if (rcvd < 0) - return NULL; + tcp_can_recv(tcp->sock, 1); + rcvd = 0; } else -#endif { - if (!ui_select(tcp->iso->mcs->sec->rdp->inst, tcp->sock)) - return NULL; /* user quit */ - - rcvd = recv(tcp->sock, s->end, length, 0); - if (rcvd < 0) - { - if (rcvd == -1 && TCP_BLOCKS) - { - tcp_can_recv(tcp->sock, 1); - rcvd = 0; - } - else - { - ui_error(tcp->iso->mcs->sec->rdp->inst, "recv: %s\n", TCP_STRERROR); - return NULL; - } - } - else if (rcvd == 0) - { - ui_error(tcp->iso->mcs->sec->rdp->inst, "Connection closed\n"); - return NULL; - } + ui_error(tcp->iso->mcs->net->rdp->inst, "recv: %s\n", TCP_STRERROR); + return -1; } - - s->end += rcvd; - length -= rcvd; + } + else if (rcvd == 0) + { + ui_error(tcp->iso->mcs->net->rdp->inst, "Connection closed\n"); + return -1; } - return s; + return rcvd; } /* Establish a connection on the TCP layer */ @@ -289,7 +228,7 @@ tcp_connect(rdpTcp * tcp, char * server, int port) if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res))) { - ui_error(tcp->iso->mcs->sec->rdp->inst, "getaddrinfo: %s\n", gai_strerror(n)); + ui_error(tcp->iso->mcs->net->sec->rdp->inst, "getaddrinfo: %s\n", gai_strerror(n)); return False; } @@ -311,7 +250,7 @@ tcp_connect(rdpTcp * tcp, char * server, int port) if (sock == -1) { - ui_error(tcp->iso->mcs->sec->rdp->inst, "%s: unable to connect\n", server); + ui_error(tcp->iso->mcs->net->sec->rdp->inst, "%s: unable to connect\n", server); return False; } diff --git a/libfreerdp-core/tcp.h b/libfreerdp-core/tcp.h index e5f2d69..1af3cf7 100644 --- a/libfreerdp-core/tcp.h +++ b/libfreerdp-core/tcp.h @@ -28,16 +28,21 @@ struct rdp_tcp { int sock; struct rdp_iso * iso; - struct stream in; - struct stream out; int tcp_port_rdp; char ipaddr[32]; + struct stream in; + struct stream out; #ifdef _WIN32 WSAEVENT wsa_event; #endif }; typedef struct rdp_tcp rdpTcp; +void +tcp_write(rdpTcp * tcp, STREAM s); +int +tcp_read(rdpTcp * tcp, char* b, int length); + RD_BOOL tcp_can_send(int sck, int millis); RD_BOOL |