20#include <freerdp/config.h>
24#include <freerdp/log.h>
25#include <freerdp/error.h>
26#include <freerdp/settings.h>
28#include <winpr/assert.h>
29#include <winpr/stream.h>
30#include <winpr/wlog.h>
36#define RDSTLS_VERSION_1 0x01
38#define RDSTLS_TYPE_CAPABILITIES 0x01
39#define RDSTLS_TYPE_AUTHREQ 0x02
40#define RDSTLS_TYPE_AUTHRSP 0x04
42#define RDSTLS_DATA_CAPABILITIES 0x01
43#define RDSTLS_DATA_PASSWORD_CREDS 0x01
44#define RDSTLS_DATA_AUTORECONNECT_COOKIE 0x02
45#define RDSTLS_DATA_RESULT_CODE 0x01
50 RDSTLS_STATE_CAPABILITIES,
51 RDSTLS_STATE_AUTH_REQ,
52 RDSTLS_STATE_AUTH_RSP,
59 RDSTLS_RESULT_SUCCESS = 0x00000000,
60 RDSTLS_RESULT_ACCESS_DENIED = 0x00000005,
61 RDSTLS_RESULT_LOGON_FAILURE = 0x0000052e,
62 RDSTLS_RESULT_INVALID_LOGON_HOURS = 0x00000530,
63 RDSTLS_RESULT_PASSWORD_EXPIRED = 0x00000532,
64 RDSTLS_RESULT_ACCOUNT_DISABLED = 0x00000533,
65 RDSTLS_RESULT_PASSWORD_MUST_CHANGE = 0x00000773,
66 RDSTLS_RESULT_ACCOUNT_LOCKED_OUT = 0x00000775
74 rdpTransport* transport;
76 RDSTLS_RESULT_CODE resultCode;
80static const char* rdstls_result_code_str(UINT32 resultCode)
84 case RDSTLS_RESULT_SUCCESS:
85 return "RDSTLS_RESULT_SUCCESS";
86 case RDSTLS_RESULT_ACCESS_DENIED:
87 return "RDSTLS_RESULT_ACCESS_DENIED";
88 case RDSTLS_RESULT_LOGON_FAILURE:
89 return "RDSTLS_RESULT_LOGON_FAILURE";
90 case RDSTLS_RESULT_INVALID_LOGON_HOURS:
91 return "RDSTLS_RESULT_INVALID_LOGON_HOURS";
92 case RDSTLS_RESULT_PASSWORD_EXPIRED:
93 return "RDSTLS_RESULT_PASSWORD_EXPIRED";
94 case RDSTLS_RESULT_ACCOUNT_DISABLED:
95 return "RDSTLS_RESULT_ACCOUNT_DISABLED";
96 case RDSTLS_RESULT_PASSWORD_MUST_CHANGE:
97 return "RDSTLS_RESULT_PASSWORD_MUST_CHANGE";
98 case RDSTLS_RESULT_ACCOUNT_LOCKED_OUT:
99 return "RDSTLS_RESULT_ACCOUNT_LOCKED_OUT";
101 return "RDSTLS_RESULT_UNKNOWN";
112rdpRdstls* rdstls_new(rdpContext* context, rdpTransport* transport)
114 WINPR_ASSERT(context);
115 WINPR_ASSERT(transport);
117 rdpSettings* settings = context->settings;
118 WINPR_ASSERT(settings);
120 rdpRdstls* rdstls = (rdpRdstls*)calloc(1,
sizeof(rdpRdstls));
124 rdstls->log = WLog_Get(FREERDP_TAG(
"core.rdstls"));
125 rdstls->context = context;
126 rdstls->transport = transport;
127 rdstls->server = settings->ServerMode;
129 rdstls->state = RDSTLS_STATE_INITIAL;
139void rdstls_free(rdpRdstls* rdstls)
144static const char* rdstls_get_state_str(RDSTLS_STATE state)
148 case RDSTLS_STATE_INITIAL:
149 return "RDSTLS_STATE_INITIAL";
150 case RDSTLS_STATE_CAPABILITIES:
151 return "RDSTLS_STATE_CAPABILITIES";
152 case RDSTLS_STATE_AUTH_REQ:
153 return "RDSTLS_STATE_AUTH_REQ";
154 case RDSTLS_STATE_AUTH_RSP:
155 return "RDSTLS_STATE_AUTH_RSP";
156 case RDSTLS_STATE_FINAL:
157 return "RDSTLS_STATE_FINAL";
163static RDSTLS_STATE rdstls_get_state(rdpRdstls* rdstls)
165 WINPR_ASSERT(rdstls);
166 return rdstls->state;
169static BOOL check_transition(wLog* log, RDSTLS_STATE current, RDSTLS_STATE expected,
170 RDSTLS_STATE requested)
172 if (requested != expected)
174 WLog_Print(log, WLOG_ERROR,
175 "Unexpected rdstls state transition from %s [%d] to %s [%d], expected %s [%d]",
176 rdstls_get_state_str(current), current, rdstls_get_state_str(requested),
177 requested, rdstls_get_state_str(expected), expected);
183static BOOL rdstls_set_state(rdpRdstls* rdstls, RDSTLS_STATE state)
186 WINPR_ASSERT(rdstls);
188 WLog_Print(rdstls->log, WLOG_DEBUG,
"-- %s\t--> %s", rdstls_get_state_str(rdstls->state),
189 rdstls_get_state_str(state));
191 switch (rdstls->state)
193 case RDSTLS_STATE_INITIAL:
194 rc = check_transition(rdstls->log, rdstls->state, RDSTLS_STATE_CAPABILITIES, state);
196 case RDSTLS_STATE_CAPABILITIES:
197 rc = check_transition(rdstls->log, rdstls->state, RDSTLS_STATE_AUTH_REQ, state);
199 case RDSTLS_STATE_AUTH_REQ:
200 rc = check_transition(rdstls->log, rdstls->state, RDSTLS_STATE_AUTH_RSP, state);
202 case RDSTLS_STATE_AUTH_RSP:
203 rc = check_transition(rdstls->log, rdstls->state, RDSTLS_STATE_FINAL, state);
205 case RDSTLS_STATE_FINAL:
206 rc = check_transition(rdstls->log, rdstls->state, RDSTLS_STATE_CAPABILITIES, state);
209 WLog_Print(rdstls->log, WLOG_ERROR,
210 "Invalid rdstls state %s [%d], requested transition to %s [%d]",
211 rdstls_get_state_str(rdstls->state), rdstls->state,
212 rdstls_get_state_str(state), state);
216 rdstls->state = state;
221static BOOL rdstls_write_capabilities(WINPR_ATTR_UNUSED rdpRdstls* rdstls,
wStream* s)
223 if (!Stream_EnsureRemainingCapacity(s, 6))
226 Stream_Write_UINT16(s, RDSTLS_TYPE_CAPABILITIES);
227 Stream_Write_UINT16(s, RDSTLS_DATA_CAPABILITIES);
228 Stream_Write_UINT16(s, RDSTLS_VERSION_1);
233static SSIZE_T rdstls_write_string(
wStream* s,
const char* str)
235 const size_t pos = Stream_GetPosition(s);
237 if (!Stream_EnsureRemainingCapacity(s, 2))
243 Stream_Write_UINT16(s, 2);
244 if (!Stream_EnsureRemainingCapacity(s, 2))
247 Stream_Write_UINT16(s, 0);
248 return (SSIZE_T)(Stream_GetPosition(s) - pos);
251 const size_t length = (strlen(str) + 1);
253 Stream_Write_UINT16(s, (UINT16)length *
sizeof(WCHAR));
255 if (!Stream_EnsureRemainingCapacity(s, length *
sizeof(WCHAR)))
258 if (Stream_Write_UTF16_String_From_UTF8(s, length, str, length, TRUE) < 0)
261 return (SSIZE_T)(Stream_GetPosition(s) - pos);
264static BOOL rdstls_write_data(
wStream* s, UINT32 length,
const BYTE* data)
266 WINPR_ASSERT(data || (length == 0));
268 if (!Stream_EnsureRemainingCapacity(s, 2) || (length > UINT16_MAX))
271 Stream_Write_UINT16(s, (UINT16)length);
273 if (!Stream_EnsureRemainingCapacity(s, length))
276 Stream_Write(s, data, length);
281static BOOL rdstls_write_authentication_request_with_password(rdpRdstls* rdstls,
wStream* s)
283 rdpSettings* settings = rdstls->context->settings;
284 WINPR_ASSERT(settings);
286 if (!Stream_EnsureRemainingCapacity(s, 4))
289 Stream_Write_UINT16(s, RDSTLS_TYPE_AUTHREQ);
290 Stream_Write_UINT16(s, RDSTLS_DATA_PASSWORD_CREDS);
292 if (!rdstls_write_data(s, settings->RedirectionGuidLength, settings->RedirectionGuid))
295 if (rdstls_write_string(s, settings->Username) < 0)
298 if (rdstls_write_string(s, settings->Domain) < 0)
301 if (!rdstls_write_data(s, settings->RedirectionPasswordLength, settings->RedirectionPassword))
307static BOOL rdstls_write_authentication_request_with_cookie(WINPR_ATTR_UNUSED rdpRdstls* rdstls,
314static BOOL rdstls_write_authentication_response(rdpRdstls* rdstls,
wStream* s)
316 if (!Stream_EnsureRemainingCapacity(s, 8))
319 Stream_Write_UINT16(s, RDSTLS_TYPE_AUTHRSP);
320 Stream_Write_UINT16(s, RDSTLS_DATA_RESULT_CODE);
321 Stream_Write_UINT32(s, rdstls->resultCode);
326static BOOL rdstls_process_capabilities(rdpRdstls* rdstls,
wStream* s)
329 UINT16 supportedVersions = 0;
331 if (Stream_GetRemainingLength(s) < 4)
334 Stream_Read_UINT16(s, dataType);
335 if (dataType != RDSTLS_DATA_CAPABILITIES)
337 WLog_Print(rdstls->log, WLOG_ERROR,
338 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX16, dataType,
339 RDSTLS_DATA_CAPABILITIES);
343 Stream_Read_UINT16(s, supportedVersions);
344 if ((supportedVersions & RDSTLS_VERSION_1) == 0)
346 WLog_Print(rdstls->log, WLOG_ERROR,
347 "received invalid supportedVersions=0x%04" PRIX16
", expected 0x%04" PRIX16,
348 supportedVersions, RDSTLS_VERSION_1);
355static BOOL rdstls_read_unicode_string(WINPR_ATTR_UNUSED wLog* log,
wStream* s,
char** str)
361 if (Stream_GetRemainingLength(s) < 2)
364 Stream_Read_UINT16(s, length);
366 if (Stream_GetRemainingLength(s) < length)
371 Stream_Seek(s, length);
375 *str = Stream_Read_UTF16_String_As_UTF8(s, length /
sizeof(WCHAR), NULL);
382static BOOL rdstls_read_data(WINPR_ATTR_UNUSED wLog* log,
wStream* s, UINT16* pLength,
387 WINPR_ASSERT(pLength);
392 if (Stream_GetRemainingLength(s) < 2)
395 Stream_Read_UINT16(s, length);
397 if (Stream_GetRemainingLength(s) < length)
402 Stream_Seek(s, length);
406 *pData = Stream_ConstPointer(s);
408 Stream_Seek(s, length);
412static BOOL rdstls_cmp_data(wLog* log,
const char* field,
const BYTE* serverData,
413 const UINT32 serverDataLength,
const BYTE* clientData,
414 const UINT16 clientDataLength)
416 if (serverDataLength > 0)
418 if (clientDataLength == 0)
420 WLog_Print(log, WLOG_ERROR,
"expected %s", field);
424 if (serverDataLength > UINT16_MAX || serverDataLength != clientDataLength ||
425 memcmp(serverData, clientData, serverDataLength) != 0)
427 WLog_Print(log, WLOG_ERROR,
"%s verification failed", field);
435static BOOL rdstls_cmp_str(wLog* log,
const char* field,
const char* serverStr,
436 const char* clientStr)
438 if (!utils_str_is_empty(serverStr))
440 if (utils_str_is_empty(clientStr))
442 WLog_Print(log, WLOG_ERROR,
"expected %s", field);
446 WINPR_ASSERT(serverStr);
447 WINPR_ASSERT(clientStr);
448 if (strcmp(serverStr, clientStr) != 0)
450 WLog_Print(log, WLOG_ERROR,
"%s verification failed", field);
458static BOOL rdstls_process_authentication_request_with_password(rdpRdstls* rdstls,
wStream* s)
462 const BYTE* clientRedirectionGuid = NULL;
463 UINT16 clientRedirectionGuidLength = 0;
464 char* clientPassword = NULL;
465 char* clientUsername = NULL;
466 char* clientDomain = NULL;
468 const BYTE* serverRedirectionGuid = NULL;
469 const char* serverPassword = NULL;
470 const char* serverUsername = NULL;
471 const char* serverDomain = NULL;
473 rdpSettings* settings = rdstls->context->settings;
474 WINPR_ASSERT(settings);
476 if (!rdstls_read_data(rdstls->log, s, &clientRedirectionGuidLength, &clientRedirectionGuid))
479 if (!rdstls_read_unicode_string(rdstls->log, s, &clientUsername))
482 if (!rdstls_read_unicode_string(rdstls->log, s, &clientDomain))
485 if (!rdstls_read_unicode_string(rdstls->log, s, &clientPassword))
489 const UINT32 serverRedirectionGuidLength =
495 rdstls->resultCode = RDSTLS_RESULT_SUCCESS;
497 if (!rdstls_cmp_data(rdstls->log,
"RedirectionGuid", serverRedirectionGuid,
498 serverRedirectionGuidLength, clientRedirectionGuid,
499 clientRedirectionGuidLength))
500 rdstls->resultCode = RDSTLS_RESULT_ACCESS_DENIED;
502 if (!rdstls_cmp_str(rdstls->log,
"UserName", serverUsername, clientUsername))
503 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
505 if (!rdstls_cmp_str(rdstls->log,
"Domain", serverDomain, clientDomain))
506 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
508 if (!rdstls_cmp_str(rdstls->log,
"Password", serverPassword, clientPassword))
509 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
516static BOOL rdstls_process_authentication_request_with_cookie(WINPR_ATTR_UNUSED rdpRdstls* rdstls,
523static BOOL rdstls_process_authentication_request(rdpRdstls* rdstls,
wStream* s)
527 if (Stream_GetRemainingLength(s) < 2)
530 Stream_Read_UINT16(s, dataType);
533 case RDSTLS_DATA_PASSWORD_CREDS:
534 if (!rdstls_process_authentication_request_with_password(rdstls, s))
537 case RDSTLS_DATA_AUTORECONNECT_COOKIE:
538 if (!rdstls_process_authentication_request_with_cookie(rdstls, s))
542 WLog_Print(rdstls->log, WLOG_ERROR,
543 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX16
545 dataType, RDSTLS_DATA_PASSWORD_CREDS, RDSTLS_DATA_AUTORECONNECT_COOKIE);
552static BOOL rdstls_process_authentication_response(rdpRdstls* rdstls,
wStream* s)
555 UINT32 resultCode = 0;
557 if (Stream_GetRemainingLength(s) < 6)
560 Stream_Read_UINT16(s, dataType);
561 if (dataType != RDSTLS_DATA_RESULT_CODE)
563 WLog_Print(rdstls->log, WLOG_ERROR,
564 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX16, dataType,
565 RDSTLS_DATA_RESULT_CODE);
569 Stream_Read_UINT32(s, resultCode);
570 if (resultCode != RDSTLS_RESULT_SUCCESS)
572 WLog_Print(rdstls->log, WLOG_ERROR,
"resultCode: %s [0x%08" PRIX32
"]",
573 rdstls_result_code_str(resultCode), resultCode);
575 UINT32 error = ERROR_INTERNAL_ERROR;
578 case RDSTLS_RESULT_ACCESS_DENIED:
579 error = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
581 case RDSTLS_RESULT_ACCOUNT_DISABLED:
582 error = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
584 case RDSTLS_RESULT_ACCOUNT_LOCKED_OUT:
585 error = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
587 case RDSTLS_RESULT_LOGON_FAILURE:
588 error = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
590 case RDSTLS_RESULT_INVALID_LOGON_HOURS:
591 error = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
593 case RDSTLS_RESULT_PASSWORD_EXPIRED:
594 error = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
596 case RDSTLS_RESULT_PASSWORD_MUST_CHANGE:
597 error = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
600 error = ERROR_INVALID_PARAMETER;
604 freerdp_set_last_error_if_not(rdstls->context, error);
611static BOOL rdstls_send(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
613 rdpRdstls* rdstls = (rdpRdstls*)extra;
614 rdpSettings* settings = NULL;
616 WINPR_ASSERT(transport);
618 WINPR_ASSERT(rdstls);
620 settings = rdstls->context->settings;
621 WINPR_ASSERT(settings);
623 if (!Stream_EnsureRemainingCapacity(s, 2))
626 Stream_Write_UINT16(s, RDSTLS_VERSION_1);
628 const RDSTLS_STATE state = rdstls_get_state(rdstls);
631 case RDSTLS_STATE_CAPABILITIES:
632 if (!rdstls_write_capabilities(rdstls, s))
635 case RDSTLS_STATE_AUTH_REQ:
636 if (settings->RedirectionFlags & LB_PASSWORD_IS_PK_ENCRYPTED)
638 if (!rdstls_write_authentication_request_with_password(rdstls, s))
641 else if (settings->ServerAutoReconnectCookie != NULL)
643 if (!rdstls_write_authentication_request_with_cookie(rdstls, s))
648 WLog_Print(rdstls->log, WLOG_ERROR,
649 "cannot authenticate with password or auto-reconnect cookie");
653 case RDSTLS_STATE_AUTH_RSP:
654 if (!rdstls_write_authentication_response(rdstls, s))
658 WLog_Print(rdstls->log, WLOG_ERROR,
"Invalid rdstls state %s [%d]",
659 rdstls_get_state_str(state), state);
663 if (transport_write(rdstls->transport, s) < 0)
669static int rdstls_recv(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
673 rdpRdstls* rdstls = (rdpRdstls*)extra;
675 WINPR_ASSERT(transport);
677 WINPR_ASSERT(rdstls);
679 if (Stream_GetRemainingLength(s) < 4)
682 Stream_Read_UINT16(s, version);
683 if (version != RDSTLS_VERSION_1)
685 WLog_Print(rdstls->log, WLOG_ERROR,
686 "received invalid RDSTLS Version=0x%04" PRIX16
", expected 0x%04" PRIX16,
687 version, RDSTLS_VERSION_1);
691 Stream_Read_UINT16(s, pduType);
694 case RDSTLS_TYPE_CAPABILITIES:
695 if (!rdstls_process_capabilities(rdstls, s))
698 case RDSTLS_TYPE_AUTHREQ:
699 if (!rdstls_process_authentication_request(rdstls, s))
702 case RDSTLS_TYPE_AUTHRSP:
703 if (!rdstls_process_authentication_response(rdstls, s))
707 WLog_Print(rdstls->log, WLOG_ERROR,
"unknown RDSTLS PDU type [0x%04" PRIx16
"]",
715#define rdstls_check_state_requirements(rdstls, expected) \
716 rdstls_check_state_requirements_((rdstls), (expected), __FILE__, __func__, __LINE__)
717static BOOL rdstls_check_state_requirements_(rdpRdstls* rdstls, RDSTLS_STATE expected,
718 const char* file,
const char* fkt,
size_t line)
720 const RDSTLS_STATE current = rdstls_get_state(rdstls);
721 if (current == expected)
724 const DWORD log_level = WLOG_ERROR;
725 if (WLog_IsLevelActive(rdstls->log, log_level))
726 WLog_PrintMessage(rdstls->log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
727 "Unexpected rdstls state %s [%d], expected %s [%d]",
728 rdstls_get_state_str(current), current, rdstls_get_state_str(expected),
734static BOOL rdstls_send_capabilities(rdpRdstls* rdstls)
739 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_CAPABILITIES))
742 s = Stream_New(NULL, 512);
746 if (!rdstls_send(rdstls->transport, s, rdstls))
749 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_REQ);
751 Stream_Free(s, TRUE);
755static BOOL rdstls_recv_authentication_request(rdpRdstls* rdstls)
761 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_REQ))
764 s = Stream_New(NULL, 4096);
768 status = transport_read_pdu(rdstls->transport, s);
773 status = rdstls_recv(rdstls->transport, s, rdstls);
778 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_RSP);
780 Stream_Free(s, TRUE);
784static BOOL rdstls_send_authentication_response(rdpRdstls* rdstls)
789 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_RSP))
792 s = Stream_New(NULL, 512);
796 if (!rdstls_send(rdstls->transport, s, rdstls))
799 rc = rdstls_set_state(rdstls, RDSTLS_STATE_FINAL);
801 Stream_Free(s, TRUE);
805static BOOL rdstls_recv_capabilities(rdpRdstls* rdstls)
811 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_CAPABILITIES))
814 s = Stream_New(NULL, 512);
818 status = transport_read_pdu(rdstls->transport, s);
823 status = rdstls_recv(rdstls->transport, s, rdstls);
828 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_REQ);
830 Stream_Free(s, TRUE);
834static BOOL rdstls_send_authentication_request(rdpRdstls* rdstls)
839 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_REQ))
842 s = Stream_New(NULL, 4096);
846 if (!rdstls_send(rdstls->transport, s, rdstls))
849 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_RSP);
851 Stream_Free(s, TRUE);
855static BOOL rdstls_recv_authentication_response(rdpRdstls* rdstls)
861 WINPR_ASSERT(rdstls);
863 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_RSP))
866 s = Stream_New(NULL, 512);
870 status = transport_read_pdu(rdstls->transport, s);
875 status = rdstls_recv(rdstls->transport, s, rdstls);
880 rc = rdstls_set_state(rdstls, RDSTLS_STATE_FINAL);
882 Stream_Free(s, TRUE);
886static int rdstls_server_authenticate(rdpRdstls* rdstls)
888 if (!rdstls_set_state(rdstls, RDSTLS_STATE_CAPABILITIES))
891 if (!rdstls_send_capabilities(rdstls))
894 if (!rdstls_recv_authentication_request(rdstls))
897 if (!rdstls_send_authentication_response(rdstls))
900 if (rdstls->resultCode != RDSTLS_RESULT_SUCCESS)
906static int rdstls_client_authenticate(rdpRdstls* rdstls)
908 if (!rdstls_set_state(rdstls, RDSTLS_STATE_CAPABILITIES))
911 if (!rdstls_recv_capabilities(rdstls))
914 if (!rdstls_send_authentication_request(rdstls))
917 if (!rdstls_recv_authentication_response(rdstls))
930int rdstls_authenticate(rdpRdstls* rdstls)
932 WINPR_ASSERT(rdstls);
935 return rdstls_server_authenticate(rdstls);
937 return rdstls_client_authenticate(rdstls);
940static SSIZE_T rdstls_parse_pdu_data_type(wLog* log, UINT16 dataType,
wStream* s)
942 size_t pduLength = 0;
946 case RDSTLS_DATA_PASSWORD_CREDS:
948 UINT16 redirGuidLength = 0;
949 if (Stream_GetRemainingLength(s) < 2)
951 Stream_Read_UINT16(s, redirGuidLength);
953 if (Stream_GetRemainingLength(s) < redirGuidLength)
955 Stream_Seek(s, redirGuidLength);
957 UINT16 usernameLength = 0;
958 if (Stream_GetRemainingLength(s) < 2)
960 Stream_Read_UINT16(s, usernameLength);
962 if (Stream_GetRemainingLength(s) < usernameLength)
964 Stream_Seek(s, usernameLength);
966 UINT16 domainLength = 0;
967 if (Stream_GetRemainingLength(s) < 2)
969 Stream_Read_UINT16(s, domainLength);
971 if (Stream_GetRemainingLength(s) < domainLength)
973 Stream_Seek(s, domainLength);
975 UINT16 passwordLength = 0;
976 if (Stream_GetRemainingLength(s) < 2)
978 Stream_Read_UINT16(s, passwordLength);
980 pduLength = Stream_GetPosition(s) + passwordLength;
983 case RDSTLS_DATA_AUTORECONNECT_COOKIE:
985 if (Stream_GetRemainingLength(s) < 4)
989 UINT16 cookieLength = 0;
990 if (Stream_GetRemainingLength(s) < 2)
992 Stream_Read_UINT16(s, cookieLength);
994 pduLength = Stream_GetPosition(s) + cookieLength;
998 WLog_Print(log, WLOG_ERROR,
"invalid RDSLTS dataType");
1002 if (pduLength > SSIZE_MAX)
1004 return (SSIZE_T)pduLength;
1007SSIZE_T rdstls_parse_pdu(wLog* log,
wStream* stream)
1009 SSIZE_T pduLength = -1;
1011 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
1014 if (Stream_GetRemainingLength(s) < 2)
1016 Stream_Read_UINT16(s, version);
1017 if (version != RDSTLS_VERSION_1)
1019 WLog_Print(log, WLOG_ERROR,
"invalid RDSTLS version");
1024 if (Stream_GetRemainingLength(s) < 2)
1026 Stream_Read_UINT16(s, pduType);
1029 case RDSTLS_TYPE_CAPABILITIES:
1032 case RDSTLS_TYPE_AUTHREQ:
1033 if (Stream_GetRemainingLength(s) < 2)
1035 UINT16 dataType = 0;
1036 Stream_Read_UINT16(s, dataType);
1037 pduLength = rdstls_parse_pdu_data_type(log, dataType, s);
1040 case RDSTLS_TYPE_AUTHRSP:
1044 WLog_Print(log, WLOG_ERROR,
"invalid RDSTLS PDU type");
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.