From d8e10ac04af887d2cd7b32c179a4768dee62f753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 11 Dec 2014 11:25:34 -0500 Subject: [PATCH 1/3] freerdp: patch leaks reported by valgrind when using TS Gateway --- client/common/client.c | 6 +++ docs/valgrind.supp | 44 +++++++++++++++++++ libfreerdp/core/gateway/http.c | 23 +++++++--- libfreerdp/core/gateway/ncacn_http.c | 10 +++-- libfreerdp/core/gateway/ntlm.c | 11 ++++- libfreerdp/core/gateway/rpc.c | 37 ++++++++++++---- libfreerdp/core/gateway/rpc_bind.c | 7 +++ libfreerdp/core/gateway/rpc_client.c | 17 +++---- libfreerdp/core/gateway/rts.c | 1 + libfreerdp/core/gateway/tsg.c | 11 ++++- libfreerdp/core/settings.c | 4 ++ libfreerdp/core/transport.c | 17 ++++++- .../utils/collections/ListDictionary.c | 2 + 13 files changed, 156 insertions(+), 34 deletions(-) diff --git a/client/common/client.c b/client/common/client.c index 86eed62c5..3c09b6703 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -112,19 +112,25 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings) { if (settings->Username) { + free(settings->GatewayUsername); settings->GatewayUsername = _strdup(settings->Username); + if (!settings->GatewayUsername) goto out_error; } if (settings->Domain) { + free(settings->GatewayDomain); settings->GatewayDomain = _strdup(settings->Domain); + if (!settings->GatewayDomain) goto out_error; } if (settings->Password) { + free(settings->GatewayPassword); settings->GatewayPassword = _strdup(settings->Password); + if (!settings->GatewayPassword) goto out_error; } diff --git a/docs/valgrind.supp b/docs/valgrind.supp index 440d92c6b..2ce34e870 100644 --- a/docs/valgrind.supp +++ b/docs/valgrind.supp @@ -81,3 +81,47 @@ fun:ssl3_write_pending fun:ssl3_write_bytes } + +{ + g_type_init + Memcheck:Leak + ... + fun:g_type_init_with_debug_flags +} +{ + gobject_init_ctor + Memcheck:Leak + ... + fun:gobject_init_ctor +} +{ + g_type_register_static + Memcheck:Leak + ... + fun:g_type_register_static +} +{ + g_type_register_fundamental + Memcheck:Leak + ... + fun:g_type_register_fundamental +} +{ + g_type_add_interface_static + Memcheck:Leak + ... + fun:g_type_add_interface_static +} +{ + g_type_class_ref + Memcheck:Leak + ... + fun:g_type_class_ref +} + +{ + XGetDefault + Memcheck:Leak + ... + fun:XGetDefault +} diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index 8eb3898bc..7fb91d1e4 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -360,17 +360,21 @@ BOOL http_response_parse_header_status_line(HttpResponse* http_response, char* s BOOL http_response_parse_header_field(HttpResponse* http_response, char* name, char* value) { + BOOL status = TRUE; + if (_stricmp(name, "Content-Length") == 0) { http_response->ContentLength = atoi(value); } else if (_stricmp(name, "WWW-Authenticate") == 0) { - char* separator; - char* authScheme, *authValue; + char* separator = NULL; + char* authScheme = NULL; + char* authValue = NULL; + separator = strchr(value, ' '); - if (separator != NULL) + if (separator) { /* WWW-Authenticate: Basic realm="" * WWW-Authenticate: NTLM base64token @@ -397,10 +401,12 @@ BOOL http_response_parse_header_field(HttpResponse* http_response, char* name, c authValue = NULL; } - return ListDictionary_Add(http_response->Authenticates, authScheme, authValue); + status = ListDictionary_Add(http_response->Authenticates, authScheme, authValue); + + free(authScheme); } - return TRUE; + return status; } BOOL http_response_parse_header(HttpResponse* http_response) @@ -498,6 +504,7 @@ HttpResponse* http_response_recv(rdpTls* tls) nbytes = 0; length = 10000; content = NULL; + buffer = calloc(length, 1); if (!buffer) @@ -637,16 +644,19 @@ static void string_free(void* obj1) HttpResponse* http_response_new() { - HttpResponse* ret = (HttpResponse*)calloc(1, sizeof(HttpResponse)); + HttpResponse* ret = (HttpResponse*) calloc(1, sizeof(HttpResponse)); if (!ret) return NULL; ret->Authenticates = ListDictionary_New(FALSE); + ListDictionary_KeyObject(ret->Authenticates)->fnObjectEquals = strings_equals_nocase; ListDictionary_KeyObject(ret->Authenticates)->fnObjectFree = string_free; + ListDictionary_ValueObject(ret->Authenticates)->fnObjectEquals = strings_equals_nocase; ListDictionary_ValueObject(ret->Authenticates)->fnObjectFree = string_free; + return ret; } @@ -665,6 +675,7 @@ void http_response_free(HttpResponse* http_response) free(http_response->lines); free(http_response->ReasonPhrase); + ListDictionary_Free(http_response->Authenticates); if (http_response->ContentLength > 0) diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index b5beff4b2..d06e9d24e 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -222,18 +222,20 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc) int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) { int ntlm_token_length = 0; - BYTE* ntlm_token_data; + BYTE* ntlm_token_data = NULL; HttpResponse* http_response; rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm; http_response = http_response_recv(rpc->TlsOut); ntlm_token_data = NULL; + if (http_response && ListDictionary_Contains(http_response->Authenticates, "NTLM")) { - char *token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); + char* token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length); } + ntlm->inputBuffer[0].pvBuffer = ntlm_token_data; ntlm->inputBuffer[0].cbBuffer = ntlm_token_length; @@ -298,16 +300,18 @@ rdpNtlmHttp* ntlm_http_new() { rdpNtlmHttp* ntlm_http; - ntlm_http = (rdpNtlmHttp *)calloc(1, sizeof(rdpNtlmHttp)); + ntlm_http = (rdpNtlmHttp*) calloc(1, sizeof(rdpNtlmHttp)); if (!ntlm_http) return NULL; ntlm_http->ntlm = ntlm_new(); + if (!ntlm_http->ntlm) goto out_free; ntlm_http->context = http_context_new(); + if (!ntlm_http->context) goto out_free_ntlm; diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index eeb2500f6..5ce2b162b 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -217,6 +217,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm) ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN; ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken; ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer); + if (!ntlm->outputBuffer[0].pvBuffer) return FALSE; @@ -295,13 +296,19 @@ void ntlm_client_uninit(rdpNtlm* ntlm) rdpNtlm* ntlm_new() { - return (rdpNtlm *)calloc(1, sizeof(rdpNtlm)); + return (rdpNtlm*) calloc(1, sizeof(rdpNtlm)); } void ntlm_free(rdpNtlm* ntlm) { - if (ntlm != NULL) + if (ntlm) { + if (ntlm->outputBuffer[0].pvBuffer) + { + free(ntlm->outputBuffer[0].pvBuffer); + ntlm->outputBuffer[0].pvBuffer = NULL; + } + free(ntlm); } } diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 4d4c67503..039fc5d86 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -519,12 +519,12 @@ RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc) return NULL; connection->State = VIRTUAL_CONNECTION_STATE_INITIAL; - connection->DefaultInChannel = (RpcInChannel*)calloc(1, sizeof(RpcInChannel)); + connection->DefaultInChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel)); if (!connection->DefaultInChannel) goto out_free; - connection->DefaultOutChannel = (RpcOutChannel*)calloc(1, sizeof(RpcOutChannel)); + connection->DefaultOutChannel = (RpcOutChannel*) calloc(1, sizeof(RpcOutChannel)); if (!connection->DefaultOutChannel) goto out_default_in; @@ -538,13 +538,15 @@ out_free: return NULL; } -void rpc_client_virtual_connection_free(RpcVirtualConnection* virtual_connection) +void rpc_client_virtual_connection_free(RpcVirtualConnection* virtualConnection) { - if (virtual_connection != NULL) + if (virtualConnection) { - free(virtual_connection->DefaultInChannel); - free(virtual_connection->DefaultOutChannel); - free(virtual_connection); + CloseHandle(virtualConnection->DefaultInChannel->Mutex); + CloseHandle(virtualConnection->DefaultOutChannel->Mutex); + free(virtualConnection->DefaultInChannel); + free(virtualConnection->DefaultOutChannel); + free(virtualConnection); } } @@ -559,6 +561,7 @@ rdpRpc* rpc_new(rdpTransport* transport) rpc->transport = transport; rpc->settings = transport->settings; rpc->SendSeqNum = 0; + rpc->ntlm = ntlm_new(); if (!rpc->ntlm) @@ -576,6 +579,7 @@ rdpRpc* rpc_new(rdpTransport* transport) rpc_ntlm_http_init_channel(rpc, rpc->NtlmHttpIn, TSG_CHANNEL_IN); rpc_ntlm_http_init_channel(rpc, rpc->NtlmHttpOut, TSG_CHANNEL_OUT); + rpc->PipeCallId = 0; rpc->StubCallId = 0; rpc->StubFragCount = 0; @@ -594,6 +598,7 @@ rdpRpc* rpc_new(rdpTransport* transport) rpc->KeepAliveInterval = 300000; rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval; rpc->CurrentKeepAliveTime = 0; + rpc->VirtualConnection = rpc_client_virtual_connection_new(rpc); if (!rpc->VirtualConnection) @@ -630,19 +635,33 @@ out_free: void rpc_free(rdpRpc* rpc) { - if (rpc != NULL) + if (rpc) { rpc_client_stop(rpc); - if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED) + if (rpc->ntlm) { ntlm_client_uninit(rpc->ntlm); ntlm_free(rpc->ntlm); + rpc->ntlm = NULL; + } + + if (rpc->NtlmHttpIn) + { + ntlm_http_free(rpc->NtlmHttpIn); + rpc->NtlmHttpIn = NULL; + } + + if (rpc->NtlmHttpOut) + { + ntlm_http_free(rpc->NtlmHttpOut); + rpc->NtlmHttpOut = NULL; } rpc_client_virtual_connection_free(rpc->VirtualConnection); ArrayList_Clear(rpc->VirtualConnectionCookieTable); ArrayList_Free(rpc->VirtualConnectionCookieTable); + free(rpc); } } diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c index a2679d426..6e982e88a 100644 --- a/libfreerdp/core/gateway/rpc_bind.c +++ b/libfreerdp/core/gateway/rpc_bind.c @@ -105,7 +105,14 @@ int rpc_send_bind_pdu(rdpRpc* rpc) DEBUG_RPC("Sending bind PDU"); + if (rpc->ntlm) + { + ntlm_free(rpc->ntlm); + rpc->ntlm = NULL; + } + rpc->ntlm = ntlm_new(); + if (!rpc->ntlm) return -1; diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 4a5544e37..4213a8424 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -547,20 +547,15 @@ static void rpc_fragment_free(wStream* fragment) int rpc_client_new(rdpRpc* rpc) { - RpcClient* client = NULL; - client = (RpcClient*)calloc(1, sizeof(RpcClient)); + RpcClient* client; + + client = (RpcClient*) calloc(1, sizeof(RpcClient)); + rpc->client = client; if (!client) return -1; - client->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rpc_client_thread, - rpc, CREATE_SUSPENDED, NULL); - - if (!client->Thread) - return -1; - client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!client->StopEvent) @@ -615,8 +610,8 @@ int rpc_client_new(rdpRpc* rpc) int rpc_client_start(rdpRpc* rpc) { rpc->client->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rpc_client_thread, - rpc, 0, NULL); + (LPTHREAD_START_ROUTINE) rpc_client_thread, rpc, 0, NULL); + return 0; } diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index a4d20f460..4652d6a97 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -212,6 +212,7 @@ BOOL rts_connect(rdpRpc* rpc) rpc_client_start(rpc); pdu = rpc_recv_dequeue_pdu(rpc); + if (!pdu) return FALSE; diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index cdd7d098f..923f2a39e 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -1142,13 +1142,20 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port) RpcClientCall* call; rdpRpc* rpc = tsg->rpc; rdpSettings* settings = rpc->settings; + tsg->Port = port; + + free(tsg->Hostname); + tsg->Hostname = NULL; ConvertToUnicode(CP_UTF8, 0, hostname, -1, &tsg->Hostname, 0); + + free(tsg->MachineName); + tsg->MachineName = NULL; ConvertToUnicode(CP_UTF8, 0, settings->ComputerName, -1, &tsg->MachineName, 0); if (!rpc_connect(rpc)) { - WLog_ERR(TAG, "rpc_connect failed!"); + WLog_ERR(TAG, "rpc_connect failed!"); return FALSE; } @@ -1518,6 +1525,7 @@ BOOL tsg_set_blocking_mode(rdpTsg* tsg, BOOL blocking) rdpTsg* tsg_new(rdpTransport* transport) { rdpTsg* tsg; + tsg = (rdpTsg*) calloc(1, sizeof(rdpTsg)); if (!tsg) @@ -1541,6 +1549,7 @@ void tsg_free(rdpTsg* tsg) { if (tsg) { + free(tsg->Hostname); free(tsg->MachineName); rpc_free(tsg->rpc); free(tsg); diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index eabb8436d..8795b5fd1 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -685,6 +685,10 @@ void freerdp_settings_free(rdpSettings* settings) free(settings->RedirectionTsvUrl); free(settings->RemoteAssistanceSessionId); free(settings->AuthenticationServiceClass); + free(settings->GatewayHostname); + free(settings->GatewayUsername); + free(settings->GatewayPassword); + free(settings->GatewayDomain); freerdp_target_net_addresses_free(settings); freerdp_device_collection_free(settings); freerdp_static_channel_collection_free(settings); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index fc2158a12..c26686daf 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -356,6 +356,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16 rdpSettings* settings = transport->settings; instance = (freerdp*) transport->settings->instance; context = instance->context; + tsg = tsg_new(transport); if (!tsg) @@ -1254,9 +1255,21 @@ void transport_free(rdpTransport* transport) transport->TcpIn = NULL; transport->TcpOut = NULL; - tsg_free(transport->tsg); - transport->tsg = NULL; + + if (transport->tsg) + { + tsg_free(transport->tsg); + transport->tsg = NULL; + } + + if (transport->TsgTls) + { + tls_free(transport->TsgTls); + transport->TsgTls = NULL; + } + DeleteCriticalSection(&(transport->ReadLock)); DeleteCriticalSection(&(transport->WriteLock)); + free(transport); } diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index a0690d804..c1733a45b 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -181,6 +181,7 @@ BOOL ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) EnterCriticalSection(&listDictionary->lock); item = (wListDictionaryItem*) malloc(sizeof(wListDictionaryItem)); + if (!item) return FALSE; @@ -205,6 +206,7 @@ BOOL ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) if (listDictionary->synchronized) LeaveCriticalSection(&listDictionary->lock); + return TRUE; } From cc2321d359fbb72fa5cd1d8c0c0e3ccee6cbf8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 11 Dec 2014 17:08:22 -0500 Subject: [PATCH 2/3] libfreerdp-core: fix leak and use after free in tsg ListDictionary usage --- libfreerdp/core/gateway/http.c | 6 ++--- libfreerdp/core/gateway/ncacn_http.c | 22 ++++++++++++------- libfreerdp/core/gateway/rts.c | 22 ++++++++++--------- libfreerdp/core/gateway/rts.h | 11 ---------- .../utils/collections/ListDictionary.c | 5 +++++ 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index 7fb91d1e4..9e3aadf9c 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -402,8 +402,6 @@ BOOL http_response_parse_header_field(HttpResponse* http_response, char* name, c } status = ListDictionary_Add(http_response->Authenticates, authScheme, authValue); - - free(authScheme); } return status; @@ -571,7 +569,7 @@ HttpResponse* http_response_recv(rdpTls* tls) if (count) { - http_response->lines = (char**)calloc(http_response->count, sizeof(char*)); + http_response->lines = (char**) calloc(http_response->count, sizeof(char*)); if (!http_response->lines) goto out_error; @@ -598,7 +596,7 @@ HttpResponse* http_response_recv(rdpTls* tls) if (http_response->bodyLen > 0) { - http_response->BodyContent = (BYTE*)malloc(http_response->bodyLen); + http_response->BodyContent = (BYTE*) malloc(http_response->bodyLen); if (!http_response->BodyContent) goto out_error; diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index d06e9d24e..d9bdf48d8 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -92,18 +92,21 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc) int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc) { + char* token64; int ntlm_token_length = 0; BYTE* ntlm_token_data = NULL; HttpResponse* http_response; rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm; http_response = http_response_recv(rpc->TlsIn); + if (!http_response) return -1; if (ListDictionary_Contains(http_response->Authenticates, "NTLM")) { - char *token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); + token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); + if (!token64) goto out; @@ -135,7 +138,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) if (instance->GatewayAuthenticate) { BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, - &settings->GatewayPassword, &settings->GatewayDomain); + &settings->GatewayPassword, &settings->GatewayDomain); if (!proceed) { @@ -170,8 +173,8 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc) { - rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm; BOOL success = FALSE; + rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm; if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) == 1) { @@ -221,6 +224,7 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc) int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) { + char* token64; int ntlm_token_length = 0; BYTE* ntlm_token_data = NULL; HttpResponse* http_response; @@ -228,11 +232,12 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) http_response = http_response_recv(rpc->TlsOut); - ntlm_token_data = NULL; + if (!http_response) + return -1; - if (http_response && ListDictionary_Contains(http_response->Authenticates, "NTLM")) + if (ListDictionary_Contains(http_response->Authenticates, "NTLM")) { - char* token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); + token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length); } @@ -240,6 +245,7 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) ntlm->inputBuffer[0].cbBuffer = ntlm_token_length; http_response_free(http_response); + return 0; } @@ -287,11 +293,11 @@ void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL if (channel == TSG_CHANNEL_IN) { - http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); + http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); } else if (channel == TSG_CHANNEL_OUT) { - http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " + http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); } } diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 4652d6a97..b9e2ead5e 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -65,6 +65,8 @@ BOOL rts_connect(rdpRpc* rpc) RPC_PDU* pdu; rpcconn_rts_hdr_t* rts; HttpResponse* http_response; + freerdp* instance = (freerdp*) rpc->settings->instance; + rdpContext* context = instance->context; /** * Connection Opening @@ -90,7 +92,7 @@ BOOL rts_connect(rdpRpc* rpc) */ rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_INITIAL; - DEBUG_RTS("VIRTUAL_CONNECTION_STATE_INITIAL"); + WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_INITIAL"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; @@ -120,7 +122,7 @@ BOOL rts_connect(rdpRpc* rpc) } rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT; - DEBUG_RTS("VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT"); + WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT"); /** * Receive OUT Channel Response @@ -170,9 +172,9 @@ BOOL rts_connect(rdpRpc* rpc) connectErrorCode = AUTHENTICATIONERROR; } - if (!freerdp_get_last_error(((freerdp*)(rpc->settings->instance))->context)) + if (!freerdp_get_last_error(context)) { - freerdp_set_last_error(((freerdp*)(rpc->settings->instance))->context, FREERDP_ERROR_AUTHENTICATION_FAILED); + freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED); } } @@ -191,7 +193,7 @@ BOOL rts_connect(rdpRpc* rpc) http_response_free(http_response); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W; - DEBUG_RTS("VIRTUAL_CONNECTION_STATE_WAIT_A3W"); + WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_A3W"); /** * Receive CONN_A3 RTS PDU @@ -229,7 +231,7 @@ BOOL rts_connect(rdpRpc* rpc) rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_C2; - DEBUG_RTS("VIRTUAL_CONNECTION_STATE_WAIT_C2"); + WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_C2"); /** * Receive CONN_C2 RTS PDU @@ -269,7 +271,7 @@ BOOL rts_connect(rdpRpc* rpc) rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OPENED; - DEBUG_RTS("VIRTUAL_CONNECTION_STATE_OPENED"); + WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OPENED"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; @@ -720,7 +722,7 @@ int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) rts_connection_timeout_command_read(rpc, &buffer[24], length - 24, &ConnectionTimeout); - DEBUG_RTS("ConnectionTimeout: %d", ConnectionTimeout); + WLog_DBG(TAG, "ConnectionTimeout: %d", ConnectionTimeout); rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout; @@ -787,8 +789,8 @@ int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) offset += rts_receive_window_size_command_read(rpc, &buffer[offset], length - offset, &ReceiveWindowSize) + 4; offset += rts_connection_timeout_command_read(rpc, &buffer[offset], length - offset, &ConnectionTimeout) + 4; - DEBUG_RTS("ConnectionTimeout: %d", ConnectionTimeout); - DEBUG_RTS("ReceiveWindowSize: %d", ReceiveWindowSize); + WLog_DBG(TAG, "ConnectionTimeout: %d", ConnectionTimeout); + WLog_DBG(TAG, "ReceiveWindowSize: %d", ReceiveWindowSize); /* TODO: verify if this is the correct protocol variable */ rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout; diff --git a/libfreerdp/core/gateway/rts.h b/libfreerdp/core/gateway/rts.h index a0fd620a9..f1c60c57a 100644 --- a/libfreerdp/core/gateway/rts.h +++ b/libfreerdp/core/gateway/rts.h @@ -143,15 +143,4 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); #include "rts_signature.h" -#ifdef WITH_DEBUG_TSG -#define WITH_DEBUG_RTS -#endif - -#define RTS_TAG FREERDP_TAG("core.gateway.rts") -#ifdef WITH_DEBUG_RTS -#define DEBUG_RTS(fmt, ...) WLog_DBG(RTS_TAG, fmt, ## __VA_ARGS__) -#else -#define DEBUG_RTS(fmt, ...) do { } while (0) -#endif - #endif /* FREERDP_CORE_RTS_H */ diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index c1733a45b..7f922dfe6 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -229,8 +229,13 @@ void ListDictionary_Clear(wListDictionary* listDictionary) while (item) { nextItem = item->next; + + if (listDictionary->objectKey.fnObjectFree) + listDictionary->objectKey.fnObjectFree(item->key); + if (listDictionary->objectValue.fnObjectFree) listDictionary->objectValue.fnObjectFree(item->value); + free(item); item = nextItem; } From aa23c4eaaae2f4ad1aa8fd28516a271e387b249a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 12 Dec 2014 09:08:39 -0500 Subject: [PATCH 3/3] libfreerdp-core: fix random TS Gateway disconnects with async modes --- libfreerdp/core/gateway/rpc_client.c | 2 +- libfreerdp/core/transport.c | 19 +++- winpr/libwinpr/winsock/winsock.c | 143 ++++++++++++++++++++++++++- 3 files changed, 153 insertions(+), 11 deletions(-) diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 4213a8424..1bec237e2 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -131,7 +131,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc) return 0; } - WLog_ERR(TAG, "Receiving Out-of-Sequence RTS PDU"); + WLog_DBG(TAG, "Receiving Out-of-Sequence RTS PDU"); rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length); rpc_client_fragment_pool_return(rpc, fragment); return 0; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index c26686daf..abcbfe1fe 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -120,15 +121,21 @@ long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, static int transport_bio_tsg_write(BIO* bio, const char* buf, int num) { int status; - rdpTsg* tsg; - tsg = (rdpTsg*) bio->ptr; + rdpTsg* tsg = (rdpTsg*) bio->ptr; + BIO_clear_flags(bio, BIO_FLAGS_WRITE); + status = tsg_write(tsg, (BYTE*) buf, num); if (status < 0) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); } + else if (status == 0) + { + BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); + WSASetLastError(WSAEWOULDBLOCK); + } else { BIO_set_flags(bio, BIO_FLAGS_WRITE); @@ -140,10 +147,11 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num) static int transport_bio_tsg_read(BIO* bio, char* buf, int size) { int status; - rdpTsg* tsg; - tsg = (rdpTsg*) bio->ptr; + rdpTsg* tsg = (rdpTsg*) bio->ptr; + BIO_clear_flags(bio, BIO_FLAGS_READ); - status = tsg_read(bio->ptr, (BYTE*) buf, size); + + status = tsg_read(tsg, (BYTE*) buf, size); if (status < 0) { @@ -152,6 +160,7 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size) else if (status == 0) { BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); + WSASetLastError(WSAEWOULDBLOCK); } else { diff --git a/winpr/libwinpr/winsock/winsock.c b/winpr/libwinpr/winsock/winsock.c index 71a64d2d4..89439da7b 100644 --- a/winpr/libwinpr/winsock/winsock.c +++ b/winpr/libwinpr/winsock/winsock.c @@ -276,7 +276,145 @@ int WSACleanup(void) void WSASetLastError(int iError) { + switch (iError) + { + /* Base error codes */ + case WSAEINTR: + errno = EINTR; + break; + case WSAEBADF: + errno = EBADF; + break; + case WSAEACCES: + errno = EACCES; + break; + case WSAEFAULT: + errno = EFAULT; + break; + case WSAEINVAL: + errno = EINVAL; + break; + case WSAEMFILE: + errno = EMFILE; + break; + + /* BSD sockets error codes */ + + case WSAEWOULDBLOCK: + errno = EWOULDBLOCK; + break; + case WSAEINPROGRESS: + errno = EINPROGRESS; + break; + case WSAEALREADY: + errno = EALREADY; + break; + case WSAENOTSOCK: + errno = ENOTSOCK; + break; + case WSAEDESTADDRREQ: + errno = EDESTADDRREQ; + break; + case WSAEMSGSIZE: + errno = EMSGSIZE; + break; + case WSAEPROTOTYPE: + errno = EPROTOTYPE; + break; + case WSAENOPROTOOPT: + errno = ENOPROTOOPT; + break; + case WSAEPROTONOSUPPORT: + errno = EPROTONOSUPPORT; + break; + case WSAESOCKTNOSUPPORT: + errno = ESOCKTNOSUPPORT; + break; + case WSAEOPNOTSUPP: + errno = EOPNOTSUPP; + break; + case WSAEPFNOSUPPORT: + errno = EPFNOSUPPORT; + break; + case WSAEAFNOSUPPORT: + errno = EAFNOSUPPORT; + break; + case WSAEADDRINUSE: + errno = EADDRINUSE; + break; + case WSAEADDRNOTAVAIL: + errno = EADDRNOTAVAIL; + break; + case WSAENETDOWN: + errno = ENETDOWN; + break; + case WSAENETUNREACH: + errno = ENETUNREACH; + break; + case WSAENETRESET: + errno = ENETRESET; + break; + case WSAECONNABORTED: + errno = ECONNABORTED; + break; + case WSAECONNRESET: + errno = ECONNRESET; + break; + case WSAENOBUFS: + errno = ENOBUFS; + break; + case WSAEISCONN: + errno = EISCONN; + break; + case WSAENOTCONN: + errno = ENOTCONN; + break; + case WSAESHUTDOWN: + errno = ESHUTDOWN; + break; + case WSAETOOMANYREFS: + errno = ETOOMANYREFS; + break; + case WSAETIMEDOUT: + errno = ETIMEDOUT; + break; + case WSAECONNREFUSED: + errno = ECONNREFUSED; + break; + case WSAELOOP: + errno = ELOOP; + break; + case WSAENAMETOOLONG: + errno = ENAMETOOLONG; + break; + case WSAEHOSTDOWN: + errno = EHOSTDOWN; + break; + case WSAEHOSTUNREACH: + errno = EHOSTUNREACH; + break; + case WSAENOTEMPTY: + errno = ENOTEMPTY; + break; +#ifdef EPROCLIM + case WSAEPROCLIM: + errno = EPROCLIM; + break; +#endif + case WSAEUSERS: + errno = EUSERS; + break; + case WSAEDQUOT: + errno = EDQUOT; + break; + case WSAESTALE: + errno = ESTALE; + break; + case WSAEREMOTE: + errno = EREMOTE; + break; + } } int WSAGetLastError(void) @@ -290,23 +428,18 @@ int WSAGetLastError(void) case EINTR: iError = WSAEINTR; break; - case EBADF: iError = WSAEBADF; break; - case EACCES: iError = WSAEACCES; break; - case EFAULT: iError = WSAEFAULT; break; - case EINVAL: iError = WSAEINVAL; break; - case EMFILE: iError = WSAEMFILE; break;