23#include <freerdp/config.h>
26#include <winpr/assert.h>
27#include <winpr/stream.h>
29#include <freerdp/log.h>
38#define NEGO_TAG FREERDP_TAG("core.nego")
47 DWORD RoutingTokenLength;
48 BOOL SendPreconnectionPdu;
49 UINT32 PreconnectionId;
50 const char* PreconnectionBlob;
54 BOOL SecurityConnected;
55 UINT32 CookieMaxLength;
58 UINT32 SelectedProtocol;
59 UINT32 RequestedProtocols;
60 BOOL NegotiateSecurityLayer;
61 BOOL EnabledProtocols[32];
62 BOOL RestrictedAdminModeRequired;
63 BOOL RestrictedAdminModeSupported;
64 BOOL RemoteCredsGuardRequired;
65 BOOL RemoteCredsGuardActive;
66 BOOL RemoteCredsGuardSupported;
68 BOOL GatewayBypassLocal;
69 BOOL ConnectChildSession;
71 rdpTransport* transport;
75static const char* nego_state_string(NEGO_STATE state)
77 static const char*
const NEGO_STATE_STRINGS[] = {
"NEGO_STATE_INITIAL",
"NEGO_STATE_RDSTLS",
78 "NEGO_STATE_AAD",
"NEGO_STATE_EXT",
79 "NEGO_STATE_NLA",
"NEGO_STATE_TLS",
80 "NEGO_STATE_RDP",
"NEGO_STATE_FAIL",
81 "NEGO_STATE_FINAL",
"NEGO_STATE_INVALID" };
82 if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
83 return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
84 return NEGO_STATE_STRINGS[state];
87static BOOL nego_tcp_connect(rdpNego* nego);
88static BOOL nego_transport_connect(rdpNego* nego);
89static BOOL nego_transport_disconnect(rdpNego* nego);
90static BOOL nego_security_connect(rdpNego* nego);
91static BOOL nego_send_preconnection_pdu(rdpNego* nego);
92static BOOL nego_recv_response(rdpNego* nego);
93static void nego_send(rdpNego* nego);
94static BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s);
95static BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s);
96static BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s);
98BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
104 nego->RequestedProtocols) &&
106 nego->SelectedProtocol) &&
118BOOL nego_connect(rdpNego* nego)
120 rdpContext* context =
nullptr;
121 rdpSettings* settings =
nullptr;
123 context = transport_get_context(nego->transport);
124 WINPR_ASSERT(context);
125 settings = context->settings;
126 WINPR_ASSERT(settings);
128 if (nego_get_state(nego) == NEGO_STATE_INITIAL)
130 if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
132 nego_set_state(nego, NEGO_STATE_AAD);
134 else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
136 nego_set_state(nego, NEGO_STATE_RDSTLS);
138 else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
140 nego_set_state(nego, NEGO_STATE_EXT);
142 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
144 nego_set_state(nego, NEGO_STATE_NLA);
146 else if (nego->EnabledProtocols[PROTOCOL_SSL])
148 nego_set_state(nego, NEGO_STATE_TLS);
150 else if (nego->EnabledProtocols[PROTOCOL_RDP])
152 nego_set_state(nego, NEGO_STATE_RDP);
156 WLog_Print(nego->log, WLOG_ERROR,
"No security protocol is enabled");
157 nego_set_state(nego, NEGO_STATE_FAIL);
161 if (!nego->NegotiateSecurityLayer)
163 WLog_Print(nego->log, WLOG_DEBUG,
"Security Layer Negotiation is disabled");
165 nego->EnabledProtocols[PROTOCOL_RDSAAD] = FALSE;
166 nego->EnabledProtocols[PROTOCOL_HYBRID] = FALSE;
167 nego->EnabledProtocols[PROTOCOL_SSL] = FALSE;
168 nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
169 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
170 nego->EnabledProtocols[PROTOCOL_RDSTLS] = FALSE;
172 UINT32 SelectedProtocol = 0;
173 switch (nego_get_state(nego))
176 nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
177 SelectedProtocol = PROTOCOL_RDSAAD;
179 case NEGO_STATE_RDSTLS:
180 nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
181 SelectedProtocol = PROTOCOL_RDSTLS;
184 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
185 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
186 SelectedProtocol = PROTOCOL_HYBRID_EX;
189 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
190 SelectedProtocol = PROTOCOL_HYBRID;
193 nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
194 SelectedProtocol = PROTOCOL_SSL;
197 nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
198 SelectedProtocol = PROTOCOL_RDP;
201 WLog_Print(nego->log, WLOG_ERROR,
"Invalid NEGO state 0x%08" PRIx32,
202 nego_get_state(nego));
205 if (!nego_set_selected_protocol(nego, SelectedProtocol))
209 if (!nego_tcp_connect(nego))
211 WLog_Print(nego->log, WLOG_ERROR,
"Failed to connect");
215 if (nego->SendPreconnectionPdu)
217 if (!nego_send_preconnection_pdu(nego))
219 WLog_Print(nego->log, WLOG_ERROR,
"Failed to send preconnection pdu");
220 nego_set_state(nego, NEGO_STATE_FINAL);
226 if (!nego->NegotiateSecurityLayer)
228 nego_set_state(nego, NEGO_STATE_FINAL);
234 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
237 if (nego_get_state(nego) == NEGO_STATE_FAIL)
239 if (freerdp_get_last_error(transport_get_context(nego->transport)) ==
240 FREERDP_ERROR_SUCCESS)
241 WLog_Print(nego->log, WLOG_ERROR,
"Protocol Security Negotiation Failure");
243 nego_set_state(nego, NEGO_STATE_FINAL);
246 }
while (nego_get_state(nego) != NEGO_STATE_FINAL);
250 char buffer[64] = WINPR_C_ARRAY_INIT;
251 WLog_Print(nego->log, WLOG_DEBUG,
"Negotiated %s security",
252 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
256 if (!nego_update_settings_from_state(nego, settings))
259 if (nego->SelectedProtocol == PROTOCOL_RDP)
271 ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
272 ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
278 if (!nego_security_connect(nego))
280 char buffer[64] = WINPR_C_ARRAY_INIT;
281 WLog_Print(nego->log, WLOG_DEBUG,
"Failed to connect with %s security",
282 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
289BOOL nego_disconnect(rdpNego* nego)
292 nego_set_state(nego, NEGO_STATE_INITIAL);
293 return nego_transport_disconnect(nego);
296static BOOL nego_try_connect(rdpNego* nego)
300 switch (nego->SelectedProtocol)
302 case PROTOCOL_RDSAAD:
303 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSAAD");
304 nego->SecurityConnected = transport_connect_aad(nego->transport);
306 case PROTOCOL_RDSTLS:
307 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSTLS");
308 nego->SecurityConnected = transport_connect_rdstls(nego->transport);
310 case PROTOCOL_HYBRID:
311 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID");
312 nego->SecurityConnected = transport_connect_nla(nego->transport, FALSE);
314 case PROTOCOL_HYBRID_EX:
315 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID_EX");
316 nego->SecurityConnected = transport_connect_nla(nego->transport, TRUE);
319 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_SSL");
320 nego->SecurityConnected = transport_connect_tls(nego->transport);
323 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDP");
324 nego->SecurityConnected = transport_connect_rdp(nego->transport);
327 WLog_Print(nego->log, WLOG_ERROR,
328 "cannot connect security layer because no protocol has been selected yet.");
331 return nego->SecurityConnected;
335BOOL nego_security_connect(rdpNego* nego)
338 if (!nego->TcpConnected)
340 nego->SecurityConnected = FALSE;
342 else if (!nego->SecurityConnected)
344 if (!nego_try_connect(nego))
348 return nego->SecurityConnected;
351static BOOL nego_tcp_connect(rdpNego* nego)
353 rdpContext* context =
nullptr;
355 if (!nego->TcpConnected)
357 UINT32 TcpConnectTimeout = 0;
359 context = transport_get_context(nego->transport);
360 WINPR_ASSERT(context);
365 if (nego->GatewayEnabled)
367 if (nego->GatewayBypassLocal)
371 nego->log, WLOG_INFO,
372 "Detecting if host can be reached locally. - This might take some time.");
373 WLog_Print(nego->log, WLOG_INFO,
374 "To disable auto detection use /gateway-usage-method:direct");
375 transport_set_gateway_enabled(nego->transport, FALSE);
376 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
380 if (!nego->TcpConnected)
382 transport_set_gateway_enabled(nego->transport, TRUE);
383 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
387 else if (nego->ConnectChildSession)
389 nego->TcpConnected = transport_connect_childsession(nego->transport);
394 transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
398 return nego->TcpConnected;
409BOOL nego_transport_connect(rdpNego* nego)
412 if (!nego_tcp_connect(nego))
415 if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
416 return nego_security_connect(nego);
418 return nego->TcpConnected;
429BOOL nego_transport_disconnect(rdpNego* nego)
432 if (nego->TcpConnected)
433 transport_disconnect(nego->transport);
435 nego->TcpConnected = FALSE;
436 nego->SecurityConnected = FALSE;
448BOOL nego_send_preconnection_pdu(rdpNego* nego)
453 WCHAR* wszPCB =
nullptr;
457 WLog_Print(nego->log, WLOG_DEBUG,
"Sending preconnection PDU");
459 if (!nego_tcp_connect(nego))
463 cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
465 if (nego->PreconnectionBlob)
468 wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
469 if (len > UINT16_MAX - 1)
474 cchPCB = (UINT16)len;
476 cbSize += cchPCB *
sizeof(WCHAR);
479 s = Stream_New(
nullptr, cbSize);
484 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
488 Stream_Write_UINT32(s, cbSize);
489 Stream_Write_UINT32(s, 0);
490 Stream_Write_UINT32(s, PRECONNECTION_PDU_V2);
491 Stream_Write_UINT32(s, nego->PreconnectionId);
492 Stream_Write_UINT16(s, cchPCB);
496 Stream_Write(s, wszPCB, cchPCB *
sizeof(WCHAR));
500 Stream_SealLength(s);
502 if (transport_write(nego->transport, s) < 0)
504 Stream_Free(s, TRUE);
508 Stream_Free(s, TRUE);
512static void nego_attempt_rdstls(rdpNego* nego)
515 nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
516 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDSTLS security");
518 if (!nego_transport_connect(nego))
520 nego_set_state(nego, NEGO_STATE_FAIL);
524 if (!nego_send_negotiation_request(nego))
526 nego_set_state(nego, NEGO_STATE_FAIL);
530 if (!nego_recv_response(nego))
532 nego_set_state(nego, NEGO_STATE_FAIL);
536 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
538 if (nego_get_state(nego) != NEGO_STATE_FINAL)
540 nego_transport_disconnect(nego);
542 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
543 nego_set_state(nego, NEGO_STATE_EXT);
544 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
545 nego_set_state(nego, NEGO_STATE_NLA);
546 else if (nego->EnabledProtocols[PROTOCOL_SSL])
547 nego_set_state(nego, NEGO_STATE_TLS);
548 else if (nego->EnabledProtocols[PROTOCOL_RDP])
549 nego_set_state(nego, NEGO_STATE_RDP);
551 nego_set_state(nego, NEGO_STATE_FAIL);
555static void nego_attempt_rdsaad(rdpNego* nego)
558 nego->RequestedProtocols = PROTOCOL_RDSAAD;
559 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDS AAD Auth security");
561 if (!nego_transport_connect(nego))
563 nego_set_state(nego, NEGO_STATE_FAIL);
567 if (!nego_send_negotiation_request(nego))
569 nego_set_state(nego, NEGO_STATE_FAIL);
573 if (!nego_recv_response(nego))
575 nego_set_state(nego, NEGO_STATE_FAIL);
579 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
581 if (nego_get_state(nego) != NEGO_STATE_FINAL)
583 nego_transport_disconnect(nego);
585 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
586 nego_set_state(nego, NEGO_STATE_EXT);
587 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
588 nego_set_state(nego, NEGO_STATE_NLA);
589 else if (nego->EnabledProtocols[PROTOCOL_SSL])
590 nego_set_state(nego, NEGO_STATE_TLS);
591 else if (nego->EnabledProtocols[PROTOCOL_RDP])
592 nego_set_state(nego, NEGO_STATE_RDP);
594 nego_set_state(nego, NEGO_STATE_FAIL);
598static void nego_attempt_ext(rdpNego* nego)
601 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
602 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA extended security");
604 if (!nego_transport_connect(nego))
606 nego_set_state(nego, NEGO_STATE_FAIL);
610 if (!nego_send_negotiation_request(nego))
612 nego_set_state(nego, NEGO_STATE_FAIL);
616 if (!nego_recv_response(nego))
618 nego_set_state(nego, NEGO_STATE_FAIL);
622 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
624 if (nego_get_state(nego) != NEGO_STATE_FINAL)
626 nego_transport_disconnect(nego);
628 if (nego->EnabledProtocols[PROTOCOL_HYBRID])
629 nego_set_state(nego, NEGO_STATE_NLA);
630 else if (nego->EnabledProtocols[PROTOCOL_SSL])
631 nego_set_state(nego, NEGO_STATE_TLS);
632 else if (nego->EnabledProtocols[PROTOCOL_RDP])
633 nego_set_state(nego, NEGO_STATE_RDP);
635 nego_set_state(nego, NEGO_STATE_FAIL);
639static void nego_attempt_nla(rdpNego* nego)
642 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
643 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA security");
645 if (!nego_transport_connect(nego))
647 nego_set_state(nego, NEGO_STATE_FAIL);
651 if (!nego_send_negotiation_request(nego))
653 nego_set_state(nego, NEGO_STATE_FAIL);
657 if (!nego_recv_response(nego))
659 nego_set_state(nego, NEGO_STATE_FAIL);
663 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
665 if (nego_get_state(nego) != NEGO_STATE_FINAL)
667 nego_transport_disconnect(nego);
669 if (nego->EnabledProtocols[PROTOCOL_SSL])
670 nego_set_state(nego, NEGO_STATE_TLS);
671 else if (nego->EnabledProtocols[PROTOCOL_RDP])
672 nego_set_state(nego, NEGO_STATE_RDP);
674 nego_set_state(nego, NEGO_STATE_FAIL);
678static void nego_attempt_tls(rdpNego* nego)
681 nego->RequestedProtocols = PROTOCOL_SSL;
682 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting TLS security");
684 if (!nego_transport_connect(nego))
686 nego_set_state(nego, NEGO_STATE_FAIL);
690 if (!nego_send_negotiation_request(nego))
692 nego_set_state(nego, NEGO_STATE_FAIL);
696 if (!nego_recv_response(nego))
698 nego_set_state(nego, NEGO_STATE_FAIL);
702 if (nego_get_state(nego) != NEGO_STATE_FINAL)
704 nego_transport_disconnect(nego);
706 if (nego->EnabledProtocols[PROTOCOL_RDP])
707 nego_set_state(nego, NEGO_STATE_RDP);
709 nego_set_state(nego, NEGO_STATE_FAIL);
713static void nego_attempt_rdp(rdpNego* nego)
716 nego->RequestedProtocols = PROTOCOL_RDP;
717 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDP security");
719 if (!nego_transport_connect(nego))
721 nego_set_state(nego, NEGO_STATE_FAIL);
725 if (!nego_send_negotiation_request(nego))
727 nego_set_state(nego, NEGO_STATE_FAIL);
731 if (!nego_recv_response(nego))
733 nego_set_state(nego, NEGO_STATE_FAIL);
746BOOL nego_recv_response(rdpNego* nego)
752 s = Stream_New(
nullptr, 1024);
756 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
760 status = transport_read_pdu(nego->transport, s);
764 Stream_Free(s, TRUE);
768 status = nego_recv(nego->transport, s, nego);
769 Stream_Free(s, TRUE);
771 return (status >= 0);
785int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
790 rdpNego* nego = (rdpNego*)extra;
793 if (!tpkt_read_header(s, &length))
796 if (!tpdu_read_connection_confirm(s, &li, length))
802 Stream_Read_UINT8(s, type);
806 case TYPE_RDP_NEG_RSP:
807 if (!nego_process_negotiation_response(nego, s))
810 char buffer[64] = WINPR_C_ARRAY_INIT;
812 nego->log, WLOG_DEBUG,
"selected_protocol: %s",
813 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
818 if (nego->SelectedProtocol)
820 if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
821 (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
823 nego_set_state(nego, NEGO_STATE_FAIL);
825 if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
826 (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
828 nego_set_state(nego, NEGO_STATE_FAIL);
831 if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
832 (!nego->EnabledProtocols[PROTOCOL_SSL]))
834 nego_set_state(nego, NEGO_STATE_FAIL);
837 else if (!nego->EnabledProtocols[PROTOCOL_RDP])
839 nego_set_state(nego, NEGO_STATE_FAIL);
844 case TYPE_RDP_NEG_FAILURE:
845 if (!nego_process_negotiation_failure(nego, s))
854 WLog_Print(nego->log, WLOG_DEBUG,
"no rdpNegData");
856 if (!nego->EnabledProtocols[PROTOCOL_RDP])
857 nego_set_state(nego, NEGO_STATE_FAIL);
859 nego_set_state(nego, NEGO_STATE_FINAL);
863 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation response");
864 nego_set_state(nego, NEGO_STATE_FAIL);
867 if (!tpkt_ensure_stream_consumed(nego->log, s, length))
877static BOOL nego_read_request_token_or_cookie(rdpNego* nego,
wStream* s)
893 BOOL isToken = FALSE;
894 size_t remain = Stream_GetRemainingLength(s);
898 const char* str = Stream_ConstPointer(s);
899 const size_t pos = Stream_GetPosition(s);
905 if (memcmp(Stream_ConstPointer(s),
"Cookie: mstshash=", 17) != 0)
907 if (memcmp(Stream_ConstPointer(s),
"Cookie: msts=", 13) != 0)
909 if (memcmp(Stream_ConstPointer(s),
"tsv:", 4) != 0)
911 if (memcmp(Stream_ConstPointer(s),
"mth://", 6) != 0)
929 while (Stream_GetRemainingLength(s) >= 2)
931 Stream_Read_UINT16(s, crlf);
942 const size_t len = Stream_GetPosition(s) - pos;
943 Stream_Write_UINT16(s, 0);
945 if (len > UINT32_MAX)
948 if (strnlen(str, len) == len)
951 result = nego_set_routing_token(nego, str, (UINT32)len);
953 result = nego_set_cookie(nego, str);
959 if (!Stream_SetPosition(s, pos))
961 WLog_Print(nego->log, WLOG_ERROR,
"invalid %s received",
962 isToken ?
"routing token" :
"cookie");
966 WLog_Print(nego->log, WLOG_DEBUG,
"received %s [%s]", isToken ?
"routing token" :
"cookie",
982BOOL nego_read_request(rdpNego* nego,
wStream* s)
991 if (!tpkt_read_header(s, &length))
994 if (!tpdu_read_connection_request(s, &li, length))
997 if (li != Stream_GetRemainingLength(s) + 6)
999 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect TPDU length indicator.");
1003 if (!nego_read_request_token_or_cookie(nego, s))
1005 WLog_Print(nego->log, WLOG_ERROR,
"Failed to parse routing token or cookie.");
1009 if (Stream_GetRemainingLength(s) >= 8)
1012 Stream_Read_UINT8(s, type);
1014 if (type != TYPE_RDP_NEG_REQ)
1016 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect negotiation request type %" PRIu8
"",
1021 if (!nego_process_negotiation_request(nego, s))
1025 return tpkt_ensure_stream_consumed(nego->log, s, length);
1034void nego_send(rdpNego* nego)
1038 switch (nego_get_state(nego))
1040 case NEGO_STATE_AAD:
1041 nego_attempt_rdsaad(nego);
1043 case NEGO_STATE_RDSTLS:
1044 nego_attempt_rdstls(nego);
1046 case NEGO_STATE_EXT:
1047 nego_attempt_ext(nego);
1049 case NEGO_STATE_NLA:
1050 nego_attempt_nla(nego);
1052 case NEGO_STATE_TLS:
1053 nego_attempt_tls(nego);
1055 case NEGO_STATE_RDP:
1056 nego_attempt_rdp(nego);
1059 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation state for sending");
1074BOOL nego_send_negotiation_request(rdpNego* nego)
1082 size_t cookie_length = 0;
1083 s = Stream_New(
nullptr, 512);
1088 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1092 length = TPDU_CONNECTION_REQUEST_LENGTH;
1093 bm = Stream_GetPosition(s);
1094 Stream_Seek(s, length);
1096 if (nego->RoutingToken)
1098 Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1102 if ((nego->RoutingTokenLength > 2) &&
1103 (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1104 (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1106 WLog_Print(nego->log, WLOG_DEBUG,
1107 "Routing token looks correctly terminated - use verbatim");
1108 length += nego->RoutingTokenLength;
1112 WLog_Print(nego->log, WLOG_DEBUG,
"Adding terminating CRLF to routing token");
1113 Stream_Write_UINT8(s, 0x0D);
1114 Stream_Write_UINT8(s, 0x0A);
1115 length += nego->RoutingTokenLength + 2;
1118 else if (nego->cookie)
1120 cookie_length = strlen(nego->cookie);
1122 if (cookie_length > nego->CookieMaxLength)
1123 cookie_length = nego->CookieMaxLength;
1125 Stream_Write(s,
"Cookie: mstshash=", 17);
1126 Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1127 Stream_Write_UINT8(s, 0x0D);
1128 Stream_Write_UINT8(s, 0x0A);
1129 length += cookie_length + 19;
1133 char buffer[64] = WINPR_C_ARRAY_INIT;
1134 WLog_Print(nego->log, WLOG_DEBUG,
"RequestedProtocols: %s",
1135 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1138 if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1141 if (nego->RestrictedAdminModeRequired)
1142 flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1144 if (nego->RemoteCredsGuardRequired)
1145 flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1147 Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1148 Stream_Write_UINT8(s, flags);
1149 Stream_Write_UINT16(s, 8);
1150 Stream_Write_UINT32(s, nego->RequestedProtocols);
1154 if (length > UINT16_MAX)
1157 em = Stream_GetPosition(s);
1158 if (!Stream_SetPosition(s, bm))
1160 if (!tpkt_write_header(s, (UINT16)length))
1162 if (!tpdu_write_connection_request(s, (UINT16)length - 5))
1164 if (!Stream_SetPosition(s, em))
1166 Stream_SealLength(s);
1167 rc = (transport_write(nego->transport, s) >= 0);
1169 Stream_Free(s, TRUE);
1173static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego,
wStream* s)
1178 BYTE correlationId[16] = WINPR_C_ARRAY_INIT;
1180 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1182 WLog_Print(nego->log, WLOG_ERROR,
1183 "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1187 Stream_Read_UINT8(s, type);
1188 if (type != TYPE_RDP_CORRELATION_INFO)
1190 WLog_Print(nego->log, WLOG_ERROR,
1191 "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1194 Stream_Read_UINT8(s, flags);
1197 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::flags != 0");
1200 Stream_Read_UINT16(s, length);
1203 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::length != 36");
1207 Stream_Read(s, correlationId,
sizeof(correlationId));
1208 if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1210 WLog_Print(nego->log, WLOG_ERROR,
1211 "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1215 for (
size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1217 if (correlationId[x] == 0x0D)
1219 WLog_Print(nego->log, WLOG_ERROR,
1220 "(RDP_NEG_CORRELATION_INFO::correlationId[%" PRIuz
1221 "] has invalid value 0x%02" PRIx8,
1222 x, correlationId[x]);
1228 WLog_Print(nego->log, WLOG_INFO,
1229 "RDP_NEG_CORRELATION_INFO::correlationId = { %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1230 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1231 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1233 correlationId[0], correlationId[1], correlationId[2], correlationId[3],
1234 correlationId[4], correlationId[5], correlationId[6], correlationId[7],
1235 correlationId[8], correlationId[9], correlationId[10], correlationId[11],
1236 correlationId[12], correlationId[13], correlationId[14], correlationId[15]);
1240BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s)
1248 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1250 Stream_Read_UINT8(s, flags);
1251 if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1252 CORRELATION_INFO_PRESENT)) != 0)
1254 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1257 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1259 if (nego->RestrictedAdminModeSupported)
1261 WLog_Print(nego->log, WLOG_INFO,
"RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1265 WLog_Print(nego->log, WLOG_ERROR,
1266 "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED but disabled");
1271 if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1273 if (nego->RemoteCredsGuardSupported)
1275 WLog_Print(nego->log, WLOG_INFO,
1276 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1277 nego->RemoteCredsGuardActive = TRUE;
1284 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1286 WLog_Print(nego->log, WLOG_INFO,
1287 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED ignored.");
1292 nego->log, WLOG_ERROR,
1293 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1299 Stream_Read_UINT16(s, length);
1302 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::length != 8");
1305 Stream_Read_UINT32(s, nego->RequestedProtocols);
1307 if (flags & CORRELATION_INFO_PRESENT)
1309 if (!nego_process_correlation_info(nego, s))
1314 char buffer[64] = WINPR_C_ARRAY_INIT;
1315 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_REQ: RequestedProtocol: %s",
1316 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1318 nego_set_state(nego, NEGO_STATE_FINAL);
1322static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1324 const uint32_t mask =
1325 (EXTENDED_CLIENT_DATA_SUPPORTED | DYNVC_GFX_PROTOCOL_SUPPORTED | RDP_NEGRSP_RESERVED |
1326 RESTRICTED_ADMIN_MODE_SUPPORTED | REDIRECTED_AUTHENTICATION_MODE_SUPPORTED);
1327 static char buffer[1024] = WINPR_C_ARRAY_INIT;
1329 (void)_snprintf(buffer, ARRAYSIZE(buffer),
"[0x%02" PRIx32
"] ", flags);
1330 if (flags & EXTENDED_CLIENT_DATA_SUPPORTED)
1331 winpr_str_append(
"EXTENDED_CLIENT_DATA_SUPPORTED", buffer,
sizeof(buffer),
"|");
1332 if (flags & DYNVC_GFX_PROTOCOL_SUPPORTED)
1333 winpr_str_append(
"DYNVC_GFX_PROTOCOL_SUPPORTED", buffer,
sizeof(buffer),
"|");
1334 if (flags & RDP_NEGRSP_RESERVED)
1335 winpr_str_append(
"RDP_NEGRSP_RESERVED", buffer,
sizeof(buffer),
"|");
1336 if (flags & RESTRICTED_ADMIN_MODE_SUPPORTED)
1337 winpr_str_append(
"RESTRICTED_ADMIN_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1338 if (flags & REDIRECTED_AUTHENTICATION_MODE_SUPPORTED)
1339 winpr_str_append(
"REDIRECTED_AUTHENTICATION_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1342 char buffer2[32] = WINPR_C_ARRAY_INIT;
1343 (void)_snprintf(buffer2,
sizeof(buffer2),
"UNKNOWN[0x%04" PRIx32
"]", flags & ~mask);
1344 winpr_str_append(buffer2, buffer,
sizeof(buffer),
"|");
1350BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s)
1357 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1359 nego_set_state(nego, NEGO_STATE_FAIL);
1363 Stream_Read_UINT8(s, nego->flags);
1364 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_RSP::flags = { %s }",
1365 nego_rdp_neg_rsp_flags_str(nego->flags));
1367 Stream_Read_UINT16(s, length);
1370 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_RSP::length != 8");
1371 nego_set_state(nego, NEGO_STATE_FAIL);
1374 UINT32 SelectedProtocol = 0;
1375 Stream_Read_UINT32(s, SelectedProtocol);
1377 if (!nego_set_selected_protocol(nego, SelectedProtocol))
1379 return nego_set_state(nego, NEGO_STATE_FINAL);
1382static const char* nego_rdp_neg_fail_str(uint32_t what)
1386 case SSL_REQUIRED_BY_SERVER:
1387 return "SSL_REQUIRED_BY_SERVER";
1388 case SSL_NOT_ALLOWED_BY_SERVER:
1389 return "SSL_NOT_ALLOWED_BY_SERVER";
1390 case SSL_CERT_NOT_ON_SERVER:
1391 return "SSL_CERT_NOT_ON_SERVER";
1392 case INCONSISTENT_FLAGS:
1393 return "INCONSISTENT_FLAGS";
1394 case HYBRID_REQUIRED_BY_SERVER:
1395 return "HYBRID_REQUIRED_BY_SERVER";
1396 case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
1397 return "SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER";
1403static void nego_disable_all_except(rdpNego* nego, uint32_t what)
1407 char buffer[32] = WINPR_C_ARRAY_INIT;
1408 WLog_Print(nego->log, WLOG_DEBUG,
"Disabling all modes except %s",
1409 nego_protocol_to_str(what, buffer,
sizeof(buffer)));
1411 for (
size_t x = 0; x < ARRAYSIZE(nego->EnabledProtocols); x++)
1415 nego->EnabledProtocols[x] = FALSE;
1427BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s)
1435 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_FAILURE");
1436 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1439 Stream_Read_UINT8(s, flags);
1442 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1445 Stream_Read_UINT16(s, length);
1448 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::length != 8");
1451 const uint32_t failureCode = Stream_Get_UINT32(s);
1452 const char* failureStr = nego_rdp_neg_fail_str(failureCode);
1453 DWORD level = WLOG_WARN;
1454 switch (failureCode)
1456 case SSL_REQUIRED_BY_SERVER:
1457 nego_disable_all_except(nego, PROTOCOL_SSL);
1460 case SSL_NOT_ALLOWED_BY_SERVER:
1461 nego_disable_all_except(nego, PROTOCOL_RDP);
1462 nego->sendNegoData = TRUE;
1465 case SSL_CERT_NOT_ON_SERVER:
1467 nego->sendNegoData = TRUE;
1470 case INCONSISTENT_FLAGS:
1474 case HYBRID_REQUIRED_BY_SERVER:
1475 nego_disable_all_except(nego, PROTOCOL_HYBRID);
1483 WLog_Print(nego->log, level,
"Error: %s [0x%08" PRIx32
"]", failureStr, failureCode);
1484 nego_set_state(nego, NEGO_STATE_FAIL);
1493BOOL nego_send_negotiation_response(rdpNego* nego)
1495 BOOL status = FALSE;
1497 rdpContext* context =
nullptr;
1498 rdpSettings* settings =
nullptr;
1501 context = transport_get_context(nego->transport);
1502 WINPR_ASSERT(context);
1504 settings = context->settings;
1505 WINPR_ASSERT(settings);
1507 wStream* s = Stream_New(
nullptr, 512);
1511 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1515 UINT16 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1516 const size_t bm = Stream_GetPosition(s);
1517 if (!Stream_SafeSeek(s, length))
1520 if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1522 UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1524 Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1525 Stream_Write_UINT8(s, flags);
1526 Stream_Write_UINT16(s, 8);
1527 Stream_Write_UINT32(s, errorCode);
1532 flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1535 flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1537 if (nego->RestrictedAdminModeSupported)
1538 flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1540 if (nego->RemoteCredsGuardSupported)
1541 flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1544 Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1545 Stream_Write_UINT8(s, flags);
1546 Stream_Write_UINT16(s, 8);
1547 Stream_Write_UINT32(s, nego->SelectedProtocol);
1551 const size_t em = Stream_GetPosition(s);
1552 if (!Stream_SetPosition(s, bm))
1554 if (!tpkt_write_header(s, length))
1557 if (!tpdu_write_connection_confirm(s, length - 5))
1560 if (!Stream_SetPosition(s, em))
1562 Stream_SealLength(s);
1564 status = (transport_write(nego->transport, s) >= 0);
1567 Stream_Free(s, TRUE);
1573 nego->RequestedProtocols))
1576 nego->SelectedProtocol))
1579 switch (nego->SelectedProtocol)
1592 ENCRYPTION_LEVEL_NONE)
1599 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1611 WLog_Print(nego->log, WLOG_INFO,
1612 "Turning off encryption for local peer with standard rdp security");
1616 ENCRYPTION_LEVEL_NONE))
1621 WLog_Print(nego->log, WLOG_ERROR,
"Missing server certificate");
1638 ENCRYPTION_LEVEL_NONE))
1641 case PROTOCOL_HYBRID:
1654 ENCRYPTION_LEVEL_NONE))
1657 case PROTOCOL_RDSTLS:
1670 ENCRYPTION_LEVEL_NONE))
1686void nego_init(rdpNego* nego)
1689 nego_set_state(nego, NEGO_STATE_INITIAL);
1690 nego->RequestedProtocols = PROTOCOL_RDP;
1691 nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
1692 nego->sendNegoData = FALSE;
1704rdpNego* nego_new(rdpTransport* transport)
1706 rdpNego* nego = (rdpNego*)calloc(1,
sizeof(rdpNego));
1711 nego->log = WLog_Get(NEGO_TAG);
1712 WINPR_ASSERT(nego->log);
1713 nego->transport = transport;
1723void nego_free(rdpNego* nego)
1727 free(nego->RoutingToken);
1742BOOL nego_set_target(rdpNego* nego,
const char* hostname, UINT16 port)
1745 WINPR_ASSERT(hostname);
1747 nego->hostname = hostname;
1759void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1761 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling security layer negotiation: %s",
1762 NegotiateSecurityLayer ?
"TRUE" :
"FALSE");
1763 nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1773void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1775 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling restricted admin mode: %s",
1776 RestrictedAdminModeRequired ?
"TRUE" :
"FALSE");
1777 nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1780void nego_set_restricted_admin_mode_supported(rdpNego* nego, BOOL enabled)
1784 nego->RestrictedAdminModeSupported = enabled;
1787void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1791 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling remoteCredentialGuards: %s",
1792 enabled ?
"TRUE" :
"FALSE");
1793 nego->RemoteCredsGuardRequired = enabled;
1796void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1800 nego->RemoteCredsGuardSupported = enabled;
1803BOOL nego_get_remoteCredentialGuard(
const rdpNego* nego)
1807 return nego->RemoteCredsGuardActive;
1810void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1813 nego->ConnectChildSession = ChildSessionEnabled;
1816void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1818 nego->GatewayEnabled = GatewayEnabled;
1821void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1823 nego->GatewayBypassLocal = GatewayBypassLocal;
1832void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1834 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDP security: %s", enable_rdp ?
"TRUE" :
"FALSE");
1835 nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1844void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1846 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling TLS security: %s", enable_tls ?
"TRUE" :
"FALSE");
1847 nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1857void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1859 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA security: %s", enable_nla ?
"TRUE" :
"FALSE");
1860 nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1870void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1872 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDSTLS security: %s",
1873 enable_rdstls ?
"TRUE" :
"FALSE");
1874 nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1884void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1886 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA extended security: %s",
1887 enable_ext ?
"TRUE" :
"FALSE");
1888 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = enable_ext;
1898void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1901 if (aad_is_supported())
1903 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDS AAD security: %s",
1904 enable_aad ?
"TRUE" :
"FALSE");
1905 nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1909 WLog_Print(nego->log, WLOG_WARN,
"This build does not support AAD security, disabling.");
1922BOOL nego_set_routing_token(rdpNego* nego,
const void* RoutingToken, DWORD RoutingTokenLength)
1924 if (RoutingTokenLength == 0)
1927 free(nego->RoutingToken);
1928 nego->RoutingTokenLength = RoutingTokenLength;
1929 nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1931 if (!nego->RoutingToken)
1934 CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1946BOOL nego_set_cookie(rdpNego* nego,
const char* cookie)
1951 nego->cookie =
nullptr;
1957 nego->cookie = _strdup(cookie);
1959 return (nego->cookie !=
nullptr);
1968void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1970 nego->CookieMaxLength = CookieMaxLength;
1979void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1981 nego->SendPreconnectionPdu = SendPreconnectionPdu;
1990void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1992 nego->PreconnectionId = PreconnectionId;
2001void nego_set_preconnection_blob(rdpNego* nego,
const char* PreconnectionBlob)
2003 nego->PreconnectionBlob = PreconnectionBlob;
2006UINT32 nego_get_selected_protocol(
const rdpNego* nego)
2011 return nego->SelectedProtocol;
2014BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
2017 nego->SelectedProtocol = SelectedProtocol;
2021UINT32 nego_get_requested_protocols(
const rdpNego* nego)
2026 return nego->RequestedProtocols;
2029BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
2034 nego->RequestedProtocols = RequestedProtocols;
2038NEGO_STATE nego_get_state(
const rdpNego* nego)
2041 return NEGO_STATE_FAIL;
2046BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
2049 nego->state = state;
2053SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
2055 rdpNla* nla =
nullptr;
2059 nla = transport_get_nla(nego->transport);
2060 return nla_get_identity(nla);
2063void nego_free_nla(rdpNego* nego)
2065 if (!nego || !nego->transport)
2068 transport_set_nla(nego->transport,
nullptr);
2071const BYTE* nego_get_routing_token(
const rdpNego* nego, DWORD* RoutingTokenLength)
2075 if (RoutingTokenLength)
2076 *RoutingTokenLength = nego->RoutingTokenLength;
2077 return nego->RoutingToken;
2080const char* nego_protocol_to_str(UINT32 protocol,
char* buffer,
size_t size)
2082 const UINT32 mask = ~(PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_RDSTLS | PROTOCOL_HYBRID_EX |
2083 PROTOCOL_RDSAAD | PROTOCOL_FAILED_NEGO);
2084 char str[48] = WINPR_C_ARRAY_INIT;
2086 if (protocol & PROTOCOL_SSL)
2087 (void)winpr_str_append(
"SSL", str,
sizeof(str),
"|");
2088 if (protocol & PROTOCOL_HYBRID)
2089 (void)winpr_str_append(
"HYBRID", str,
sizeof(str),
"|");
2090 if (protocol & PROTOCOL_RDSTLS)
2091 (void)winpr_str_append(
"RDSTLS", str,
sizeof(str),
"|");
2092 if (protocol & PROTOCOL_HYBRID_EX)
2093 (void)winpr_str_append(
"HYBRID_EX", str,
sizeof(str),
"|");
2094 if (protocol & PROTOCOL_RDSAAD)
2095 (void)winpr_str_append(
"RDSAAD", str,
sizeof(str),
"|");
2096 if (protocol & PROTOCOL_FAILED_NEGO)
2097 (void)winpr_str_append(
"NEGO FAILED", str,
sizeof(str),
"|");
2099 if (protocol == PROTOCOL_RDP)
2100 (void)winpr_str_append(
"RDP", str,
sizeof(str),
"");
2101 else if ((protocol & mask) != 0)
2102 (
void)winpr_str_append(
"UNKNOWN", str,
sizeof(str),
"|");
2104 (void)_snprintf(buffer, size,
"[%s][0x%08" PRIx32
"]", str, protocol);
WINPR_ATTR_NODISCARD FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.