Added tpkt header length plausibility checks.

This commit is contained in:
Armin Novak 2020-02-20 08:22:19 +01:00 committed by akallabeth
parent 66352741f2
commit 318cb3dd47
14 changed files with 153 additions and 83 deletions

View File

@ -3486,20 +3486,20 @@ static BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOO
}
#endif
static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCapabilities)
static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCapabilities,
UINT16 totalLength)
{
BYTE* mark;
UINT16 count;
UINT16 type;
UINT16 length;
BYTE *bm, *em;
BOOL treated;
Stream_GetPointer(s, mark);
count = numberCapabilities;
size_t start, end, len;
UINT16 count = numberCapabilities;
start = Stream_GetPosition(s);
while (numberCapabilities > 0 && Stream_GetRemainingLength(s) >= 4)
{
Stream_GetPointer(s, bm);
UINT16 type;
UINT16 length;
BYTE* em;
BYTE* bm = Stream_Pointer(s);
rdp_read_capability_set_header(s, &length, &type);
if (type < 32)
@ -3513,7 +3513,7 @@ static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 n
em = bm + length;
if (Stream_GetRemainingLength(s) < ((size_t)length - 4))
if (Stream_GetRemainingLength(s) + 4 < ((size_t)length))
{
WLog_ERR(TAG, "error processing stream");
return FALSE;
@ -3733,12 +3733,15 @@ static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 n
WLog_ERR(TAG,
"incorrect offset, type:0x%04" PRIX16 " actual:%" PRIuz " expected:%" PRIuz "",
type, Stream_Pointer(s) - bm, em - bm);
Stream_SetPointer(s, em);
}
Stream_SetPointer(s, em);
numberCapabilities--;
}
end = Stream_GetPosition(s);
len = end - start;
if (numberCapabilities)
{
WLog_ERR(TAG,
@ -3748,21 +3751,26 @@ static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 n
}
#ifdef WITH_DEBUG_CAPABILITIES
Stream_GetPointer(s, em);
Stream_SetPointer(s, mark);
numberCapabilities = count;
rdp_print_capability_sets(s, numberCapabilities, TRUE);
Stream_SetPointer(s, em);
{
Stream_SetPosition(s, start);
numberCapabilities = count;
rdp_print_capability_sets(s, numberCapabilities, TRUE);
Stream_SetPosition(s, end);
}
#endif
if (len < totalLength)
{
if (!Stream_SafeSeek(s, totalLength - len))
return FALSE;
}
return TRUE;
}
BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId, UINT16* length)
{
UINT16 length;
UINT16 securityFlags = 0;
if (!rdp_read_header(rdp, s, &length, pChannelId))
if (!rdp_read_header(rdp, s, length, pChannelId))
return FALSE;
if (freerdp_shall_disconnect(rdp->instance))
@ -3770,12 +3778,12 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
if (rdp->settings->UseRdpSecurityLayer)
{
if (!rdp_read_security_header(s, &securityFlags, &length))
if (!rdp_read_security_header(s, &securityFlags, length))
return FALSE;
if (securityFlags & SEC_ENCRYPT)
{
if (!rdp_decrypt(rdp, s, length, securityFlags))
if (!rdp_decrypt(rdp, s, *length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return FALSE;
@ -3803,11 +3811,12 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
UINT16 pduType;
UINT16 pduLength;
UINT16 pduSource;
UINT16 length;
UINT16 numberCapabilities;
UINT16 lengthSourceDescriptor;
UINT16 lengthCombinedCapabilities;
if (!rdp_recv_get_active_header(rdp, s, &channelId))
if (!rdp_recv_get_active_header(rdp, s, &channelId, &length))
return FALSE;
if (freerdp_shall_disconnect(rdp->instance))
@ -3857,14 +3866,14 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
/* capabilitySets */
if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities))
if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities, lengthCombinedCapabilities))
{
WLog_ERR(TAG, "rdp_read_capability_sets failed");
return FALSE;
}
rdp->update->secondary->glyph_v2 = (rdp->settings->GlyphSupportLevel > GLYPH_SUPPORT_FULL);
return TRUE;
return tpkt_ensure_stream_consumed(s, length);
}
static BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings)
@ -3970,13 +3979,14 @@ BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s)
Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
Stream_Read_UINT16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */
if (((int)Stream_GetRemainingLength(s)) < lengthSourceDescriptor + 4)
if ((Stream_GetRemainingLength(s)) < lengthSourceDescriptor + 4)
return FALSE;
Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor */
Stream_Read_UINT16(s, numberCapabilities); /* numberCapabilities (2 bytes) */
Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
status = rdp_read_capability_sets(s, rdp->settings, numberCapabilities);
status =
rdp_read_capability_sets(s, rdp->settings, numberCapabilities, lengthCombinedCapabilities);
if (!settings->ReceivedCapabilities[CAPSET_TYPE_SURFACE_COMMANDS])
{

View File

@ -165,7 +165,8 @@
#define CLW_ENTROPY_RLGR1 0x01
#define CLW_ENTROPY_RLGR3 0x04
FREERDP_LOCAL BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId);
FREERDP_LOCAL BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId,
UINT16* length);
FREERDP_LOCAL BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_send_demand_active(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s);

View File

@ -55,7 +55,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, int s
int left;
wStream* s;
UINT32 flags;
int chunkSize;
size_t chunkSize;
rdpMcs* mcs = rdp->mcs;
rdpMcsChannel* channel = NULL;
@ -126,7 +126,7 @@ BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId)
{
UINT32 length;
UINT32 flags;
int chunkLength;
size_t chunkLength;
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
@ -134,9 +134,11 @@ BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId)
Stream_Read_UINT32(s, length);
Stream_Read_UINT32(s, flags);
chunkLength = Stream_GetRemainingLength(s);
if (length > chunkLength)
return FALSE;
IFCALL(instance->ReceiveChannelData, instance, channelId, Stream_Pointer(s), chunkLength, flags,
length);
return TRUE;
return Stream_SafeSeek(s, length);
}
BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)

View File

@ -852,7 +852,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key)
goto end;
ret = TRUE;
ret = tpkt_ensure_stream_consumed(s, length);
end:
free(crypt_client_random);
@ -999,7 +999,7 @@ BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s)
}
if (rdp_recv_message_channel_pdu(rdp, s, securityFlags) == 0)
return TRUE;
return tpkt_ensure_stream_consumed(s, length);
}
}
@ -1036,20 +1036,28 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
BYTE* mark;
UINT16 width;
UINT16 height;
UINT16 length;
width = rdp->settings->DesktopWidth;
height = rdp->settings->DesktopHeight;
Stream_GetPointer(s, mark);
if (!rdp_recv_demand_active(rdp, s))
{
int rc;
UINT16 channelId;
Stream_SetPointer(s, mark);
rdp_recv_get_active_header(rdp, s, &channelId);
if (!rdp_recv_get_active_header(rdp, s, &channelId, &length))
return -1;
/* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
* but the headers aren't always that length,
* so that could result in a bad offset.
*/
return rdp_recv_out_of_sequence_pdu(rdp, s);
rc = rdp_recv_out_of_sequence_pdu(rdp, s);
if (rc < 0)
return rc;
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return rc;
}
if (freerdp_shall_disconnect(rdp->instance))

View File

@ -478,7 +478,7 @@ fail:
* @param settings settings
*/
static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength)
{
UINT32 flags;
UINT16 cbDomain;
@ -701,7 +701,7 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (settings->RdpVersion >= RDP_VERSION_5_PLUS)
return rdp_read_extended_info_packet(rdp, s); /* extraInfo */
return TRUE;
return tpkt_ensure_stream_consumed(s, tpktlength);
}
/**
@ -818,9 +818,11 @@ static BOOL rdp_write_info_packet(rdpRdp* rdp, wStream* s)
{
if (settings->RedirectionPassword && settings->RedirectionPasswordLength > 0)
{
if (settings->RedirectionPasswordLength > UINT16_MAX)
return FALSE;
usedPasswordCookie = TRUE;
passwordW = (WCHAR*)settings->RedirectionPassword;
cbPassword = (UINT16)settings->RedirectionPasswordLength;
}
@ -985,7 +987,7 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
}
}
return rdp_read_info_packet(rdp, s);
return rdp_read_info_packet(rdp, s, length);
}
/**

View File

@ -530,6 +530,8 @@ int license_recv(rdpLicense* license, wStream* s)
return -1;
}
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return 0;
}

View File

@ -245,7 +245,7 @@ BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU,
if (!tpkt_read_header(s, length))
return FALSE;
if (!tpdu_read_data(s, &li))
if (!tpdu_read_data(s, &li, *length))
return FALSE;
MCSPDU = *domainMCSPDU;
@ -273,7 +273,7 @@ void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU,
{
tpkt_write_header(s, length);
tpdu_write_data(s);
per_write_choice(s, (domainMCSPDU << 2) | options);
per_write_choice(s, (BYTE)((domainMCSPDU << 2) | options));
}
/**
@ -529,7 +529,7 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
if (!tpkt_read_header(s, &tlength))
return FALSE;
if (!tpdu_read_data(s, &li))
if (!tpdu_read_data(s, &li, tlength))
return FALSE;
if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
@ -573,7 +573,7 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
&mcs->maximumParameters, &mcs->domainParameters))
return FALSE;
return TRUE;
return tpkt_ensure_stream_consumed(s, tlength);
}
/**
@ -731,8 +731,10 @@ BOOL mcs_send_connect_initial(rdpMcs* mcs)
em = Stream_GetPosition(s);
length = (em - bm);
if (length > UINT16_MAX)
goto out;
Stream_SetPosition(s, bm);
tpkt_write_header(s, length);
tpkt_write_header(s, (UINT16)length);
tpdu_write_data(s);
Stream_SetPosition(s, em);
Stream_SealLength(s);
@ -764,7 +766,7 @@ BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
if (!tpkt_read_header(s, &tlength))
return FALSE;
if (!tpdu_read_data(s, &li))
if (!tpdu_read_data(s, &li, tlength))
return FALSE;
if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
@ -782,7 +784,7 @@ BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
return FALSE;
}
return TRUE;
return tpkt_ensure_stream_consumed(s, tlength);
}
/**
@ -840,8 +842,10 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
em = Stream_GetPosition(s);
length = (em - bm);
if (length > UINT16_MAX)
goto error_write_connect_response;
Stream_SetPosition(s, bm);
tpkt_write_header(s, length);
tpkt_write_header(s, (UINT16)length);
tpdu_write_data(s);
Stream_SetPosition(s, em);
Stream_SealLength(s);
@ -887,7 +891,7 @@ BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
return FALSE;
return TRUE;
return tpkt_ensure_stream_consumed(s, length);
}
/**
@ -938,7 +942,9 @@ BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s)
return FALSE;
MCSPDU = DomainMCSPDU_AttachUserRequest;
return mcs_read_domain_mcspdu_header(s, &MCSPDU, &length);
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
return FALSE;
return tpkt_ensure_stream_consumed(s, length);
}
/**
@ -979,7 +985,6 @@ BOOL mcs_send_attach_user_request(rdpMcs* mcs)
BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
{
BOOL status;
BYTE result;
UINT16 length;
enum DomainMCSPDU MCSPDU;
@ -988,10 +993,13 @@ BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
return FALSE;
MCSPDU = DomainMCSPDU_AttachUserConfirm;
status = mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) &&
per_read_enumerated(s, &result, MCS_Result_enum_length) && /* result */
per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
return status;
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
return FALSE;
if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
return FALSE;
if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
return FALSE;
return tpkt_ensure_stream_consumed(s, length);
}
/**
@ -1044,9 +1052,15 @@ BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channelId)
return FALSE;
MCSPDU = DomainMCSPDU_ChannelJoinRequest;
return mcs_read_domain_mcspdu_header(s, &MCSPDU, &length) &&
per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID) && (userId == mcs->userId) &&
per_read_integer16(s, channelId, 0);
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
return FALSE;
if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID) && (userId == mcs->userId))
return FALSE;
if (!per_read_integer16(s, channelId, 0))
return FALSE;
return tpkt_ensure_stream_consumed(s, length);
}
/**
@ -1102,12 +1116,18 @@ BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId)
status = TRUE;
MCSPDU = DomainMCSPDU_ChannelJoinConfirm;
status &= mcs_read_domain_mcspdu_header(s, &MCSPDU, &length);
status &= per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */
status &= per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
status &= per_read_integer16(s, &requested, 0); /* requested (ChannelId) */
status &= per_read_integer16(s, channelId, 0); /* channelId */
return status;
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
return FALSE;
if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
return FALSE;
if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
return FALSE;
if (!per_read_integer16(s, &requested, 0)) /* requested (ChannelId) */
return FALSE;
if (!per_read_integer16(s, channelId, 0)) /* channelId */
return FALSE;
return tpkt_ensure_stream_consumed(s, length);
}
/**

View File

@ -607,10 +607,7 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
if (!tpkt_read_header(s, &length))
return -1;
if (length == 0)
return -1;
if (!tpdu_read_connection_confirm(s, &li))
if (!tpdu_read_connection_confirm(s, &li, length))
return -1;
if (li > 6)
@ -667,6 +664,8 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
nego->state = NEGO_STATE_FAIL;
}
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return 0;
}
@ -770,7 +769,7 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
if (!tpkt_read_header(s, &length))
return FALSE;
if (!tpdu_read_connection_request(s, &li))
if (!tpdu_read_connection_request(s, &li, length))
return FALSE;
if (li != Stream_GetRemainingLength(s) + 6)
@ -799,7 +798,7 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
nego_process_negotiation_request(nego, s);
}
return TRUE;
return tpkt_ensure_stream_consumed(s, length);
}
/**

View File

@ -430,6 +430,8 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
return -1;
}
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return 0;
}

View File

@ -371,7 +371,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
if (!tpkt_read_header(s, length))
return FALSE;
if (!tpdu_read_header(s, &code, &li))
if (!tpdu_read_header(s, &code, &li, *length))
return FALSE;
if (code != X224_TPDU_DATA)
@ -1231,6 +1231,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, INT32 length, UINT16 securityFlags)
static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
{
int rc = 0;
UINT16 length;
UINT16 pduType;
UINT16 pduLength;
@ -1278,7 +1279,9 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
*/
Stream_Rewind(s, 2);
rdp->inPackets++;
return rdp_recv_enhanced_security_redirection_packet(rdp, s);
rc = rdp_recv_enhanced_security_redirection_packet(rdp, s);
goto out;
}
}
@ -1320,7 +1323,6 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
case PDU_TYPE_SERVER_REDIRECTION:
return rdp_recv_enhanced_security_redirection_packet(rdp, s);
break;
case PDU_TYPE_FLOW_RESPONSE:
case PDU_TYPE_FLOW_STOP:
@ -1342,7 +1344,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
rdp->inPackets++;
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
rc = rdp_recv_message_channel_pdu(rdp, s, securityFlags);
}
else
{
@ -1355,7 +1357,10 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
}
}
return 0;
out:
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return rc;
}
static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)

View File

@ -74,7 +74,7 @@ static void tpdu_write_header(wStream* s, UINT16 length, BYTE code);
* @return TPDU length indicator (LI)
*/
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li)
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li, UINT16 tpktlength)
{
if (Stream_GetRemainingLength(s) < 3)
return FALSE;
@ -82,6 +82,12 @@ BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li)
Stream_Read_UINT8(s, *li); /* LI */
Stream_Read_UINT8(s, *code); /* Code */
if (*li + 4 > tpktlength)
{
WLog_ERR(TAG, "tpdu length %" PRIu16 " > tpkt header length %" PRIu16, li, tpktlength);
return FALSE;
}
if (*code == X224_TPDU_DATA)
{
/* EOT (1 byte) */
@ -128,11 +134,11 @@ void tpdu_write_header(wStream* s, UINT16 length, BYTE code)
* @return length indicator (LI)
*/
BOOL tpdu_read_connection_request(wStream* s, BYTE* li)
BOOL tpdu_read_connection_request(wStream* s, BYTE* li, UINT16 tpktlength)
{
BYTE code;
if (!tpdu_read_header(s, &code, li))
if (!tpdu_read_header(s, &code, li, tpktlength))
return FALSE;
if (code != X224_TPDU_CONNECTION_REQUEST)
@ -161,7 +167,7 @@ void tpdu_write_connection_request(wStream* s, UINT16 length)
* @return length indicator (LI)
*/
BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li)
BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li, UINT16 tpktlength)
{
BYTE code;
size_t position;
@ -170,7 +176,7 @@ BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li)
/* save the position to determine the number of bytes read */
position = Stream_GetPosition(s);
if (!tpdu_read_header(s, &code, li))
if (!tpdu_read_header(s, &code, li, tpktlength))
return FALSE;
if (code != X224_TPDU_CONNECTION_CONFIRM)
@ -227,12 +233,12 @@ void tpdu_write_data(wStream* s)
* @param s stream
*/
BOOL tpdu_read_data(wStream* s, UINT16* LI)
BOOL tpdu_read_data(wStream* s, UINT16* LI, UINT16 tpktlength)
{
BYTE code;
BYTE li;
if (!tpdu_read_header(s, &code, &li))
if (!tpdu_read_header(s, &code, &li, tpktlength))
return FALSE;
if (code != X224_TPDU_DATA)

View File

@ -42,13 +42,13 @@ enum X224_TPDU_TYPE
#define TPDU_CONNECTION_CONFIRM_LENGTH (TPKT_HEADER_LENGTH + TPDU_CONNECTION_CONFIRM_HEADER_LENGTH)
#define TPDU_DISCONNECT_REQUEST_LENGTH (TPKT_HEADER_LENGTH + TPDU_DISCONNECT_REQUEST_HEADER_LENGTH)
FREERDP_LOCAL BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li);
FREERDP_LOCAL BOOL tpdu_read_connection_request(wStream* s, BYTE* li);
FREERDP_LOCAL BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li, UINT16 tpktlength);
FREERDP_LOCAL BOOL tpdu_read_connection_request(wStream* s, BYTE* li, UINT16 tpktlength);
FREERDP_LOCAL void tpdu_write_connection_request(wStream* s, UINT16 length);
FREERDP_LOCAL BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li);
FREERDP_LOCAL BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li, UINT16 tpktlength);
FREERDP_LOCAL void tpdu_write_connection_confirm(wStream* s, UINT16 length);
FREERDP_LOCAL void tpdu_write_disconnect_request(wStream* s, UINT16 length);
FREERDP_LOCAL BOOL tpdu_read_data(wStream* s, UINT16* li);
FREERDP_LOCAL BOOL tpdu_read_data(wStream* s, UINT16* li, UINT16 tpktlength);
FREERDP_LOCAL void tpdu_write_data(wStream* s);
#endif /* FREERDP_LIB_CORE_TPDU_H */

View File

@ -129,6 +129,18 @@ BOOL tpkt_read_header(wStream* s, UINT16* length)
return TRUE;
}
BOOL tpkt_ensure_stream_consumed(wStream* s, UINT16 length)
{
size_t rem = Stream_GetRemainingLength(s);
if (rem > 0)
{
WLog_ERR(TAG, "Received invalid TPKT header length %" PRIu16 ", %" PRIdz " bytes too long!",
length, rem);
return FALSE;
}
return TRUE;
}
/**
* Write a TPKT header.\n
* @param s

View File

@ -31,5 +31,6 @@
FREERDP_LOCAL BOOL tpkt_verify_header(wStream* s);
FREERDP_LOCAL BOOL tpkt_read_header(wStream* s, UINT16* length);
FREERDP_LOCAL void tpkt_write_header(wStream* s, UINT16 length);
FREERDP_LOCAL BOOL tpkt_ensure_stream_consumed(wStream* s, UINT16 length);
#endif /* FREERDP_LIB_CORE_TPKT_H */