diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 07f8054a7..b7963de27 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -104,6 +104,7 @@ BOOL rdp_client_connect(rdpRdp* rdp) cookie[cookie_length] = '\0'; nego_set_cookie(rdp->nego, cookie); + free(cookie); settings->RdpSecurity = TRUE; settings->TlsSecurity = FALSE; diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index ca0e68c37..3cf4578e2 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -191,6 +191,7 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) HttpResponse* http_response; rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm; + printf("TlsOut: %p\n", rpc->TlsOut); http_response = http_response_recv(rpc->TlsOut); ntlm_token_data = NULL; diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index e990fe5fd..9e8b45e44 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -255,6 +255,7 @@ void ntlm_client_uninit(rdpNtlm* ntlm) ntlm->table->FreeCredentialsHandle(&ntlm->credentials); ntlm->table->FreeContextBuffer(ntlm->pPackageInfo); + ntlm->table->DeleteSecurityContext(&ntlm->context); } rdpNtlm* ntlm_new() diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index ae15d185a..df1f6ffbe 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -384,9 +384,6 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum) if (request_pdu->opnum == TsProxySetupReceivePipeOpnum) rpc->PipeCallId = request_pdu->call_id; - printf("Request CallId: %d OpNum: %d\n", - request_pdu->call_id, request_pdu->opnum); - request_pdu->stub_data = data; offset = 24; @@ -585,9 +582,19 @@ rdpRpc* rpc_new(rdpTransport* transport) void rpc_free(rdpRpc* rpc) { + printf("rpc_free\n"); + if (rpc != NULL) { - ntlm_free(rpc->ntlm); + rpc_client_stop(rpc); + + printf("rpc_client stopped\n"); + + if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED) + { + ntlm_client_uninit(rpc->ntlm); + ntlm_free(rpc->ntlm); + } ntlm_http_free(rpc->NtlmHttpIn); ntlm_http_free(rpc->NtlmHttpOut); diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 0877668be..fcb01fefb 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -152,7 +152,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc) if (StubLength == 4) { - printf("Ignoring TsProxySendToServer Response\n"); + //printf("Ignoring TsProxySendToServer Response\n"); rpc_client_fragment_pool_return(rpc, fragment); return 0; } @@ -177,7 +177,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc) if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2)) { - printf("Sending Flow Control Ack PDU\n"); + //printf("Sending Flow Control Ack PDU\n"); rts_send_flow_control_ack_pdu(rpc); } @@ -462,31 +462,38 @@ static void rpc_fragment_free(wStream* fragment) int rpc_client_new(rdpRpc* rpc) { - rpc->client = (RpcClient*) malloc(sizeof(RpcClient)); + RpcClient* client = NULL; - rpc->client->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rpc_client_thread, - rpc, CREATE_SUSPENDED, NULL); + client = (RpcClient*) malloc(sizeof(RpcClient)); - rpc->client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - rpc->client->PduSentEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (client) + { + client->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) rpc_client_thread, + rpc, CREATE_SUSPENDED, NULL); - rpc->client->SendQueue = Queue_New(TRUE, -1, -1); - Queue_Object(rpc->client->SendQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; + client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + client->PduSentEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - rpc->client->ReceivePool = Queue_New(TRUE, -1, -1); - rpc->client->ReceiveQueue = Queue_New(TRUE, -1, -1); - Queue_Object(rpc->client->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; - Queue_Object(rpc->client->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; + client->SendQueue = Queue_New(TRUE, -1, -1); + Queue_Object(client->SendQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; - rpc->client->FragmentPool = Queue_New(TRUE, -1, -1); - rpc->client->FragmentQueue = Queue_New(TRUE, -1, -1); + client->ReceivePool = Queue_New(TRUE, -1, -1); + client->ReceiveQueue = Queue_New(TRUE, -1, -1); + Queue_Object(client->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; + Queue_Object(client->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free; - Queue_Object(rpc->client->FragmentPool)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free; - Queue_Object(rpc->client->FragmentQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free; + client->FragmentPool = Queue_New(TRUE, -1, -1); + client->FragmentQueue = Queue_New(TRUE, -1, -1); - rpc->client->ClientCallList = ArrayList_New(TRUE); - ArrayList_Object(rpc->client->ClientCallList)->fnObjectFree = (OBJECT_FREE_FN) rpc_client_call_free; + Queue_Object(client->FragmentPool)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free; + Queue_Object(client->FragmentQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free; + + client->ClientCallList = ArrayList_New(TRUE); + ArrayList_Object(client->ClientCallList)->fnObjectFree = (OBJECT_FREE_FN) rpc_client_call_free; + } + + rpc->client = client; return 0; } @@ -502,27 +509,39 @@ int rpc_client_stop(rdpRpc* rpc) { SetEvent(rpc->client->StopEvent); + printf("rpc_client_stop waiting for thread\n"); + WaitForSingleObject(rpc->client->Thread, INFINITE); + return 0; } int rpc_client_free(rdpRpc* rpc) { - Queue_Clear(rpc->client->SendQueue); - Queue_Free(rpc->client->SendQueue); + RpcClient* client; - Queue_Clear(rpc->client->ReceivePool); - Queue_Free(rpc->client->ReceivePool); + client = rpc->client; - Queue_Clear(rpc->client->ReceiveQueue); - Queue_Free(rpc->client->ReceiveQueue); + printf("rpc_client_free\n"); - ArrayList_Clear(rpc->client->ClientCallList); - ArrayList_Free(rpc->client->ClientCallList); + if (client) + { + Queue_Clear(client->SendQueue); + Queue_Free(client->SendQueue); - CloseHandle(rpc->client->StopEvent); - CloseHandle(rpc->client->PduSentEvent); + Queue_Clear(client->ReceivePool); + Queue_Free(client->ReceivePool); - free(rpc->client); + Queue_Clear(client->ReceiveQueue); + Queue_Free(client->ReceiveQueue); + + ArrayList_Clear(client->ClientCallList); + ArrayList_Free(client->ClientCallList); + + CloseHandle(client->StopEvent); + CloseHandle(client->PduSentEvent); + + free(client); + } return 0; } diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index a6a35e890..ef2f96a5d 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -177,7 +177,7 @@ BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg) TSG_MESSAGING_CAP_REAUTH; /* - * FIXME: Alternate Code Path + * Alternate Code Path * * Using reduced capabilities appears to trigger * TSG_PACKET_TYPE_QUARENC_RESPONSE instead of TSG_PACKET_TYPE_CAPS_RESPONSE @@ -1104,6 +1104,33 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port) return TRUE; } +BOOL tsg_disconnect(rdpTsg* tsg) +{ + printf("tsg_disconnect\n"); + + /** + * Gateway Shutdown Phase + * + * Client Server + * | | + * |-------------TsProxyCloseChannel Request---------->| + * | | + * |<-------TsProxySetupReceivePipe Final Response-----| + * |<-----------TsProxyCloseChannel Response-----------| + * | | + * |----TsProxyMakeTunnelCall Request (cancel async)-->| + * | | + * |<---TsProxyMakeTunnelCall Response (call async)----| + * |<---TsProxyMakeTunnelCall Response (cancel async)--| + * | | + * |--------------TsProxyCloseTunnel Request---------->| + * |<-------------TsProxyCloseTunnel Response----------| + * | | + */ + + return TRUE; +} + int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) { int CopyLength; @@ -1194,6 +1221,8 @@ rdpTsg* tsg_new(rdpTransport* transport) void tsg_free(rdpTsg* tsg) { + printf("tsg_free\n"); + if (tsg != NULL) { free(tsg->MachineName); diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h index a3c365c9e..eee223d47 100644 --- a/libfreerdp/core/gateway/tsg.h +++ b/libfreerdp/core/gateway/tsg.h @@ -303,6 +303,7 @@ typedef struct _TSG_PACKET DWORD TsProxySendToServer(handle_t IDL_handle, BYTE pRpcMessage[], UINT32 count, UINT32* lengths); BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port); +BOOL tsg_disconnect(rdpTsg* tsg); int tsg_write(rdpTsg* tsg, BYTE* data, UINT32 length); int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 8348acdbd..b774bddf5 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -75,10 +75,21 @@ void transport_attach(rdpTransport* transport, int sockfd) BOOL transport_disconnect(rdpTransport* transport) { - if (transport->layer == TRANSPORT_LAYER_TLS) - tls_disconnect(transport->TlsIn); + BOOL status = TRUE; - return tcp_disconnect(transport->TcpIn); + if (transport->layer == TRANSPORT_LAYER_TLS) + status &= tls_disconnect(transport->TlsIn); + + if (transport->layer == TRANSPORT_LAYER_TSG) + { + tsg_disconnect(transport->tsg); + } + else + { + status &= tcp_disconnect(transport->TcpIn); + } + + return status; } BOOL transport_connect_rdp(rdpTransport* transport) diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c index bcea44f7c..f404ca750 100644 --- a/winpr/libwinpr/sspi/sspi.c +++ b/winpr/libwinpr/sspi/sspi.c @@ -370,17 +370,28 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE } } +static BOOL sspi_initialized = FALSE; + void sspi_GlobalInit() { - SSL_load_error_strings(); - SSL_library_init(); + if (!sspi_initialized) + { + SSL_load_error_strings(); + SSL_library_init(); - sspi_ContextBufferAllocTableNew(); + sspi_ContextBufferAllocTableNew(); + sspi_initialized = TRUE; + } } void sspi_GlobalFinish() { - sspi_ContextBufferAllocTableFree(); + if (sspi_initialized) + { + sspi_ContextBufferAllocTableFree(); + } + + sspi_initialized = FALSE; } #ifndef WITH_NATIVE_SSPI