From 1a96bdc7a519f9919998270d7b5b569654a0330b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 16 Aug 2013 10:34:54 +0200 Subject: [PATCH 01/14] Fixed initialization of serial device, now aborting pending read / write operations. --- channels/serial/client/serial_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index d2ff16a48..80a5435bf 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -113,6 +113,14 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) else { serial->tty = tty; + + serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, + STATUS_CANCELLED); + serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, + STATUS_CANCELLED); + serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, + STATUS_CANCELLED); + DEBUG_SVC("%s(%d) created.", serial->path, FileId); } @@ -332,7 +340,6 @@ static void* serial_thread_func(void* arg) if (WAIT_OBJECT_0 == status) break; - serial->nfds = 1; FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); From 7f89966efcfd0d356ddacc360f880278074d4598 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 16 Aug 2013 10:50:07 +0200 Subject: [PATCH 02/14] Fixed compilation error, now using WaitForMultipleObjects. --- channels/smartcard/client/smartcard_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index 4efff88ff..855df3ff0 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -128,7 +128,7 @@ static void* smartcard_thread_func(void* arg) while (1) { - DWORD status = WaitForSingleObject(2, ev, FALSE, INFINITE); + DWORD status = WaitForMultipleObjects(2, ev, FALSE, INFINITE); if (status == WAIT_OBJECT_0 + 1) break; From 1a3a6c3e0f7fc7a78aaf28ce4f5f34b1c36d3019 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 16 Aug 2013 11:49:35 +0200 Subject: [PATCH 03/14] Fixed check for _GNU_SOURCE pthread extensions. --- winpr/libwinpr/synch/CMakeLists.txt | 9 +++++++++ winpr/libwinpr/synch/wait.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/winpr/libwinpr/synch/CMakeLists.txt b/winpr/libwinpr/synch/CMakeLists.txt index cd93e84f8..fbc607292 100644 --- a/winpr/libwinpr/synch/CMakeLists.txt +++ b/winpr/libwinpr/synch/CMakeLists.txt @@ -18,6 +18,15 @@ set(MODULE_NAME "winpr-synch") set(MODULE_PREFIX "WINPR_SYNCH") +INCLUDE (CheckLibraryExists) +list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) +check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT) +list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) + +if(HAVE_PTHREAD_GNU_EXT) + add_definitions(-D_GNU_SOURCE -DHAVE_PTHREAD_GNU_EXT) +endif(HAVE_PTHREAD_GNU_EXT) + include_directories(../thread) set(${MODULE_PREFIX}_SRCS diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index dccb071ae..9a8eba120 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -77,7 +77,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { if (dwMilliseconds != INFINITE) { -#if _GNU_SOURCE +#if HAVE_PTHREAD_GNU_EXT struct timespec timeout; clock_gettime(CLOCK_REALTIME, &timeout); @@ -105,7 +105,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) mutex = (WINPR_MUTEX*) Object; -#if _GNU_SOURCE +#if HAVE_PTHREAD_GNU_EXT if (dwMilliseconds != INFINITE) { struct timespec timeout; From 60d38daf0a62b3de0f9b80f87b844fe67e69a424 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 16 Aug 2013 12:40:06 +0200 Subject: [PATCH 04/14] Reset file descriptor set only, if necessary now. --- channels/serial/client/serial_main.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 80a5435bf..d34dd7a0a 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -340,21 +340,22 @@ static void* serial_thread_func(void* arg) if (WAIT_OBJECT_0 == status) break; - FD_ZERO(&serial->read_fds); - FD_ZERO(&serial->write_fds); - - serial->tv.tv_sec = 0; - serial->tv.tv_usec = 0; - serial->select_timeout = 0; - if (status == WAIT_OBJECT_0 + 1) { + FD_ZERO(&serial->read_fds); + FD_ZERO(&serial->write_fds); + + serial->tv.tv_sec = 0; + serial->tv.tv_usec = 0; + serial->select_timeout = 0; + if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); continue; } - serial_check_fds(serial); + if(serial->tty) + serial_check_fds(serial); } return NULL; @@ -680,6 +681,13 @@ static BOOL serial_check_fds(SERIAL_DEVICE* serial) if (list_size(serial->pending_irps) == 0) return 1; + FD_ZERO(&serial->read_fds); + FD_ZERO(&serial->write_fds); + + serial->tv.tv_sec = 0; + serial->tv.tv_usec = 0; + serial->select_timeout = 0; + serial_set_fds(serial); DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec); From 6f9183c7aadeb88a797e0c60b8accd3150e83edb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 16 Aug 2013 15:51:44 +0200 Subject: [PATCH 05/14] Using a monitor thread for tty input now to work around a WaitForMultipleObjects limitation of winpr. Using infinite timeout now in threads to reduce CPU usage to nearly zero. --- channels/serial/client/serial_main.c | 64 +++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index d34dd7a0a..5f8002008 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -63,7 +63,9 @@ struct _SERIAL_DEVICE SERIAL_TTY* tty; HANDLE thread; + HANDLE mthread; HANDLE stopEvent; + HANDLE newEvent; wQueue* queue; LIST* pending_irps; @@ -80,6 +82,7 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32 static void serial_check_for_events(SERIAL_DEVICE* serial); static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp); static BOOL serial_check_fds(SERIAL_DEVICE* serial); +static void* serial_thread_mfunc(void* arg); static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { @@ -121,6 +124,10 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED); + serial->mthread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) serial_thread_mfunc, (void*) serial, + 0, NULL); + DEBUG_SVC("%s(%d) created.", serial->path, FileId); } @@ -147,6 +154,11 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) { DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); + TerminateThread(serial->mthread, 0); + WaitForSingleObject(serial->mthread, INFINITE); + CloseHandle(serial->mthread); + serial->mthread = NULL; + serial_tty_free(tty); serial->tty = NULL; } @@ -326,21 +338,51 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) serial_check_for_events(serial); } +/* This thread is used as a workaround for the missing serial event + * support in WaitForMultipleObjects. + * It monitors the terminal for events and posts it in a supported + * form that WaitForMultipleObjects can use it. */ +void* serial_thread_mfunc(void* arg) +{ + SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; + + while(1) + { + int sl; + fd_set rd; + + if(!serial->tty || serial->tty->fd <= 0) + { + DEBUG_WARN("Monitor thread still running, but no terminal opened!"); + sleep(1); + } + else + { + FD_ZERO(&rd); + FD_SET(serial->tty->fd, &rd); + sl = select(serial->tty->fd + 1, &rd, NULL, NULL, NULL); + if( sl > 0 ) + SetEvent(serial->newEvent); + } + } + + return NULL; +} + static void* serial_thread_func(void* arg) { IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; - HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)}; + HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent}; while (1) { - status = WaitForMultipleObjects(2, ev, FALSE, 1); - + status = WaitForMultipleObjects(3, ev, FALSE, INFINITE); + if (WAIT_OBJECT_0 == status) break; - - if (status == WAIT_OBJECT_0 + 1) + else if (status == WAIT_OBJECT_0 + 1) { FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); @@ -351,8 +393,9 @@ static void* serial_thread_func(void* arg) if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); - continue; } + else if (status == WAIT_OBJECT_0 + 2) + ResetEvent(serial->newEvent); if(serial->tty) serial_check_fds(serial); @@ -376,6 +419,12 @@ static void serial_free(DEVICE* device) /* Stop thread */ SetEvent(serial->stopEvent); + if(serial->mthread) + { + TerminateThread(serial->mthread, 0); + WaitForSingleObject(serial->mthread, INFINITE); + CloseHandle(serial->mthread); + } WaitForSingleObject(serial->thread, INFINITE); serial_tty_free(serial->tty); @@ -385,6 +434,7 @@ static void serial_free(DEVICE* device) Queue_Free(serial->queue); list_free(serial->pending_irps); CloseHandle(serial->stopEvent); + CloseHandle(serial->newEvent); CloseHandle(serial->thread); free(serial); } @@ -754,11 +804,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) serial->pending_irps = list_new(); serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + serial->newEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial); serial->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL); + serial->mthread = NULL; } return 0; From 2f20a8c12ba87095ec0fecbe8c50be5607e36333 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 19 Aug 2013 17:44:52 +0200 Subject: [PATCH 06/14] Fixed various memory leaks and resource deallocation problems. --- client/X11/xf_client.c | 23 +++++++++++++++++++++-- client/X11/xf_input.c | 3 ++- client/X11/xf_monitor.c | 13 +++++++++++++ client/X11/xf_monitor.h | 1 + client/common/client.c | 1 + include/freerdp/freerdp.h | 7 ++++++- libfreerdp/core/freerdp.c | 7 +++++++ libfreerdp/core/nego.c | 1 + winpr/libwinpr/synch/wait.c | 3 ++- 9 files changed, 54 insertions(+), 5 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 5ad3f4f04..886c3a8d2 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -22,6 +22,8 @@ #include "config.h" #endif +#include + #include #include @@ -718,6 +720,20 @@ int _xf_error_handler(Display* d, XErrorEvent* ev) return xf_error_handler(d, ev); } +static void xf_post_disconnect(freerdp *instance) +{ + xfContext* xfc = (xfContext*) instance->context; + + assert(NULL != instance); + assert(NULL != xfc); + assert(NULL != instance->settings); + + WaitForSingleObject(xfc->mutex, INFINITE); + CloseHandle(xfc->mutex); + + xf_monitors_free(xfc, instance->settings); +} + /** * Callback given to freerdp_connect() to process the pre-connect operations. * It will fill the rdp_freerdp structure (instance) with the appropriate options to use for the connection. @@ -735,7 +751,6 @@ BOOL xf_pre_connect(freerdp* instance) xfContext* xfc = (xfContext*) instance->context; xfc->mutex = CreateMutex(NULL, FALSE, NULL); - xfc->settings = instance->settings; xfc->instance = instance; @@ -1355,7 +1370,7 @@ void* xf_thread(void* param) { freerdp_disconnect(instance); fprintf(stderr, "%s:%d: Authentication only, exit status %d\n", __FILE__, __LINE__, !status); - exit(!status); + ExitThread(exit_code); } if (!status) @@ -1714,6 +1729,9 @@ int xfreerdp_client_stop(rdpContext* context) xfc->disconnect = TRUE; } + WaitForSingleObject(xfc->thread, INFINITE); + CloseHandle(xfc->thread); + return 0; } @@ -1726,6 +1744,7 @@ int xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; + instance->PostDisconnect = xf_post_disconnect; instance->Authenticate = xf_authenticate; instance->VerifyCertificate = xf_verify_certificate; instance->LogonErrorInfo = xf_logon_error_info; diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 7f19d4ba3..8d1adf509 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -197,7 +197,8 @@ int xf_input_init(xfContext* xfc, Window window) } } } - + XIFreeDeviceInfo(info); + if (nmasks > 0) xstatus = XISelectEvents(xfc->display, window, evmasks, nmasks); diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index cd9301681..fc4d23bf2 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -255,3 +255,16 @@ BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings) return TRUE; } + +/** Clean up all resources allocated by functions in this file. + */ +void xf_monitors_free(xfContext *xfc, rdpSettings *settings) +{ +#ifdef WITH_XINERAMA + if(xfc->vscreen.monitors) + free(xfc->vscreen.monitors); +#endif + + if(settings->MonitorIds) + free(settings->MonitorIds); +} diff --git a/client/X11/xf_monitor.h b/client/X11/xf_monitor.h index ed4bd21a8..9e29eec85 100644 --- a/client/X11/xf_monitor.h +++ b/client/X11/xf_monitor.h @@ -45,5 +45,6 @@ typedef struct _VIRTUAL_SCREEN VIRTUAL_SCREEN; int xf_list_monitors(xfContext* xfc); BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings); +void xf_monitors_free(xfContext *xfc, rdpSettings *settings); #endif /* __XF_MONITOR_H */ diff --git a/client/common/client.c b/client/common/client.c index 824b46859..9bba04740 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -66,6 +66,7 @@ void freerdp_client_context_free(rdpContext* context) { freerdp* instance = context->instance; + free(instance->pClientEntryPoints); freerdp_context_free(instance); freerdp_free(instance); } diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index e3ce2bf84..881c92fbc 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -57,6 +57,7 @@ typedef void (*pContextFree)(freerdp* instance, rdpContext* context); typedef BOOL (*pPreConnect)(freerdp* instance); typedef BOOL (*pPostConnect)(freerdp* instance); +typedef void (*pPostDisconnect)(freerdp* instance); typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint); typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint); @@ -194,7 +195,11 @@ struct rdp_freerdp ALIGN64 pLogonErrorInfo LogonErrorInfo; /**< (offset 53) Callback for logon error info, important for logon system messages with RemoteApp */ - UINT64 paddingD[64 - 54]; /* 54 */ + ALIGN64 pPostDisconnect PostDisconnect; /**< (offset 54) + Callback for cleaning up resources allocated + by connect callbacks. */ + + UINT64 paddingD[64 - 55]; /* 55 */ ALIGN64 pSendChannelData SendChannelData; /* (offset 64) Callback for sending data to a channel. diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index b447a8477..d068beca3 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -30,6 +30,8 @@ #include "extension.h" #include "message.h" +#include + #include #include @@ -158,8 +160,11 @@ BOOL freerdp_connect(freerdp* instance) update_recv_surfcmds(update, Stream_Length(s) , s); update->EndPaint(update->context); Stream_Release(s); + + StreamPool_Return(rdp->transport->ReceivePool, s); } + status = TRUE; goto freerdp_connect_finally; } @@ -299,6 +304,8 @@ BOOL freerdp_disconnect(freerdp* instance) rdp = instance->context->rdp; transport_disconnect(rdp->transport); + IFCALL(instance->PostDisconnect, instance); + return TRUE; } diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 115c1f683..e60b2f680 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -488,6 +488,7 @@ BOOL nego_recv_response(rdpNego* nego) return FALSE; } + Stream_Free(s, TRUE); return TRUE; } diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index 9a8eba120..bfb221315 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -93,7 +93,8 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) status = pthread_join(thread->thread, &thread_status); if (status != 0) - fprintf(stderr, "WaitForSingleObject: pthread_join failure: %d\n", status); + fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n", + status, strerror(status)); if (thread_status) thread->dwExitCode = ((DWORD) (size_t) thread_status); From f71f179c2819211a2a1303f2184ccff5fd273710 Mon Sep 17 00:00:00 2001 From: Daryl Poe Date: Wed, 7 Aug 2013 16:28:31 -0600 Subject: [PATCH 07/14] fix per-device CAL licensing (cherry picked from commit d6d0d81d08df4ee697ed4e8eb81264e95e1355df) --- include/freerdp/crypto/crypto.h | 8 ++++---- libfreerdp/core/license.c | 19 ++++++++++--------- libfreerdp/crypto/crypto.c | 32 +++++++++++++++++--------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index fdf20e715..b939e2060 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -132,10 +132,10 @@ extern const BYTE tssk_modulus[]; extern const BYTE tssk_privateExponent[]; extern const BYTE tssk_exponent[]; -FREERDP_API void crypto_rsa_public_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output); -FREERDP_API void crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output); -FREERDP_API void crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); -FREERDP_API void crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); +FREERDP_API int crypto_rsa_public_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output); +FREERDP_API int crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output); +FREERDP_API int crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); +FREERDP_API int crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); FREERDP_API void crypto_reverse(BYTE* data, int length); FREERDP_API void crypto_nonce(BYTE* nonce, int size); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index ebc462fa5..88d039eb8 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -28,8 +28,8 @@ #include "license.h" -//#define LICENSE_NULL_CLIENT_RANDOM 1 -#define LICENSE_NULL_PREMASTER_SECRET 1 +/* #define LICENSE_NULL_CLIENT_RANDOM 1 */ +/* #define LICENSE_NULL_PREMASTER_SECRET 1 */ #ifdef WITH_DEBUG_LICENSE @@ -195,7 +195,7 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type) * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when * running in server mode! This flag seems to be incorrectly documented. */ - flags = PREAMBLE_VERSION_3_0; + flags = PREAMBLE_VERSION_3_0 | EXTENDED_ERROR_MSG_SUPPORTED; rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, sec_flags); @@ -409,7 +409,7 @@ void license_get_server_rsa_public_key(rdpLicense* license) license->ModulusLength = ModulusLength; license->Modulus = (BYTE*) malloc(ModulusLength); - ZeroMemory(license->Modulus, ModulusLength); + memcpy(license->Modulus, Modulus, ModulusLength); } void license_encrypt_premaster_secret(rdpLicense* license) @@ -430,14 +430,15 @@ void license_encrypt_premaster_secret(rdpLicense* license) EncryptedPremasterSecret = (BYTE*) malloc(license->ModulusLength); ZeroMemory(EncryptedPremasterSecret, license->ModulusLength); + license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB; + license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH; #ifndef LICENSE_NULL_PREMASTER_SECRET - crypto_rsa_public_encrypt(license->PremasterSecret, PREMASTER_SECRET_LENGTH, + license->EncryptedPremasterSecret->length = + crypto_rsa_public_encrypt(license->PremasterSecret, PREMASTER_SECRET_LENGTH, license->ModulusLength, license->Modulus, license->Exponent, EncryptedPremasterSecret); #endif - license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB; - license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH; license->EncryptedPremasterSecret->data = EncryptedPremasterSecret; } @@ -1044,11 +1045,11 @@ void license_send_platform_challenge_response_packet(rdpLicense* license) fprintf(stderr, "\n"); fprintf(stderr, "HardwareId:\n"); - winpr_HexDump(license->HardwareId, 20); + winpr_HexDump(license->HardwareId, HWID_LENGTH); fprintf(stderr, "\n"); fprintf(stderr, "EncryptedHardwareId:\n"); - winpr_HexDump(license->EncryptedHardwareId->data, 20); + winpr_HexDump(license->EncryptedHardwareId->data, HWID_LENGTH); fprintf(stderr, "\n"); #endif diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 2ffa2bd84..f227e9736 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -207,7 +207,7 @@ exit: return status; } -static void crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, int exponent_size, BYTE* output) +static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, int exponent_size, BYTE* output) { BN_CTX* ctx; int output_length; @@ -250,41 +250,43 @@ static void crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, BN_free(&mod); BN_CTX_free(ctx); free(input_reverse); + + return output_length; } -static void crypto_rsa_public(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) +static int crypto_rsa_public(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) { - crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); + return crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); } -static void crypto_rsa_private(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +static int crypto_rsa_private(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) { - crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); + return crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); } -void crypto_rsa_public_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) +int crypto_rsa_public_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) { - crypto_rsa_public(input, length, key_length, modulus, exponent, output); + return crypto_rsa_public(input, length, key_length, modulus, exponent, output); } -void crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) +int crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, BYTE* output) { - crypto_rsa_public(input, length, key_length, modulus, exponent, output); + return crypto_rsa_public(input, length, key_length, modulus, exponent, output); } -void crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +int crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) { - crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); + return crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); } -void crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +int crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) { - crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); + return crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); } -void crypto_rsa_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +int crypto_rsa_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output) { - crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); + return crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); } void crypto_reverse(BYTE* data, int length) From c7c5be0bf71b04228d58f7192517ee6b7fae6c61 Mon Sep 17 00:00:00 2001 From: Hardening Date: Wed, 28 Aug 2013 23:47:37 +0200 Subject: [PATCH 08/14] Extract shared code in RAIL channel This patch starts a code mutualisation for a RAIL server-side implementation. The file rail_common.c contains code that is shared by both client and server. --- channels/rail/client/CMakeLists.txt | 2 + channels/rail/client/rail_main.c | 6 +- channels/rail/client/rail_main.h | 28 +------ channels/rail/client/rail_orders.c | 120 +++------------------------- channels/rail/client/rail_orders.h | 35 -------- channels/rail/rail_common.c | 102 +++++++++++++++++++++++ channels/rail/rail_common.h | 82 +++++++++++++++++++ include/freerdp/rail.h | 6 +- 8 files changed, 206 insertions(+), 175 deletions(-) create mode 100644 channels/rail/rail_common.c create mode 100644 channels/rail/rail_common.h diff --git a/channels/rail/client/CMakeLists.txt b/channels/rail/client/CMakeLists.txt index 748f7141d..2db2b2ddd 100644 --- a/channels/rail/client/CMakeLists.txt +++ b/channels/rail/client/CMakeLists.txt @@ -18,6 +18,8 @@ define_channel_client("rail") set(${MODULE_PREFIX}_SRCS + ../rail_common.h + ../rail_common.c rail_main.c rail_main.h rail_orders.c diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 717cbabea..913eb2896 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -104,9 +104,9 @@ static void rail_process_addin_args(rdpRailOrder* rail_order, rdpSettings* setti rail_order->exec.flags |= RAIL_EXEC_FLAG_FILE; } - rail_string_to_unicode_string(rail_order, settings->RemoteApplicationProgram, &rail_order->exec.exeOrFile); - rail_string_to_unicode_string(rail_order, settings->ShellWorkingDirectory, &rail_order->exec.workingDir); - rail_string_to_unicode_string(rail_order, settings->RemoteApplicationCmdLine, &rail_order->exec.arguments); + rail_string_to_unicode_string(settings->RemoteApplicationProgram, &rail_order->exec.exeOrFile); + rail_string_to_unicode_string(settings->ShellWorkingDirectory, &rail_order->exec.workingDir); + rail_string_to_unicode_string(settings->RemoteApplicationCmdLine, &rail_order->exec.arguments); rail_send_client_exec_order(rail_order); } diff --git a/channels/rail/client/rail_main.h b/channels/rail/client/rail_main.h index 6e0abb179..808ae4fdd 100644 --- a/channels/rail/client/rail_main.h +++ b/channels/rail/client/rail_main.h @@ -29,27 +29,7 @@ #include -struct rdp_rail_order -{ - rdpSettings* settings; - void* plugin; - RAIL_HANDSHAKE_ORDER handshake; - RAIL_CLIENT_STATUS_ORDER client_status; - RAIL_EXEC_ORDER exec; - RAIL_EXEC_RESULT_ORDER exec_result; - RAIL_SYSPARAM_ORDER sysparam; - RAIL_ACTIVATE_ORDER activate; - RAIL_SYSMENU_ORDER sysmenu; - RAIL_SYSCOMMAND_ORDER syscommand; - RAIL_NOTIFY_EVENT_ORDER notify_event; - RAIL_MINMAXINFO_ORDER minmaxinfo; - RAIL_LOCALMOVESIZE_ORDER localmovesize; - RAIL_WINDOW_MOVE_ORDER window_move; - RAIL_LANGBAR_INFO_ORDER langbar_info; - RAIL_GET_APPID_REQ_ORDER get_appid_req; - RAIL_GET_APPID_RESP_ORDER get_appid_resp; -}; -typedef struct rdp_rail_order rdpRailOrder; +#include "../rail_common.h" struct rail_plugin { @@ -61,10 +41,6 @@ typedef struct rail_plugin railPlugin; void rail_send_channel_event(void* rail_object, UINT16 event_type, void* param); void rail_send_channel_data(void* rail_object, void* data, size_t length); -#ifdef WITH_DEBUG_RAIL -#define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__) -#else -#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) -#endif + #endif /* FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H */ diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c index e6bb690ec..0128079f5 100644 --- a/channels/rail/client/rail_orders.c +++ b/channels/rail/client/rail_orders.c @@ -31,85 +31,7 @@ #include "rail_orders.h" -#define RAIL_ORDER_TYPE_EXEC 0x0001 -#define RAIL_ORDER_TYPE_ACTIVATE 0x0002 -#define RAIL_ORDER_TYPE_SYSPARAM 0x0003 -#define RAIL_ORDER_TYPE_SYSCOMMAND 0x0004 -#define RAIL_ORDER_TYPE_HANDSHAKE 0x0005 -#define RAIL_ORDER_TYPE_NOTIFY_EVENT 0x0006 -#define RAIL_ORDER_TYPE_WINDOW_MOVE 0x0008 -#define RAIL_ORDER_TYPE_LOCALMOVESIZE 0x0009 -#define RAIL_ORDER_TYPE_MINMAXINFO 0x000A -#define RAIL_ORDER_TYPE_CLIENT_STATUS 0x000B -#define RAIL_ORDER_TYPE_SYSMENU 0x000C -#define RAIL_ORDER_TYPE_LANGBAR_INFO 0x000D -#define RAIL_ORDER_TYPE_EXEC_RESULT 0x0080 -#define RAIL_ORDER_TYPE_GET_APPID_REQ 0x000E -#define RAIL_ORDER_TYPE_GET_APPID_RESP 0x000F -static const char* const RAIL_ORDER_TYPE_STRINGS[] = -{ - "", - "Execute", - "Activate", - "System Parameters Update", - "System Command", - "Handshake", - "Notify Event", - "", - "Window Move", - "Local Move/Size", - "Min Max Info", - "Client Status", - "System Menu", - "Language Bar Info", - "Get Application ID Request", - "Get Application ID Response", - "Execute Result" -}; - -void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string) -{ - WCHAR* buffer = NULL; - int length = 0; - - if (unicode_string->string != NULL) - free(unicode_string->string); - - unicode_string->string = NULL; - unicode_string->length = 0; - - if (string == NULL || strlen(string) < 1) - return; - - length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2; - - unicode_string->string = (BYTE*) buffer; - unicode_string->length = (UINT16) length; -} - -BOOL rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength) -{ - if (Stream_GetRemainingLength(s) < 4) - return FALSE; - Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ - Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ - return TRUE; -} - -void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength) -{ - Stream_Write_UINT16(s, orderType); /* orderType (2 bytes) */ - Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */ -} - -wStream* rail_pdu_init(int length) -{ - wStream* s; - s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH); - Stream_Seek(s, RAIL_PDU_HEADER_LENGTH); - return s; -} void rail_send_pdu(rdpRailOrder* rail_order, wStream* s, UINT16 orderType) { @@ -128,7 +50,7 @@ void rail_send_pdu(rdpRailOrder* rail_order, wStream* s, UINT16 orderType) rail_send_channel_data(rail_order->plugin, Stream_Buffer(s), orderLength); } -void rail_write_high_contrast(wStream* s, HIGH_CONTRAST* high_contrast) +void rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* high_contrast) { high_contrast->colorSchemeLength = high_contrast->colorScheme.length + 2; Stream_Write_UINT32(s, high_contrast->flags); /* flags (4 bytes) */ @@ -136,14 +58,6 @@ void rail_write_high_contrast(wStream* s, HIGH_CONTRAST* high_contrast) rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */ } -BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) -{ - if (Stream_GetRemainingLength(s) < 4) - return FALSE; - Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ - return TRUE; -} - BOOL rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec_result) { if (Stream_GetRemainingLength(s) < 8) @@ -232,10 +146,6 @@ BOOL rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_i return TRUE; } -void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) -{ - Stream_Write_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ -} void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client_status) { @@ -512,7 +422,7 @@ void rail_send_handshake_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH); rail_write_handshake_order(s, &rail_order->handshake); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_HANDSHAKE); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_HANDSHAKE); Stream_Free(s, TRUE); } @@ -521,7 +431,7 @@ void rail_send_client_status_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH); rail_write_client_status_order(s, &rail_order->client_status); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_CLIENT_STATUS); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_CLIENTSTATUS); Stream_Free(s, TRUE); } @@ -537,7 +447,7 @@ void rail_send_client_exec_order(rdpRailOrder* rail_order) s = rail_pdu_init(RAIL_EXEC_ORDER_LENGTH); rail_write_client_exec_order(s, &rail_order->exec); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_EXEC); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_EXEC); Stream_Free(s, TRUE); } @@ -570,7 +480,7 @@ void rail_send_client_sysparam_order(rdpRailOrder* rail_order) s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8); rail_write_client_sysparam_order(s, &rail_order->sysparam); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSPARAM); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSPARAM); Stream_Free(s, TRUE); } @@ -624,7 +534,7 @@ void rail_send_client_activate_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH); rail_write_client_activate_order(s, &rail_order->activate); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_ACTIVATE); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_ACTIVATE); Stream_Free(s, TRUE); } @@ -633,7 +543,7 @@ void rail_send_client_sysmenu_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH); rail_write_client_sysmenu_order(s, &rail_order->sysmenu); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSMENU); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSMENU); Stream_Free(s, TRUE); } @@ -642,7 +552,7 @@ void rail_send_client_syscommand_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH); rail_write_client_syscommand_order(s, &rail_order->syscommand); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSCOMMAND); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSCOMMAND); Stream_Free(s, TRUE); } @@ -651,7 +561,7 @@ void rail_send_client_notify_event_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH); rail_write_client_notify_event_order(s, &rail_order->notify_event); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_NOTIFY_EVENT); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_NOTIFY_EVENT); Stream_Free(s, TRUE); } @@ -660,7 +570,7 @@ void rail_send_client_window_move_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH); rail_write_client_window_move_order(s, &rail_order->window_move); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_WINDOW_MOVE); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_WINDOWMOVE); Stream_Free(s, TRUE); } @@ -669,7 +579,7 @@ void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH); rail_write_client_get_appid_req_order(s, &rail_order->get_appid_req); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_GET_APPID_REQ); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_GET_APPID_REQ); Stream_Free(s, TRUE); } @@ -678,7 +588,7 @@ void rail_send_client_langbar_info_order(rdpRailOrder* rail_order) wStream* s; s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); rail_write_langbar_info_order(s, &rail_order->langbar_info); - rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_LANGBAR_INFO); + rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_LANGBARINFO); Stream_Free(s, TRUE); } @@ -688,12 +598,6 @@ rdpRailOrder* rail_order_new() rail_order = (rdpRailOrder*) malloc(sizeof(rdpRailOrder)); ZeroMemory(rail_order, sizeof(rdpRailOrder)); - - if (rail_order != NULL) - { - - } - return rail_order; } diff --git a/channels/rail/client/rail_orders.h b/channels/rail/client/rail_orders.h index 9c7f52a3d..c18ffd971 100644 --- a/channels/rail/client/rail_orders.h +++ b/channels/rail/client/rail_orders.h @@ -23,40 +23,6 @@ #include "rail_main.h" -#define RAIL_ORDER_TYPE_EXEC 0x0001 -#define RAIL_ORDER_TYPE_ACTIVATE 0x0002 -#define RAIL_ORDER_TYPE_SYSPARAM 0x0003 -#define RAIL_ORDER_TYPE_SYSCOMMAND 0x0004 -#define RAIL_ORDER_TYPE_HANDSHAKE 0x0005 -#define RAIL_ORDER_TYPE_NOTIFY_EVENT 0x0006 -#define RAIL_ORDER_TYPE_WINDOW_MOVE 0x0008 -#define RAIL_ORDER_TYPE_LOCALMOVESIZE 0x0009 -#define RAIL_ORDER_TYPE_MINMAXINFO 0x000A -#define RAIL_ORDER_TYPE_CLIENT_STATUS 0x000B -#define RAIL_ORDER_TYPE_SYSMENU 0x000C -#define RAIL_ORDER_TYPE_LANGBAR_INFO 0x000D -#define RAIL_ORDER_TYPE_EXEC_RESULT 0x0080 -#define RAIL_ORDER_TYPE_GET_APPID_REQ 0x000E -#define RAIL_ORDER_TYPE_GET_APPID_RESP 0x000F - -#define RAIL_PDU_HEADER_LENGTH 4 - -/* Fixed length of PDUs, excluding variable lengths */ -#define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */ -#define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */ -#define RAIL_EXEC_ORDER_LENGTH 8 /* variable */ -#define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */ -#define RAIL_ACTIVATE_ORDER_LENGTH 5 /* fixed */ -#define RAIL_SYSMENU_ORDER_LENGTH 8 /* fixed */ -#define RAIL_SYSCOMMAND_ORDER_LENGTH 6 /* fixed */ -#define RAIL_NOTIFY_EVENT_ORDER_LENGTH 12 /* fixed */ -#define RAIL_WINDOW_MOVE_ORDER_LENGTH 12 /* fixed */ -#define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */ -#define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */ - -void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string); - -BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake); BOOL rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec_result); BOOL rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam); BOOL rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo); @@ -64,7 +30,6 @@ BOOL rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* BOOL rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp); BOOL rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info); -void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake); void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client_status); void rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec); void rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam); diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c new file mode 100644 index 000000000..1f2c8d2e9 --- /dev/null +++ b/channels/rail/rail_common.c @@ -0,0 +1,102 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RAIL common functions + * + * Copyright 2011 Marc-Andre Moreau + * Copyright 2011 Roman Barabanov + * Copyright 2011 Vic Lee + * + * 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 "rail_common.h" + +#include + +const char* const RAIL_ORDER_TYPE_STRINGS[] = +{ + "", + "Execute", + "Activate", + "System Parameters Update", + "System Command", + "Handshake", + "Notify Event", + "", + "Window Move", + "Local Move/Size", + "Min Max Info", + "Client Status", + "System Menu", + "Language Bar Info", + "Get Application ID Request", + "Get Application ID Response", + "Execute Result" +}; + + +void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_string) +{ + WCHAR* buffer = NULL; + int length = 0; + + if (unicode_string->string != NULL) + free(unicode_string->string); + + unicode_string->string = NULL; + unicode_string->length = 0; + + if (string == NULL || strlen(string) < 1) + return; + + length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2; + + unicode_string->string = (BYTE*) buffer; + unicode_string->length = (UINT16) length; +} + +BOOL rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength) +{ + if (Stream_GetRemainingLength(s) < 4) + return FALSE; + Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ + Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ + return TRUE; +} + +void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength) +{ + Stream_Write_UINT16(s, orderType); /* orderType (2 bytes) */ + Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */ +} + +wStream* rail_pdu_init(int length) +{ + wStream* s; + s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH); + Stream_Seek(s, RAIL_PDU_HEADER_LENGTH); + return s; +} + +BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) +{ + if (Stream_GetRemainingLength(s) < 4) + return FALSE; + Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ + return TRUE; +} + +void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) +{ + Stream_Write_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ +} + diff --git a/channels/rail/rail_common.h b/channels/rail/rail_common.h new file mode 100644 index 000000000..446de5a58 --- /dev/null +++ b/channels/rail/rail_common.h @@ -0,0 +1,82 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RAIL Virtual Channel Plugin + * + * Copyright 2011 Marc-Andre Moreau + * Copyright 2011 Roman Barabanov + * Copyright 2011 Vic Lee + * + * 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 FREERDP_CHANNEL_RAIL_COMMON_H +#define FREERDP_CHANNEL_RAIL_COMMON_H + +#include + +#ifdef WITH_DEBUG_RAIL +#define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__) +#else +#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +extern const char* const RAIL_ORDER_TYPE_STRINGS[]; + + +#define RAIL_PDU_HEADER_LENGTH 4 + +/* Fixed length of PDUs, excluding variable lengths */ +#define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */ +#define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */ +#define RAIL_EXEC_ORDER_LENGTH 8 /* variable */ +#define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */ +#define RAIL_ACTIVATE_ORDER_LENGTH 5 /* fixed */ +#define RAIL_SYSMENU_ORDER_LENGTH 8 /* fixed */ +#define RAIL_SYSCOMMAND_ORDER_LENGTH 6 /* fixed */ +#define RAIL_NOTIFY_EVENT_ORDER_LENGTH 12 /* fixed */ +#define RAIL_WINDOW_MOVE_ORDER_LENGTH 12 /* fixed */ +#define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */ +#define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */ + +struct rdp_rail_order +{ + rdpSettings* settings; + void* plugin; + RAIL_HANDSHAKE_ORDER handshake; + RAIL_CLIENT_STATUS_ORDER client_status; + RAIL_EXEC_ORDER exec; + RAIL_EXEC_RESULT_ORDER exec_result; + RAIL_SYSPARAM_ORDER sysparam; + RAIL_ACTIVATE_ORDER activate; + RAIL_SYSMENU_ORDER sysmenu; + RAIL_SYSCOMMAND_ORDER syscommand; + RAIL_NOTIFY_EVENT_ORDER notify_event; + RAIL_MINMAXINFO_ORDER minmaxinfo; + RAIL_LOCALMOVESIZE_ORDER localmovesize; + RAIL_WINDOW_MOVE_ORDER window_move; + RAIL_LANGBAR_INFO_ORDER langbar_info; + RAIL_GET_APPID_REQ_ORDER get_appid_req; + RAIL_GET_APPID_RESP_ORDER get_appid_resp; +}; +typedef struct rdp_rail_order rdpRailOrder; + + +void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_string); +BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake); +void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake); + +wStream* rail_pdu_init(int length); +BOOL rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength); +void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength); + +#endif /* FREERDP_CHANNEL_RAIL_COMMON_H */ diff --git a/include/freerdp/rail.h b/include/freerdp/rail.h index 08225c0de..847529d06 100644 --- a/include/freerdp/rail.h +++ b/include/freerdp/rail.h @@ -157,13 +157,13 @@ struct _RAIL_UNICODE_STRING }; typedef struct _RAIL_UNICODE_STRING RAIL_UNICODE_STRING; -struct _HIGH_CONTRAST +struct _RAIL_HIGH_CONTRAST { UINT32 flags; UINT32 colorSchemeLength; RAIL_UNICODE_STRING colorScheme; }; -typedef struct _HIGH_CONTRAST HIGH_CONTRAST; +typedef struct _RAIL_HIGH_CONTRAST RAIL_HIGH_CONTRAST; /* RAIL Orders */ @@ -208,7 +208,7 @@ struct _RAIL_SYSPARAM_ORDER RECTANGLE_16 workArea; RECTANGLE_16 displayChange; RECTANGLE_16 taskbarPos; - HIGH_CONTRAST highContrast; + RAIL_HIGH_CONTRAST highContrast; BOOL setScreenSaveActive; BOOL setScreenSaveSecure; }; From de6fa579de33b08295d6a88e6477cd512537b289 Mon Sep 17 00:00:00 2001 From: ilammy Date: Fri, 30 Aug 2013 19:02:02 +0300 Subject: [PATCH 09/14] Fixed invalid reallocations --- libfreerdp/common/settings.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 59eeb92e8..f790bd260 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -138,7 +138,8 @@ void freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device) if (settings->DeviceArraySize < (settings->DeviceCount + 1)) { settings->DeviceArraySize *= 2; - settings->DeviceArray = (RDPDR_DEVICE**) realloc(settings->DeviceArray, settings->DeviceArraySize); + settings->DeviceArray = (RDPDR_DEVICE**) + realloc(settings->DeviceArray, settings->DeviceArraySize * sizeof(RDPDR_DEVICE*)); } settings->DeviceArray[settings->DeviceCount++] = device; @@ -208,7 +209,7 @@ void freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* ch { settings->StaticChannelArraySize *= 2; settings->StaticChannelArray = (ADDIN_ARGV**) - realloc(settings->StaticChannelArray, settings->StaticChannelArraySize); + realloc(settings->StaticChannelArray, settings->StaticChannelArraySize * sizeof(ADDIN_ARGV*)); } settings->StaticChannelArray[settings->StaticChannelCount++] = channel; @@ -256,7 +257,7 @@ void freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* c { settings->DynamicChannelArraySize *= 2; settings->DynamicChannelArray = (ADDIN_ARGV**) - realloc(settings->DynamicChannelArray, settings->DynamicChannelArraySize); + realloc(settings->DynamicChannelArray, settings->DynamicChannelArraySize * sizeof(ADDIN_ARGV*)); } settings->DynamicChannelArray[settings->DynamicChannelCount++] = channel; From 2802efd52a44b269813ab94051e9e04dbebf42b5 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 2 Sep 2013 18:07:55 +0200 Subject: [PATCH 10/14] fastpath: fixed sending of multiple input messages --- libfreerdp/core/fastpath.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 67106c7b7..5b05b995b 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -711,6 +711,14 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu BYTE eventHeader; int sec_bytes; + /* + * A maximum of 15 events are allowed per request + * if the optional numEvents field isn't used + * see MS-RDPBCGR 2.2.8.1.2 for details + */ + if (iNumEvents > 15) + return FALSE; + rdp = fastpath->rdp; length = Stream_GetPosition(s); @@ -722,7 +730,7 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu } eventHeader = FASTPATH_INPUT_ACTION_FASTPATH; - eventHeader |= (1 << 2); /* numberEvents */ + eventHeader |= (iNumEvents << 2); /* numberEvents */ if (rdp->sec_flags & SEC_ENCRYPT) eventHeader |= (FASTPATH_INPUT_ENCRYPTED << 6); From 63856f26cfe34ab0ffcd016b42aa6d3c2173ca4d Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 2 Sep 2013 19:43:57 +0200 Subject: [PATCH 11/14] cmd line: fixed description --- client/common/cmdline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index ce14ab125..0faf2f6f2 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -66,7 +66,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "gp", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway password" }, { "gd", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway domain" }, { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Load balance info" }, - { "app", COMMAND_LINE_VALUE_REQUIRED, "|| or ", NULL, NULL, -1, NULL, "Remote application program" }, + { "app", COMMAND_LINE_VALUE_REQUIRED, " or <||alias>", NULL, NULL, -1, NULL, "Remote application program" }, { "app-name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Remote application name for user interface" }, { "app-icon", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Remote application icon for user interface" }, { "app-cmd", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Remote application command-line parameters" }, From 1d660cb217de3f884ec4cb7251611dc05827bf88 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 2 Sep 2013 19:53:31 +0200 Subject: [PATCH 12/14] cmd: fixed some compatibility messages closes #1442 --- client/common/compatibility.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/common/compatibility.c b/client/common/compatibility.c index 788b41354..40f7a326e 100644 --- a/client/common/compatibility.c +++ b/client/common/compatibility.c @@ -517,7 +517,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe settings->PerformanceFlags = type; } - fprintf(stderr, "-x %s -> /network ", arg->Value); + fprintf(stderr, "-x %s -> /network:", arg->Value); if (type == CONNECTION_TYPE_MODEM) fprintf(stderr, "modem"); @@ -541,7 +541,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe CommandLineSwitchCase(arg, "app") { settings->RemoteApplicationMode = TRUE; - fprintf(stderr, "--app -> /app + program name or alias\n"); + fprintf(stderr, "--app -> /app: + program name or alias\n"); } CommandLineSwitchCase(arg, "ext") { @@ -606,7 +606,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe else if (arg->Value[0] == 'i') settings->RemoteFxCodecMode = 0x02; - fprintf(stderr, "--rfx-mode -> /rfx-mode\n"); + fprintf(stderr, "--rfx-mode -> /rfx-mode:%s\n", settings->RemoteFxCodecMode ? "image" : "video"); } CommandLineSwitchCase(arg, "nsc") { From b04544121cb5696041ae01f9ad4d07d77aaddc0a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 3 Sep 2013 19:09:53 +0800 Subject: [PATCH 13/14] server: fix double demand active pdu during reactivation. --- libfreerdp/core/connection.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index e2cfdc283..0a081ad47 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -975,6 +975,8 @@ BOOL rdp_server_reactivate(rdpRdp* rdp) if (!rdp_send_demand_active(rdp)) return FALSE; + rdp->AwaitCapabilities = TRUE; + return TRUE; } From 86e783e4fb9e6ccd65013966fe92d0f8a7d74a8f Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 3 Sep 2013 20:27:08 +0800 Subject: [PATCH 14/14] libfreerdp-codec/rfx: fix memory corruptions. --- include/freerdp/codec/rfx.h | 1 + libfreerdp/codec/rfx.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 254cadfb5..57f4fed44 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -55,6 +55,7 @@ struct _RFX_TILE int height; BYTE* data; int scanline; + BOOL allocated; BYTE quantIdxY; BYTE quantIdxCb; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 5d6bbe7a1..0cbcbd0d8 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -164,6 +164,7 @@ RFX_TILE* rfx_tile_new() ZeroMemory(tile, sizeof(RFX_TILE)); tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ + tile->allocated = TRUE; } return tile; @@ -173,7 +174,8 @@ void rfx_tile_free(RFX_TILE* tile) { if (tile) { - free(tile->data); + if (tile->allocated) + free(tile->data); free(tile); } } @@ -1065,7 +1067,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, if (!context->numQuant) { context->numQuant = 1; - context->quants = (UINT32*) rfx_default_quantization_values; + context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values)); + memcpy(context->quants, rfx_default_quantization_values, sizeof(rfx_default_quantization_values)); context->quantIdxY = 0; context->quantIdxCb = 0; context->quantIdxCr = 0; @@ -1111,6 +1114,11 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, ax = rect->x + tile->x; ay = rect->y + tile->y; + if (tile->data && tile->allocated) + { + free(tile->data); + tile->allocated = FALSE; + } tile->data = &data[(ay * scanline) + (ax * BytesPerPixel)]; tile->quantIdxY = context->quantIdxY;