File freerdp-Fix-TALOS-issues.patch of Package freerdp.5376
diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c
index d6e46e8..1a16b03 100644
--- a/libfreerdp/core/capabilities.c
+++ b/libfreerdp/core/capabilities.c
@@ -3657,12 +3657,12 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
if (rdp->settings->UseRdpSecurityLayer)
{
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
return FALSE;
if (securityFlags & SEC_ENCRYPT)
{
- if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
+ if (!rdp_decrypt(rdp, s, length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return FALSE;
diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c
index 9ce68f3..d750685 100644
--- a/libfreerdp/core/certificate.c
+++ b/libfreerdp/core/certificate.c
@@ -361,7 +361,6 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w
UINT32 keylen;
UINT32 bitlen;
UINT32 datalen;
- UINT32 modlen;
if (Stream_GetRemainingLength(s) < 20)
return FALSE;
@@ -378,12 +377,11 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w
Stream_Read_UINT32(s, bitlen);
Stream_Read_UINT32(s, datalen);
Stream_Read(s, certificate->cert_info.exponent, 4);
- modlen = keylen - 8;
- if (Stream_GetRemainingLength(s) < modlen + 8) // count padding
+ if ((keylen <= 8) || (Stream_GetRemainingLength(s) < keylen))
return FALSE;
- certificate->cert_info.ModulusLength = modlen;
+ certificate->cert_info.ModulusLength = keylen - 8;
certificate->cert_info.Modulus = malloc(certificate->cert_info.ModulusLength);
if (!certificate->cert_info.Modulus)
@@ -547,7 +545,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s)
{
- int i;
+ UINT32 i;
BOOL ret;
UINT32 certLength;
UINT32 numCertBlobs;
@@ -563,7 +561,7 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
if (!certificate->x509_cert_chain)
return FALSE;
- for (i = 0; i < (int) numCertBlobs; i++)
+ for (i = 0; i < numCertBlobs; i++)
{
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
@@ -622,7 +620,7 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
* @param length certificate length
*/
-BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, int length)
+BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, size_t length)
{
BOOL ret;
wStream* s;
diff --git a/libfreerdp/core/certificate.h b/libfreerdp/core/certificate.h
index a48701b..3b0b4a2 100644
--- a/libfreerdp/core/certificate.h
+++ b/libfreerdp/core/certificate.h
@@ -51,7 +51,7 @@ void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain);
BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s);
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s);
-BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, int length);
+BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, size_t length);
rdpCertificate* certificate_clone(rdpCertificate* certificate);
diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c
index f66e181..e03ffb9 100644
--- a/libfreerdp/core/connection.c
+++ b/libfreerdp/core/connection.c
@@ -565,7 +565,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
return FALSE;
}
- if (!rdp_read_security_header(s, &sec_flags))
+ if (!rdp_read_security_header(s, &sec_flags, NULL))
{
WLog_ERR(TAG, "invalid security header");
return FALSE;
@@ -787,7 +787,7 @@ BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s)
{
UINT16 securityFlags;
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
return FALSE;
if (rdp_recv_message_channel_pdu(rdp, s, securityFlags) == 0)
diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c
index e19e019..019b48b 100644
--- a/libfreerdp/core/gcc.c
+++ b/libfreerdp/core/gcc.c
@@ -33,6 +33,7 @@
#define TAG FREERDP_TAG("core.gcc")
+
/**
* T.124 GCC is defined in:
*
@@ -1113,34 +1114,49 @@ BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs)
Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */
- if (Stream_GetRemainingLength(s) < settings->ServerRandomLength + settings->ServerCertificateLength)
+ if ((settings->ServerRandomLength == 0) || (settings->ServerCertificateLength == 0))
return FALSE;
- if ((settings->ServerRandomLength <= 0) || (settings->ServerCertificateLength <= 0))
+ if (Stream_GetRemainingLength(s) < settings->ServerRandomLength)
return FALSE;
/* serverRandom */
settings->ServerRandom = (BYTE*) malloc(settings->ServerRandomLength);
if (!settings->ServerRandom)
- return FALSE;
+ goto fail;
Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
+
+ if (Stream_GetRemainingLength(s) < settings->ServerCertificateLength)
+ goto fail;
+
/* serverCertificate */
settings->ServerCertificate = (BYTE*) malloc(settings->ServerCertificateLength);
if (!settings->ServerCertificate)
- return FALSE;
+ goto fail;
Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
certificate_free(settings->RdpServerCertificate);
settings->RdpServerCertificate = certificate_new();
if (!settings->RdpServerCertificate)
- return FALSE;
+ goto fail;
data = settings->ServerCertificate;
length = settings->ServerCertificateLength;
- return certificate_read_server_certificate(settings->RdpServerCertificate, data, length);
+ if (!certificate_read_server_certificate(settings->RdpServerCertificate, data,
+ length))
+ goto fail;
+
+ return TRUE;
+
+ fail:
+ free (settings->ServerRandom);
+ free (settings->ServerCertificate);
+ settings->ServerRandom = NULL;
+ settings->ServerCertificate = NULL;
+ return FALSE;
}
static const BYTE initial_signature[] =
diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c
index 4f6c703..ab1161a 100644
--- a/libfreerdp/core/info.c
+++ b/libfreerdp/core/info.c
@@ -759,7 +759,7 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
if (!rdp_read_header(rdp, s, &length, &channelId))
return FALSE;
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
return FALSE;
if ((securityFlags & SEC_INFO_PKT) == 0)
@@ -775,7 +775,7 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
if (securityFlags & SEC_ENCRYPT)
{
- if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
+ if (!rdp_decrypt(rdp, s, length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return FALSE;
diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c
index 055a2dc..83328c1 100644
--- a/libfreerdp/core/license.c
+++ b/libfreerdp/core/license.c
@@ -36,6 +36,40 @@
/* #define LICENSE_NULL_CLIENT_RANDOM 1 */
/* #define LICENSE_NULL_PREMASTER_SECRET 1 */
+static wStream* license_send_stream_init(rdpLicense* license);
+
+static void license_generate_randoms(rdpLicense* license);
+static BOOL license_generate_keys(rdpLicense* license);
+static BOOL license_generate_hwid(rdpLicense* license);
+static BOOL license_encrypt_premaster_secret(rdpLicense* license);
+static BOOL license_decrypt_platform_challenge(rdpLicense* license);
+
+static LICENSE_PRODUCT_INFO* license_new_product_info(void);
+static void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
+static BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
+
+static LICENSE_BLOB* license_new_binary_blob(UINT16 type);
+static void license_free_binary_blob(LICENSE_BLOB* blob);
+static BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
+static BOOL license_write_binary_blob(wStream* s, LICENSE_BLOB* blob);
+
+static SCOPE_LIST* license_new_scope_list(void);
+static void license_free_scope_list(SCOPE_LIST* scopeList);
+static BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
+
+static BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
+static BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
+static void license_read_new_license_packet(rdpLicense* license, wStream* s);
+static void license_read_upgrade_license_packet(rdpLicense* license, wStream* s);
+static BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
+
+static BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s);
+static BOOL license_send_new_license_request_packet(rdpLicense* license);
+
+static BOOL license_write_platform_challenge_response_packet(
+ rdpLicense* license, wStream* s, BYTE* mac_data);
+static BOOL license_send_platform_challenge_response_packet(rdpLicense* license);
+
#ifdef WITH_DEBUG_LICENSE
static const char* const LICENSE_MESSAGE_STRINGS[] =
@@ -82,7 +116,7 @@ static const char* const state_transitions[] =
"ST_RESEND_LAST_MESSAGE"
};
-void license_print_product_info(LICENSE_PRODUCT_INFO* productInfo)
+static void license_print_product_info(LICENSE_PRODUCT_INFO* productInfo)
{
char* CompanyName = NULL;
char* ProductId = NULL;
@@ -98,7 +132,7 @@ void license_print_product_info(LICENSE_PRODUCT_INFO* productInfo)
free(ProductId);
}
-void license_print_scope_list(SCOPE_LIST* scopeList)
+static void license_print_scope_list(SCOPE_LIST* scopeList)
{
int index;
LICENSE_BLOB* scope;
@@ -251,12 +285,12 @@ int license_recv(rdpLicense* license, wStream* s)
return -1;
}
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
return -1;
if (securityFlags & SEC_ENCRYPT)
{
- if (!rdp_decrypt(license->rdp, s, length - 4, securityFlags))
+ if (!rdp_decrypt(license->rdp, s, length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return -1;
@@ -468,7 +502,12 @@ BOOL license_decrypt_platform_challenge(rdpLicense* license)
if ((rc4 = winpr_RC4_New(license->LicensingEncryptionKey,
LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL)
+ {
+ free(license->PlatformChallenge->data);
+ license->PlatformChallenge->data = NULL;
+ license->PlatformChallenge->length = 0;
return FALSE;
+ }
rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length,
license->EncryptedPlatformChallenge->data,
license->PlatformChallenge->data);
@@ -492,15 +531,27 @@ BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
Stream_Read_UINT32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */
Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
- if (Stream_GetRemainingLength(s) < productInfo->cbCompanyName + 4)
+ /* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
+ if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0))
+ return FALSE;
+
+ if (Stream_GetRemainingLength(s) < productInfo->cbCompanyName)
return FALSE;
+ productInfo->pbProductId = NULL;
productInfo->pbCompanyName = (BYTE*) malloc(productInfo->cbCompanyName);
if (!productInfo->pbCompanyName)
return FALSE;
Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
+
+ if (Stream_GetRemainingLength(s) < 4)
+ goto out_fail;
+
Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
+ if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0))
+ goto out_fail;
+
if (Stream_GetRemainingLength(s) < productInfo->cbProductId)
goto out_fail;
@@ -512,7 +563,9 @@ BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
out_fail:
free(productInfo->pbCompanyName);
+ free(productInfo->pbProductId);
productInfo->pbCompanyName = NULL;
+ productInfo->pbProductId = NULL;
return FALSE;
}
@@ -811,7 +864,9 @@ BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
/* EncryptedPlatformChallenge */
license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
- license_read_binary_blob(s, license->EncryptedPlatformChallenge);
+ if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
+ return FALSE;
+
license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;
if (Stream_GetRemainingLength(s) < 16)
diff --git a/libfreerdp/core/license.h b/libfreerdp/core/license.h
index aba0a02..ef128ea 100644
--- a/libfreerdp/core/license.h
+++ b/libfreerdp/core/license.h
@@ -17,8 +17,8 @@
* limitations under the License.
*/
-#ifndef __LICENSE_H
-#define __LICENSE_H
+#ifndef FREERDP_LICENSE_H
+#define FREERDP_LICENSE_H
typedef struct rdp_license rdpLicense;
@@ -202,38 +202,6 @@ struct rdp_license
int license_recv(rdpLicense* license, wStream* s);
BOOL license_send(rdpLicense* license, wStream* s, BYTE type);
-wStream* license_send_stream_init(rdpLicense* license);
-
-void license_generate_randoms(rdpLicense* license);
-BOOL license_generate_keys(rdpLicense* license);
-BOOL license_generate_hwid(rdpLicense* license);
-BOOL license_encrypt_premaster_secret(rdpLicense* license);
-BOOL license_decrypt_platform_challenge(rdpLicense* license);
-
-LICENSE_PRODUCT_INFO* license_new_product_info(void);
-void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
-BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
-
-LICENSE_BLOB* license_new_binary_blob(UINT16 type);
-void license_free_binary_blob(LICENSE_BLOB* blob);
-BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
-BOOL license_write_binary_blob(wStream* s, LICENSE_BLOB* blob);
-
-SCOPE_LIST* license_new_scope_list(void);
-void license_free_scope_list(SCOPE_LIST* scopeList);
-BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
-
-BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
-BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
-void license_read_new_license_packet(rdpLicense* license, wStream* s);
-void license_read_upgrade_license_packet(rdpLicense* license, wStream* s);
-BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
-
-BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s);
-BOOL license_send_new_license_request_packet(rdpLicense* license);
-
-BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s, BYTE* mac_data);
-BOOL license_send_platform_challenge_response_packet(rdpLicense* license);
BOOL license_send_valid_client_error_packet(rdpLicense* license);
diff --git a/libfreerdp/core/mcs.c b/libfreerdp/core/mcs.c
index 27c9126..e3f2a71 100644
--- a/libfreerdp/core/mcs.c
+++ b/libfreerdp/core/mcs.c
@@ -223,7 +223,8 @@ BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU,
BYTE choice;
enum DomainMCSPDU MCSPDU;
- *length = tpkt_read_header(s);
+ if (!tpkt_read_header(s, length))
+ return FALSE;
if (!tpdu_read_data(s, &li))
return FALSE;
@@ -480,8 +481,10 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
UINT16 li;
int length;
BOOL upwardFlag;
+ UINT16 tlength;
- tpkt_read_header(s);
+ if (!tpkt_read_header(s, &tlength))
+ return FALSE;
if (!tpdu_read_data(s, &li))
return FALSE;
@@ -697,11 +700,13 @@ out:
BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
{
int length;
+ UINT16 tlength;
BYTE result;
UINT16 li;
UINT32 calledConnectId;
- tpkt_read_header(s);
+ if (!tpkt_read_header(s, &tlength))
+ return FALSE;
if (!tpdu_read_data(s, &li))
return FALSE;
diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c
index 136b305..3cbad6a 100644
--- a/libfreerdp/core/nego.c
+++ b/libfreerdp/core/nego.c
@@ -575,7 +575,8 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
UINT16 length;
rdpNego* nego = (rdpNego*) extra;
- length = tpkt_read_header(s);
+ if (!tpkt_read_header(s, &length))
+ return -1;
if (length == 0)
return -1;
@@ -739,8 +740,10 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
{
BYTE li;
BYTE type;
+ UINT16 length;
- tpkt_read_header(s);
+ if (!tpkt_read_header(s, &length))
+ return FALSE;
if (!tpdu_read_connection_request(s, &li))
return FALSE;
diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c
index 8318c4d..7263feb 100644
--- a/libfreerdp/core/peer.c
+++ b/libfreerdp/core/peer.c
@@ -369,12 +369,12 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
if (rdp->settings->UseRdpSecurityLayer)
{
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
return -1;
if (securityFlags & SEC_ENCRYPT)
{
- if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
+ if (!rdp_decrypt(rdp, s, length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return -1;
@@ -414,7 +414,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
else if (rdp->mcs->messageChannelId && channelId == rdp->mcs->messageChannelId)
{
if (!rdp->settings->UseRdpSecurityLayer)
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c
index e7c5bd2..2d34a34 100644
--- a/libfreerdp/core/rdp.c
+++ b/libfreerdp/core/rdp.c
@@ -79,13 +79,17 @@ const char* DATA_PDU_TYPE_STRINGS[80] =
* @param flags security flags
*/
-BOOL rdp_read_security_header(wStream* s, UINT16* flags)
+BOOL rdp_read_security_header(wStream* s, UINT16* flags, UINT16* length)
{
/* Basic Security Header */
- if (Stream_GetRemainingLength(s) < 4)
+ if ((Stream_GetRemainingLength(s) < 4) || (length && (*length < 4)))
return FALSE;
Stream_Read_UINT16(s, *flags); /* flags */
Stream_Seek(s, 2); /* flagsHi (unused) */
+
+ if (length)
+ *length -= 4;
+
return TRUE;
}
@@ -301,7 +305,8 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication;
- *length = tpkt_read_header(s);
+ if (!tpkt_read_header(s, length))
+ return FALSE;
if (!tpdu_read_header(s, &code, &li))
return FALSE;
@@ -330,7 +335,10 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
MCSPDU = domainMCSPDU;
- if ((size_t) (*length - 8) > Stream_GetRemainingLength(s))
+ if (*length < 8)
+ return FALSE;
+
+ if ((*length - 8) > Stream_GetRemainingLength(s))
return FALSE;
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
@@ -376,8 +384,12 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
if (Stream_GetRemainingLength(s) < 5)
return FALSE;
- per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
- per_read_integer16(s, channelId, 0); /* channelId */
+ if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
+ return FALSE;
+
+ if (!per_read_integer16(s, channelId, 0)) /* channelId */
+ return FALSE;
+
Stream_Read_UINT8(s, byte); /* dataPriority + Segmentation (0x70) */
if (!per_read_length(s, length)) /* userData (OCTET_STRING) */
@@ -1024,17 +1036,21 @@ void rdp_read_flow_control_pdu(wStream* s, UINT16* type)
* @param length int
*/
-BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
+BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, INT32 length, UINT16 securityFlags)
{
BYTE cmac[8];
BYTE wmac[8];
BOOL status;
+ if (!rdp || !s || (length < 0))
+ return FALSE;
+
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
UINT16 len;
BYTE version, pad;
BYTE* sig;
+ INT64 padLength;
if (Stream_GetRemainingLength(s) < 12)
return FALSE;
@@ -1047,6 +1063,9 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
Stream_Seek(s, 8); /* signature */
length -= 12;
+ padLength = length - pad;
+ if ((length <= 0) || (padLength <= 0))
+ return FALSE;
if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
{
@@ -1064,11 +1083,13 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
return TRUE;
}
- if (Stream_GetRemainingLength(s) < 8)
+ if (Stream_GetRemainingLength(s) < sizeof(wmac))
return FALSE;
Stream_Read(s, wmac, sizeof(wmac));
length -= sizeof(wmac);
+ if (length <= 0)
+ return FALSE;
if (!security_decrypt(Stream_Pointer(s), length, rdp))
return FALSE;
@@ -1129,7 +1150,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (rdp->settings->UseRdpSecurityLayer)
{
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, &length))
{
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_security_header() fail");
return -1;
@@ -1137,7 +1158,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT))
{
- if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
+ if (!rdp_decrypt(rdp, s, length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return -1;
@@ -1210,7 +1231,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
else if (rdp->mcs->messageChannelId && channelId == rdp->mcs->messageChannelId)
{
if (!rdp->settings->UseRdpSecurityLayer)
- if (!rdp_read_security_header(s, &securityFlags))
+ if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h
index ef8e0dc..5c6ce35 100644
--- a/libfreerdp/core/rdp.h
+++ b/libfreerdp/core/rdp.h
@@ -178,7 +178,7 @@ struct rdp_rdp
rdpSettings* settingsCopy;
};
-BOOL rdp_read_security_header(wStream* s, UINT16* flags);
+BOOL rdp_read_security_header(wStream* s, UINT16* flags, UINT16* length);
void rdp_write_security_header(wStream* s, UINT16 flags);
BOOL rdp_read_share_control_header(wStream* s, UINT16* length, UINT16* type, UINT16* channel_id);
@@ -232,7 +232,7 @@ void rdp_free(rdpRdp* rdp);
#define DEBUG_RDP(fmt, ...) do { } while (0)
#endif
-BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags);
+BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, INT32 length, UINT16 securityFlags);
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo);
BOOL rdp_send_error_info(rdpRdp* rdp);
diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c
index e415786..e6121d4 100644
--- a/libfreerdp/core/security.c
+++ b/libfreerdp/core/security.c
@@ -580,7 +580,7 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp)
return TRUE;
}
-BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp)
+BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
if (rdp->encrypt_use_count >= 4096)
{
@@ -602,7 +602,7 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
-BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp)
+BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
if (rdp->rc4_decrypt_key == NULL)
return FALSE;
@@ -626,7 +626,7 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
-BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp)
+BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpRdp* rdp)
{
BYTE buf[WINPR_SHA1_DIGEST_LENGTH];
BYTE use_count_le[4];
@@ -647,7 +647,7 @@ BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp*
return TRUE;
}
-BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp)
+BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
size_t olen;
@@ -657,7 +657,7 @@ BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
-BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp)
+BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
size_t olen;
@@ -666,7 +666,7 @@ BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
-BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp)
+BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig, rdpRdp* rdp)
{
BYTE buf[WINPR_SHA1_DIGEST_LENGTH];
BYTE use_count_le[4];
diff --git a/libfreerdp/core/security.h b/libfreerdp/core/security.h
index fc03a3e..14f4664 100644
--- a/libfreerdp/core/security.h
+++ b/libfreerdp/core/security.h
@@ -17,8 +17,8 @@
* limitations under the License.
*/
-#ifndef __SECURITY_H
-#define __SECURITY_H
+#ifndef FREERDP_SECURITY_H
+#define FREERDP_SECURITY_H
#include "rdp.h"
#include <freerdp/crypto/crypto.h>
@@ -37,12 +37,12 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE*
BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BOOL encryption, BYTE* output);
BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp);
-BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp);
-BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp);
+BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
+BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
-BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp);
-BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp);
-BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp);
-BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp);
+BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpRdp* rdp);
+BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
+BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
+BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig, rdpRdp* rdp);
#endif /* __SECURITY_H */
diff --git a/libfreerdp/core/tpkt.c b/libfreerdp/core/tpkt.c
index 5689d62..eed79d7 100644
--- a/libfreerdp/core/tpkt.c
+++ b/libfreerdp/core/tpkt.c
@@ -78,28 +78,39 @@ BOOL tpkt_verify_header(wStream* s)
/**
* Read a TPKT header.\n
* @param s
- * @return length
+ * @param length
+ * @return success
*/
-UINT16 tpkt_read_header(wStream* s)
+BOOL tpkt_read_header(wStream* s, UINT16* length)
{
BYTE version;
- UINT16 length;
+
+ if (Stream_GetRemainingLength(s) < 1)
+ return FALSE;
Stream_Peek_UINT8(s, version);
if (version == 3)
{
+ UINT16 len;
+ if (Stream_GetRemainingLength(s) < 4)
+ return FALSE;
+
Stream_Seek(s, 2);
- Stream_Read_UINT16_BE(s, length);
+ Stream_Read_UINT16_BE(s, len);
+ if (len < 4)
+ return FALSE;
+
+ *length = len;
}
else
{
/* not a TPKT header */
- length = 0;
+ *length = 0;
}
- return length;
+ return TRUE;
}
/**
diff --git a/libfreerdp/core/tpkt.h b/libfreerdp/core/tpkt.h
index af984c1..9b51749 100644
--- a/libfreerdp/core/tpkt.h
+++ b/libfreerdp/core/tpkt.h
@@ -28,7 +28,7 @@
#define TPKT_HEADER_LENGTH 4
BOOL tpkt_verify_header(wStream* s);
-UINT16 tpkt_read_header(wStream* s);
+BOOL tpkt_read_header(wStream* s, UINT16* length);
void tpkt_write_header(wStream* s, UINT16 length);
#endif /* __TPKT_H */