libfreerdp-core: improve error handling in ts gateway

This commit is contained in:
Marc-André Moreau 2015-02-03 14:44:31 -05:00
parent 5aea07d401
commit 7b25f9130b
6 changed files with 187 additions and 125 deletions

View File

@ -94,9 +94,8 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc)
if (!s)
return -1;
WLog_DBG(TAG, "\n%s", Stream_Buffer(s));
status = rpc_in_write(rpc, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
return (status > 0) ? 1 : -1;
@ -104,33 +103,39 @@ 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;
int status = -1;
char* token64 = NULL;
HttpResponse* response;
int ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
http_response = http_response_recv(rpc->TlsIn);
response = http_response_recv(rpc->TlsIn);
if (!http_response)
if (!response)
return -1;
if (ListDictionary_Contains(http_response->Authenticates, "NTLM"))
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{
token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM");
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
if (!token64)
goto out;
crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
}
if (ntlmTokenData && ntlmTokenLength)
{
ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
status = 1;
}
out:
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(http_response);
http_response_free(response);
return 1;
return status;
}
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
@ -182,36 +187,48 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
return 1;
}
void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel)
{
if (channel == TSG_CHANNEL_IN)
{
ntlm_client_uninit(rpc->NtlmHttpIn->ntlm);
ntlm_free(rpc->NtlmHttpIn->ntlm);
rpc->NtlmHttpIn->ntlm = NULL;
}
else if (channel == TSG_CHANNEL_OUT)
{
ntlm_client_uninit(rpc->NtlmHttpOut->ntlm);
ntlm_free(rpc->NtlmHttpOut->ntlm);
rpc->NtlmHttpOut->ntlm = NULL;
}
}
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
{
BOOL status = FALSE;
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) <= 0)
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) < 0)
goto out;
/* Send IN Channel Request */
if (rpc_ncacn_http_send_in_channel_request(rpc) <= 0)
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
goto out;
/* Receive IN Channel Response */
if (rpc_ncacn_http_recv_in_channel_response(rpc) <= 0)
if (rpc_ncacn_http_recv_in_channel_response(rpc) < 0)
goto out;
/* Send IN Channel Request */
if (rpc_ncacn_http_send_in_channel_request(rpc) <= 0)
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
goto out;
status = TRUE;
out:
ntlm_client_uninit(ntlm);
ntlm_free(ntlm);
rpc->NtlmHttpIn->ntlm = NULL;
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_IN);
return status;
}
@ -219,22 +236,21 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
{
wStream* s;
int status;
int content_length;
BOOL continue_needed;
int contentLength;
BOOL continueNeeded;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
continue_needed = ntlm_authenticate(ntlm);
continueNeeded = ntlm_authenticate(ntlm);
content_length = (continue_needed) ? 0 : 76;
contentLength = (continueNeeded) ? 0 : 76;
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], content_length, TSG_CHANNEL_OUT);
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_OUT);
if (!s)
return -1;
WLog_DBG(TAG, "\n%s", Stream_Buffer(s));
status = rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
return (status > 0) ? 1 : -1;
@ -242,10 +258,11 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
{
char* token64;
int status = -1;
char* token64 = NULL;
HttpResponse* response;
int ntlm_token_length = 0;
BYTE* ntlm_token_data = NULL;
int ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
response = http_response_recv(rpc->TlsOut);
@ -260,57 +277,64 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
if (!token64)
goto out;
crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
}
if (ntlmTokenData && ntlmTokenLength)
{
ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
status = 1;
}
out:
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(response);
return 1;
return status;
}
int rpc_http_send_replacement_out_channel_request(rdpRpc* rpc)
{
int status;
wStream* s;
int content_length;
content_length = 120;
s = rpc_ntlm_http_request(rpc, NULL, 120, TSG_CHANNEL_OUT);
s = rpc_ntlm_http_request(rpc, NULL, content_length, TSG_CHANNEL_OUT);
if (!s)
return -1;
WLog_DBG(TAG, "\n%s", Stream_Buffer(s));
rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
status = rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
return 0;
return (status > 0) ? 1 : -1;
}
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
{
BOOL status = FALSE;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) <= 0)
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) < 0)
goto out;
/* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0)
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
goto out;
}
/* Receive OUT Channel Response */
if (rpc_ncacn_http_recv_out_channel_response(rpc) <= 0)
if (rpc_ncacn_http_recv_out_channel_response(rpc) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
goto out;
}
/* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0)
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
goto out;
@ -319,10 +343,7 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
status = TRUE;
out:
ntlm_client_uninit(ntlm);
ntlm_free(ntlm);
rpc->NtlmHttpOut->ntlm = NULL;
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_OUT);
return status;
}

View File

@ -32,6 +32,9 @@
#include "rpc.h"
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel);
void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel);
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc);
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc);

View File

@ -260,16 +260,19 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
rpc_offset_align(offset, 8);
alloc_hint = header->response.alloc_hint;
break;
case PTYPE_REQUEST:
*offset += 4;
rpc_offset_align(offset, 8);
alloc_hint = header->request.alloc_hint;
break;
case PTYPE_RTS:
*offset += 4;
break;
default:
WLog_ERR(TAG, "unknown ptype=0x%x", header->common.ptype);
WLog_ERR(TAG, "Unknown PTYPE: 0x%04X", header->common.ptype);
return FALSE;
}
@ -289,13 +292,12 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
sec_trailer_offset = frag_length - auth_length - 8;
sec_trailer = (rpc_sec_trailer*) &buffer[sec_trailer_offset];
auth_pad_length = sec_trailer->auth_pad_length;
#if 0
WLog_DBG(TAG, "sec_trailer: type: %d level: %d pad_length: %d reserved: %d context_id: %d",
sec_trailer->auth_type,
sec_trailer->auth_level,
sec_trailer->auth_pad_length,
sec_trailer->auth_reserved,
sec_trailer->auth_context_id);
WLog_DBG(TAG, "sec_trailer: type: %d level: %d pad_length: %d reserved: %d context_id: %d",
sec_trailer->auth_type, sec_trailer->auth_level,
sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
sec_trailer->auth_context_id);
#endif
/**
@ -363,7 +365,6 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
if (!ntlm || !ntlm->table)
{
WLog_ERR(TAG, "invalid ntlm context");
fprintf(stderr, "invalid ntlm context: %p %p\n", ntlm, ntlm->table);
return -1;
}
@ -372,6 +373,7 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
return -1;
}
ZeroMemory(&Buffers, sizeof(Buffers));
request_pdu = (rpcconn_request_hdr_t*) calloc(1, sizeof(rpcconn_request_hdr_t));
@ -454,6 +456,8 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
length = -1;
free(request_pdu);
free(buffer);
return length;
out_free_clientCall:
@ -522,12 +526,15 @@ void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* conne
RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
{
RpcVirtualConnection* connection = (RpcVirtualConnection*) calloc(1, sizeof(RpcVirtualConnection));
RpcVirtualConnection* connection;
connection = (RpcVirtualConnection*) calloc(1, sizeof(RpcVirtualConnection));
if (!connection)
return NULL;
connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
connection->DefaultInChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel));
if (!connection->DefaultInChannel)
@ -539,6 +546,7 @@ RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
goto out_default_in;
rpc_client_virtual_connection_init(rpc, connection);
return connection;
out_default_in:
free(connection->DefaultInChannel);

View File

@ -264,6 +264,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
free(buffer);
return -1;
}
if (ArrayList_Add(rpc->client->ClientCallList, clientCall) < 0)
{
free(buffer);
@ -277,7 +278,9 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
free(bind_pdu->p_context_elem.p_cont_elem);
free(bind_pdu);
return status;
free(buffer);
return (status > 0) ? 1 : -1;
}
/**
@ -397,6 +400,7 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
status = rpc_send_pdu(rpc, buffer, length);
free(auth_3_pdu);
free(buffer);
return status;
return (status > 0) ? 1 : -1;
}

View File

@ -194,7 +194,13 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
return -1;
}
rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
status = rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
if (status < 0)
{
WLog_ERR(TAG, "rts_recv_CONN_A3_pdu failure");
return -1;
}
rpc_client_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_WAIT_C2);
@ -210,10 +216,16 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_C2_SIGNATURE, rts))
{
WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2");
return FALSE;
return -1;
}
rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
status = rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
if (status < 0)
{
WLog_ERR(TAG, "rts_recv_CONN_C2_pdu failure");
return -1;
}
rpc_client_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OPENED);
@ -573,6 +585,9 @@ int rpc_send_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
status = rpc_in_write(rpc, buffer, length);
if (status <= 0)
return -1;
header = (rpcconn_common_hdr_t*) buffer;
clientCall = rpc_client_call_find_by_id(rpc, header->call_id);
clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
@ -590,8 +605,6 @@ int rpc_send_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
inChannel->SenderAvailableWindow -= status;
}
free(buffer);
return status;
}

View File

@ -33,6 +33,25 @@
#define TAG FREERDP_TAG("core.gateway.rts")
const char* const RTS_CMD_STRINGS[] =
{
"ReceiveWindowSize",
"FlowControlAck",
"ConnectionTimeout",
"Cookie",
"ChannelLifetime",
"ClientKeepalive",
"Version",
"Empty",
"Padding",
"NegativeANCE",
"ANCE",
"ClientAddress",
"AssociationGroupId",
"Destination",
"PingTrafficSentNotify"
};
/**
* [MS-RPCH]: Remote Procedure Call over HTTP Protocol Specification:
* http://msdn.microsoft.com/en-us/library/cc243950/
@ -75,6 +94,8 @@ BOOL rts_connect(rdpRpc* rpc)
return FALSE;
}
/* Send CONN/A1 PDU over OUT channel */
if (rts_send_CONN_A1_pdu(rpc) < 0)
{
WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!");
@ -87,6 +108,8 @@ BOOL rts_connect(rdpRpc* rpc)
return FALSE;
}
/* Send CONN/B1 PDU over IN channel */
if (rts_send_CONN_B1_pdu(rpc) < 0)
{
WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!");
@ -96,6 +119,8 @@ BOOL rts_connect(rdpRpc* rpc)
rpc_client_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
/* Receive OUT channel response */
response = http_response_recv(rpc->TlsOut);
if (!response)
@ -134,25 +159,6 @@ BOOL rts_connect(rdpRpc* rpc)
return TRUE;
}
const char* const RTS_CMD_STRINGS[] =
{
"ReceiveWindowSize",
"FlowControlAck",
"ConnectionTimeout",
"Cookie",
"ChannelLifetime",
"ClientKeepalive",
"Version",
"Empty",
"Padding",
"NegativeANCE",
"ANCE",
"ClientAddress",
"AssociationGroupId",
"Destination",
"PingTrafficSentNotify"
};
/**
* RTS PDU Header
*
@ -530,6 +536,7 @@ void rts_generate_cookie(BYTE* cookie)
int rts_send_CONN_A1_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
UINT32 ReceiveWindowSize;
@ -561,11 +568,11 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc)
rts_cookie_command_write(&buffer[48], OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[68], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
rpc_out_write(rpc, buffer, header.frag_length);
status = rpc_out_write(rpc, buffer, header.frag_length);
free(buffer);
return 0;
return (status > 0) ? 1 : -1;
}
int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
@ -578,7 +585,7 @@ int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
return 0;
return 1;
}
/* CONN/B Sequence */
@ -626,7 +633,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
free(buffer);
return status;
return (status > 0) ? 1 : -1;
}
/* CONN/C Sequence */
@ -653,13 +660,14 @@ int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
rpc->VirtualConnection->DefaultInChannel->State = CLIENT_IN_CHANNEL_STATE_OPENED;
rpc->VirtualConnection->DefaultOutChannel->State = CLIENT_OUT_CHANNEL_STATE_OPENED;
return 0;
return 1;
}
/* Out-of-Sequence PDUs */
int rts_send_keep_alive_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
@ -681,18 +689,16 @@ int rts_send_keep_alive_pdu(rdpRpc* rpc)
length = header.frag_length;
if (rpc_in_write(rpc, buffer, length) < 0)
{
free (buffer);
return -1;
}
status = rpc_in_write(rpc, buffer, length);
free(buffer);
return length;
return (status > 0) ? 1 : -1;
}
int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
@ -727,15 +733,11 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
length = header.frag_length;
if (rpc_in_write(rpc, buffer, length) < 0)
{
free(buffer);
return -1;
}
status = rpc_in_write(rpc, buffer, length);
free(buffer);
return 0;
return (status > 0) ? 1 : -1;
}
int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
@ -750,15 +752,15 @@ int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
&BytesReceived, &AvailableWindow, (BYTE*) &ChannelCookie) + 4;
#if 0
WLog_ERR(TAG, "BytesReceived: %d AvailableWindow: %d",
WLog_ERR(TAG, "BytesReceived: %d AvailableWindow: %d",
BytesReceived, AvailableWindow);
WLog_ERR(TAG, "ChannelCookie: " RPC_UUID_FORMAT_STRING "", RPC_UUID_FORMAT_ARGUMENTS(ChannelCookie));
WLog_ERR(TAG, "ChannelCookie: " RPC_UUID_FORMAT_STRING "", RPC_UUID_FORMAT_ARGUMENTS(ChannelCookie));
#endif
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
return 0;
return 1;
}
int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
@ -799,11 +801,12 @@ int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UI
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =
AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived);
return 0;
return 1;
}
int rts_send_ping_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
@ -824,14 +827,11 @@ int rts_send_ping_pdu(rdpRpc* rpc)
length = header.frag_length;
if (rpc_in_write(rpc, buffer, length) < 0)
{
free (buffer);
return -1;
}
status = rpc_in_write(rpc, buffer, length);
free(buffer);
return length;
return (status > 0) ? 1 : -1;
}
int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 length)
@ -901,7 +901,7 @@ int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 len
break;
default:
WLog_ERR(TAG, "Error: Unknown RTS Command Type: 0x%x", CommandType);
WLog_ERR(TAG, "Error: Unknown RTS Command Type: 0x%x", CommandType);
return -1;
break;
}
@ -911,6 +911,7 @@ int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 len
int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
UINT32 ReceiveWindowSize;
@ -944,15 +945,16 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
rts_cookie_command_write(&buffer[68], SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[88], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
rpc_out_write(rpc, buffer, header.frag_length);
status = rpc_out_write(rpc, buffer, header.frag_length);
free(buffer);
return 0;
return (status > 0) ? 1 : -1;
}
int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
int status;
UINT32 offset;
UINT32 Destination = 0;
@ -963,15 +965,22 @@ int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
WLog_ERR(TAG, "TS Gateway channel recycling is incomplete");
rpc_http_send_replacement_out_channel_request(rpc);
status = rpc_http_send_replacement_out_channel_request(rpc);
rts_send_OUT_R1_A3_pdu(rpc);
if (status < 0)
return -1;
return 0;
status = rts_send_OUT_R1_A3_pdu(rpc);
if (status < 0)
return -1;
return 1;
}
int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
int status = -1;
UINT32 SignatureId;
rpcconn_rts_hdr_t* rts;
RtsPduSignature signature;
@ -984,16 +993,20 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
switch (SignatureId)
{
case RTS_PDU_FLOW_CONTROL_ACK:
return rts_recv_flow_control_ack_pdu(rpc, buffer, length);
status = rts_recv_flow_control_ack_pdu(rpc, buffer, length);
break;
case RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION:
return rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer, length);
status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer, length);
break;
case RTS_PDU_PING:
return rts_send_ping_pdu(rpc);
status = rts_send_ping_pdu(rpc);
break;
case RTS_PDU_OUT_R1_A2:
return rts_recv_OUT_R1_A2_pdu(rpc, buffer, length);
status = rts_recv_OUT_R1_A2_pdu(rpc, buffer, length);
break;
default:
WLog_ERR(TAG, "unimplemented signature id: 0x%08X", SignatureId);
@ -1001,5 +1014,5 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
break;
}
return 0;
return status;
}