From 0dc59f3a4199146d9baa4a478140312aac8c83a8 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 8 Mar 2023 11:33:04 +0100 Subject: [PATCH] [core,rdstls] hide rdstls parsing * move rdstls specific code from transport_parse_pdu to rdstls_parse_pdu * hide rdstls implementation details --- libfreerdp/core/rdstls.c | 119 ++++++++++++++++++++++++++++++++++++ libfreerdp/core/rdstls.h | 24 +------- libfreerdp/core/transport.c | 86 +------------------------- 3 files changed, 123 insertions(+), 106 deletions(-) diff --git a/libfreerdp/core/rdstls.c b/libfreerdp/core/rdstls.c index 0e21fa38e..601f5e52e 100644 --- a/libfreerdp/core/rdstls.c +++ b/libfreerdp/core/rdstls.c @@ -33,6 +33,26 @@ #define TAG FREERDP_TAG("core.rdstls") +#define RDSTLS_VERSION_1 0x01 + +#define RDSTLS_TYPE_CAPABILITIES 0x01 +#define RDSTLS_TYPE_AUTHREQ 0x02 +#define RDSTLS_TYPE_AUTHRSP 0x04 + +#define RDSTLS_DATA_CAPABILITIES 0x01 +#define RDSTLS_DATA_PASSWORD_CREDS 0x01 +#define RDSTLS_DATA_AUTORECONNECT_COOKIE 0x02 +#define RDSTLS_DATA_RESULT_CODE 0x01 + +typedef enum +{ + RDSTLS_STATE_INITIAL, + RDSTLS_STATE_CAPABILITIES, + RDSTLS_STATE_AUTH_REQ, + RDSTLS_STATE_AUTH_RSP, + RDSTLS_STATE_FINAL, +} RDSTLS_STATE; + struct rdp_rdstls { BOOL server; @@ -809,3 +829,102 @@ int rdstls_authenticate(rdpRdstls* rdstls) else return rdstls_client_authenticate(rdstls); } + +static SSIZE_T rdstls_parse_pdu_data_type(wLog* log, UINT16 dataType, wStream* s) +{ + switch (dataType) + { + case RDSTLS_DATA_PASSWORD_CREDS: + { + UINT16 redirGuidLength; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, redirGuidLength); + + if (!Stream_SafeSeek(s, redirGuidLength)) + return 0; + + UINT16 usernameLength; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, usernameLength); + + if (!Stream_SafeSeek(s, usernameLength)) + return 0; + + UINT16 domainLength; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, domainLength); + + if (!Stream_SafeSeek(s, domainLength)) + return 0; + + UINT16 passwordLength; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, passwordLength); + + if (!Stream_SafeSeek(s, passwordLength)) + return 0; + + return Stream_GetPosition(s) + 2ull; + } + case RDSTLS_DATA_AUTORECONNECT_COOKIE: + { + SSIZE_T pduLength; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, pduLength); + return pduLength + 12u; + } + default: + WLog_Print(log, WLOG_ERROR, "invalid RDSLTS dataType"); + return -1; + } +} + +SSIZE_T rdstls_parse_pdu(wLog* log, wStream* stream) +{ + SSIZE_T pduLength = -1; + wStream sbuffer = { 0 }; + wStream* s = + Stream_StaticConstInit(&sbuffer, Stream_Pointer(stream), Stream_GetRemainingLength(stream)); + + UINT16 version; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, version); + if (version != RDSTLS_VERSION_1) + { + WLog_Print(log, WLOG_ERROR, "invalid RDSTLS version"); + return -1; + } + + UINT16 pduType; + if (Stream_GetRemainingLength(s) < 2) + return 0; + Stream_Read_UINT16(s, pduType); + switch (pduType) + { + case RDSTLS_TYPE_CAPABILITIES: + pduLength = 8; + break; + case RDSTLS_TYPE_AUTHREQ: + if (Stream_GetRemainingLength(s) < 2) + return 0; + UINT16 dataType; + Stream_Read_UINT16(s, dataType); + pduLength = rdstls_parse_pdu_data_type(log, dataType, s); + + break; + case RDSTLS_TYPE_AUTHRSP: + pduLength = 10; + break; + default: + WLog_Print(log, WLOG_ERROR, "invalid RDSTLS PDU type"); + return -1; + } + + return pduLength; +} diff --git a/libfreerdp/core/rdstls.h b/libfreerdp/core/rdstls.h index f5686e76f..3b078d885 100644 --- a/libfreerdp/core/rdstls.h +++ b/libfreerdp/core/rdstls.h @@ -24,29 +24,11 @@ typedef struct rdp_rdstls rdpRdstls; #include -#define RDSTLS_VERSION_1 0x01 - -#define RDSTLS_TYPE_CAPABILITIES 0x01 -#define RDSTLS_TYPE_AUTHREQ 0x02 -#define RDSTLS_TYPE_AUTHRSP 0x04 - -#define RDSTLS_DATA_CAPABILITIES 0x01 -#define RDSTLS_DATA_PASSWORD_CREDS 0x01 -#define RDSTLS_DATA_AUTORECONNECT_COOKIE 0x02 -#define RDSTLS_DATA_RESULT_CODE 0x01 - -typedef enum -{ - RDSTLS_STATE_INITIAL, - RDSTLS_STATE_CAPABILITIES, - RDSTLS_STATE_AUTH_REQ, - RDSTLS_STATE_AUTH_RSP, - RDSTLS_STATE_FINAL, -} RDSTLS_STATE; - -FREERDP_LOCAL int rdstls_authenticate(rdpRdstls* rdstls); +FREERDP_LOCAL SSIZE_T rdstls_parse_pdu(wLog* log, wStream* s); FREERDP_LOCAL rdpRdstls* rdstls_new(rdpContext* context, rdpTransport* transport); FREERDP_LOCAL void rdstls_free(rdpRdstls* rdstls); +FREERDP_LOCAL int rdstls_authenticate(rdpRdstls* rdstls); + #endif /* FREERDP_LIB_CORE_RDSTLS_H */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index fcb675f07..fdff4b081 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -848,91 +848,7 @@ SSIZE_T transport_parse_pdu(rdpTransport* transport, wStream* s, BOOL* incomplet } } else if (transport->RdstlsMode) - { - UINT16 version; - UINT16 pduType; - UINT16 dataType; - - Stream_Read_UINT16(staticStream, version); - if (version != RDSTLS_VERSION_1) - { - WLog_Print(transport->log, WLOG_ERROR, "invalid RDSTLS version"); - return -1; - } - - if (position < 4) - return 0; - - Stream_Read_UINT16(staticStream, pduType); - switch (pduType) - { - case RDSTLS_TYPE_CAPABILITIES: - pduLength = 8; - break; - case RDSTLS_TYPE_AUTHREQ: - if (position < 6) - return 0; - - Stream_Read_UINT16(staticStream, dataType); - if (dataType == RDSTLS_DATA_PASSWORD_CREDS) - { - UINT16 redirGuidLength; - UINT16 usernameLength; - UINT16 domainLength; - UINT16 passwordLength; - - if (position < 8) - return 0; - - Stream_Read_UINT16(staticStream, redirGuidLength); - - if (position < 8 + redirGuidLength + 2) - return 0; - - Stream_Seek(staticStream, redirGuidLength); - Stream_Read_UINT16(staticStream, usernameLength); - - if (position < 8 + redirGuidLength + 2 + usernameLength + 2) - return 0; - - Stream_Seek(staticStream, usernameLength); - Stream_Read_UINT16(staticStream, domainLength); - - if (position < 8 + redirGuidLength + 2 + usernameLength + 2 + domainLength + 2) - return 0; - - Stream_Seek(staticStream, domainLength); - Stream_Read_UINT16(staticStream, passwordLength); - - pduLength = 8 + redirGuidLength + 2 + usernameLength + 2 + domainLength + 2 + - passwordLength; - } - else if (dataType == RDSTLS_DATA_AUTORECONNECT_COOKIE) - { - UINT16 cookieLength; - - if (position < 12) - return 0; - - Stream_Seek(staticStream, 4); - Stream_Read_UINT16(staticStream, cookieLength); - - pduLength = 12 + cookieLength; - } - else - { - WLog_Print(transport->log, WLOG_ERROR, "invalid RDSLTS dataType"); - return -1; - } - break; - case RDSTLS_TYPE_AUTHRSP: - pduLength = 10; - break; - default: - WLog_Print(transport->log, WLOG_ERROR, "invalid RDSTLS PDU type"); - return -1; - } - } + pduLength = rdstls_parse_pdu(transport->log, s); else { UINT8 version;