if (!s)
return -1;
- status = rpc_in_write(rpc, Stream_Buffer(s), Stream_Length(s));
+ status = rpc_in_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
if (!s)
return -1;
- status = rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
+ status = rpc_out_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
inChannel = rpc->VirtualConnection->DefaultInChannel;
outChannel = rpc->VirtualConnection->DefaultOutChannel;
- rpc_client_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_INITIAL);
+ rpc_virtual_connection_transition_to_state(rpc, rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_INITIAL);
/* Connect IN Channel */
- rpc_client_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
+ rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) inChannel) < 0)
return FALSE;
return FALSE;
}
- rpc_client_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY);
+ rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY);
/* Connect OUT Channel */
- rpc_client_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
+ rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0)
return FALSE;
return FALSE;
}
- rpc_client_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
+ rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
return TRUE;
}
return TRUE;
}
-int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
+int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length)
{
int status;
- RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
status = BIO_read(outChannel->tls->bio, data, length);
return -1;
}
-int rpc_out_write(rdpRpc* rpc, const BYTE* data, int length)
+int rpc_in_channel_write(RpcInChannel* inChannel, const BYTE* data, int length)
{
int status;
- RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
- status = tls_write_all(outChannel->tls, data, length);
+ status = tls_write_all(inChannel->tls, data, length);
return status;
}
-int rpc_in_write(rdpRpc* rpc, const BYTE* data, int length)
+int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length)
{
int status;
- RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
- status = tls_write_all(inChannel->tls, data, length);
+ status = tls_write_all(outChannel->tls, data, length);
return status;
}
-int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
-{
- UINT32 offset;
- BYTE* buffer = NULL;
- UINT32 stub_data_pad;
- SecBuffer Buffers[2];
- SecBufferDesc Message;
- RpcClientCall* clientCall;
- SECURITY_STATUS encrypt_status;
- rpcconn_request_hdr_t* request_pdu = NULL;
- rdpNtlm* ntlm = rpc->ntlm;
-
- if (!ntlm || !ntlm->table)
- {
- WLog_ERR(TAG, "invalid ntlm context");
- return -1;
- }
-
- if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
- {
- 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));
-
- if (!request_pdu)
- return -1;
-
- rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) request_pdu);
- request_pdu->ptype = PTYPE_REQUEST;
- request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
- request_pdu->auth_length = (UINT16) ntlm->ContextSizes.cbMaxSignature;
- request_pdu->call_id = rpc->CallId++;
- request_pdu->alloc_hint = length;
- request_pdu->p_cont_id = 0x0000;
- request_pdu->opnum = opnum;
-
- clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum);
-
- if (!clientCall)
- goto out_free_pdu;
-
- if (ArrayList_Add(rpc->client->ClientCallList, clientCall) < 0)
- goto out_free_clientCall;
-
- if (request_pdu->opnum == TsProxySetupReceivePipeOpnum)
- rpc->PipeCallId = request_pdu->call_id;
-
- request_pdu->stub_data = data;
- offset = 24;
- stub_data_pad = 0;
- stub_data_pad = rpc_offset_align(&offset, 8);
- offset += length;
- request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
- request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
- request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
- request_pdu->auth_verifier.auth_reserved = 0x00;
- request_pdu->auth_verifier.auth_context_id = 0x00000000;
- offset += (8 + request_pdu->auth_length);
- request_pdu->frag_length = offset;
-
- buffer = (BYTE*) calloc(1, request_pdu->frag_length);
-
- if (!buffer)
- goto out_free_pdu;
-
- CopyMemory(buffer, request_pdu, 24);
- offset = 24;
- rpc_offset_pad(&offset, stub_data_pad);
- CopyMemory(&buffer[offset], request_pdu->stub_data, length);
- offset += length;
- rpc_offset_pad(&offset, request_pdu->auth_verifier.auth_pad_length);
- CopyMemory(&buffer[offset], &request_pdu->auth_verifier.auth_type, 8);
- offset += 8;
- Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */
- Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */
- Buffers[0].pvBuffer = buffer;
- Buffers[0].cbBuffer = offset;
- Buffers[1].cbBuffer = ntlm->ContextSizes.cbMaxSignature;
- Buffers[1].pvBuffer = calloc(1, Buffers[1].cbBuffer);
-
- if (!Buffers[1].pvBuffer)
- goto out_free_pdu;
-
- Message.cBuffers = 2;
- Message.ulVersion = SECBUFFER_VERSION;
- Message.pBuffers = (PSecBuffer) &Buffers;
- encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, 0, &Message, rpc->SendSeqNum++);
-
- if (encrypt_status != SEC_E_OK)
- {
- WLog_ERR(TAG, "EncryptMessage status: 0x%08X", encrypt_status);
- goto out_free_pdu;
- }
-
- CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer);
- offset += Buffers[1].cbBuffer;
- free(Buffers[1].pvBuffer);
-
- if (rpc_send_pdu(rpc, buffer, request_pdu->frag_length) < 0)
- length = -1;
-
- free(request_pdu);
- free(buffer);
-
- return length;
-
-out_free_clientCall:
- rpc_client_call_free(clientCall);
-out_free_pdu:
- free(buffer);
- free(Buffers[1].pvBuffer);
- free(request_pdu);
- return -1;
-}
-
-int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
+int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
{
int status = 1;
const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";
return status;
}
-int rpc_client_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel)
+int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel)
{
HttpContext* http;
return 1;
}
-int rpc_client_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel)
+int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel)
{
rts_generate_cookie((BYTE*) &inChannel->Cookie);
+ inChannel->rpc = rpc;
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)
+ if (rpc_in_channel_rpch_init(rpc, inChannel) < 0)
return -1;
return 1;
}
-void rpc_client_in_channel_rpch_uninit(RpcInChannel* inChannel)
+void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel)
{
if (inChannel->ntlm)
{
}
}
-RpcInChannel* rpc_client_in_channel_new(rdpRpc* rpc)
+RpcInChannel* rpc_in_channel_new(rdpRpc* rpc)
{
RpcInChannel* inChannel = NULL;
if (inChannel)
{
- rpc_client_in_channel_init(rpc, inChannel);
+ rpc_in_channel_init(rpc, inChannel);
}
return inChannel;
}
-void rpc_client_in_channel_free(RpcInChannel* inChannel)
+void rpc_in_channel_free(RpcInChannel* inChannel)
{
if (!inChannel)
return;
- rpc_client_in_channel_rpch_uninit(inChannel);
+ rpc_in_channel_rpch_uninit(inChannel);
free(inChannel);
}
-int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
+int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
{
int status = 1;
const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
return status;
}
-int rpc_client_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel)
+int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel)
{
HttpContext* http;
return 1;
}
-int rpc_client_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
+int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
{
rts_generate_cookie((BYTE*) &outChannel->Cookie);
+ outChannel->rpc = rpc;
outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
outChannel->BytesReceived = 0;
outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
- if (rpc_client_out_channel_rpch_init(rpc, outChannel) < 0)
+ if (rpc_out_channel_rpch_init(rpc, outChannel) < 0)
return -1;
return 1;
}
-void rpc_client_out_channel_rpch_uninit(RpcOutChannel* outChannel)
+void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel)
{
if (outChannel->ntlm)
{
}
}
-RpcOutChannel* rpc_client_out_channel_new(rdpRpc* rpc)
+RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc)
{
RpcOutChannel* outChannel = NULL;
if (outChannel)
{
- rpc_client_out_channel_init(rpc, outChannel);
+ rpc_out_channel_init(rpc, outChannel);
}
return outChannel;
}
-void rpc_client_out_channel_free(RpcOutChannel* outChannel)
+void rpc_out_channel_free(RpcOutChannel* outChannel)
{
if (!outChannel)
return;
- rpc_client_out_channel_rpch_uninit(outChannel);
+ rpc_out_channel_rpch_uninit(outChannel);
free(outChannel);
}
-int rpc_client_virtual_connection_transition_to_state(rdpRpc* rpc,
+int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state)
{
int status = 1;
return status;
}
-RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
+RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc)
{
RpcVirtualConnection* connection;
connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
- connection->DefaultInChannel = rpc_client_in_channel_new(rpc);
+ connection->DefaultInChannel = rpc_in_channel_new(rpc);
if (!connection->DefaultInChannel)
goto out_free;
- connection->DefaultOutChannel = rpc_client_out_channel_new(rpc);
+ connection->DefaultOutChannel = rpc_out_channel_new(rpc);
if (!connection->DefaultOutChannel)
goto out_default_in;
return NULL;
}
-void rpc_client_virtual_connection_free(RpcVirtualConnection* connection)
+void rpc_virtual_connection_free(RpcVirtualConnection* connection)
{
if (!connection)
return;
- rpc_client_in_channel_free(connection->DefaultInChannel);
- rpc_client_in_channel_free(connection->NonDefaultInChannel);
+ rpc_in_channel_free(connection->DefaultInChannel);
+ rpc_in_channel_free(connection->NonDefaultInChannel);
- rpc_client_out_channel_free(connection->DefaultOutChannel);
- rpc_client_out_channel_free(connection->NonDefaultOutChannel);
+ rpc_out_channel_free(connection->DefaultOutChannel);
+ rpc_out_channel_free(connection->NonDefaultOutChannel);
free(connection);
}
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
rpc->CurrentKeepAliveTime = 0;
- rpc->VirtualConnection = rpc_client_virtual_connection_new(rpc);
+ rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
if (!rpc->VirtualConnection)
goto out_free_virtual_connection;
out_free_rpc_client:
rpc_client_free(rpc);
out_free_virtual_connection:
- rpc_client_virtual_connection_free(rpc->VirtualConnection);
+ rpc_virtual_connection_free(rpc->VirtualConnection);
out_free:
free(rpc);
return NULL;
rpc->ntlm = NULL;
}
- rpc_client_virtual_connection_free(rpc->VirtualConnection);
+ rpc_virtual_connection_free(rpc->VirtualConnection);
free(rpc);
}
typedef struct rpc_client_call RpcClientCall;
#define RPC_CHANNEL_COMMON() \
+ rdpRpc* rpc; \
rdpTcp* tcp; \
rdpTls* tls; \
rdpNtlm* ntlm; \
UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment);
UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad);
-int rpc_out_read(rdpRpc* rpc, BYTE* data, int length);
+BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* length);
-int rpc_out_write(rdpRpc* rpc, const BYTE* data, int length);
-int rpc_in_write(rdpRpc* rpc, const BYTE* data, int length);
+int rpc_in_channel_write(RpcInChannel* inChannel, const BYTE* data, int length);
-BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* length);
+int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length);
+int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length);
RpcInChannel* rpc_client_in_channel_new(rdpRpc* rpc);
-void rpc_client_in_channel_free(RpcInChannel* inChannel);
+void rpc_in_channel_free(RpcInChannel* inChannel);
-RpcOutChannel* rpc_client_out_channel_new(rdpRpc* rpc);
+RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc);
void rpc_client_out_channel_free(RpcOutChannel* outChannel);
-int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state);
-int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state);
+int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state);
+int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state);
-int rpc_client_virtual_connection_transition_to_state(rdpRpc* rpc,
+int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state);
-int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum);
-
BOOL rpc_connect(rdpRpc* rpc);
rdpRpc* rpc_new(rdpTransport* transport);
RpcClientCall* clientCall;
p_cont_elem_t* p_cont_elem;
rpcconn_bind_hdr_t* bind_pdu;
- rdpSettings* settings = rpc->settings;
BOOL promptPassword = FALSE;
+ rdpSettings* settings = rpc->settings;
freerdp* instance = (freerdp*) settings->instance;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
WLog_DBG(TAG, "Sending Bind PDU");
bind_pdu->frag_length = offset;
buffer = (BYTE*) malloc(bind_pdu->frag_length);
+
if (!buffer)
return -1;
return -1;
}
- status = rpc_send_pdu(rpc, buffer, length);
+ status = rpc_in_channel_send_pdu(inChannel, buffer, length);
free(bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes);
free(bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes);
UINT32 length;
RpcClientCall* clientCall;
rpcconn_rpc_auth_3_hdr_t* auth_3_pdu;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
WLog_DBG(TAG, "Sending RpcAuth3 PDU");
clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0);
ArrayList_Add(rpc->client->ClientCallList, clientCall);
- status = rpc_send_pdu(rpc, buffer, length);
+ status = rpc_in_channel_send_pdu(inChannel, buffer, length);
free(auth_3_pdu);
free(buffer);
return -1;
}
- rpc_client_virtual_connection_transition_to_state(rpc,
+ rpc_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_WAIT_C2);
status = 1;
return -1;
}
- rpc_client_virtual_connection_transition_to_state(rpc,
+ rpc_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OPENED);
rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_ESTABLISHED);
return 1;
}
-int rpc_client_recv(rdpRpc* rpc)
-{
- int status = -1;
- wStream* fragment;
- rpcconn_common_hdr_t* header;
-
- fragment = rpc->client->ReceiveFragment;
-
- while (1)
- {
- while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
- {
- status = rpc_out_read(rpc, Stream_Pointer(fragment),
- RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
-
- if (status < 0)
- return -1;
-
- if (!status)
- return 0;
-
- Stream_Seek(fragment, status);
- }
-
- if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
- return status;
-
- header = (rpcconn_common_hdr_t*) Stream_Buffer(fragment);
-
- if (header->frag_length > rpc->max_recv_frag)
- {
- WLog_ERR(TAG, "rpc_client_recv: invalid fragment size: %d (max: %d)",
- header->frag_length, rpc->max_recv_frag);
- winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment), Stream_GetPosition(fragment));
- return -1;
- }
-
- while (Stream_GetPosition(fragment) < header->frag_length)
- {
- status = rpc_out_read(rpc, Stream_Pointer(fragment),
- header->frag_length - Stream_GetPosition(fragment));
-
- if (status < 0)
- {
- WLog_ERR(TAG, "error reading fragment body");
- return -1;
- }
-
- if (!status)
- return 0;
-
- Stream_Seek(fragment, status);
- }
-
- if (status < 0)
- return -1;
-
- if (Stream_GetPosition(fragment) >= header->frag_length)
- {
- /* complete fragment received */
-
- Stream_SealLength(fragment);
- Stream_SetPosition(fragment, 0);
-
- status = rpc_client_recv_fragment(rpc, fragment);
-
- if (status < 0)
- return status;
-
- Stream_SetPosition(fragment, 0);
- }
- }
-
- return 1;
-}
-
int rpc_client_out_channel_recv(rdpRpc* rpc)
{
int status = -1;
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) outChannel);
- rpc_client_out_channel_transition_to_state(outChannel,
+ rpc_out_channel_transition_to_state(outChannel,
CLIENT_OUT_CHANNEL_STATE_NEGOTIATED);
/* Send CONN/A1 PDU over OUT channel */
return -1;
}
- rpc_client_out_channel_transition_to_state(outChannel,
+ rpc_out_channel_transition_to_state(outChannel,
CLIENT_OUT_CHANNEL_STATE_OPENED);
if (inChannel->State == CLIENT_IN_CHANNEL_STATE_OPENED)
{
- rpc_client_virtual_connection_transition_to_state(rpc,
+ rpc_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
}
http_response_free(response);
- rpc_client_virtual_connection_transition_to_state(rpc,
+ rpc_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_WAIT_A3W);
status = 1;
}
else
{
- status = rpc_client_recv(rpc);
+ wStream* fragment;
+ rpcconn_common_hdr_t* header;
+
+ fragment = rpc->client->ReceiveFragment;
+
+ while (1)
+ {
+ while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
+ {
+ status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment),
+ RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
+
+ if (status < 0)
+ return -1;
+
+ if (!status)
+ return 0;
+
+ Stream_Seek(fragment, status);
+ }
+
+ if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
+ return status;
+
+ header = (rpcconn_common_hdr_t*) Stream_Buffer(fragment);
+
+ if (header->frag_length > rpc->max_recv_frag)
+ {
+ WLog_ERR(TAG, "rpc_client_recv: invalid fragment size: %d (max: %d)",
+ header->frag_length, rpc->max_recv_frag);
+ winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment), Stream_GetPosition(fragment));
+ return -1;
+ }
+
+ while (Stream_GetPosition(fragment) < header->frag_length)
+ {
+ status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment),
+ header->frag_length - Stream_GetPosition(fragment));
+
+ if (status < 0)
+ {
+ WLog_ERR(TAG, "error reading fragment body");
+ return -1;
+ }
+
+ if (!status)
+ return 0;
+
+ Stream_Seek(fragment, status);
+ }
+
+ if (status < 0)
+ return -1;
+
+ if (Stream_GetPosition(fragment) >= header->frag_length)
+ {
+ /* complete fragment received */
+
+ Stream_SealLength(fragment);
+ Stream_SetPosition(fragment, 0);
+
+ status = rpc_client_recv_fragment(rpc, fragment);
+
+ if (status < 0)
+ return status;
+
+ Stream_SetPosition(fragment, 0);
+ }
+ }
}
return status;
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) inChannel);
- rpc_client_in_channel_transition_to_state(inChannel,
+ rpc_in_channel_transition_to_state(inChannel,
CLIENT_IN_CHANNEL_STATE_NEGOTIATED);
/* Send CONN/B1 PDU over IN channel */
return -1;
}
- rpc_client_in_channel_transition_to_state(inChannel,
+ rpc_in_channel_transition_to_state(inChannel,
CLIENT_IN_CHANNEL_STATE_OPENED);
if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
{
- rpc_client_virtual_connection_transition_to_state(rpc,
+ rpc_virtual_connection_transition_to_state(rpc,
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
}
free(clientCall);
}
-int rpc_send_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
+int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length)
{
int status;
- RpcInChannel* inChannel;
RpcClientCall* clientCall;
rpcconn_common_hdr_t* header;
+ rdpRpc* rpc = inChannel->rpc;
- inChannel = rpc->VirtualConnection->DefaultInChannel;
-
- status = rpc_in_write(rpc, buffer, length);
+ status = rpc_in_channel_write(inChannel, buffer, length);
if (status <= 0)
return -1;
return status;
}
+int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
+{
+ UINT32 offset;
+ BYTE* buffer = NULL;
+ UINT32 stub_data_pad;
+ SecBuffer Buffers[2];
+ SecBufferDesc Message;
+ RpcClientCall* clientCall;
+ rdpNtlm* ntlm = rpc->ntlm;
+ SECURITY_STATUS encrypt_status;
+ rpcconn_request_hdr_t* request_pdu = NULL;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
+
+ if (!ntlm || !ntlm->table)
+ {
+ WLog_ERR(TAG, "invalid ntlm context");
+ return -1;
+ }
+
+ if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
+ {
+ 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));
+
+ if (!request_pdu)
+ return -1;
+
+ rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) request_pdu);
+ request_pdu->ptype = PTYPE_REQUEST;
+ request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
+ request_pdu->auth_length = (UINT16) ntlm->ContextSizes.cbMaxSignature;
+ request_pdu->call_id = rpc->CallId++;
+ request_pdu->alloc_hint = length;
+ request_pdu->p_cont_id = 0x0000;
+ request_pdu->opnum = opnum;
+
+ clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum);
+
+ if (!clientCall)
+ goto out_free_pdu;
+
+ if (ArrayList_Add(rpc->client->ClientCallList, clientCall) < 0)
+ goto out_free_clientCall;
+
+ if (request_pdu->opnum == TsProxySetupReceivePipeOpnum)
+ rpc->PipeCallId = request_pdu->call_id;
+
+ request_pdu->stub_data = data;
+ offset = 24;
+ stub_data_pad = 0;
+ stub_data_pad = rpc_offset_align(&offset, 8);
+ offset += length;
+ request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
+ request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
+ request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
+ request_pdu->auth_verifier.auth_reserved = 0x00;
+ request_pdu->auth_verifier.auth_context_id = 0x00000000;
+ offset += (8 + request_pdu->auth_length);
+ request_pdu->frag_length = offset;
+
+ buffer = (BYTE*) calloc(1, request_pdu->frag_length);
+
+ if (!buffer)
+ goto out_free_pdu;
+
+ CopyMemory(buffer, request_pdu, 24);
+ offset = 24;
+ rpc_offset_pad(&offset, stub_data_pad);
+ CopyMemory(&buffer[offset], request_pdu->stub_data, length);
+ offset += length;
+ rpc_offset_pad(&offset, request_pdu->auth_verifier.auth_pad_length);
+ CopyMemory(&buffer[offset], &request_pdu->auth_verifier.auth_type, 8);
+ offset += 8;
+ Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */
+ Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */
+ Buffers[0].pvBuffer = buffer;
+ Buffers[0].cbBuffer = offset;
+ Buffers[1].cbBuffer = ntlm->ContextSizes.cbMaxSignature;
+ Buffers[1].pvBuffer = calloc(1, Buffers[1].cbBuffer);
+
+ if (!Buffers[1].pvBuffer)
+ goto out_free_pdu;
+
+ Message.cBuffers = 2;
+ Message.ulVersion = SECBUFFER_VERSION;
+ Message.pBuffers = (PSecBuffer) &Buffers;
+ encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, 0, &Message, rpc->SendSeqNum++);
+
+ if (encrypt_status != SEC_E_OK)
+ {
+ WLog_ERR(TAG, "EncryptMessage status: 0x%08X", encrypt_status);
+ goto out_free_pdu;
+ }
+
+ CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer);
+ offset += Buffers[1].cbBuffer;
+ free(Buffers[1].pvBuffer);
+
+ if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu->frag_length) < 0)
+ length = -1;
+
+ free(request_pdu);
+ free(buffer);
+
+ return length;
+
+out_free_clientCall:
+ rpc_client_call_free(clientCall);
+out_free_pdu:
+ free(buffer);
+ free(Buffers[1].pvBuffer);
+ free(request_pdu);
+ return -1;
+}
+
int rpc_client_new(rdpRpc* rpc)
{
RpcClient* client;
RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum);
void rpc_client_call_free(RpcClientCall* client_call);
-int rpc_send_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length);
-int rpc_client_recv(rdpRpc* rpc);
+int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length);
int rpc_client_in_channel_recv(rdpRpc* rpc);
int rpc_client_out_channel_recv(rdpRpc* rpc);
int rpc_client_receive_pipe_read(rdpRpc* rpc, BYTE* buffer, size_t length);
+int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum);
+
int rpc_client_new(rdpRpc* rpc);
void rpc_client_free(rdpRpc* rpc);
UINT32 ReceiveWindowSize;
BYTE* OUTChannelCookie;
BYTE* VirtualConnectionCookie;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcOutChannel* outChannel = connection->DefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 76;
WLog_DBG(TAG, "Sending CONN_A1 RTS PDU");
- VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie);
- OUTChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie);
- ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow;
+ VirtualConnectionCookie = (BYTE*) &(connection->Cookie);
+ OUTChannelCookie = (BYTE*) &(outChannel->Cookie);
+ ReceiveWindowSize = outChannel->ReceiveWindow;
buffer = (BYTE*) malloc(header.frag_length);
rts_cookie_command_write(&buffer[48], OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[68], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
- status = rpc_out_write(rpc, buffer, header.frag_length);
+ status = rpc_out_channel_write(outChannel, buffer, header.frag_length);
free(buffer);
BYTE* INChannelCookie;
BYTE* AssociationGroupId;
BYTE* VirtualConnectionCookie;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 104;
WLog_DBG(TAG, "Sending CONN_B1 RTS PDU");
- VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie);
- INChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultInChannel->Cookie);
- AssociationGroupId = (BYTE*) &(rpc->VirtualConnection->AssociationGroupId);
+ VirtualConnectionCookie = (BYTE*) &(connection->Cookie);
+ INChannelCookie = (BYTE*) &(inChannel->Cookie);
+ AssociationGroupId = (BYTE*) &(connection->AssociationGroupId);
buffer = (BYTE*) malloc(header.frag_length);
length = header.frag_length;
- status = rpc_in_write(rpc, buffer, length);
+ status = rpc_in_channel_write(inChannel, buffer, length);
free(buffer);
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
+ RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 28;
length = header.frag_length;
- status = rpc_in_write(rpc, buffer, length);
+ status = rpc_in_channel_write(inChannel, buffer, length);
free(buffer);
UINT32 BytesReceived;
UINT32 AvailableWindow;
BYTE* ChannelCookie;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
+ RpcOutChannel* outChannel = connection->DefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 56;
WLog_DBG(TAG, "Sending FlowControlAck RTS PDU");
- BytesReceived = rpc->VirtualConnection->DefaultOutChannel->BytesReceived;
- AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised;
- ChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie);
+ BytesReceived = outChannel->BytesReceived;
+ AvailableWindow = outChannel->AvailableWindowAdvertised;
+ ChannelCookie = (BYTE*) &(outChannel->Cookie);
- rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow =
- rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised;
+ outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
buffer = (BYTE*) malloc(header.frag_length);
length = header.frag_length;
- status = rpc_in_write(rpc, buffer, length);
+ status = rpc_in_channel_write(inChannel, buffer, length);
free(buffer);
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
+ RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 20;
length = header.frag_length;
- status = rpc_in_write(rpc, buffer, length);
+ status = rpc_in_channel_write(inChannel, buffer, length);
free(buffer);
BYTE* buffer;
rpcconn_rts_hdr_t header;
BYTE* SuccessorChannelCookie;
+ RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
+ RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 56;
WLog_DBG(TAG, "Sending OUT R2/A7 RTS PDU");
- SuccessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->NonDefaultOutChannel->Cookie);
+ SuccessorChannelCookie = (BYTE*) &(nextOutChannel->Cookie);
buffer = (BYTE*) malloc(header.frag_length);
rts_cookie_command_write(&buffer[28], SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
rts_version_command_write(&buffer[48]); /* Version (8 bytes) */
- status = rpc_out_write(rpc, buffer, header.frag_length);
+ status = rpc_out_channel_write(outChannel, buffer, header.frag_length);
free(buffer);
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
+ RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 24;
CopyMemory(buffer, ((BYTE*) &header), 20); /* RTS Header (20 bytes) */
rts_empty_command_write(&buffer[20]); /* Empty command (4 bytes) */
- status = rpc_out_write(rpc, buffer, header.frag_length);
+ status = rpc_out_channel_write(outChannel, buffer, header.frag_length);
free(buffer);
BYTE* VirtualConnectionCookie;
BYTE* PredecessorChannelCookie;
BYTE* SuccessorChannelCookie;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+ RpcOutChannel* outChannel = connection->DefaultOutChannel;
+ RpcOutChannel* nextOutChannel = connection->NonDefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 96;
WLog_DBG(TAG, "Sending OUT R1/A3 RTS PDU");
- VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie);
- PredecessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannel->Cookie);
- SuccessorChannelCookie = (BYTE*) &(rpc->VirtualConnection->NonDefaultOutChannel->Cookie);
- ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow;
+ VirtualConnectionCookie = (BYTE*) &(connection->Cookie);
+ PredecessorChannelCookie = (BYTE*) &(outChannel->Cookie);
+ SuccessorChannelCookie = (BYTE*) &(nextOutChannel->Cookie);
+ ReceiveWindowSize = outChannel->ReceiveWindow;
buffer = (BYTE*) malloc(header.frag_length);
rts_cookie_command_write(&buffer[68], SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[88], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
- status = rpc_out_write(rpc, buffer, header.frag_length);
+ status = rpc_out_channel_write(outChannel, buffer, header.frag_length);
free(buffer);
WLog_ERR(TAG, "TS Gateway channel recycling is incomplete");
- connection->NonDefaultOutChannel = rpc_client_out_channel_new(rpc);
+ connection->NonDefaultOutChannel = rpc_out_channel_new(rpc);
return 1;
}
if (buffer3Length > 0)
Stream_Write(s, buffer3, buffer3Length); /* buffer3 (variable) */
- Stream_Length(s) = Stream_GetPosition(s);
- status = rpc_write(tsg->rpc, Stream_Buffer(s), Stream_Length(s), TsProxySendToServerOpnum);
+ Stream_SealLength(s);
+ status = rpc_client_write_call(tsg->rpc, Stream_Buffer(s), Stream_Length(s), TsProxySendToServerOpnum);
Stream_Free(s, TRUE);
if (status <= 0)
CopyMemory(&buffer[88], &NDR_UUID, sizeof(p_uuid_t));
*((UINT32*) &buffer[104]) = NDR_SYNTAX_IF_VERSION;
- status = rpc_write(rpc, buffer, length, TsProxyCreateTunnelOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyCreateTunnelOpnum);
if (status <= 0)
return FALSE;
ZeroMemory(&buffer[offset - pad], pad);
*((UINT32*) &buffer[offset]) = 0x00000000; /* MaxCount */
offset += 4;
- status = rpc_write(rpc, buffer, length, TsProxyAuthorizeTunnelOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyAuthorizeTunnelOpnum);
if (status <= 0)
return FALSE;
*((UINT32*) &buffer[28]) = TSG_PACKET_TYPE_MSGREQUEST_PACKET; /* SwitchValue */
*((UINT32*) &buffer[32]) = 0x00020000; /* PacketMsgRequestPtr */
*((UINT32*) &buffer[36]) = 0x00000001; /* MaxMessagesPerBatch */
- status = rpc_write(rpc, buffer, length, TsProxyMakeTunnelCallOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyMakeTunnelCallOpnum);
if (status <= 0)
return FALSE;
*((UINT32*) &buffer[52]) = 0; /* Offset */
*((UINT32*) &buffer[56]) = count; /* ActualCount */
CopyMemory(&buffer[60], tsg->Hostname, count * 2); /* Array */
- status = rpc_write(rpc, buffer, length, TsProxyCreateChannelOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyCreateChannelOpnum);
if (status <= 0)
return FALSE;
/* TunnelContext */
CopyMemory(&buffer[0], &tsg->ChannelContext.ContextType, 4); /* ContextType */
CopyMemory(&buffer[4], tsg->ChannelContext.ContextUuid, 16); /* ContextUuid */
- status = rpc_write(rpc, buffer, length, TsProxyCloseChannelOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyCloseChannelOpnum);
if (status <= 0)
return FALSE;
/* TunnelContext */
CopyMemory(&buffer[0], &tsg->TunnelContext.ContextType, 4); /* ContextType */
CopyMemory(&buffer[4], tsg->TunnelContext.ContextUuid, 16); /* ContextUuid */
- status = rpc_write(rpc, buffer, length, TsProxyCloseTunnelOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxyCloseTunnelOpnum);
if (status <= 0)
return FALSE;
/* ChannelContext */
CopyMemory(&buffer[0], &tsg->ChannelContext.ContextType, 4); /* ContextType */
CopyMemory(&buffer[4], tsg->ChannelContext.ContextUuid, 16); /* ContextUuid */
- status = rpc_write(rpc, buffer, length, TsProxySetupReceivePipeOpnum);
+ status = rpc_client_write_call(rpc, buffer, length, TsProxySetupReceivePipeOpnum);
if (status <= 0)
return FALSE;