Added tpkt header length plausibility checks.
This commit is contained in:
parent
66352741f2
commit
318cb3dd47
@ -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])
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -530,6 +530,8 @@ int license_recv(rdpLicense* license, wStream* s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!tpkt_ensure_stream_consumed(s, length))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user