Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRDP/FreeRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libfreerdp/core/gateway/rpc.c')
-rw-r--r--libfreerdp/core/gateway/rpc.c134
1 files changed, 78 insertions, 56 deletions
diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c
index c5f85922e..4d6bf9222 100644
--- a/libfreerdp/core/gateway/rpc.c
+++ b/libfreerdp/core/gateway/rpc.c
@@ -24,6 +24,7 @@
#endif
#include <winpr/crt.h>
+#include <assert.h>
#include <winpr/tchar.h>
#include <winpr/synch.h>
#include <winpr/dsparse.h>
@@ -46,6 +47,7 @@
#include "rpc_client.h"
#include "rpc.h"
+#include "rts.h"
#define TAG FREERDP_TAG("core.gateway.rpc")
@@ -88,8 +90,10 @@ static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST", "PTYPE_PING",
*
*/
-void rpc_pdu_header_print(rpcconn_hdr_t* header)
+void rpc_pdu_header_print(const rpcconn_hdr_t* header)
{
+ assert(header);
+
WLog_INFO(TAG, "rpc_vers: %" PRIu8 "", header->common.rpc_vers);
WLog_INFO(TAG, "rpc_vers_minor: %" PRIu8 "", header->common.rpc_vers_minor);
@@ -139,26 +143,30 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header)
}
}
-void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header)
+rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc)
{
- header->rpc_vers = rpc->rpc_vers;
- header->rpc_vers_minor = rpc->rpc_vers_minor;
- header->packed_drep[0] = rpc->packed_drep[0];
- header->packed_drep[1] = rpc->packed_drep[1];
- header->packed_drep[2] = rpc->packed_drep[2];
- header->packed_drep[3] = rpc->packed_drep[3];
+ rpcconn_common_hdr_t header = { 0 };
+ assert(rpc);
+
+ header.rpc_vers = rpc->rpc_vers;
+ header.rpc_vers_minor = rpc->rpc_vers_minor;
+ header.packed_drep[0] = rpc->packed_drep[0];
+ header.packed_drep[1] = rpc->packed_drep[1];
+ header.packed_drep[2] = rpc->packed_drep[2];
+ header.packed_drep[3] = rpc->packed_drep[3];
+ return header;
}
-UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment)
+size_t rpc_offset_align(size_t* offset, size_t alignment)
{
- UINT32 pad;
+ size_t pad;
pad = *offset;
*offset = (*offset + alignment - 1) & ~(alignment - 1);
pad = *offset - pad;
return pad;
}
-UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
+size_t rpc_offset_pad(size_t* offset, size_t pad)
{
*offset += pad;
return pad;
@@ -239,64 +247,67 @@ UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
*
*/
-BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length)
+BOOL rpc_get_stub_data_info(const rpcconn_hdr_t* header, size_t* poffset, size_t* length)
{
- UINT32 alloc_hint = 0;
- rpcconn_hdr_t* header;
+ size_t used = 0;
+ size_t offset = 0;
+ BOOL rc = FALSE;
UINT32 frag_length;
UINT32 auth_length;
- UINT32 auth_pad_length;
+ UINT32 auth_pad_length = 0;
UINT32 sec_trailer_offset;
- rpc_sec_trailer* sec_trailer;
- *offset = RPC_COMMON_FIELDS_LENGTH;
- header = ((rpcconn_hdr_t*)buffer);
+ const rpc_sec_trailer* sec_trailer = NULL;
+
+ assert(header);
+ assert(poffset);
+ assert(length);
+
+ offset = RPC_COMMON_FIELDS_LENGTH;
switch (header->common.ptype)
{
case PTYPE_RESPONSE:
- *offset += 8;
- rpc_offset_align(offset, 8);
- alloc_hint = header->response.alloc_hint;
+ offset += 8;
+ rpc_offset_align(&offset, 8);
+ sec_trailer = &header->response.auth_verifier;
break;
case PTYPE_REQUEST:
- *offset += 4;
- rpc_offset_align(offset, 8);
- alloc_hint = header->request.alloc_hint;
+ offset += 4;
+ rpc_offset_align(&offset, 8);
+ sec_trailer = &header->request.auth_verifier;
break;
case PTYPE_RTS:
- *offset += 4;
+ offset += 4;
break;
default:
WLog_ERR(TAG, "Unknown PTYPE: 0x%02" PRIX8 "", header->common.ptype);
- return FALSE;
+ goto fail;
}
- if (!length)
- return TRUE;
+ frag_length = header->common.frag_length;
+ auth_length = header->common.auth_length;
+
+ if (poffset)
+ *poffset = offset;
- if (header->common.ptype == PTYPE_REQUEST)
+ /* The fragment must be larger than the authentication trailer */
+ used = offset + auth_length + 8ull;
+ if (sec_trailer)
{
- UINT32 sec_trailer_offset;
- sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8;
- *length = sec_trailer_offset - *offset;
- return TRUE;
+ auth_pad_length = sec_trailer->auth_pad_length;
+ used += sec_trailer->auth_pad_length;
}
- frag_length = header->common.frag_length;
- auth_length = header->common.auth_length;
+ if (frag_length < used)
+ goto fail;
+
+ if (!length)
+ return TRUE;
+
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: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"",
- sec_trailer->auth_type, sec_trailer->auth_level,
- sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
- sec_trailer->auth_context_id);
-#endif
/**
* According to [MS-RPCE], auth_pad_length is the number of padding
@@ -310,18 +321,21 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
auth_length, (frag_length - (sec_trailer_offset + 8)));
}
- *length = frag_length - auth_length - 24 - 8 - auth_pad_length;
- return TRUE;
+ *length = sec_trailer_offset - auth_pad_length - offset;
+
+ rc = TRUE;
+fail:
+ return rc;
}
SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length)
{
int status;
- if (!channel)
+ if (!channel || (length > INT32_MAX))
return -1;
- status = BIO_read(channel->tls->bio, Stream_Pointer(s), length);
+ status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
if (status > 0)
{
@@ -340,10 +354,10 @@ SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length)
{
int status;
- if (!channel)
+ if (!channel || (length > INT32_MAX))
return -1;
- status = tls_write_all(channel->tls, data, length);
+ status = tls_write_all(channel->tls, data, (INT32)length);
return status;
}
@@ -629,7 +643,7 @@ static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
free(connection);
}
-static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
+static BOOL rpc_channel_tls_connect(RpcChannel* channel, UINT32 timeout)
{
int sockfd;
rdpTls* tls;
@@ -719,7 +733,7 @@ static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
return TRUE;
}
-static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout)
+static int rpc_in_channel_connect(RpcInChannel* inChannel, UINT32 timeout)
{
rdpContext* context;
@@ -814,7 +828,7 @@ int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
return 1;
}
-BOOL rpc_connect(rdpRpc* rpc, int timeout)
+BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
{
RpcInChannel* inChannel;
RpcOutChannel* outChannel;
@@ -840,7 +854,15 @@ BOOL rpc_connect(rdpRpc* rpc, int timeout)
rdpRpc* rpc_new(rdpTransport* transport)
{
- rdpRpc* rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
+ rdpContext* context;
+ rdpRpc* rpc;
+
+ assert(transport);
+
+ context = transport->context;
+ assert(context);
+
+ rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
if (!rpc)
return NULL;
@@ -848,7 +870,7 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->State = RPC_CLIENT_STATE_INITIAL;
rpc->transport = transport;
rpc->settings = transport->settings;
- rpc->context = transport->context;
+ rpc->context = context;
rpc->SendSeqNum = 0;
rpc->ntlm = ntlm_new();
@@ -873,7 +895,7 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
rpc->CurrentKeepAliveTime = 0;
rpc->CallId = 2;
- rpc->client = rpc_client_new(rpc->context, rpc->max_recv_frag);
+ rpc->client = rpc_client_new(context, rpc->max_recv_frag);
if (!rpc->client)
goto out_free;