libfreerdp-core: improve TSG virtual connection and channel management
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 12 Feb 2015 17:03:15 +0000 (12:03 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 12 Feb 2015 17:03:15 +0000 (12:03 -0500)
libfreerdp/core/gateway/ncacn_http.c
libfreerdp/core/gateway/ncacn_http.h
libfreerdp/core/gateway/rpc.c
libfreerdp/core/gateway/rpc.h
libfreerdp/core/gateway/rpc_client.c
libfreerdp/core/gateway/rts.c

index fc5433b..00716de 100644 (file)
@@ -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");
-       }
-}
index f9c696d..5551ec4 100644 (file)
 #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
index 2268cad..0e56048 100644 (file)
@@ -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)
index 566fb2c..e2141fb 100644 (file)
@@ -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;
 
index 9a05a12..7d71bb0 100644 (file)
@@ -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);
index 69acdb3..a61eb4f 100644 (file)
@@ -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;