Implemented 2.2.1.17.1 Persistent Key List PDU Data, added checks

* Implemented missing server side version of PDU (just skip data)
* Refactored read/write functions to properly check stream
  length/capacity and handle return values.

(cherry picked from commit ec3c333656b4d8a00ff278a70b52c11b18e2d643)
This commit is contained in:
akallabeth 2020-11-19 15:21:49 +01:00 committed by akallabeth
parent db1287ddad
commit 812233e180
9 changed files with 181 additions and 64 deletions

View File

@ -38,14 +38,18 @@ static const char* const CTRLACTION_STRINGS[] =
*/ */
static BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s);
static BOOL rdp_recv_client_font_list_pdu(wStream* s); static BOOL rdp_recv_client_font_list_pdu(wStream* s);
static BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s);
static BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s);
static BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s);
static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp); static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
static void rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings) static BOOL rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings)
{ {
if (Stream_GetRemainingCapacity(s) < 4)
return FALSE;
Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */ Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */
Stream_Write_UINT16(s, settings->PduSource); /* targetUser (2 bytes) */ Stream_Write_UINT16(s, settings->PduSource); /* targetUser (2 bytes) */
return TRUE;
} }
BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s) BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s)
@ -65,7 +69,13 @@ BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s)
BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp) BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
rdp_write_synchronize_pdu(s, rdp->settings); if (!s)
return FALSE;
if (!rdp_write_synchronize_pdu(s, rdp->settings))
{
Stream_Free(s, TRUE);
return FALSE;
}
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
} }
@ -90,7 +100,13 @@ BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp) BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
rdp_write_synchronize_pdu(s, rdp->settings); if (!s)
return FALSE;
if (!rdp_write_synchronize_pdu(s, rdp->settings))
{
Stream_Free(s, TRUE);
return FALSE;
}
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
} }
@ -105,11 +121,14 @@ static BOOL rdp_recv_control_pdu(wStream* s, UINT16* action)
return TRUE; return TRUE;
} }
static void rdp_write_client_control_pdu(wStream* s, UINT16 action) static BOOL rdp_write_client_control_pdu(wStream* s, UINT16 action)
{ {
if (Stream_GetRemainingCapacity(s) < 8)
return FALSE;
Stream_Write_UINT16(s, action); /* action (2 bytes) */ Stream_Write_UINT16(s, action); /* action (2 bytes) */
Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */ Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */ Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
return TRUE;
} }
BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s) BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
@ -137,6 +156,13 @@ BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
if (!s)
return FALSE;
if (Stream_GetRemainingCapacity(s) < 8)
{
Stream_Free(s, TRUE);
return FALSE;
}
Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */ Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */ Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */ Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
@ -146,6 +172,13 @@ BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp) BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
if (!s)
return FALSE;
if (Stream_GetRemainingCapacity(s) < 8)
{
Stream_Free(s, TRUE);
return FALSE;
}
Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */ Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */ Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */
Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */ Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
@ -155,18 +188,29 @@ BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action) BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
rdp_write_client_control_pdu(s, action); if (!s)
return FALSE;
if (!rdp_write_client_control_pdu(s, action))
{
Stream_Free(s, TRUE);
return FALSE;
}
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
} }
static void rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2) static BOOL rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2)
{ {
if (Stream_GetRemainingCapacity(s) < 8)
return FALSE;
Stream_Write_UINT32(s, key1); /* key1 (4 bytes) */ Stream_Write_UINT32(s, key1); /* key1 (4 bytes) */
Stream_Write_UINT32(s, key2); /* key2 (4 bytes) */ Stream_Write_UINT32(s, key2); /* key2 (4 bytes) */
return TRUE;
} }
static void rdp_write_client_persistent_key_list_pdu(wStream* s, rdpSettings* settings) static BOOL rdp_write_client_persistent_key_list_pdu(wStream* s, const rdpSettings* settings)
{ {
if (Stream_GetRemainingCapacity(s) < 24)
return FALSE;
Stream_Write_UINT16(s, 0); /* numEntriesCache0 (2 bytes) */ Stream_Write_UINT16(s, 0); /* numEntriesCache0 (2 bytes) */
Stream_Write_UINT16(s, 0); /* numEntriesCache1 (2 bytes) */ Stream_Write_UINT16(s, 0); /* numEntriesCache1 (2 bytes) */
Stream_Write_UINT16(s, 0); /* numEntriesCache2 (2 bytes) */ Stream_Write_UINT16(s, 0); /* numEntriesCache2 (2 bytes) */
@ -181,38 +225,77 @@ static void rdp_write_client_persistent_key_list_pdu(wStream* s, rdpSettings* se
Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */ Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */
/* entries */ /* entries */
return TRUE;
} }
BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
{ {
wStream* s; wStream* s = rdp_data_pdu_init(rdp);
s = rdp_data_pdu_init(rdp); if (!s)
rdp_write_client_persistent_key_list_pdu(s, rdp->settings); return FALSE;
if (!rdp_write_client_persistent_key_list_pdu(s, rdp->settings))
{
Stream_Free(s, TRUE);
return FALSE;
}
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId);
} }
BOOL rdp_recv_client_font_list_pdu(wStream* s) BOOL rdp_recv_client_font_list_pdu(wStream* s)
{ {
if (Stream_GetRemainingLength(s) < 8) /* 2.2.1.18 Client Font List PDU */
return FALSE; return Stream_SafeSeek(s, 8);
/* 2.2.1.18.1 Font List PDU Data (TS_FONT_LIST_PDU) */
Stream_Seek(s, 8);
return TRUE;
} }
static void rdp_write_client_font_list_pdu(wStream* s, UINT16 flags) BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s)
{ {
BYTE flags;
size_t count = 0;
UINT16 cache, x;
/* 2.2.1.17.1 Persistent Key List PDU Data (TS_BITMAPCACHE_PERSISTENT_LIST_PDU) */
if (Stream_GetRemainingLength(s) < 21)
return FALSE;
/* Read numEntriesCacheX for variable length data in PDU */
for (x = 0; x < 5; x++)
{
Stream_Read_UINT16(s, cache);
count += cache;
}
/* Skip totalEntriesCacheX */
if (!Stream_SafeSeek(s, 10))
return FALSE;
Stream_Read_UINT8(s, flags);
/* Skip padding */
if (!Stream_SafeSeek(s, 3))
return FALSE;
/* Skip actual entries sent by client */
return Stream_SafeSeek(s, count * sizeof(UINT64));
}
static BOOL rdp_write_client_font_list_pdu(wStream* s, UINT16 flags)
{
if (Stream_GetRemainingCapacity(s) < 8)
return FALSE;
Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */ Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */
Stream_Write_UINT16(s, 0); /* totalNumFonts (2 bytes) */ Stream_Write_UINT16(s, 0); /* totalNumFonts (2 bytes) */
Stream_Write_UINT16(s, flags); /* listFlags (2 bytes) */ Stream_Write_UINT16(s, flags); /* listFlags (2 bytes) */
Stream_Write_UINT16(s, 50); /* entrySize (2 bytes) */ Stream_Write_UINT16(s, 50); /* entrySize (2 bytes) */
return TRUE;
} }
BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags) BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
{ {
wStream* s = rdp_data_pdu_init(rdp); wStream* s = rdp_data_pdu_init(rdp);
rdp_write_client_font_list_pdu(s, flags); if (!s)
return FALSE;
if (!rdp_write_client_font_list_pdu(s, flags))
{
Stream_Free(s, TRUE);
return FALSE;
}
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId);
} }
@ -247,8 +330,14 @@ BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s)
BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp) BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
{ {
wStream* s; wStream* s = rdp_data_pdu_init(rdp);
s = rdp_data_pdu_init(rdp); if (!s)
return FALSE;
if (Stream_GetRemainingCapacity(s) < 8)
{
Stream_Free(s, TRUE);
return FALSE;
}
Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */ Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */
Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */ Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */
Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */ Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
@ -314,15 +403,18 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
BOOL rdp_send_deactivate_all(rdpRdp* rdp) BOOL rdp_send_deactivate_all(rdpRdp* rdp)
{ {
wStream* s = rdp_send_stream_pdu_init(rdp); wStream* s = rdp_send_stream_pdu_init(rdp);
BOOL status; BOOL status = FALSE;
if (!s) if (!s)
return FALSE; return FALSE;
if (Stream_GetRemainingCapacity(s) < 7)
goto fail;
Stream_Write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */ Stream_Write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */ Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */
Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */ Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */
status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId); status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId);
fail:
Stream_Release(s); Stream_Release(s);
return status; return status;
} }
@ -384,3 +476,12 @@ BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
return TRUE; return TRUE;
} }
BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s)
{
if (!rdp_recv_client_persistent_key_list_pdu(s))
return FALSE;
// TODO: Actually do something with this
return TRUE;
}

View File

@ -55,5 +55,6 @@ FREERDP_LOCAL BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s);
#endif /* FREERDP_LIB_CORE_ACTIVATION_H */ #endif /* FREERDP_LIB_CORE_ACTIVATION_H */

View File

@ -734,7 +734,8 @@ BOOL mcs_send_connect_initial(rdpMcs* mcs)
if (length > UINT16_MAX) if (length > UINT16_MAX)
goto out; goto out;
Stream_SetPosition(s, bm); Stream_SetPosition(s, bm);
tpkt_write_header(s, (UINT16)length); if (!tpkt_write_header(s, (UINT16)length))
goto out;
tpdu_write_data(s); tpdu_write_data(s);
Stream_SetPosition(s, em); Stream_SetPosition(s, em);
Stream_SealLength(s); Stream_SealLength(s);
@ -796,11 +797,11 @@ BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
BOOL mcs_send_connect_response(rdpMcs* mcs) BOOL mcs_send_connect_response(rdpMcs* mcs)
{ {
size_t length; size_t length;
int status; int status = -1;
wStream* s; wStream* s = NULL;
size_t bm, em; size_t bm, em;
wStream* gcc_CCrsp; wStream* gcc_CCrsp = NULL;
wStream* server_data; wStream* server_data = NULL;
if (!mcs) if (!mcs)
return FALSE; return FALSE;
@ -814,14 +815,14 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
} }
if (!gcc_write_server_data_blocks(server_data, mcs)) if (!gcc_write_server_data_blocks(server_data, mcs))
goto error_data_blocks; goto out;
gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data)); gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data));
if (!gcc_CCrsp) if (!gcc_CCrsp)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
goto error_data_blocks; goto out;
} }
gcc_write_conference_create_response(gcc_CCrsp, server_data); gcc_write_conference_create_response(gcc_CCrsp, server_data);
@ -831,36 +832,31 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
if (!s) if (!s)
{ {
WLog_ERR(TAG, "Stream_New failed!"); WLog_ERR(TAG, "Stream_New failed!");
goto error_stream_s; goto out;
} }
bm = Stream_GetPosition(s); bm = Stream_GetPosition(s);
Stream_Seek(s, 7); Stream_Seek(s, 7);
if (!mcs_write_connect_response(s, mcs, gcc_CCrsp)) if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
goto error_write_connect_response; goto out;
em = Stream_GetPosition(s); em = Stream_GetPosition(s);
length = (em - bm); length = (em - bm);
if (length > UINT16_MAX) if (length > UINT16_MAX)
goto error_write_connect_response; goto out;
Stream_SetPosition(s, bm); Stream_SetPosition(s, bm);
tpkt_write_header(s, (UINT16)length); if (!tpkt_write_header(s, (UINT16)length))
goto out;
tpdu_write_data(s); tpdu_write_data(s);
Stream_SetPosition(s, em); Stream_SetPosition(s, em);
Stream_SealLength(s); Stream_SealLength(s);
status = transport_write(mcs->transport, s); status = transport_write(mcs->transport, s);
out:
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
Stream_Free(gcc_CCrsp, TRUE); Stream_Free(gcc_CCrsp, TRUE);
Stream_Free(server_data, TRUE); Stream_Free(server_data, TRUE);
return (status < 0) ? FALSE : TRUE; return (status < 0) ? FALSE : TRUE;
error_write_connect_response:
Stream_Free(s, TRUE);
error_stream_s:
Stream_Free(gcc_CCrsp, TRUE);
error_data_blocks:
Stream_Free(server_data, TRUE);
return FALSE;
} }
/** /**

View File

@ -1067,17 +1067,15 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
em = Stream_GetPosition(s); em = Stream_GetPosition(s);
Stream_SetPosition(s, bm); Stream_SetPosition(s, bm);
tpkt_write_header(s, length); status = tpkt_write_header(s, length);
tpdu_write_connection_confirm(s, length - 5); if (status)
Stream_SetPosition(s, em);
Stream_SealLength(s);
if (transport_write(nego->transport, s) < 0)
{ {
Stream_Free(s, TRUE); tpdu_write_connection_confirm(s, length - 5);
return FALSE; Stream_SetPosition(s, em);
} Stream_SealLength(s);
status = (transport_write(nego->transport, s) >= 0);
}
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
if (status) if (status)

View File

@ -300,7 +300,8 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLen
break; break;
case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
/* TODO: notify server bitmap cache data */ if (!rdp_server_accept_client_persistent_key_list_pdu(client->context->rdp, s))
return FALSE;
break; break;
case DATA_PDU_TYPE_FONT_LIST: case DATA_PDU_TYPE_FONT_LIST:
@ -385,6 +386,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
client->settings->PduSource = pduSource; client->settings->PduSource = pduSource;
WLog_DBG(TAG, "Received %s", pdu_type_to_str(pduType));
switch (pduType) switch (pduType)
{ {
case PDU_TYPE_DATA: case PDU_TYPE_DATA:
@ -424,9 +426,9 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
if (!freerdp_channel_peer_process(client, s, channelId)) if (!freerdp_channel_peer_process(client, s, channelId))
return -1; return -1;
} }
if (!tpkt_ensure_stream_consumed(s, length)) if (!tpkt_ensure_stream_consumed(s, length))
return -1; return -1;
return 0; return 0;
} }

View File

@ -110,9 +110,9 @@ const char* data_pdu_type_to_string(UINT8 type)
} }
static BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type, UINT16* channel_id); static BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type, UINT16* channel_id);
static void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, static BOOL rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type,
UINT16 channel_id); UINT16 channel_id);
static void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id); static BOOL rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id);
/** /**
* Read RDP Security Header.\n * Read RDP Security Header.\n
@ -199,13 +199,18 @@ BOOL rdp_read_share_control_header(wStream* s, UINT16* tpktLength, UINT16* remai
return TRUE; return TRUE;
} }
void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id) BOOL rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id)
{ {
if (length < RDP_PACKET_HEADER_MAX_LENGTH)
return FALSE;
if (Stream_GetRemainingCapacity(s) < 6)
return FALSE;
length -= RDP_PACKET_HEADER_MAX_LENGTH; length -= RDP_PACKET_HEADER_MAX_LENGTH;
/* Share Control Header */ /* Share Control Header */
Stream_Write_UINT16(s, length); /* totalLength */ Stream_Write_UINT16(s, length); /* totalLength */
Stream_Write_UINT16(s, type | 0x10); /* pduType */ Stream_Write_UINT16(s, type | 0x10); /* pduType */
Stream_Write_UINT16(s, channel_id); /* pduSource */ Stream_Write_UINT16(s, channel_id); /* pduSource */
return TRUE;
} }
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId, BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId,
@ -225,11 +230,16 @@ BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32*
return TRUE; return TRUE;
} }
void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id) BOOL rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id)
{ {
length -= RDP_PACKET_HEADER_MAX_LENGTH; const size_t headerLen = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SHARE_CONTROL_HEADER_LENGTH +
length -= RDP_SHARE_CONTROL_HEADER_LENGTH; RDP_SHARE_DATA_HEADER_LENGTH;
length -= RDP_SHARE_DATA_HEADER_LENGTH; if (length < headerLen)
return FALSE;
length -= headerLen;
if (Stream_GetRemainingCapacity(s) < 12)
return FALSE;
/* Share Data Header */ /* Share Data Header */
Stream_Write_UINT32(s, share_id); /* shareId (4 bytes) */ Stream_Write_UINT32(s, share_id); /* shareId (4 bytes) */
Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */ Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
@ -238,6 +248,7 @@ void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 sh
Stream_Write_UINT8(s, type); /* pduType2, Data PDU Type (1 byte) */ Stream_Write_UINT8(s, type); /* pduType2, Data PDU Type (1 byte) */
Stream_Write_UINT8(s, 0); /* compressedType (1 byte) */ Stream_Write_UINT8(s, 0); /* compressedType (1 byte) */
Stream_Write_UINT16(s, 0); /* compressedLength (2 bytes) */ Stream_Write_UINT16(s, 0); /* compressedLength (2 bytes) */
return TRUE;
} }
static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header) static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
@ -669,7 +680,8 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
sec_bytes = rdp_get_sec_bytes(rdp, 0); sec_bytes = rdp_get_sec_bytes(rdp, 0);
sec_hold = Stream_GetPosition(s); sec_hold = Stream_GetPosition(s);
Stream_Seek(s, sec_bytes); Stream_Seek(s, sec_bytes);
rdp_write_share_control_header(s, length - sec_bytes, type, channel_id); if (!rdp_write_share_control_header(s, length - sec_bytes, type, channel_id))
return FALSE;
Stream_SetPosition(s, sec_hold); Stream_SetPosition(s, sec_hold);
if (!rdp_security_stream_out(rdp, s, length, 0, &pad)) if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
@ -705,8 +717,10 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
sec_bytes = rdp_get_sec_bytes(rdp, 0); sec_bytes = rdp_get_sec_bytes(rdp, 0);
sec_hold = Stream_GetPosition(s); sec_hold = Stream_GetPosition(s);
Stream_Seek(s, sec_bytes); Stream_Seek(s, sec_bytes);
rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id); if (!rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id))
rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId); goto fail;
if (!rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId))
goto fail;
Stream_SetPosition(s, sec_hold); Stream_SetPosition(s, sec_hold);
if (!rdp_security_stream_out(rdp, s, length, 0, &pad)) if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
@ -1256,7 +1270,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
return TRUE; return TRUE;
} }
static const char* pdu_type_to_str(UINT16 pduType) const char* pdu_type_to_str(UINT16 pduType)
{ {
static char buffer[1024] = { 0 }; static char buffer[1024] = { 0 };
switch (pduType) switch (pduType)

View File

@ -227,7 +227,6 @@ FREERDP_LOCAL void rdp_free(rdpRdp* rdp);
#define RDP_TAG FREERDP_TAG("core.rdp") #define RDP_TAG FREERDP_TAG("core.rdp")
#ifdef WITH_DEBUG_RDP #ifdef WITH_DEBUG_RDP
#define DEBUG_RDP(...) WLog_DBG(RDP_TAG, __VA_ARGS__) #define DEBUG_RDP(...) WLog_DBG(RDP_TAG, __VA_ARGS__)
const char* data_pdu_type_to_string(UINT8 type);
#else #else
#define DEBUG_RDP(...) \ #define DEBUG_RDP(...) \
do \ do \
@ -235,6 +234,9 @@ const char* data_pdu_type_to_string(UINT8 type);
} while (0) } while (0)
#endif #endif
const char* data_pdu_type_to_string(UINT8 type);
const char* pdu_type_to_str(UINT16 pduType);
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags); BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags);
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo); BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo);

View File

@ -148,9 +148,12 @@ BOOL tpkt_ensure_stream_consumed_(wStream* s, UINT16 length, const char* fkt)
* @param length * @param length
*/ */
void tpkt_write_header(wStream* s, UINT16 length) BOOL tpkt_write_header(wStream* s, UINT16 length)
{ {
if (Stream_GetRemainingCapacity(s) < 4)
return FALSE;
Stream_Write_UINT8(s, 3); /* version */ Stream_Write_UINT8(s, 3); /* version */
Stream_Write_UINT8(s, 0); /* reserved */ Stream_Write_UINT8(s, 0); /* reserved */
Stream_Write_UINT16_BE(s, length); /* length */ Stream_Write_UINT16_BE(s, length); /* length */
return TRUE;
} }

View File

@ -30,7 +30,7 @@
FREERDP_LOCAL BOOL tpkt_verify_header(wStream* s); FREERDP_LOCAL BOOL tpkt_verify_header(wStream* s);
FREERDP_LOCAL BOOL tpkt_read_header(wStream* s, UINT16* length); FREERDP_LOCAL BOOL tpkt_read_header(wStream* s, UINT16* length);
FREERDP_LOCAL void tpkt_write_header(wStream* s, UINT16 length); FREERDP_LOCAL BOOL tpkt_write_header(wStream* s, UINT16 length);
#define tpkt_ensure_stream_consumed(s, length) \ #define tpkt_ensure_stream_consumed(s, length) \
tpkt_ensure_stream_consumed_((s), (length), __FUNCTION__) tpkt_ensure_stream_consumed_((s), (length), __FUNCTION__)
FREERDP_LOCAL BOOL tpkt_ensure_stream_consumed_(wStream* s, UINT16 length, const char* fkt); FREERDP_LOCAL BOOL tpkt_ensure_stream_consumed_(wStream* s, UINT16 length, const char* fkt);