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;
61 BOOL NegotiateSecurityLayer;
62 BOOL EnabledProtocols[32];
63 BOOL RestrictedAdminModeRequired;
64 BOOL RestrictedAdminModeSupported;
65 BOOL RemoteCredsGuardRequired;
66 BOOL RemoteCredsGuardActive;
67 BOOL RemoteCredsGuardSupported;
69 BOOL GatewayBypassLocal;
70 BOOL ConnectChildSession;
72 rdpTransport* transport;
76static const char* nego_state_string(NEGO_STATE state)
78 static const char*
const NEGO_STATE_STRINGS[] = {
"NEGO_STATE_INITIAL",
"NEGO_STATE_RDSTLS",
79 "NEGO_STATE_AAD",
"NEGO_STATE_EXT",
80 "NEGO_STATE_NLA",
"NEGO_STATE_TLS",
81 "NEGO_STATE_RDP",
"NEGO_STATE_FAIL",
82 "NEGO_STATE_FINAL",
"NEGO_STATE_INVALID" };
83 if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
84 return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
85 return NEGO_STATE_STRINGS[state];
88static BOOL nego_tcp_connect(rdpNego* nego);
89static BOOL nego_transport_connect(rdpNego* nego);
90static BOOL nego_transport_disconnect(rdpNego* nego);
91static BOOL nego_security_connect(rdpNego* nego);
92static BOOL nego_send_preconnection_pdu(rdpNego* nego);
93static BOOL nego_recv_response(rdpNego* nego);
94static void nego_send(rdpNego* nego);
95static BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s);
96static BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s);
97static BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s);
98static const char* nego_rdp_neg_fail_str(uint32_t what);
105static UINT32 nego_failure_to_error(uint32_t failureCode)
109 case SSL_CERT_NOT_ON_SERVER:
111 return FREERDP_ERROR_TLS_CONNECT_FAILED;
113 case HYBRID_REQUIRED_BY_SERVER:
116 return FREERDP_ERROR_CONNECT_HYBRID_REQUIRED_BY_SERVER;
120 return FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED;
124BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
130 nego->RequestedProtocols) &&
132 nego->SelectedProtocol) &&
144BOOL nego_connect(rdpNego* nego)
146 rdpContext* context =
nullptr;
147 rdpSettings* settings =
nullptr;
149 context = transport_get_context(nego->transport);
150 WINPR_ASSERT(context);
151 settings = context->settings;
152 WINPR_ASSERT(settings);
154 if (nego_get_state(nego) == NEGO_STATE_INITIAL)
156 if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
158 nego_set_state(nego, NEGO_STATE_AAD);
160 else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
162 nego_set_state(nego, NEGO_STATE_RDSTLS);
164 else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
166 nego_set_state(nego, NEGO_STATE_EXT);
168 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
170 nego_set_state(nego, NEGO_STATE_NLA);
172 else if (nego->EnabledProtocols[PROTOCOL_SSL])
174 nego_set_state(nego, NEGO_STATE_TLS);
176 else if (nego->EnabledProtocols[PROTOCOL_RDP])
178 nego_set_state(nego, NEGO_STATE_RDP);
182 WLog_Print(nego->log, WLOG_ERROR,
"No security protocol is enabled");
183 nego_set_state(nego, NEGO_STATE_FAIL);
187 if (!nego->NegotiateSecurityLayer)
189 WLog_Print(nego->log, WLOG_DEBUG,
"Security Layer Negotiation is disabled");
191 nego->EnabledProtocols[PROTOCOL_RDSAAD] = FALSE;
192 nego->EnabledProtocols[PROTOCOL_HYBRID] = FALSE;
193 nego->EnabledProtocols[PROTOCOL_SSL] = FALSE;
194 nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
195 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
196 nego->EnabledProtocols[PROTOCOL_RDSTLS] = FALSE;
198 UINT32 SelectedProtocol = 0;
199 switch (nego_get_state(nego))
202 nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
203 SelectedProtocol = PROTOCOL_RDSAAD;
205 case NEGO_STATE_RDSTLS:
206 nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
207 SelectedProtocol = PROTOCOL_RDSTLS;
210 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
211 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
212 SelectedProtocol = PROTOCOL_HYBRID_EX;
215 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
216 SelectedProtocol = PROTOCOL_HYBRID;
219 nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
220 SelectedProtocol = PROTOCOL_SSL;
223 nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
224 SelectedProtocol = PROTOCOL_RDP;
227 WLog_Print(nego->log, WLOG_ERROR,
"Invalid NEGO state 0x%08" PRIx32,
228 nego_get_state(nego));
231 if (!nego_set_selected_protocol(nego, SelectedProtocol))
235 if (!nego_tcp_connect(nego))
237 WLog_Print(nego->log, WLOG_ERROR,
"Failed to connect");
241 if (nego->SendPreconnectionPdu)
243 if (!nego_send_preconnection_pdu(nego))
245 WLog_Print(nego->log, WLOG_ERROR,
"Failed to send preconnection pdu");
246 nego_set_state(nego, NEGO_STATE_FINAL);
252 if (!nego->NegotiateSecurityLayer)
254 nego_set_state(nego, NEGO_STATE_FINAL);
260 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
263 if (nego_get_state(nego) == NEGO_STATE_FAIL)
265 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
267 if (nego->failureCode != 0)
268 WLog_Print(nego->log, WLOG_ERROR,
269 "Protocol Security Negotiation Failure: %s [0x%08" PRIx32
"]",
270 nego_rdp_neg_fail_str(nego->failureCode), nego->failureCode);
272 WLog_Print(nego->log, WLOG_ERROR,
"Protocol Security Negotiation Failure");
275 if (nego->failureCode != 0)
276 freerdp_set_last_error_if_not(context,
277 nego_failure_to_error(nego->failureCode));
279 nego_set_state(nego, NEGO_STATE_FINAL);
282 }
while (nego_get_state(nego) != NEGO_STATE_FINAL);
286 char buffer[64] = WINPR_C_ARRAY_INIT;
287 WLog_Print(nego->log, WLOG_DEBUG,
"Negotiated %s security",
288 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
292 if (!nego_update_settings_from_state(nego, settings))
295 if (nego->SelectedProtocol == PROTOCOL_RDP)
307 ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
308 ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
314 if (!nego_security_connect(nego))
316 char buffer[64] = WINPR_C_ARRAY_INIT;
317 WLog_Print(nego->log, WLOG_DEBUG,
"Failed to connect with %s security",
318 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
325BOOL nego_disconnect(rdpNego* nego)
328 nego_set_state(nego, NEGO_STATE_INITIAL);
329 return nego_transport_disconnect(nego);
332static BOOL nego_try_connect(rdpNego* nego)
336 switch (nego->SelectedProtocol)
338 case PROTOCOL_RDSAAD:
339 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSAAD");
340 nego->SecurityConnected = transport_connect_aad(nego->transport);
342 case PROTOCOL_RDSTLS:
343 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSTLS");
344 nego->SecurityConnected = transport_connect_rdstls(nego->transport);
346 case PROTOCOL_HYBRID:
347 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID");
348 nego->SecurityConnected = transport_connect_nla(nego->transport, FALSE);
350 case PROTOCOL_HYBRID_EX:
351 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID_EX");
352 nego->SecurityConnected = transport_connect_nla(nego->transport, TRUE);
355 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_SSL");
356 nego->SecurityConnected = transport_connect_tls(nego->transport);
359 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDP");
360 nego->SecurityConnected = transport_connect_rdp(nego->transport);
363 WLog_Print(nego->log, WLOG_ERROR,
364 "cannot connect security layer because no protocol has been selected yet.");
367 return nego->SecurityConnected;
371BOOL nego_security_connect(rdpNego* nego)
374 if (!nego->TcpConnected)
376 nego->SecurityConnected = FALSE;
378 else if (!nego->SecurityConnected)
380 if (!nego_try_connect(nego))
384 return nego->SecurityConnected;
387static BOOL nego_tcp_connect(rdpNego* nego)
389 rdpContext* context =
nullptr;
391 if (!nego->TcpConnected)
393 UINT32 TcpConnectTimeout = 0;
395 context = transport_get_context(nego->transport);
396 WINPR_ASSERT(context);
401 if (nego->GatewayEnabled)
403 if (nego->GatewayBypassLocal)
407 nego->log, WLOG_INFO,
408 "Detecting if host can be reached locally. - This might take some time.");
409 WLog_Print(nego->log, WLOG_INFO,
410 "To disable auto detection use /gateway-usage-method:direct");
411 transport_set_gateway_enabled(nego->transport, FALSE);
412 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
416 if (!nego->TcpConnected)
418 transport_set_gateway_enabled(nego->transport, TRUE);
419 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
423 else if (nego->ConnectChildSession)
425 nego->TcpConnected = transport_connect_childsession(nego->transport);
430 transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
434 return nego->TcpConnected;
445BOOL nego_transport_connect(rdpNego* nego)
448 if (!nego_tcp_connect(nego))
451 if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
452 return nego_security_connect(nego);
454 return nego->TcpConnected;
465BOOL nego_transport_disconnect(rdpNego* nego)
468 if (nego->TcpConnected)
469 transport_disconnect(nego->transport);
471 nego->TcpConnected = FALSE;
472 nego->SecurityConnected = FALSE;
484BOOL nego_send_preconnection_pdu(rdpNego* nego)
489 WCHAR* wszPCB =
nullptr;
493 WLog_Print(nego->log, WLOG_DEBUG,
"Sending preconnection PDU");
495 if (!nego_tcp_connect(nego))
499 cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
501 if (nego->PreconnectionBlob)
504 wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
505 if (len > UINT16_MAX - 1)
510 cchPCB = (UINT16)len;
512 cbSize += cchPCB *
sizeof(WCHAR);
515 s = Stream_New(
nullptr, cbSize);
520 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
524 Stream_Write_UINT32(s, cbSize);
525 Stream_Write_UINT32(s, 0);
526 Stream_Write_UINT32(s, PRECONNECTION_PDU_V2);
527 Stream_Write_UINT32(s, nego->PreconnectionId);
528 Stream_Write_UINT16(s, cchPCB);
532 Stream_Write(s, wszPCB, cchPCB *
sizeof(WCHAR));
536 Stream_SealLength(s);
538 if (transport_write(nego->transport, s) < 0)
540 Stream_Free(s, TRUE);
544 Stream_Free(s, TRUE);
548static void nego_attempt_rdstls(rdpNego* nego)
551 nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
552 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDSTLS security");
554 if (!nego_transport_connect(nego))
556 nego_set_state(nego, NEGO_STATE_FAIL);
560 if (!nego_send_negotiation_request(nego))
562 nego_set_state(nego, NEGO_STATE_FAIL);
566 if (!nego_recv_response(nego))
568 nego_set_state(nego, NEGO_STATE_FAIL);
572 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
574 if (nego_get_state(nego) != NEGO_STATE_FINAL)
576 nego_transport_disconnect(nego);
578 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
579 nego_set_state(nego, NEGO_STATE_EXT);
580 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
581 nego_set_state(nego, NEGO_STATE_NLA);
582 else if (nego->EnabledProtocols[PROTOCOL_SSL])
583 nego_set_state(nego, NEGO_STATE_TLS);
584 else if (nego->EnabledProtocols[PROTOCOL_RDP])
585 nego_set_state(nego, NEGO_STATE_RDP);
587 nego_set_state(nego, NEGO_STATE_FAIL);
591static void nego_attempt_rdsaad(rdpNego* nego)
594 nego->RequestedProtocols = PROTOCOL_RDSAAD;
595 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDS AAD Auth security");
597 if (!nego_transport_connect(nego))
599 nego_set_state(nego, NEGO_STATE_FAIL);
603 if (!nego_send_negotiation_request(nego))
605 nego_set_state(nego, NEGO_STATE_FAIL);
609 if (!nego_recv_response(nego))
611 nego_set_state(nego, NEGO_STATE_FAIL);
615 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
617 if (nego_get_state(nego) != NEGO_STATE_FINAL)
619 nego_transport_disconnect(nego);
621 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
622 nego_set_state(nego, NEGO_STATE_EXT);
623 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
624 nego_set_state(nego, NEGO_STATE_NLA);
625 else if (nego->EnabledProtocols[PROTOCOL_SSL])
626 nego_set_state(nego, NEGO_STATE_TLS);
627 else if (nego->EnabledProtocols[PROTOCOL_RDP])
628 nego_set_state(nego, NEGO_STATE_RDP);
630 nego_set_state(nego, NEGO_STATE_FAIL);
634static void nego_attempt_ext(rdpNego* nego)
637 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
638 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA extended security");
640 if (!nego_transport_connect(nego))
642 nego_set_state(nego, NEGO_STATE_FAIL);
646 if (!nego_send_negotiation_request(nego))
648 nego_set_state(nego, NEGO_STATE_FAIL);
652 if (!nego_recv_response(nego))
654 nego_set_state(nego, NEGO_STATE_FAIL);
658 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
660 if (nego_get_state(nego) != NEGO_STATE_FINAL)
662 nego_transport_disconnect(nego);
664 if (nego->EnabledProtocols[PROTOCOL_HYBRID])
665 nego_set_state(nego, NEGO_STATE_NLA);
666 else if (nego->EnabledProtocols[PROTOCOL_SSL])
667 nego_set_state(nego, NEGO_STATE_TLS);
668 else if (nego->EnabledProtocols[PROTOCOL_RDP])
669 nego_set_state(nego, NEGO_STATE_RDP);
671 nego_set_state(nego, NEGO_STATE_FAIL);
675static void nego_attempt_nla(rdpNego* nego)
678 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
679 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA security");
681 if (!nego_transport_connect(nego))
683 nego_set_state(nego, NEGO_STATE_FAIL);
687 if (!nego_send_negotiation_request(nego))
689 nego_set_state(nego, NEGO_STATE_FAIL);
693 if (!nego_recv_response(nego))
695 nego_set_state(nego, NEGO_STATE_FAIL);
699 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
701 if (nego_get_state(nego) != NEGO_STATE_FINAL)
703 nego_transport_disconnect(nego);
705 if (nego->EnabledProtocols[PROTOCOL_SSL])
706 nego_set_state(nego, NEGO_STATE_TLS);
707 else if (nego->EnabledProtocols[PROTOCOL_RDP])
708 nego_set_state(nego, NEGO_STATE_RDP);
710 nego_set_state(nego, NEGO_STATE_FAIL);
714static void nego_attempt_tls(rdpNego* nego)
717 nego->RequestedProtocols = PROTOCOL_SSL;
718 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting TLS security");
720 if (!nego_transport_connect(nego))
722 nego_set_state(nego, NEGO_STATE_FAIL);
726 if (!nego_send_negotiation_request(nego))
728 nego_set_state(nego, NEGO_STATE_FAIL);
732 if (!nego_recv_response(nego))
734 nego_set_state(nego, NEGO_STATE_FAIL);
738 if (nego_get_state(nego) != NEGO_STATE_FINAL)
740 nego_transport_disconnect(nego);
742 if (nego->EnabledProtocols[PROTOCOL_RDP])
743 nego_set_state(nego, NEGO_STATE_RDP);
745 nego_set_state(nego, NEGO_STATE_FAIL);
749static void nego_attempt_rdp(rdpNego* nego)
752 nego->RequestedProtocols = PROTOCOL_RDP;
753 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDP security");
755 if (!nego_transport_connect(nego))
757 nego_set_state(nego, NEGO_STATE_FAIL);
761 if (!nego_send_negotiation_request(nego))
763 nego_set_state(nego, NEGO_STATE_FAIL);
767 if (!nego_recv_response(nego))
769 nego_set_state(nego, NEGO_STATE_FAIL);
782BOOL nego_recv_response(rdpNego* nego)
788 s = Stream_New(
nullptr, 1024);
792 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
796 status = transport_read_pdu(nego->transport, s);
800 Stream_Free(s, TRUE);
804 status = nego_recv(nego->transport, s, nego);
805 Stream_Free(s, TRUE);
807 return (status >= 0);
821int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
826 rdpNego* nego = (rdpNego*)extra;
829 if (!tpkt_read_header(s, &length))
832 if (!tpdu_read_connection_confirm(s, &li, length))
838 Stream_Read_UINT8(s, type);
842 case TYPE_RDP_NEG_RSP:
843 if (!nego_process_negotiation_response(nego, s))
846 char buffer[64] = WINPR_C_ARRAY_INIT;
848 nego->log, WLOG_DEBUG,
"selected_protocol: %s",
849 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
854 if (nego->SelectedProtocol)
856 if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
857 (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
859 nego_set_state(nego, NEGO_STATE_FAIL);
861 if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
862 (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
864 nego_set_state(nego, NEGO_STATE_FAIL);
867 if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
868 (!nego->EnabledProtocols[PROTOCOL_SSL]))
870 nego_set_state(nego, NEGO_STATE_FAIL);
873 else if (!nego->EnabledProtocols[PROTOCOL_RDP])
875 nego_set_state(nego, NEGO_STATE_FAIL);
880 case TYPE_RDP_NEG_FAILURE:
881 if (!nego_process_negotiation_failure(nego, s))
890 WLog_Print(nego->log, WLOG_DEBUG,
"no rdpNegData");
892 if (!nego->EnabledProtocols[PROTOCOL_RDP])
893 nego_set_state(nego, NEGO_STATE_FAIL);
895 nego_set_state(nego, NEGO_STATE_FINAL);
899 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation response");
900 nego_set_state(nego, NEGO_STATE_FAIL);
903 if (!tpkt_ensure_stream_consumed(nego->log, s, length))
913static BOOL nego_read_request_token_or_cookie(rdpNego* nego,
wStream* s)
929 BOOL isToken = FALSE;
930 size_t remain = Stream_GetRemainingLength(s);
934 const char* str = Stream_ConstPointer(s);
935 const size_t pos = Stream_GetPosition(s);
941 if ((remain < 17) || (memcmp(Stream_ConstPointer(s),
"Cookie: mstshash=", 17) != 0))
943 if (memcmp(Stream_ConstPointer(s),
"Cookie: msts=", 13) != 0)
945 if (memcmp(Stream_ConstPointer(s),
"tsv:", 4) != 0)
947 if (memcmp(Stream_ConstPointer(s),
"mth://", 6) != 0)
965 while (Stream_GetRemainingLength(s) >= 2)
967 Stream_Read_UINT16(s, crlf);
978 const size_t len = Stream_GetPosition(s) - pos;
979 Stream_Write_UINT16(s, 0);
981 if (len > UINT32_MAX)
984 if (strnlen(str, len) == len)
987 result = nego_set_routing_token(nego, str, (UINT32)len);
989 result = nego_set_cookie(nego, str);
995 if (!Stream_SetPosition(s, pos))
997 WLog_Print(nego->log, WLOG_ERROR,
"invalid %s received",
998 isToken ?
"routing token" :
"cookie");
1002 WLog_Print(nego->log, WLOG_DEBUG,
"received %s [%s]", isToken ?
"routing token" :
"cookie",
1018BOOL nego_read_request(rdpNego* nego,
wStream* s)
1027 if (!tpkt_read_header(s, &length))
1030 if (!tpdu_read_connection_request(s, &li, length))
1033 if (li != Stream_GetRemainingLength(s) + 6)
1035 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect TPDU length indicator.");
1039 if (!nego_read_request_token_or_cookie(nego, s))
1041 WLog_Print(nego->log, WLOG_ERROR,
"Failed to parse routing token or cookie.");
1045 if (Stream_GetRemainingLength(s) >= 8)
1048 Stream_Read_UINT8(s, type);
1050 if (type != TYPE_RDP_NEG_REQ)
1052 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect negotiation request type %" PRIu8
"",
1057 if (!nego_process_negotiation_request(nego, s))
1061 return tpkt_ensure_stream_consumed(nego->log, s, length);
1070void nego_send(rdpNego* nego)
1074 switch (nego_get_state(nego))
1076 case NEGO_STATE_AAD:
1077 nego_attempt_rdsaad(nego);
1079 case NEGO_STATE_RDSTLS:
1080 nego_attempt_rdstls(nego);
1082 case NEGO_STATE_EXT:
1083 nego_attempt_ext(nego);
1085 case NEGO_STATE_NLA:
1086 nego_attempt_nla(nego);
1088 case NEGO_STATE_TLS:
1089 nego_attempt_tls(nego);
1091 case NEGO_STATE_RDP:
1092 nego_attempt_rdp(nego);
1095 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation state for sending");
1110BOOL nego_send_negotiation_request(rdpNego* nego)
1113 wStream* s = Stream_New(
nullptr, 512);
1118 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1122 const size_t bm = Stream_GetPosition(s);
1123 if (!Stream_SafeSeek(s, TPDU_CONNECTION_REQUEST_LENGTH))
1126 if (nego->RoutingToken)
1128 if (!Stream_EnsureRemainingCapacity(s, nego->RoutingTokenLength))
1130 Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1134 if ((nego->RoutingTokenLength > 2) &&
1135 (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1136 (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1138 WLog_Print(nego->log, WLOG_DEBUG,
1139 "Routing token looks correctly terminated - use verbatim");
1143 WLog_Print(nego->log, WLOG_DEBUG,
"Adding terminating CRLF to routing token");
1144 if (!Stream_EnsureRemainingCapacity(s, 2))
1146 Stream_Write_UINT8(s, 0x0D);
1147 Stream_Write_UINT8(s, 0x0A);
1150 else if (nego->cookie)
1152 size_t cookie_length = strlen(nego->cookie);
1154 if (cookie_length > nego->CookieMaxLength)
1155 cookie_length = nego->CookieMaxLength;
1157 if (!Stream_EnsureRemainingCapacity(s, 17))
1159 Stream_Write(s,
"Cookie: mstshash=", 17);
1160 if (!Stream_EnsureRemainingCapacity(s, cookie_length))
1162 Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1163 if (!Stream_EnsureRemainingCapacity(s, 2))
1165 Stream_Write_UINT8(s, 0x0D);
1166 Stream_Write_UINT8(s, 0x0A);
1170 char buffer[64] = WINPR_C_ARRAY_INIT;
1171 WLog_Print(nego->log, WLOG_DEBUG,
"RequestedProtocols: %s",
1172 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1175 if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1180 if (nego->RestrictedAdminModeRequired)
1181 flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1183 if (nego->RemoteCredsGuardRequired)
1184 flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1186 if (!Stream_EnsureRemainingCapacity(s, 8))
1189 Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1190 Stream_Write_UINT8(s, flags);
1191 Stream_Write_UINT16(s, 8);
1192 Stream_Write_UINT32(s, nego->RequestedProtocols);
1195 const size_t em = Stream_GetPosition(s);
1196 if ((em < 5) || (em > UINT16_MAX))
1198 if (!Stream_SetPosition(s, bm))
1200 if (!tpkt_write_header(s, (UINT16)em))
1202 if (!tpdu_write_connection_request(s, (UINT16)em - 5))
1204 if (!Stream_SetPosition(s, em))
1206 Stream_SealLength(s);
1207 rc = (transport_write(nego->transport, s) >= 0);
1209 Stream_Free(s, TRUE);
1213static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego,
wStream* s)
1218 BYTE correlationId[16] = WINPR_C_ARRAY_INIT;
1220 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1222 WLog_Print(nego->log, WLOG_ERROR,
1223 "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1227 Stream_Read_UINT8(s, type);
1228 if (type != TYPE_RDP_CORRELATION_INFO)
1230 WLog_Print(nego->log, WLOG_ERROR,
1231 "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1234 Stream_Read_UINT8(s, flags);
1237 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::flags != 0");
1240 Stream_Read_UINT16(s, length);
1243 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::length != 36");
1247 Stream_Read(s, correlationId,
sizeof(correlationId));
1248 if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1250 WLog_Print(nego->log, WLOG_ERROR,
1251 "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1255 for (
size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1257 if (correlationId[x] == 0x0D)
1259 WLog_Print(nego->log, WLOG_ERROR,
1260 "(RDP_NEG_CORRELATION_INFO::correlationId[%" PRIuz
1261 "] has invalid value 0x%02" PRIx8,
1262 x, correlationId[x]);
1268 WLog_Print(nego->log, WLOG_INFO,
1269 "RDP_NEG_CORRELATION_INFO::correlationId = { %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1270 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1271 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1273 correlationId[0], correlationId[1], correlationId[2], correlationId[3],
1274 correlationId[4], correlationId[5], correlationId[6], correlationId[7],
1275 correlationId[8], correlationId[9], correlationId[10], correlationId[11],
1276 correlationId[12], correlationId[13], correlationId[14], correlationId[15]);
1280BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s)
1288 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1290 Stream_Read_UINT8(s, flags);
1291 if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1292 CORRELATION_INFO_PRESENT)) != 0)
1294 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1297 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1299 if (nego->RestrictedAdminModeSupported)
1301 WLog_Print(nego->log, WLOG_INFO,
"RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1305 WLog_Print(nego->log, WLOG_ERROR,
1306 "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED but disabled");
1311 if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1313 if (nego->RemoteCredsGuardSupported)
1315 WLog_Print(nego->log, WLOG_INFO,
1316 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1317 nego->RemoteCredsGuardActive = TRUE;
1324 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1326 WLog_Print(nego->log, WLOG_INFO,
1327 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED ignored.");
1332 nego->log, WLOG_ERROR,
1333 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1339 Stream_Read_UINT16(s, length);
1342 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::length != 8");
1345 Stream_Read_UINT32(s, nego->RequestedProtocols);
1347 if (flags & CORRELATION_INFO_PRESENT)
1349 if (!nego_process_correlation_info(nego, s))
1354 char buffer[64] = WINPR_C_ARRAY_INIT;
1355 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_REQ: RequestedProtocol: %s",
1356 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1358 nego_set_state(nego, NEGO_STATE_FINAL);
1362static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1364 const uint32_t mask =
1365 (EXTENDED_CLIENT_DATA_SUPPORTED | DYNVC_GFX_PROTOCOL_SUPPORTED | RDP_NEGRSP_RESERVED |
1366 RESTRICTED_ADMIN_MODE_SUPPORTED | REDIRECTED_AUTHENTICATION_MODE_SUPPORTED);
1367 static char buffer[1024] = WINPR_C_ARRAY_INIT;
1369 (void)_snprintf(buffer, ARRAYSIZE(buffer),
"[0x%02" PRIx32
"] ", flags);
1370 if (flags & EXTENDED_CLIENT_DATA_SUPPORTED)
1371 winpr_str_append(
"EXTENDED_CLIENT_DATA_SUPPORTED", buffer,
sizeof(buffer),
"|");
1372 if (flags & DYNVC_GFX_PROTOCOL_SUPPORTED)
1373 winpr_str_append(
"DYNVC_GFX_PROTOCOL_SUPPORTED", buffer,
sizeof(buffer),
"|");
1374 if (flags & RDP_NEGRSP_RESERVED)
1375 winpr_str_append(
"RDP_NEGRSP_RESERVED", buffer,
sizeof(buffer),
"|");
1376 if (flags & RESTRICTED_ADMIN_MODE_SUPPORTED)
1377 winpr_str_append(
"RESTRICTED_ADMIN_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1378 if (flags & REDIRECTED_AUTHENTICATION_MODE_SUPPORTED)
1379 winpr_str_append(
"REDIRECTED_AUTHENTICATION_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1382 char buffer2[32] = WINPR_C_ARRAY_INIT;
1383 (void)_snprintf(buffer2,
sizeof(buffer2),
"UNKNOWN[0x%04" PRIx32
"]", flags & ~mask);
1384 winpr_str_append(buffer2, buffer,
sizeof(buffer),
"|");
1390BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s)
1397 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1399 nego_set_state(nego, NEGO_STATE_FAIL);
1403 Stream_Read_UINT8(s, nego->flags);
1404 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_RSP::flags = { %s }",
1405 nego_rdp_neg_rsp_flags_str(nego->flags));
1407 Stream_Read_UINT16(s, length);
1410 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_RSP::length != 8");
1411 nego_set_state(nego, NEGO_STATE_FAIL);
1414 UINT32 SelectedProtocol = 0;
1415 Stream_Read_UINT32(s, SelectedProtocol);
1417 if (!nego_set_selected_protocol(nego, SelectedProtocol))
1419 return nego_set_state(nego, NEGO_STATE_FINAL);
1422static const char* nego_rdp_neg_fail_str(uint32_t what)
1426 case SSL_REQUIRED_BY_SERVER:
1427 return "SSL_REQUIRED_BY_SERVER";
1428 case SSL_NOT_ALLOWED_BY_SERVER:
1429 return "SSL_NOT_ALLOWED_BY_SERVER";
1430 case SSL_CERT_NOT_ON_SERVER:
1431 return "SSL_CERT_NOT_ON_SERVER";
1432 case INCONSISTENT_FLAGS:
1433 return "INCONSISTENT_FLAGS";
1434 case HYBRID_REQUIRED_BY_SERVER:
1435 return "HYBRID_REQUIRED_BY_SERVER";
1436 case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
1437 return "SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER";
1443static void nego_disable_all_except(rdpNego* nego, uint32_t what)
1447 char buffer[32] = WINPR_C_ARRAY_INIT;
1448 WLog_Print(nego->log, WLOG_DEBUG,
"Disabling all modes except %s",
1449 nego_protocol_to_str(what, buffer,
sizeof(buffer)));
1451 for (
size_t x = 0; x < ARRAYSIZE(nego->EnabledProtocols); x++)
1455 nego->EnabledProtocols[x] = FALSE;
1467BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s)
1475 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_FAILURE");
1476 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1479 Stream_Read_UINT8(s, flags);
1482 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1485 Stream_Read_UINT16(s, length);
1488 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::length != 8");
1491 const uint32_t failureCode = Stream_Get_UINT32(s);
1492 const char* failureStr = nego_rdp_neg_fail_str(failureCode);
1493 DWORD level = WLOG_WARN;
1497 nego->failureCode = failureCode;
1499 switch (failureCode)
1501 case SSL_REQUIRED_BY_SERVER:
1502 nego_disable_all_except(nego, PROTOCOL_SSL);
1505 case SSL_NOT_ALLOWED_BY_SERVER:
1506 nego_disable_all_except(nego, PROTOCOL_RDP);
1507 nego->sendNegoData = TRUE;
1510 case SSL_CERT_NOT_ON_SERVER:
1512 nego->sendNegoData = TRUE;
1515 case INCONSISTENT_FLAGS:
1519 case HYBRID_REQUIRED_BY_SERVER:
1520 nego_disable_all_except(nego, PROTOCOL_HYBRID);
1528 WLog_Print(nego->log, level,
"Error: %s [0x%08" PRIx32
"]", failureStr, failureCode);
1529 nego_set_state(nego, NEGO_STATE_FAIL);
1538BOOL nego_send_negotiation_response(rdpNego* nego)
1540 BOOL status = FALSE;
1542 rdpContext* context =
nullptr;
1543 rdpSettings* settings =
nullptr;
1546 context = transport_get_context(nego->transport);
1547 WINPR_ASSERT(context);
1549 settings = context->settings;
1550 WINPR_ASSERT(settings);
1552 wStream* s = Stream_New(
nullptr, 512);
1556 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1560 UINT16 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1561 const size_t bm = Stream_GetPosition(s);
1562 if (!Stream_SafeSeek(s, length))
1565 if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1567 UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1569 Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1570 Stream_Write_UINT8(s, flags);
1571 Stream_Write_UINT16(s, 8);
1572 Stream_Write_UINT32(s, errorCode);
1577 flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1580 flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1582 if (nego->RestrictedAdminModeSupported)
1583 flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1585 if (nego->RemoteCredsGuardSupported)
1586 flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1589 Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1590 Stream_Write_UINT8(s, flags);
1591 Stream_Write_UINT16(s, 8);
1592 Stream_Write_UINT32(s, nego->SelectedProtocol);
1596 const size_t em = Stream_GetPosition(s);
1597 if (!Stream_SetPosition(s, bm))
1599 if (!tpkt_write_header(s, length))
1602 if (!tpdu_write_connection_confirm(s, length - 5))
1605 if (!Stream_SetPosition(s, em))
1607 Stream_SealLength(s);
1609 status = (transport_write(nego->transport, s) >= 0);
1612 Stream_Free(s, TRUE);
1618 nego->RequestedProtocols))
1621 nego->SelectedProtocol))
1624 switch (nego->SelectedProtocol)
1637 ENCRYPTION_LEVEL_NONE)
1644 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1656 WLog_Print(nego->log, WLOG_INFO,
1657 "Turning off encryption for local peer with standard rdp security");
1661 ENCRYPTION_LEVEL_NONE))
1666 WLog_Print(nego->log, WLOG_ERROR,
"Missing server certificate");
1683 ENCRYPTION_LEVEL_NONE))
1686 case PROTOCOL_HYBRID:
1699 ENCRYPTION_LEVEL_NONE))
1702 case PROTOCOL_RDSTLS:
1715 ENCRYPTION_LEVEL_NONE))
1731void nego_init(rdpNego* nego)
1734 nego_set_state(nego, NEGO_STATE_INITIAL);
1735 nego->RequestedProtocols = PROTOCOL_RDP;
1736 nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
1737 nego->sendNegoData = FALSE;
1739 nego->failureCode = 0;
1750rdpNego* nego_new(rdpTransport* transport)
1752 rdpNego* nego = (rdpNego*)calloc(1,
sizeof(rdpNego));
1757 nego->log = WLog_Get(NEGO_TAG);
1758 WINPR_ASSERT(nego->log);
1759 nego->transport = transport;
1769void nego_free(rdpNego* nego)
1773 free(nego->RoutingToken);
1788BOOL nego_set_target(rdpNego* nego,
const char* hostname, UINT16 port)
1791 WINPR_ASSERT(hostname);
1793 nego->hostname = hostname;
1805void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1807 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling security layer negotiation: %s",
1808 NegotiateSecurityLayer ?
"TRUE" :
"FALSE");
1809 nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1819void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1821 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling restricted admin mode: %s",
1822 RestrictedAdminModeRequired ?
"TRUE" :
"FALSE");
1823 nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1826void nego_set_restricted_admin_mode_supported(rdpNego* nego, BOOL enabled)
1830 nego->RestrictedAdminModeSupported = enabled;
1833void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1837 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling remoteCredentialGuards: %s",
1838 enabled ?
"TRUE" :
"FALSE");
1839 nego->RemoteCredsGuardRequired = enabled;
1842void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1846 nego->RemoteCredsGuardSupported = enabled;
1849BOOL nego_get_remoteCredentialGuard(
const rdpNego* nego)
1853 return nego->RemoteCredsGuardActive;
1856void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1859 nego->ConnectChildSession = ChildSessionEnabled;
1862void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1864 nego->GatewayEnabled = GatewayEnabled;
1867void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1869 nego->GatewayBypassLocal = GatewayBypassLocal;
1878void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1880 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDP security: %s", enable_rdp ?
"TRUE" :
"FALSE");
1881 nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1890void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1892 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling TLS security: %s", enable_tls ?
"TRUE" :
"FALSE");
1893 nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1903void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1905 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA security: %s", enable_nla ?
"TRUE" :
"FALSE");
1906 nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1916void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1918 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDSTLS security: %s",
1919 enable_rdstls ?
"TRUE" :
"FALSE");
1920 nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1930void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1932 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA extended security: %s",
1933 enable_ext ?
"TRUE" :
"FALSE");
1934 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = enable_ext;
1944void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1947 if (aad_is_supported())
1949 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDS AAD security: %s",
1950 enable_aad ?
"TRUE" :
"FALSE");
1951 nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1955 WLog_Print(nego->log, WLOG_WARN,
"This build does not support AAD security, disabling.");
1968BOOL nego_set_routing_token(rdpNego* nego,
const void* RoutingToken, DWORD RoutingTokenLength)
1970 if (RoutingTokenLength == 0)
1973 free(nego->RoutingToken);
1974 nego->RoutingTokenLength = RoutingTokenLength;
1975 nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1977 if (!nego->RoutingToken)
1980 CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1992BOOL nego_set_cookie(rdpNego* nego,
const char* cookie)
1997 nego->cookie =
nullptr;
2003 nego->cookie = _strdup(cookie);
2005 return (nego->cookie !=
nullptr);
2014void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
2016 nego->CookieMaxLength = CookieMaxLength;
2025void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
2027 nego->SendPreconnectionPdu = SendPreconnectionPdu;
2036void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
2038 nego->PreconnectionId = PreconnectionId;
2047void nego_set_preconnection_blob(rdpNego* nego,
const char* PreconnectionBlob)
2049 nego->PreconnectionBlob = PreconnectionBlob;
2052UINT32 nego_get_selected_protocol(
const rdpNego* nego)
2057 return nego->SelectedProtocol;
2060BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
2063 nego->SelectedProtocol = SelectedProtocol;
2067UINT32 nego_get_requested_protocols(
const rdpNego* nego)
2072 return nego->RequestedProtocols;
2075BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
2080 nego->RequestedProtocols = RequestedProtocols;
2084NEGO_STATE nego_get_state(
const rdpNego* nego)
2087 return NEGO_STATE_FAIL;
2092BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
2095 nego->state = state;
2099SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
2101 rdpNla* nla =
nullptr;
2105 nla = transport_get_nla(nego->transport);
2106 return nla_get_identity(nla);
2109void nego_free_nla(rdpNego* nego)
2111 if (!nego || !nego->transport)
2114 transport_set_nla(nego->transport,
nullptr);
2117const BYTE* nego_get_routing_token(
const rdpNego* nego, DWORD* RoutingTokenLength)
2121 if (RoutingTokenLength)
2122 *RoutingTokenLength = nego->RoutingTokenLength;
2123 return nego->RoutingToken;
2126const char* nego_protocol_to_str(UINT32 protocol,
char* buffer,
size_t size)
2128 const UINT32 mask = ~(PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_RDSTLS | PROTOCOL_HYBRID_EX |
2129 PROTOCOL_RDSAAD | PROTOCOL_FAILED_NEGO);
2130 char str[48] = WINPR_C_ARRAY_INIT;
2132 if (protocol & PROTOCOL_SSL)
2133 (void)winpr_str_append(
"SSL", str,
sizeof(str),
"|");
2134 if (protocol & PROTOCOL_HYBRID)
2135 (void)winpr_str_append(
"HYBRID", str,
sizeof(str),
"|");
2136 if (protocol & PROTOCOL_RDSTLS)
2137 (void)winpr_str_append(
"RDSTLS", str,
sizeof(str),
"|");
2138 if (protocol & PROTOCOL_HYBRID_EX)
2139 (void)winpr_str_append(
"HYBRID_EX", str,
sizeof(str),
"|");
2140 if (protocol & PROTOCOL_RDSAAD)
2141 (void)winpr_str_append(
"RDSAAD", str,
sizeof(str),
"|");
2142 if (protocol & PROTOCOL_FAILED_NEGO)
2143 (void)winpr_str_append(
"NEGO FAILED", str,
sizeof(str),
"|");
2145 if (protocol == PROTOCOL_RDP)
2146 (void)winpr_str_append(
"RDP", str,
sizeof(str),
"");
2147 else if ((protocol & mask) != 0)
2148 (
void)winpr_str_append(
"UNKNOWN", str,
sizeof(str),
"|");
2150 (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.
WINPR_ATTR_NODISCARD 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 BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 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.