libfreerdp-core: fix transport failure case with session redirection
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 1 Nov 2013 18:13:09 +0000 (14:13 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 1 Nov 2013 18:13:09 +0000 (14:13 -0400)
libfreerdp/core/connection.c
libfreerdp/core/fastpath.h
libfreerdp/core/nego.c
libfreerdp/core/rdp.c
libfreerdp/core/rdp.h
libfreerdp/core/redirection.h
libfreerdp/core/settings.c
libfreerdp/core/transport.c

index cade9ac..1f061c1 100644 (file)
@@ -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 };
index 2431969..8efa162 100644 (file)
 #ifndef __FASTPATH_H
 #define __FASTPATH_H
 
+typedef struct rdp_fastpath rdpFastPath;
+
 #include "rdp.h"
 
 #include <winpr/stream.h>
 
-typedef struct rdp_fastpath rdpFastPath;
-
 enum FASTPATH_INPUT_ACTION_TYPE
 {
        FASTPATH_INPUT_ACTION_FASTPATH = 0x0,
index 299cd72..9fb281f 100644 (file)
@@ -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));
 
index 2b795b6..ffdd312 100644 (file)
@@ -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);
index aa43b98..c70d0c3 100644 (file)
@@ -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);
index 8203336..b4f05e3 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __REDIRECTION_H
 #define __REDIRECTION_H
 
+typedef struct rdp_redirection rdpRedirection;
+
 #include "rdp.h"
 
 #include <freerdp/freerdp.h>
@@ -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);
index 6b0cd3f..1524afe 100644 (file)
@@ -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;
index c4b7564..0d086e0 100644 (file)
@@ -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;