diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index cade9acd6..1f061c175 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -170,6 +170,14 @@ BOOL rdp_client_connect(rdpRdp* rdp) { rdpSettings* settings = rdp->settings; + if (rdp->settingsCopy) + { + freerdp_settings_free(rdp->settingsCopy); + rdp->settingsCopy = NULL; + } + + rdp->settingsCopy = freerdp_settings_clone(settings); + nego_init(rdp->nego); nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort); @@ -278,6 +286,7 @@ BOOL rdp_client_disconnect(rdpRdp* rdp) BOOL rdp_client_redirect(rdpRdp* rdp) { + BOOL status; rdpSettings* settings = rdp->settings; rdpRedirection* redirection = rdp->redirection; @@ -297,7 +306,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp) rdp->fips_hmac = NULL; free(settings->ServerRandom); - settings->ServerRandom = NULL ; + settings->ServerRandom = NULL; free(settings->ServerCertificate); settings->ServerCertificate = NULL; free(settings->ClientAddress); @@ -361,7 +370,9 @@ BOOL rdp_client_redirect(rdpRdp* rdp) settings->RedirectionPasswordLength = redirection->PasswordCookieLength; } - return rdp_client_connect(rdp); + status = rdp_client_connect(rdp); + + return status; } static BYTE fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; diff --git a/libfreerdp/core/fastpath.h b/libfreerdp/core/fastpath.h index 243196959..8efa162ec 100644 --- a/libfreerdp/core/fastpath.h +++ b/libfreerdp/core/fastpath.h @@ -20,12 +20,12 @@ #ifndef __FASTPATH_H #define __FASTPATH_H +typedef struct rdp_fastpath rdpFastPath; + #include "rdp.h" #include -typedef struct rdp_fastpath rdpFastPath; - enum FASTPATH_INPUT_ACTION_TYPE { FASTPATH_INPUT_ACTION_FASTPATH = 0x0, diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 299cd7203..9fb281f85 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -964,7 +964,7 @@ void nego_init(rdpNego* nego) * @return */ -rdpNego* nego_new(struct rdp_transport * transport) +rdpNego* nego_new(rdpTransport* transport) { rdpNego* nego = (rdpNego*) malloc(sizeof(rdpNego)); diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 2b795b64b..ffdd312ba 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -816,7 +816,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) */ Stream_Rewind(s, 2); rdp_recv_enhanced_security_redirection_packet(rdp, s); - return -1; + return 1; /* 1 = redirection */ } } @@ -976,7 +976,9 @@ void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking) int rdp_check_fds(rdpRdp* rdp) { - return transport_check_fds(&(rdp->transport)); + int status; + status = transport_check_fds(&(rdp->transport)); + return status; } /** @@ -1035,7 +1037,7 @@ rdpRdp* rdp_new(rdpContext* context) void rdp_free(rdpRdp* rdp) { - if (rdp != NULL) + if (rdp) { crypto_rc4_free(rdp->rc4_decrypt_key); crypto_rc4_free(rdp->rc4_encrypt_key); @@ -1043,6 +1045,7 @@ void rdp_free(rdpRdp* rdp) crypto_des3_free(rdp->fips_decrypt); crypto_hmac_free(rdp->fips_hmac); freerdp_settings_free(rdp->settings); + freerdp_settings_free(rdp->settingsCopy); extension_free(rdp->extension); transport_free(rdp->transport); license_free(rdp->license); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index aa43b988f..c70d0c3d8 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -121,16 +121,16 @@ struct rdp_rdp int state; freerdp* instance; rdpContext* context; - struct rdp_mcs* mcs; - struct rdp_nego* nego; - struct rdp_input* input; - struct rdp_update* update; - struct rdp_fastpath* fastpath; - struct rdp_license* license; - struct rdp_redirection* redirection; - struct rdp_settings* settings; - struct rdp_transport* transport; - struct rdp_extension* extension; + rdpMcs* mcs; + rdpNego* nego; + rdpInput* input; + rdpUpdate* update; + rdpFastPath* fastpath; + rdpLicense* license; + rdpRedirection* redirection; + rdpSettings* settings; + rdpTransport* transport; + rdpExtension* extension; struct rdp_mppc_dec* mppc_dec; struct rdp_mppc_enc* mppc_enc; struct crypto_rc4_struct* rc4_decrypt_key; @@ -160,6 +160,7 @@ struct rdp_rdp BOOL resendFocus; BOOL deactivation_reactivation; BOOL AwaitCapabilities; + rdpSettings* settingsCopy; }; BOOL rdp_read_security_header(wStream* s, UINT16* flags); diff --git a/libfreerdp/core/redirection.h b/libfreerdp/core/redirection.h index 8203336b1..b4f05e37f 100644 --- a/libfreerdp/core/redirection.h +++ b/libfreerdp/core/redirection.h @@ -20,6 +20,8 @@ #ifndef __REDIRECTION_H #define __REDIRECTION_H +typedef struct rdp_redirection rdpRedirection; + #include "rdp.h" #include @@ -46,7 +48,6 @@ struct rdp_redirection UINT32 TargetNetAddressesCount; char** TargetNetAddresses; }; -typedef struct rdp_redirection rdpRedirection; BOOL rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s); BOOL rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s); diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 6b0cd3f1c..1524afe76 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -301,6 +301,9 @@ rdpSettings* freerdp_settings_new(DWORD flags) ZeroMemory(settings->ClientHostname, 32); ZeroMemory(settings->ClientProductId, 32); + gethostname(settings->ClientHostname, 31); + settings->ClientHostname[31] = 0; + settings->ColorPointerFlag = TRUE; settings->LargePointerFlag = TRUE; settings->PointerCacheSize = 20; @@ -381,9 +384,6 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->FastPathOutput = TRUE; settings->FrameAcknowledge = 2; - - gethostname(settings->ClientHostname, 31); - settings->ClientHostname[31] = 0; settings->MouseMotion = TRUE; settings->AutoReconnectionEnabled = TRUE; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index c4b756439..0d086e0d0 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -94,6 +94,7 @@ BOOL transport_disconnect(rdpTransport* transport) CloseHandle(transport->thread); CloseHandle(transport->stopEvent); } + return status; } @@ -889,23 +890,32 @@ int transport_check_fds(rdpTransport** ptransport) Stream_SealLength(received); Stream_SetPosition(received, 0); + /** + * status: + * -1: error + * 0: success + * 1: redirection + */ + recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); - if (transport == *ptransport) + if (recv_status == 1) { - /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ - /* so only release if still valid */ - Stream_Release(received); + /** + * Last call to ReceiveCallback resulted in a session redirection, + * which means the current rdpTransport* transport pointer has been freed. + * Return 0 for success, the rest of this function is meant for non-redirected cases. + */ + return 0; } + Stream_Release(received); + if (recv_status < 0) status = -1; if (status < 0) return status; - - /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ - transport = *ptransport; } return 0;