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 [%u] to %s [%u], expected %s [%u]",
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 [%u], requested transition to %s [%u]",
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);
283 WINPR_ASSERT(cookie);
284 const uint16_t length = 28;
286 if (!Stream_EnsureRemainingCapacity(s, 2))
289 Stream_Write_UINT16(s, length);
291 if (!Stream_EnsureRemainingCapacity(s, length))
294 Stream_Write_UINT32(s, cookie->cbLen);
295 Stream_Write_UINT32(s, cookie->version);
296 Stream_Write_UINT32(s, cookie->logonId);
297 Stream_Write(s, cookie->arcRandomBits,
sizeof(cookie->arcRandomBits));
301static BOOL rdstls_write_authentication_request_with_password(rdpRdstls* rdstls,
wStream* s)
303 WINPR_ASSERT(rdstls);
304 WINPR_ASSERT(rdstls->context);
306 WLog_Print(rdstls->log, WLOG_DEBUG,
"Writing RDSTLS password authentication message");
308 rdpSettings* settings = rdstls->context->settings;
309 WINPR_ASSERT(settings);
311 if (!Stream_EnsureRemainingCapacity(s, 4))
314 Stream_Write_UINT16(s, RDSTLS_TYPE_AUTHREQ);
315 Stream_Write_UINT16(s, RDSTLS_DATA_PASSWORD_CREDS);
317 if (!rdstls_write_data(s, settings->RedirectionGuidLength, settings->RedirectionGuid))
320 if (rdstls_write_string(s, settings->Username) < 0)
323 if (rdstls_write_string(s, settings->Domain) < 0)
326 if (!rdstls_write_data(s, settings->RedirectionPasswordLength, settings->RedirectionPassword))
332static BOOL rdstls_write_authentication_request_with_cookie(WINPR_ATTR_UNUSED rdpRdstls* rdstls,
335 WINPR_ASSERT(rdstls);
336 WINPR_ASSERT(rdstls->context);
338 WLog_Print(rdstls->log, WLOG_DEBUG,
"Writing RDSTLS cookie authentication message");
340 rdpSettings* settings = rdstls->context->settings;
341 WINPR_ASSERT(settings);
343 if (!Stream_EnsureRemainingCapacity(s, 8))
346 Stream_Write_UINT16(s, RDSTLS_TYPE_AUTHREQ);
347 Stream_Write_UINT16(s, RDSTLS_DATA_AUTORECONNECT_COOKIE);
348 Stream_Write_UINT32(s, settings->RedirectedSessionId);
350 if (!rdstls_write_cookie(s, settings->ServerAutoReconnectCookie))
356static BOOL rdstls_write_authentication_response(rdpRdstls* rdstls,
wStream* s)
358 WINPR_ASSERT(rdstls);
359 if (!Stream_EnsureRemainingCapacity(s, 8))
362 Stream_Write_UINT16(s, RDSTLS_TYPE_AUTHRSP);
363 Stream_Write_UINT16(s, RDSTLS_DATA_RESULT_CODE);
364 Stream_Write_UINT32(s, rdstls->resultCode);
369static BOOL rdstls_process_capabilities(rdpRdstls* rdstls,
wStream* s)
371 WINPR_ASSERT(rdstls);
372 if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 4))
375 const UINT16 dataType = Stream_Get_UINT16(s);
376 if (dataType != RDSTLS_DATA_CAPABILITIES)
378 WLog_Print(rdstls->log, WLOG_ERROR,
379 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX32, dataType,
380 WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_DATA_CAPABILITIES));
384 const UINT16 supportedVersions = Stream_Get_UINT16(s);
385 if ((supportedVersions & RDSTLS_VERSION_1) == 0)
387 WLog_Print(rdstls->log, WLOG_ERROR,
388 "received invalid supportedVersions=0x%04" PRIX16
", expected 0x%04" PRIX32,
389 supportedVersions, WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_VERSION_1));
396static BOOL rdstls_read_unicode_string(WINPR_ATTR_UNUSED wLog* log,
wStream* s,
char** str)
400 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 2))
403 const UINT16 length = Stream_Get_UINT16(s);
405 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, length))
410 Stream_Seek(s, length);
414 *str = Stream_Read_UTF16_String_As_UTF8(s, length /
sizeof(WCHAR), NULL);
421static BOOL rdstls_read_data(WINPR_ATTR_UNUSED wLog* log,
wStream* s, UINT16* pLength,
424 WINPR_ASSERT(pLength);
429 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 2))
432 const UINT16 length = Stream_Get_UINT16(s);
434 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, length))
439 Stream_Seek(s, length);
443 *pData = Stream_ConstPointer(s);
445 Stream_Seek(s, length);
449static BOOL rdstls_cmp_data(wLog* log,
const char* field,
const BYTE* serverData,
450 const UINT32 serverDataLength,
const BYTE* clientData,
451 const UINT16 clientDataLength)
453 if (serverDataLength > 0)
455 if (clientDataLength == 0)
457 WLog_Print(log, WLOG_ERROR,
"expected %s", field);
461 if (serverDataLength > UINT16_MAX || serverDataLength != clientDataLength ||
462 memcmp(serverData, clientData, serverDataLength) != 0)
464 WLog_Print(log, WLOG_ERROR,
"%s verification failed", field);
472static BOOL rdstls_cmp_str(wLog* log,
const char* field,
const char* serverStr,
473 const char* clientStr)
475 if (!utils_str_is_empty(serverStr))
477 if (utils_str_is_empty(clientStr))
479 WLog_Print(log, WLOG_ERROR,
"expected %s", field);
483 WINPR_ASSERT(serverStr);
484 WINPR_ASSERT(clientStr);
485 if (strcmp(serverStr, clientStr) != 0)
487 WLog_Print(log, WLOG_ERROR,
"%s verification failed", field);
495static BOOL rdstls_process_authentication_request_with_password(rdpRdstls* rdstls,
wStream* s)
497 WINPR_ASSERT(rdstls);
498 WINPR_ASSERT(rdstls->context);
502 const BYTE* clientRedirectionGuid = NULL;
503 UINT16 clientRedirectionGuidLength = 0;
504 char* clientPassword = NULL;
505 char* clientUsername = NULL;
506 char* clientDomain = NULL;
508 const rdpSettings* settings = rdstls->context->settings;
509 WINPR_ASSERT(settings);
511 if (!rdstls_read_data(rdstls->log, s, &clientRedirectionGuidLength, &clientRedirectionGuid))
514 if (!rdstls_read_unicode_string(rdstls->log, s, &clientUsername))
517 if (!rdstls_read_unicode_string(rdstls->log, s, &clientDomain))
520 if (!rdstls_read_unicode_string(rdstls->log, s, &clientPassword))
523 const BYTE* serverRedirectionGuid =
525 const UINT32 serverRedirectionGuidLength =
531 rdstls->resultCode = RDSTLS_RESULT_SUCCESS;
533 if (!rdstls_cmp_data(rdstls->log,
"RedirectionGuid", serverRedirectionGuid,
534 serverRedirectionGuidLength, clientRedirectionGuid,
535 clientRedirectionGuidLength))
536 rdstls->resultCode = RDSTLS_RESULT_ACCESS_DENIED;
538 if (!rdstls_cmp_str(rdstls->log,
"UserName", serverUsername, clientUsername))
539 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
541 if (!rdstls_cmp_str(rdstls->log,
"Domain", serverDomain, clientDomain))
542 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
544 if (!rdstls_cmp_str(rdstls->log,
"Password", serverPassword, clientPassword))
545 rdstls->resultCode = RDSTLS_RESULT_LOGON_FAILURE;
552static BOOL rdstls_process_authentication_request_with_cookie(WINPR_ATTR_UNUSED rdpRdstls* rdstls,
556 WLog_Print(rdstls->log, WLOG_ERROR,
"TODO: RDSTLS Cookie authentication not implemented");
560static BOOL rdstls_process_authentication_request(rdpRdstls* rdstls,
wStream* s)
562 if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 2))
565 const UINT16 dataType = Stream_Get_UINT16(s);
568 case RDSTLS_DATA_PASSWORD_CREDS:
569 if (!rdstls_process_authentication_request_with_password(rdstls, s))
572 case RDSTLS_DATA_AUTORECONNECT_COOKIE:
573 if (!rdstls_process_authentication_request_with_cookie(rdstls, s))
577 WLog_Print(rdstls->log, WLOG_ERROR,
578 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX32
580 dataType, WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_DATA_PASSWORD_CREDS),
581 WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_DATA_AUTORECONNECT_COOKIE));
588static BOOL rdstls_process_authentication_response(rdpRdstls* rdstls,
wStream* s)
590 if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 6))
593 const UINT16 dataType = Stream_Get_UINT16(s);
594 if (dataType != RDSTLS_DATA_RESULT_CODE)
596 WLog_Print(rdstls->log, WLOG_ERROR,
597 "received invalid DataType=0x%04" PRIX16
", expected 0x%04" PRIX32, dataType,
598 WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_DATA_RESULT_CODE));
602 const UINT32 resultCode = Stream_Get_UINT32(s);
603 if (resultCode != RDSTLS_RESULT_SUCCESS)
605 WLog_Print(rdstls->log, WLOG_ERROR,
"resultCode: %s [0x%08" PRIX32
"]",
606 rdstls_result_code_str(resultCode), resultCode);
608 UINT32 error = FREERDP_ERROR_CONNECT_UNDEFINED;
611 case RDSTLS_RESULT_ACCESS_DENIED:
612 error = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
614 case RDSTLS_RESULT_ACCOUNT_DISABLED:
615 error = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
617 case RDSTLS_RESULT_ACCOUNT_LOCKED_OUT:
618 error = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
620 case RDSTLS_RESULT_LOGON_FAILURE:
621 error = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
623 case RDSTLS_RESULT_INVALID_LOGON_HOURS:
624 error = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
626 case RDSTLS_RESULT_PASSWORD_EXPIRED:
627 error = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
629 case RDSTLS_RESULT_PASSWORD_MUST_CHANGE:
630 error = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
633 WLog_Print(rdstls->log, WLOG_ERROR,
634 "Unexpected resultCode: [0x%08" PRIX32
"], NTSTATUS=%s, Win32Error=%s",
635 resultCode, GetSecurityStatusString((SECURITY_STATUS)resultCode),
636 Win32ErrorCode2Tag(resultCode & 0xFFFF));
637 error = FREERDP_ERROR_CONNECT_UNDEFINED;
641 freerdp_set_last_error_if_not(rdstls->context, error);
648static BOOL rdstls_send(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
650 rdpRdstls* rdstls = (rdpRdstls*)extra;
651 rdpSettings* settings = NULL;
653 WINPR_ASSERT(transport);
655 WINPR_ASSERT(rdstls);
657 settings = rdstls->context->settings;
658 WINPR_ASSERT(settings);
660 if (!Stream_EnsureRemainingCapacity(s, 2))
663 Stream_Write_UINT16(s, RDSTLS_VERSION_1);
665 const RDSTLS_STATE state = rdstls_get_state(rdstls);
668 case RDSTLS_STATE_CAPABILITIES:
669 if (!rdstls_write_capabilities(rdstls, s))
672 case RDSTLS_STATE_AUTH_REQ:
673 if (settings->RedirectionFlags & LB_PASSWORD_IS_PK_ENCRYPTED)
675 if (!rdstls_write_authentication_request_with_password(rdstls, s))
678 else if (settings->ServerAutoReconnectCookie != NULL)
680 if (!rdstls_write_authentication_request_with_cookie(rdstls, s))
685 WLog_Print(rdstls->log, WLOG_ERROR,
686 "cannot authenticate with password or auto-reconnect cookie");
690 case RDSTLS_STATE_AUTH_RSP:
691 if (!rdstls_write_authentication_response(rdstls, s))
695 WLog_Print(rdstls->log, WLOG_ERROR,
"Invalid rdstls state %s [%" PRIu32
"]",
696 rdstls_get_state_str(state), state);
700 if (transport_write(rdstls->transport, s) < 0)
706static int rdstls_recv(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
708 rdpRdstls* rdstls = (rdpRdstls*)extra;
710 WINPR_ASSERT(transport);
712 WINPR_ASSERT(rdstls);
714 if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 4))
717 const UINT16 version = Stream_Get_UINT16(s);
718 if (version != RDSTLS_VERSION_1)
720 WLog_Print(rdstls->log, WLOG_ERROR,
721 "received invalid RDSTLS Version=0x%04" PRIX16
", expected 0x%04" PRIX16,
722 version, WINPR_CXX_COMPAT_CAST(UINT32, RDSTLS_VERSION_1));
726 const UINT16 pduType = Stream_Get_UINT16(s);
729 case RDSTLS_TYPE_CAPABILITIES:
730 if (!rdstls_process_capabilities(rdstls, s))
733 case RDSTLS_TYPE_AUTHREQ:
734 if (!rdstls_process_authentication_request(rdstls, s))
737 case RDSTLS_TYPE_AUTHRSP:
738 if (!rdstls_process_authentication_response(rdstls, s))
742 WLog_Print(rdstls->log, WLOG_ERROR,
"unknown RDSTLS PDU type [0x%04" PRIx16
"]",
750#define rdstls_check_state_requirements(rdstls, expected) \
751 rdstls_check_state_requirements_((rdstls), (expected), __FILE__, __func__, __LINE__)
752static BOOL rdstls_check_state_requirements_(rdpRdstls* rdstls, RDSTLS_STATE expected,
753 const char* file,
const char* fkt,
size_t line)
755 const RDSTLS_STATE current = rdstls_get_state(rdstls);
756 if (current == expected)
759 WINPR_ASSERT(rdstls);
761 const DWORD log_level = WLOG_ERROR;
762 if (WLog_IsLevelActive(rdstls->log, log_level))
763 WLog_PrintTextMessage(rdstls->log, log_level, line, file, fkt,
764 "Unexpected rdstls state %s [%u], expected %s [%u]",
765 rdstls_get_state_str(current), current,
766 rdstls_get_state_str(expected), expected);
771static BOOL rdstls_send_capabilities(rdpRdstls* rdstls)
775 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_CAPABILITIES))
778 wStream* s = Stream_New(NULL, 512);
782 WINPR_ASSERT(rdstls);
783 if (!rdstls_send(rdstls->transport, s, rdstls))
786 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_REQ);
788 Stream_Free(s, TRUE);
792static BOOL rdstls_recv_authentication_request(rdpRdstls* rdstls)
796 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_REQ))
799 wStream* s = Stream_New(NULL, 4096);
803 WINPR_ASSERT(rdstls);
804 const int res = transport_read_pdu(rdstls->transport, s);
809 const int status = rdstls_recv(rdstls->transport, s, rdstls);
814 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_RSP);
816 Stream_Free(s, TRUE);
820static BOOL rdstls_send_authentication_response(rdpRdstls* rdstls)
824 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_RSP))
827 wStream* s = Stream_New(NULL, 512);
831 WINPR_ASSERT(rdstls);
832 if (!rdstls_send(rdstls->transport, s, rdstls))
835 rc = rdstls_set_state(rdstls, RDSTLS_STATE_FINAL);
837 Stream_Free(s, TRUE);
841static BOOL rdstls_recv_capabilities(rdpRdstls* rdstls)
845 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_CAPABILITIES))
848 wStream* s = Stream_New(NULL, 512);
852 WINPR_ASSERT(rdstls);
853 const int res = transport_read_pdu(rdstls->transport, s);
858 const int status = rdstls_recv(rdstls->transport, s, rdstls);
863 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_REQ);
865 Stream_Free(s, TRUE);
869static BOOL rdstls_send_authentication_request(rdpRdstls* rdstls)
873 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_REQ))
876 wStream* s = Stream_New(NULL, 4096);
880 WINPR_ASSERT(rdstls);
881 if (!rdstls_send(rdstls->transport, s, rdstls))
884 rc = rdstls_set_state(rdstls, RDSTLS_STATE_AUTH_RSP);
886 Stream_Free(s, TRUE);
890static BOOL rdstls_recv_authentication_response(rdpRdstls* rdstls)
894 WINPR_ASSERT(rdstls);
896 if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_RSP))
899 wStream* s = Stream_New(NULL, 512);
903 const int res = transport_read_pdu(rdstls->transport, s);
908 const int status = rdstls_recv(rdstls->transport, s, rdstls);
913 rc = rdstls_set_state(rdstls, RDSTLS_STATE_FINAL);
915 Stream_Free(s, TRUE);
919static int rdstls_server_authenticate(rdpRdstls* rdstls)
921 WINPR_ASSERT(rdstls);
923 if (!rdstls_set_state(rdstls, RDSTLS_STATE_CAPABILITIES))
926 if (!rdstls_send_capabilities(rdstls))
929 if (!rdstls_recv_authentication_request(rdstls))
932 if (!rdstls_send_authentication_response(rdstls))
935 if (rdstls->resultCode != RDSTLS_RESULT_SUCCESS)
941static int rdstls_client_authenticate(rdpRdstls* rdstls)
943 if (!rdstls_set_state(rdstls, RDSTLS_STATE_CAPABILITIES))
946 if (!rdstls_recv_capabilities(rdstls))
949 if (!rdstls_send_authentication_request(rdstls))
952 if (!rdstls_recv_authentication_response(rdstls))
965int rdstls_authenticate(rdpRdstls* rdstls)
967 WINPR_ASSERT(rdstls);
970 return rdstls_server_authenticate(rdstls);
972 return rdstls_client_authenticate(rdstls);
975static SSIZE_T rdstls_parse_pdu_data_type(wLog* log, UINT16 dataType,
wStream* s)
977 size_t pduLength = 0;
981 case RDSTLS_DATA_PASSWORD_CREDS:
983 if (Stream_GetRemainingLength(s) < 2)
986 const UINT16 redirGuidLength = Stream_Get_UINT16(s);
988 if (Stream_GetRemainingLength(s) < redirGuidLength)
990 Stream_Seek(s, redirGuidLength);
992 if (Stream_GetRemainingLength(s) < 2)
995 const UINT16 usernameLength = Stream_Get_UINT16(s);
997 if (Stream_GetRemainingLength(s) < usernameLength)
999 Stream_Seek(s, usernameLength);
1001 if (Stream_GetRemainingLength(s) < 2)
1003 const UINT16 domainLength = Stream_Get_UINT16(s);
1005 if (Stream_GetRemainingLength(s) < domainLength)
1007 Stream_Seek(s, domainLength);
1009 if (Stream_GetRemainingLength(s) < 2)
1011 const UINT16 passwordLength = Stream_Get_UINT16(s);
1013 pduLength = Stream_GetPosition(s) + passwordLength;
1016 case RDSTLS_DATA_AUTORECONNECT_COOKIE:
1018 if (Stream_GetRemainingLength(s) < 4)
1022 if (Stream_GetRemainingLength(s) < 2)
1024 const UINT16 cookieLength = Stream_Get_UINT16(s);
1026 pduLength = Stream_GetPosition(s) + cookieLength;
1030 WLog_Print(log, WLOG_ERROR,
"invalid RDSLTS dataType");
1034 if (pduLength > SSIZE_MAX)
1036 return (SSIZE_T)pduLength;
1039SSIZE_T rdstls_parse_pdu(wLog* log,
wStream* stream)
1041 SSIZE_T pduLength = -1;
1043 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
1045 if (Stream_GetRemainingLength(s) < 2)
1048 const UINT16 version = Stream_Get_UINT16(s);
1049 if (version != RDSTLS_VERSION_1)
1051 WLog_Print(log, WLOG_ERROR,
"invalid RDSTLS version");
1055 if (Stream_GetRemainingLength(s) < 2)
1058 const UINT16 pduType = Stream_Get_UINT16(s);
1061 case RDSTLS_TYPE_CAPABILITIES:
1064 case RDSTLS_TYPE_AUTHREQ:
1065 if (Stream_GetRemainingLength(s) < 2)
1068 const UINT16 dataType = Stream_Get_UINT16(s);
1069 pduLength = rdstls_parse_pdu_data_type(log, dataType, s);
1072 case RDSTLS_TYPE_AUTHRSP:
1076 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.