From c92e82b3dc3627c5a417cc00788c82a338e9f948 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 12 Feb 2015 12:03:15 -0500 Subject: [PATCH] libfreerdp-core: improve TSG virtual connection and channel management --- libfreerdp/core/gateway/ncacn_http.c | 81 +++++++------------------------- libfreerdp/core/gateway/ncacn_http.h | 8 ++-- libfreerdp/core/gateway/rpc.c | 90 +++++++++++++++++++++++++++--------- libfreerdp/core/gateway/rpc.h | 30 ++++++------ libfreerdp/core/gateway/rpc_client.c | 6 +-- libfreerdp/core/gateway/rts.c | 8 ++-- 6 files changed, 109 insertions(+), 114 deletions(-) diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index fc5433b..00716de 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -33,7 +33,7 @@ #define TAG FREERDP_TAG("core.gateway.ntlm") -wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, SecBuffer* ntlmToken, int contentLength, TSG_CHANNEL channel) +wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken) { wStream* s; HttpRequest* request; @@ -44,10 +44,7 @@ wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, SecBuffer* ntlmTo if (ntlmToken) base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer); - if (channel == TSG_CHANNEL_IN) - http_request_set_method(request, "RPC_IN_DATA"); - else if (channel == TSG_CHANNEL_OUT) - http_request_set_method(request, "RPC_OUT_DATA"); + http_request_set_method(request, method); request->ContentLength = contentLength; http_request_set_uri(request, http->URI); @@ -79,7 +76,7 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel) contentLength = (continueNeeded) ? 0 : 0x40000000; - s = rpc_ntlm_http_request(rpc, http, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_IN); + s = rpc_ntlm_http_request(rpc, http, "RPC_IN_DATA", contentLength, &ntlm->outputBuffer[0]); if (!s) return -1; @@ -117,25 +114,14 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel return 1; } -int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) +int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel) { - rdpTls* tls = NULL; - rdpNtlm* ntlm = NULL; + rdpTls* tls = channel->tls; + rdpNtlm* ntlm = channel->ntlm; rdpContext* context = rpc->context; rdpSettings* settings = rpc->settings; freerdp* instance = context->instance; - if (channel == TSG_CHANNEL_IN) - { - tls = rpc->VirtualConnection->DefaultInChannel->tls; - ntlm = rpc->VirtualConnection->DefaultInChannel->ntlm; - } - else if (channel == TSG_CHANNEL_OUT) - { - tls = rpc->VirtualConnection->DefaultOutChannel->tls; - ntlm = rpc->VirtualConnection->DefaultOutChannel->ntlm; - } - if (!settings->GatewayPassword || !settings->GatewayUsername || !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername)) { @@ -174,25 +160,14 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) return 1; } -void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel) +void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, RpcChannel* channel) { - if (channel == TSG_CHANNEL_IN) - { - RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; - ntlm_client_uninit(inChannel->ntlm); - ntlm_free(inChannel->ntlm); - inChannel->ntlm = NULL; - } - else if (channel == TSG_CHANNEL_OUT) - { - RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel; - ntlm_client_uninit(outChannel->ntlm); - ntlm_free(outChannel->ntlm); - outChannel->ntlm = NULL; - } + ntlm_client_uninit(channel->ntlm); + ntlm_free(channel->ntlm); + channel->ntlm = NULL; } -int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel) +int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel, BOOL replacement) { wStream* s; int status; @@ -203,9 +178,12 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChann continueNeeded = ntlm_authenticate(ntlm); - contentLength = (continueNeeded) ? 0 : 76; + if (!replacement) + contentLength = (continueNeeded) ? 0 : 76; + else + contentLength = (continueNeeded) ? 0 : 120; - s = rpc_ntlm_http_request(rpc, http, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_OUT); + s = rpc_ntlm_http_request(rpc, http, "RPC_OUT_DATA", contentLength, &ntlm->outputBuffer[0]); if (!s) return -1; @@ -242,30 +220,3 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChan return 1; } - -void rpc_ntlm_http_init_channel(rdpRpc* rpc, HttpContext* http, TSG_CHANNEL channel) -{ - if (channel == TSG_CHANNEL_IN) - http_context_set_method(http, "RPC_IN_DATA"); - else if (channel == TSG_CHANNEL_OUT) - http_context_set_method(http, "RPC_OUT_DATA"); - - http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388"); - http_context_set_accept(http, "application/rpc"); - http_context_set_cache_control(http, "no-cache"); - http_context_set_connection(http, "Keep-Alive"); - http_context_set_user_agent(http, "MSRPC"); - http_context_set_host(http, rpc->settings->GatewayHostname); - - if (channel == TSG_CHANNEL_IN) - { - http_context_set_pragma(http, - "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); - } - else if (channel == TSG_CHANNEL_OUT) - { - http_context_set_pragma(http, - "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " - "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); - } -} diff --git a/libfreerdp/core/gateway/ncacn_http.h b/libfreerdp/core/gateway/ncacn_http.h index f9c696d..5551ec4 100644 --- a/libfreerdp/core/gateway/ncacn_http.h +++ b/libfreerdp/core/gateway/ncacn_http.h @@ -31,15 +31,13 @@ #include "rpc.h" #include "http.h" -int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel); -void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel); +int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel); +void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, RpcChannel* channel); int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel); int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel, HttpResponse* response); -int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel); +int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel, BOOL replacement); int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel, HttpResponse* response); -void rpc_ntlm_http_init_channel(rdpRpc* rpc, HttpContext* http, TSG_CHANNEL channel); - #endif diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 2268cad..0e56048 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -131,7 +131,7 @@ BOOL rpc_connect(rdpRpc* rpc) rpc_client_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED); - if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) < 0) + if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) inChannel) < 0) return FALSE; /* Send IN Channel Request */ @@ -148,12 +148,12 @@ BOOL rpc_connect(rdpRpc* rpc) rpc_client_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED); - if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) < 0) + if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0) return FALSE; /* Send OUT Channel Request */ - if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel) < 0) + if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, FALSE) < 0) { WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure"); return FALSE; @@ -594,6 +594,8 @@ int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN int rpc_client_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel) { + HttpContext* http; + inChannel->ntlm = ntlm_new(); if (!inChannel->ntlm) @@ -604,7 +606,34 @@ int rpc_client_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel) if (!inChannel->http) return -1; - rpc_ntlm_http_init_channel(rpc, inChannel->http, TSG_CHANNEL_IN); + http = inChannel->http; + + http_context_set_method(http, "RPC_IN_DATA"); + + http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388"); + http_context_set_accept(http, "application/rpc"); + http_context_set_cache_control(http, "no-cache"); + http_context_set_connection(http, "Keep-Alive"); + http_context_set_user_agent(http, "MSRPC"); + http_context_set_host(http, rpc->settings->GatewayHostname); + + http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); + + return 1; +} + +int rpc_client_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel) +{ + rts_generate_cookie((BYTE*) &inChannel->Cookie); + + inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL; + inChannel->BytesSent = 0; + inChannel->SenderAvailableWindow = rpc->ReceiveWindow; + inChannel->PingOriginator.ConnectionTimeout = 30; + inChannel->PingOriginator.KeepAliveInterval = 0; + + if (rpc_client_in_channel_rpch_init(rpc, inChannel) < 0) + return -1; return 1; } @@ -700,6 +729,8 @@ int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT int rpc_client_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel) { + HttpContext* http; + outChannel->ntlm = ntlm_new(); if (!outChannel->ntlm) @@ -710,7 +741,37 @@ int rpc_client_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel) if (!outChannel->http) return -1; - rpc_ntlm_http_init_channel(rpc, outChannel->http, TSG_CHANNEL_OUT); + http = outChannel->http; + + http_context_set_method(http, "RPC_OUT_DATA"); + + http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388"); + http_context_set_accept(http, "application/rpc"); + http_context_set_cache_control(http, "no-cache"); + http_context_set_connection(http, "Keep-Alive"); + http_context_set_user_agent(http, "MSRPC"); + http_context_set_host(http, rpc->settings->GatewayHostname); + + http_context_set_pragma(http, + "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " + "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); + + return 1; +} + +int rpc_client_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel) +{ + rts_generate_cookie((BYTE*) &outChannel->Cookie); + + outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL; + outChannel->BytesReceived = 0; + outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow; + outChannel->ReceiveWindow = rpc->ReceiveWindow; + outChannel->ReceiveWindowSize = rpc->ReceiveWindow; + outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow; + + if (rpc_client_out_channel_rpch_init(rpc, outChannel) < 0) + return -1; return 1; } @@ -798,24 +859,11 @@ void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* conne rts_generate_cookie((BYTE*) &(connection->Cookie)); rts_generate_cookie((BYTE*) &(connection->AssociationGroupId)); - connection->DefaultInChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL; - connection->DefaultInChannel->BytesSent = 0; - connection->DefaultInChannel->SenderAvailableWindow = rpc->ReceiveWindow; - connection->DefaultInChannel->PingOriginator.ConnectionTimeout = 30; - connection->DefaultInChannel->PingOriginator.KeepAliveInterval = 0; - rts_generate_cookie((BYTE*) &(connection->DefaultInChannelCookie)); + rpc_client_in_channel_init(rpc, connection->DefaultInChannel); + rpc_client_out_channel_init(rpc, connection->DefaultOutChannel); + rts_generate_cookie((BYTE*) &(connection->NonDefaultInChannelCookie)); - rpc_client_in_channel_rpch_init(rpc, connection->DefaultInChannel); - - connection->DefaultOutChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL; - connection->DefaultOutChannel->BytesReceived = 0; - connection->DefaultOutChannel->ReceiverAvailableWindow = rpc->ReceiveWindow; - connection->DefaultOutChannel->ReceiveWindow = rpc->ReceiveWindow; - connection->DefaultOutChannel->ReceiveWindowSize = rpc->ReceiveWindow; - connection->DefaultOutChannel->AvailableWindowAdvertised = rpc->ReceiveWindow; - rts_generate_cookie((BYTE*) &(connection->DefaultOutChannelCookie)); rts_generate_cookie((BYTE*) &(connection->NonDefaultOutChannelCookie)); - rpc_client_out_channel_rpch_init(rpc, connection->DefaultOutChannel); } RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc) diff --git a/libfreerdp/core/gateway/rpc.h b/libfreerdp/core/gateway/rpc.h index 566fb2c..e2141fb 100644 --- a/libfreerdp/core/gateway/rpc.h +++ b/libfreerdp/core/gateway/rpc.h @@ -584,12 +584,18 @@ struct rpc_client_call }; typedef struct rpc_client_call RpcClientCall; -enum _TSG_CHANNEL +#define RPC_CHANNEL_COMMON() \ + rdpTcp* tcp; \ + rdpTls* tls; \ + rdpNtlm* ntlm; \ + HttpContext* http; \ + BYTE Cookie[16] + +struct rpc_channel { - TSG_CHANNEL_IN, - TSG_CHANNEL_OUT + RPC_CHANNEL_COMMON(); }; -typedef enum _TSG_CHANNEL TSG_CHANNEL; +typedef struct rpc_channel RpcChannel; /* Ping Originator */ @@ -619,10 +625,7 @@ struct rpc_in_channel { /* Sending Channel */ - rdpTcp* tcp; - rdpTls* tls; - rdpNtlm* ntlm; - HttpContext* http; + RPC_CHANNEL_COMMON(); CLIENT_IN_CHANNEL_STATE State; @@ -656,13 +659,10 @@ typedef enum _CLIENT_OUT_CHANNEL_STATE CLIENT_OUT_CHANNEL_STATE; struct rpc_out_channel { - rdpTcp* tcp; - rdpTls* tls; - rdpNtlm* ntlm; - HttpContext* http; - /* Receiving Channel */ + RPC_CHANNEL_COMMON(); + CLIENT_OUT_CHANNEL_STATE State; UINT32 ReceiveWindow; @@ -689,16 +689,14 @@ typedef enum _VIRTUAL_CONNECTION_STATE VIRTUAL_CONNECTION_STATE; struct rpc_virtual_connection { BYTE Cookie[16]; /* Virtual Connection Cookie */ + BYTE AssociationGroupId[16]; /* AssociationGroupId */ VIRTUAL_CONNECTION_STATE State; /* Virtual Connection State */ RpcInChannel* DefaultInChannel; /* Default IN Channel */ RpcInChannel* NonDefaultInChannel; /* Non-Default IN Channel */ - BYTE DefaultInChannelCookie[16]; /* Default IN Channel Cookie */ BYTE NonDefaultInChannelCookie[16]; /* Non-Default Default IN Channel Cookie */ RpcOutChannel* DefaultOutChannel; /* Default OUT Channel */ RpcOutChannel* NonDefaultOutChannel; /* Non-Default OUT Channel */ - BYTE DefaultOutChannelCookie[16]; /* Default OUT Channel Cookie */ BYTE NonDefaultOutChannelCookie[16]; /* Non-Default Default OUT Channel Cookie */ - BYTE AssociationGroupId[16]; /* AssociationGroupId */ }; typedef struct rpc_virtual_connection RpcVirtualConnection; diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 9a05a12..7d71bb0 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -557,13 +557,13 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) /* Send OUT Channel Request */ - if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel) < 0) + if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, FALSE) < 0) { WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure"); return -1; } - rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_OUT); + rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) outChannel); rpc_client_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_NEGOTIATED); @@ -673,7 +673,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) return -1; } - rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_IN); + rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) inChannel); rpc_client_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_NEGOTIATED); diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 69acdb3..a61eb4f 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -444,7 +444,7 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc) WLog_DBG(TAG, "Sending CONN_A1 RTS PDU"); VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie); - OUTChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie); + OUTChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie); ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow; buffer = (BYTE*) malloc(header.frag_length); @@ -498,7 +498,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc) WLog_DBG(TAG, "Sending CONN_B1 RTS PDU"); VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie); - INChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultInChannelCookie); + INChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultInChannel->Cookie); AssociationGroupId = (BYTE*) &(rpc->VirtualConnection->AssociationGroupId); buffer = (BYTE*) malloc(header.frag_length); @@ -602,7 +602,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc) BytesReceived = rpc->VirtualConnection->DefaultOutChannel->BytesReceived; AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised; - ChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie); + ChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie); rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow = rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised; @@ -814,7 +814,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) WLog_DBG(TAG, "Sending OUT R1/A3 RTS PDU"); VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie); - PredecessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie); + PredecessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie); SuccessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->NonDefaultOutChannelCookie); ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow; -- 2.7.4