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 RemoteCredsGuardRequired;
64 BOOL RemoteCredsGuardActive;
65 BOOL RemoteCredsGuardSupported;
67 BOOL GatewayBypassLocal;
68 BOOL ConnectChildSession;
70 rdpTransport* transport;
74static const char* nego_state_string(NEGO_STATE state)
76 static const char*
const NEGO_STATE_STRINGS[] = {
"NEGO_STATE_INITIAL",
"NEGO_STATE_RDSTLS",
77 "NEGO_STATE_AAD",
"NEGO_STATE_EXT",
78 "NEGO_STATE_NLA",
"NEGO_STATE_TLS",
79 "NEGO_STATE_RDP",
"NEGO_STATE_FAIL",
80 "NEGO_STATE_FINAL",
"NEGO_STATE_INVALID" };
81 if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
82 return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
83 return NEGO_STATE_STRINGS[state];
86static BOOL nego_tcp_connect(rdpNego* nego);
87static BOOL nego_transport_connect(rdpNego* nego);
88static BOOL nego_transport_disconnect(rdpNego* nego);
89static BOOL nego_security_connect(rdpNego* nego);
90static BOOL nego_send_preconnection_pdu(rdpNego* nego);
91static BOOL nego_recv_response(rdpNego* nego);
92static void nego_send(rdpNego* nego);
93static BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s);
94static BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s);
95static BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s);
97BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
103 nego->RequestedProtocols) &&
105 nego->SelectedProtocol) &&
117BOOL nego_connect(rdpNego* nego)
119 rdpContext* context = NULL;
120 rdpSettings* settings = NULL;
122 context = transport_get_context(nego->transport);
123 WINPR_ASSERT(context);
124 settings = context->settings;
125 WINPR_ASSERT(settings);
127 if (nego_get_state(nego) == NEGO_STATE_INITIAL)
129 if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
131 nego_set_state(nego, NEGO_STATE_AAD);
133 else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
135 nego_set_state(nego, NEGO_STATE_RDSTLS);
137 else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
139 nego_set_state(nego, NEGO_STATE_EXT);
141 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
143 nego_set_state(nego, NEGO_STATE_NLA);
145 else if (nego->EnabledProtocols[PROTOCOL_SSL])
147 nego_set_state(nego, NEGO_STATE_TLS);
149 else if (nego->EnabledProtocols[PROTOCOL_RDP])
151 nego_set_state(nego, NEGO_STATE_RDP);
155 WLog_Print(nego->log, WLOG_ERROR,
"No security protocol is enabled");
156 nego_set_state(nego, NEGO_STATE_FAIL);
160 if (!nego->NegotiateSecurityLayer)
162 WLog_Print(nego->log, WLOG_DEBUG,
"Security Layer Negotiation is disabled");
164 nego->EnabledProtocols[PROTOCOL_RDSAAD] = FALSE;
165 nego->EnabledProtocols[PROTOCOL_HYBRID] = FALSE;
166 nego->EnabledProtocols[PROTOCOL_SSL] = FALSE;
167 nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
168 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
169 nego->EnabledProtocols[PROTOCOL_RDSTLS] = FALSE;
171 UINT32 SelectedProtocol = 0;
172 switch (nego_get_state(nego))
175 nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
176 SelectedProtocol = PROTOCOL_RDSAAD;
178 case NEGO_STATE_RDSTLS:
179 nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
180 SelectedProtocol = PROTOCOL_RDSTLS;
183 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
184 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
185 SelectedProtocol = PROTOCOL_HYBRID_EX;
188 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
189 SelectedProtocol = PROTOCOL_HYBRID;
192 nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
193 SelectedProtocol = PROTOCOL_SSL;
196 nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
197 SelectedProtocol = PROTOCOL_RDP;
200 WLog_Print(nego->log, WLOG_ERROR,
"Invalid NEGO state 0x%08" PRIx32,
201 nego_get_state(nego));
204 if (!nego_set_selected_protocol(nego, SelectedProtocol))
208 if (!nego_tcp_connect(nego))
210 WLog_Print(nego->log, WLOG_ERROR,
"Failed to connect");
214 if (nego->SendPreconnectionPdu)
216 if (!nego_send_preconnection_pdu(nego))
218 WLog_Print(nego->log, WLOG_ERROR,
"Failed to send preconnection pdu");
219 nego_set_state(nego, NEGO_STATE_FINAL);
225 if (!nego->NegotiateSecurityLayer)
227 nego_set_state(nego, NEGO_STATE_FINAL);
233 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
236 if (nego_get_state(nego) == NEGO_STATE_FAIL)
238 if (freerdp_get_last_error(transport_get_context(nego->transport)) ==
239 FREERDP_ERROR_SUCCESS)
240 WLog_Print(nego->log, WLOG_ERROR,
"Protocol Security Negotiation Failure");
242 nego_set_state(nego, NEGO_STATE_FINAL);
245 }
while (nego_get_state(nego) != NEGO_STATE_FINAL);
249 char buffer[64] = { 0 };
250 WLog_Print(nego->log, WLOG_DEBUG,
"Negotiated %s security",
251 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
255 if (!nego_update_settings_from_state(nego, settings))
258 if (nego->SelectedProtocol == PROTOCOL_RDP)
270 ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
271 ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
277 if (!nego_security_connect(nego))
279 char buffer[64] = { 0 };
280 WLog_Print(nego->log, WLOG_DEBUG,
"Failed to connect with %s security",
281 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
288BOOL nego_disconnect(rdpNego* nego)
291 nego_set_state(nego, NEGO_STATE_INITIAL);
292 return nego_transport_disconnect(nego);
295static BOOL nego_try_connect(rdpNego* nego)
299 switch (nego->SelectedProtocol)
301 case PROTOCOL_RDSAAD:
302 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSAAD");
303 nego->SecurityConnected = transport_connect_aad(nego->transport);
305 case PROTOCOL_RDSTLS:
306 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDSTLS");
307 nego->SecurityConnected = transport_connect_rdstls(nego->transport);
309 case PROTOCOL_HYBRID:
310 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID");
311 nego->SecurityConnected = transport_connect_nla(nego->transport, FALSE);
313 case PROTOCOL_HYBRID_EX:
314 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_HYBRID_EX");
315 nego->SecurityConnected = transport_connect_nla(nego->transport, TRUE);
318 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_SSL");
319 nego->SecurityConnected = transport_connect_tls(nego->transport);
322 WLog_Print(nego->log, WLOG_DEBUG,
"nego_security_connect with PROTOCOL_RDP");
323 nego->SecurityConnected = transport_connect_rdp(nego->transport);
326 WLog_Print(nego->log, WLOG_ERROR,
327 "cannot connect security layer because no protocol has been selected yet.");
330 return nego->SecurityConnected;
334BOOL nego_security_connect(rdpNego* nego)
337 if (!nego->TcpConnected)
339 nego->SecurityConnected = FALSE;
341 else if (!nego->SecurityConnected)
343 if (!nego_try_connect(nego))
347 return nego->SecurityConnected;
350static BOOL nego_tcp_connect(rdpNego* nego)
352 rdpContext* context = NULL;
354 if (!nego->TcpConnected)
356 UINT32 TcpConnectTimeout = 0;
358 context = transport_get_context(nego->transport);
359 WINPR_ASSERT(context);
364 if (nego->GatewayEnabled)
366 if (nego->GatewayBypassLocal)
370 nego->log, WLOG_INFO,
371 "Detecting if host can be reached locally. - This might take some time.");
372 WLog_Print(nego->log, WLOG_INFO,
373 "To disable auto detection use /gateway-usage-method:direct");
374 transport_set_gateway_enabled(nego->transport, FALSE);
375 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
379 if (!nego->TcpConnected)
381 transport_set_gateway_enabled(nego->transport, TRUE);
382 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
386 else if (nego->ConnectChildSession)
388 nego->TcpConnected = transport_connect_childsession(nego->transport);
393 transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
397 return nego->TcpConnected;
408BOOL nego_transport_connect(rdpNego* nego)
411 if (!nego_tcp_connect(nego))
414 if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
415 return nego_security_connect(nego);
417 return nego->TcpConnected;
428BOOL nego_transport_disconnect(rdpNego* nego)
431 if (nego->TcpConnected)
432 transport_disconnect(nego->transport);
434 nego->TcpConnected = FALSE;
435 nego->SecurityConnected = FALSE;
447BOOL nego_send_preconnection_pdu(rdpNego* nego)
452 WCHAR* wszPCB = NULL;
456 WLog_Print(nego->log, WLOG_DEBUG,
"Sending preconnection PDU");
458 if (!nego_tcp_connect(nego))
462 cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
464 if (nego->PreconnectionBlob)
467 wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
468 if (len > UINT16_MAX - 1)
473 cchPCB = (UINT16)len;
475 cbSize += cchPCB *
sizeof(WCHAR);
478 s = Stream_New(NULL, cbSize);
483 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
487 Stream_Write_UINT32(s, cbSize);
488 Stream_Write_UINT32(s, 0);
489 Stream_Write_UINT32(s, PRECONNECTION_PDU_V2);
490 Stream_Write_UINT32(s, nego->PreconnectionId);
491 Stream_Write_UINT16(s, cchPCB);
495 Stream_Write(s, wszPCB, cchPCB *
sizeof(WCHAR));
499 Stream_SealLength(s);
501 if (transport_write(nego->transport, s) < 0)
503 Stream_Free(s, TRUE);
507 Stream_Free(s, TRUE);
511static void nego_attempt_rdstls(rdpNego* nego)
514 nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
515 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDSTLS security");
517 if (!nego_transport_connect(nego))
519 nego_set_state(nego, NEGO_STATE_FAIL);
523 if (!nego_send_negotiation_request(nego))
525 nego_set_state(nego, NEGO_STATE_FAIL);
529 if (!nego_recv_response(nego))
531 nego_set_state(nego, NEGO_STATE_FAIL);
535 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
537 if (nego_get_state(nego) != NEGO_STATE_FINAL)
539 nego_transport_disconnect(nego);
541 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
542 nego_set_state(nego, NEGO_STATE_EXT);
543 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
544 nego_set_state(nego, NEGO_STATE_NLA);
545 else if (nego->EnabledProtocols[PROTOCOL_SSL])
546 nego_set_state(nego, NEGO_STATE_TLS);
547 else if (nego->EnabledProtocols[PROTOCOL_RDP])
548 nego_set_state(nego, NEGO_STATE_RDP);
550 nego_set_state(nego, NEGO_STATE_FAIL);
554static void nego_attempt_rdsaad(rdpNego* nego)
557 nego->RequestedProtocols = PROTOCOL_RDSAAD;
558 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDS AAD Auth security");
560 if (!nego_transport_connect(nego))
562 nego_set_state(nego, NEGO_STATE_FAIL);
566 if (!nego_send_negotiation_request(nego))
568 nego_set_state(nego, NEGO_STATE_FAIL);
572 if (!nego_recv_response(nego))
574 nego_set_state(nego, NEGO_STATE_FAIL);
578 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
580 if (nego_get_state(nego) != NEGO_STATE_FINAL)
582 nego_transport_disconnect(nego);
584 if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
585 nego_set_state(nego, NEGO_STATE_EXT);
586 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
587 nego_set_state(nego, NEGO_STATE_NLA);
588 else if (nego->EnabledProtocols[PROTOCOL_SSL])
589 nego_set_state(nego, NEGO_STATE_TLS);
590 else if (nego->EnabledProtocols[PROTOCOL_RDP])
591 nego_set_state(nego, NEGO_STATE_RDP);
593 nego_set_state(nego, NEGO_STATE_FAIL);
597static void nego_attempt_ext(rdpNego* nego)
600 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
601 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA extended security");
603 if (!nego_transport_connect(nego))
605 nego_set_state(nego, NEGO_STATE_FAIL);
609 if (!nego_send_negotiation_request(nego))
611 nego_set_state(nego, NEGO_STATE_FAIL);
615 if (!nego_recv_response(nego))
617 nego_set_state(nego, NEGO_STATE_FAIL);
621 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
623 if (nego_get_state(nego) != NEGO_STATE_FINAL)
625 nego_transport_disconnect(nego);
627 if (nego->EnabledProtocols[PROTOCOL_HYBRID])
628 nego_set_state(nego, NEGO_STATE_NLA);
629 else if (nego->EnabledProtocols[PROTOCOL_SSL])
630 nego_set_state(nego, NEGO_STATE_TLS);
631 else if (nego->EnabledProtocols[PROTOCOL_RDP])
632 nego_set_state(nego, NEGO_STATE_RDP);
634 nego_set_state(nego, NEGO_STATE_FAIL);
638static void nego_attempt_nla(rdpNego* nego)
641 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
642 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting NLA security");
644 if (!nego_transport_connect(nego))
646 nego_set_state(nego, NEGO_STATE_FAIL);
650 if (!nego_send_negotiation_request(nego))
652 nego_set_state(nego, NEGO_STATE_FAIL);
656 if (!nego_recv_response(nego))
658 nego_set_state(nego, NEGO_STATE_FAIL);
662 WLog_Print(nego->log, WLOG_DEBUG,
"state: %s", nego_state_string(nego_get_state(nego)));
664 if (nego_get_state(nego) != NEGO_STATE_FINAL)
666 nego_transport_disconnect(nego);
668 if (nego->EnabledProtocols[PROTOCOL_SSL])
669 nego_set_state(nego, NEGO_STATE_TLS);
670 else if (nego->EnabledProtocols[PROTOCOL_RDP])
671 nego_set_state(nego, NEGO_STATE_RDP);
673 nego_set_state(nego, NEGO_STATE_FAIL);
677static void nego_attempt_tls(rdpNego* nego)
680 nego->RequestedProtocols = PROTOCOL_SSL;
681 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting TLS security");
683 if (!nego_transport_connect(nego))
685 nego_set_state(nego, NEGO_STATE_FAIL);
689 if (!nego_send_negotiation_request(nego))
691 nego_set_state(nego, NEGO_STATE_FAIL);
695 if (!nego_recv_response(nego))
697 nego_set_state(nego, NEGO_STATE_FAIL);
701 if (nego_get_state(nego) != NEGO_STATE_FINAL)
703 nego_transport_disconnect(nego);
705 if (nego->EnabledProtocols[PROTOCOL_RDP])
706 nego_set_state(nego, NEGO_STATE_RDP);
708 nego_set_state(nego, NEGO_STATE_FAIL);
712static void nego_attempt_rdp(rdpNego* nego)
715 nego->RequestedProtocols = PROTOCOL_RDP;
716 WLog_Print(nego->log, WLOG_DEBUG,
"Attempting RDP security");
718 if (!nego_transport_connect(nego))
720 nego_set_state(nego, NEGO_STATE_FAIL);
724 if (!nego_send_negotiation_request(nego))
726 nego_set_state(nego, NEGO_STATE_FAIL);
730 if (!nego_recv_response(nego))
732 nego_set_state(nego, NEGO_STATE_FAIL);
745BOOL nego_recv_response(rdpNego* nego)
751 s = Stream_New(NULL, 1024);
755 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
759 status = transport_read_pdu(nego->transport, s);
763 Stream_Free(s, TRUE);
767 status = nego_recv(nego->transport, s, nego);
768 Stream_Free(s, TRUE);
787int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s,
void* extra)
792 rdpNego* nego = (rdpNego*)extra;
795 if (!tpkt_read_header(s, &length))
798 if (!tpdu_read_connection_confirm(s, &li, length))
804 Stream_Read_UINT8(s, type);
808 case TYPE_RDP_NEG_RSP:
809 if (!nego_process_negotiation_response(nego, s))
812 char buffer[64] = { 0 };
814 nego->log, WLOG_DEBUG,
"selected_protocol: %s",
815 nego_protocol_to_str(nego->SelectedProtocol, buffer,
sizeof(buffer)));
820 if (nego->SelectedProtocol)
822 if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
823 (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
825 nego_set_state(nego, NEGO_STATE_FAIL);
827 if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
828 (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
830 nego_set_state(nego, NEGO_STATE_FAIL);
833 if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
834 (!nego->EnabledProtocols[PROTOCOL_SSL]))
836 nego_set_state(nego, NEGO_STATE_FAIL);
839 else if (!nego->EnabledProtocols[PROTOCOL_RDP])
841 nego_set_state(nego, NEGO_STATE_FAIL);
846 case TYPE_RDP_NEG_FAILURE:
847 if (!nego_process_negotiation_failure(nego, s))
856 WLog_Print(nego->log, WLOG_DEBUG,
"no rdpNegData");
858 if (!nego->EnabledProtocols[PROTOCOL_RDP])
859 nego_set_state(nego, NEGO_STATE_FAIL);
861 nego_set_state(nego, NEGO_STATE_FINAL);
865 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation response");
866 nego_set_state(nego, NEGO_STATE_FAIL);
869 if (!tpkt_ensure_stream_consumed(nego->log, s, length))
879static BOOL nego_read_request_token_or_cookie(rdpNego* nego,
wStream* s)
895 BOOL isToken = FALSE;
896 size_t remain = Stream_GetRemainingLength(s);
900 const char* str = Stream_ConstPointer(s);
901 const size_t pos = Stream_GetPosition(s);
907 if (memcmp(Stream_ConstPointer(s),
"Cookie: mstshash=", 17) != 0)
909 if (memcmp(Stream_ConstPointer(s),
"Cookie: msts=", 13) != 0)
911 if (memcmp(Stream_ConstPointer(s),
"tsv:", 4) != 0)
913 if (memcmp(Stream_ConstPointer(s),
"mth://", 6) != 0)
931 while (Stream_GetRemainingLength(s) >= 2)
933 Stream_Read_UINT16(s, crlf);
944 const size_t len = Stream_GetPosition(s) - pos;
945 Stream_Write_UINT16(s, 0);
947 if (len > UINT32_MAX)
950 if (strnlen(str, len) == len)
953 result = nego_set_routing_token(nego, str, (UINT32)len);
955 result = nego_set_cookie(nego, str);
961 Stream_SetPosition(s, pos);
962 WLog_Print(nego->log, WLOG_ERROR,
"invalid %s received",
963 isToken ?
"routing token" :
"cookie");
967 WLog_Print(nego->log, WLOG_DEBUG,
"received %s [%s]", isToken ?
"routing token" :
"cookie",
983BOOL nego_read_request(rdpNego* nego,
wStream* s)
992 if (!tpkt_read_header(s, &length))
995 if (!tpdu_read_connection_request(s, &li, length))
998 if (li != Stream_GetRemainingLength(s) + 6)
1000 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect TPDU length indicator.");
1004 if (!nego_read_request_token_or_cookie(nego, s))
1006 WLog_Print(nego->log, WLOG_ERROR,
"Failed to parse routing token or cookie.");
1010 if (Stream_GetRemainingLength(s) >= 8)
1013 Stream_Read_UINT8(s, type);
1015 if (type != TYPE_RDP_NEG_REQ)
1017 WLog_Print(nego->log, WLOG_ERROR,
"Incorrect negotiation request type %" PRIu8
"",
1022 if (!nego_process_negotiation_request(nego, s))
1026 return tpkt_ensure_stream_consumed(nego->log, s, length);
1035void nego_send(rdpNego* nego)
1039 switch (nego_get_state(nego))
1041 case NEGO_STATE_AAD:
1042 nego_attempt_rdsaad(nego);
1044 case NEGO_STATE_RDSTLS:
1045 nego_attempt_rdstls(nego);
1047 case NEGO_STATE_EXT:
1048 nego_attempt_ext(nego);
1050 case NEGO_STATE_NLA:
1051 nego_attempt_nla(nego);
1053 case NEGO_STATE_TLS:
1054 nego_attempt_tls(nego);
1056 case NEGO_STATE_RDP:
1057 nego_attempt_rdp(nego);
1060 WLog_Print(nego->log, WLOG_ERROR,
"invalid negotiation state for sending");
1075BOOL nego_send_negotiation_request(rdpNego* nego)
1083 size_t cookie_length = 0;
1084 s = Stream_New(NULL, 512);
1089 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1093 length = TPDU_CONNECTION_REQUEST_LENGTH;
1094 bm = Stream_GetPosition(s);
1095 Stream_Seek(s, length);
1097 if (nego->RoutingToken)
1099 Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1103 if ((nego->RoutingTokenLength > 2) &&
1104 (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1105 (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1107 WLog_Print(nego->log, WLOG_DEBUG,
1108 "Routing token looks correctly terminated - use verbatim");
1109 length += nego->RoutingTokenLength;
1113 WLog_Print(nego->log, WLOG_DEBUG,
"Adding terminating CRLF to routing token");
1114 Stream_Write_UINT8(s, 0x0D);
1115 Stream_Write_UINT8(s, 0x0A);
1116 length += nego->RoutingTokenLength + 2;
1119 else if (nego->cookie)
1121 cookie_length = strlen(nego->cookie);
1123 if (cookie_length > nego->CookieMaxLength)
1124 cookie_length = nego->CookieMaxLength;
1126 Stream_Write(s,
"Cookie: mstshash=", 17);
1127 Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1128 Stream_Write_UINT8(s, 0x0D);
1129 Stream_Write_UINT8(s, 0x0A);
1130 length += cookie_length + 19;
1134 char buffer[64] = { 0 };
1135 WLog_Print(nego->log, WLOG_DEBUG,
"RequestedProtocols: %s",
1136 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1139 if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1142 if (nego->RestrictedAdminModeRequired)
1143 flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1145 if (nego->RemoteCredsGuardRequired)
1146 flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1148 Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1149 Stream_Write_UINT8(s, flags);
1150 Stream_Write_UINT16(s, 8);
1151 Stream_Write_UINT32(s, nego->RequestedProtocols);
1155 if (length > UINT16_MAX)
1158 em = Stream_GetPosition(s);
1159 Stream_SetPosition(s, bm);
1160 if (!tpkt_write_header(s, (UINT16)length))
1162 if (!tpdu_write_connection_request(s, (UINT16)length - 5))
1164 Stream_SetPosition(s, em);
1165 Stream_SealLength(s);
1166 rc = (transport_write(nego->transport, s) >= 0);
1168 Stream_Free(s, TRUE);
1172static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego,
wStream* s)
1177 BYTE correlationId[16] = { 0 };
1179 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1181 WLog_Print(nego->log, WLOG_ERROR,
1182 "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1186 Stream_Read_UINT8(s, type);
1187 if (type != TYPE_RDP_CORRELATION_INFO)
1189 WLog_Print(nego->log, WLOG_ERROR,
1190 "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1193 Stream_Read_UINT8(s, flags);
1196 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::flags != 0");
1199 Stream_Read_UINT16(s, length);
1202 WLog_Print(nego->log, WLOG_ERROR,
"(RDP_NEG_CORRELATION_INFO::length != 36");
1206 Stream_Read(s, correlationId,
sizeof(correlationId));
1207 if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1209 WLog_Print(nego->log, WLOG_ERROR,
1210 "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1214 for (
size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1216 if (correlationId[x] == 0x0D)
1218 WLog_Print(nego->log, WLOG_ERROR,
1219 "(RDP_NEG_CORRELATION_INFO::correlationId[%" PRIuz
1220 "] has invalid value 0x%02" PRIx8,
1221 x, correlationId[x]);
1227 WLog_Print(nego->log, WLOG_INFO,
1228 "RDP_NEG_CORRELATION_INFO::correlationId = { %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1229 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1230 ", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
", %02" PRIx8
1232 correlationId[0], correlationId[1], correlationId[2], correlationId[3],
1233 correlationId[4], correlationId[5], correlationId[6], correlationId[7],
1234 correlationId[8], correlationId[9], correlationId[10], correlationId[11],
1235 correlationId[12], correlationId[13], correlationId[14], correlationId[15]);
1239BOOL nego_process_negotiation_request(rdpNego* nego,
wStream* s)
1247 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1249 Stream_Read_UINT8(s, flags);
1250 if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1251 CORRELATION_INFO_PRESENT)) != 0)
1253 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1256 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1257 WLog_Print(nego->log, WLOG_INFO,
"RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1259 if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1261 if (!nego->RemoteCredsGuardSupported)
1263 WLog_Print(nego->log, WLOG_ERROR,
1264 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1269 WLog_Print(nego->log, WLOG_INFO,
1270 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1272 nego->RemoteCredsGuardActive = TRUE;
1275 Stream_Read_UINT16(s, length);
1278 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_REQ::length != 8");
1281 Stream_Read_UINT32(s, nego->RequestedProtocols);
1283 if (flags & CORRELATION_INFO_PRESENT)
1285 if (!nego_process_correlation_info(nego, s))
1290 char buffer[64] = { 0 };
1291 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_REQ: RequestedProtocol: %s",
1292 nego_protocol_to_str(nego->RequestedProtocols, buffer,
sizeof(buffer)));
1294 nego_set_state(nego, NEGO_STATE_FINAL);
1298static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1300 static char buffer[1024] = { 0 };
1302 (void)_snprintf(buffer, ARRAYSIZE(buffer),
"[0x%02" PRIx32
"] ", flags);
1303 if (flags & EXTENDED_CLIENT_DATA_SUPPORTED)
1304 winpr_str_append(
"EXTENDED_CLIENT_DATA_SUPPORTED", buffer,
sizeof(buffer),
"|");
1305 if (flags & DYNVC_GFX_PROTOCOL_SUPPORTED)
1306 winpr_str_append(
"DYNVC_GFX_PROTOCOL_SUPPORTED", buffer,
sizeof(buffer),
"|");
1307 if (flags & RDP_NEGRSP_RESERVED)
1308 winpr_str_append(
"RDP_NEGRSP_RESERVED", buffer,
sizeof(buffer),
"|");
1309 if (flags & RESTRICTED_ADMIN_MODE_SUPPORTED)
1310 winpr_str_append(
"RESTRICTED_ADMIN_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1311 if (flags & REDIRECTED_AUTHENTICATION_MODE_SUPPORTED)
1312 winpr_str_append(
"REDIRECTED_AUTHENTICATION_MODE_SUPPORTED", buffer,
sizeof(buffer),
"|");
1313 if ((flags & (uint32_t)~(EXTENDED_CLIENT_DATA_SUPPORTED | DYNVC_GFX_PROTOCOL_SUPPORTED |
1314 RDP_NEGRSP_RESERVED | RESTRICTED_ADMIN_MODE_SUPPORTED |
1315 REDIRECTED_AUTHENTICATION_MODE_SUPPORTED)))
1316 winpr_str_append(
"UNKNOWN", buffer,
sizeof(buffer),
"|");
1321BOOL nego_process_negotiation_response(rdpNego* nego,
wStream* s)
1328 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1330 nego_set_state(nego, NEGO_STATE_FAIL);
1334 Stream_Read_UINT8(s, nego->flags);
1335 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_RSP::flags = { %s }",
1336 nego_rdp_neg_rsp_flags_str(nego->flags));
1338 Stream_Read_UINT16(s, length);
1341 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_RSP::length != 8");
1342 nego_set_state(nego, NEGO_STATE_FAIL);
1345 UINT32 SelectedProtocol = 0;
1346 Stream_Read_UINT32(s, SelectedProtocol);
1348 if (!nego_set_selected_protocol(nego, SelectedProtocol))
1350 return nego_set_state(nego, NEGO_STATE_FINAL);
1361BOOL nego_process_negotiation_failure(rdpNego* nego,
wStream* s)
1365 UINT32 failureCode = 0;
1370 WLog_Print(nego->log, WLOG_DEBUG,
"RDP_NEG_FAILURE");
1371 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1374 Stream_Read_UINT8(s, flags);
1377 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1380 Stream_Read_UINT16(s, length);
1383 WLog_Print(nego->log, WLOG_ERROR,
"RDP_NEG_FAILURE::length != 8");
1386 Stream_Read_UINT32(s, failureCode);
1388 switch (failureCode)
1390 case SSL_REQUIRED_BY_SERVER:
1391 WLog_Print(nego->log, WLOG_WARN,
"Error: SSL_REQUIRED_BY_SERVER");
1394 case SSL_NOT_ALLOWED_BY_SERVER:
1395 WLog_Print(nego->log, WLOG_WARN,
"Error: SSL_NOT_ALLOWED_BY_SERVER");
1396 nego->sendNegoData = TRUE;
1399 case SSL_CERT_NOT_ON_SERVER:
1400 WLog_Print(nego->log, WLOG_ERROR,
"Error: SSL_CERT_NOT_ON_SERVER");
1401 nego->sendNegoData = TRUE;
1404 case INCONSISTENT_FLAGS:
1405 WLog_Print(nego->log, WLOG_ERROR,
"Error: INCONSISTENT_FLAGS");
1408 case HYBRID_REQUIRED_BY_SERVER:
1409 WLog_Print(nego->log, WLOG_WARN,
"Error: HYBRID_REQUIRED_BY_SERVER");
1413 WLog_Print(nego->log, WLOG_ERROR,
"Error: Unknown protocol security error %" PRIu32
"",
1418 nego_set_state(nego, NEGO_STATE_FAIL);
1427BOOL nego_send_negotiation_response(rdpNego* nego)
1435 rdpContext* context = NULL;
1436 rdpSettings* settings = NULL;
1439 context = transport_get_context(nego->transport);
1440 WINPR_ASSERT(context);
1442 settings = context->settings;
1443 WINPR_ASSERT(settings);
1445 s = Stream_New(NULL, 512);
1449 WLog_Print(nego->log, WLOG_ERROR,
"Stream_New failed!");
1453 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1454 bm = Stream_GetPosition(s);
1455 Stream_Seek(s, length);
1457 if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1459 UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1461 Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1462 Stream_Write_UINT8(s, flags);
1463 Stream_Write_UINT16(s, 8);
1464 Stream_Write_UINT32(s, errorCode);
1469 flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1472 flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1475 flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1477 if (nego->RemoteCredsGuardSupported)
1478 flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1481 Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1482 Stream_Write_UINT8(s, flags);
1483 Stream_Write_UINT16(s, 8);
1484 Stream_Write_UINT32(s, nego->SelectedProtocol);
1488 em = Stream_GetPosition(s);
1489 Stream_SetPosition(s, bm);
1490 status = tpkt_write_header(s, length);
1493 tpdu_write_connection_confirm(s, length - 5);
1494 Stream_SetPosition(s, em);
1495 Stream_SealLength(s);
1497 status = (transport_write(nego->transport, s) >= 0);
1499 Stream_Free(s, TRUE);
1505 nego->RequestedProtocols))
1508 nego->SelectedProtocol))
1511 switch (nego->SelectedProtocol)
1524 ENCRYPTION_LEVEL_NONE)
1531 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1543 WLog_Print(nego->log, WLOG_INFO,
1544 "Turning off encryption for local peer with standard rdp security");
1548 ENCRYPTION_LEVEL_NONE))
1553 WLog_Print(nego->log, WLOG_ERROR,
"Missing server certificate");
1570 ENCRYPTION_LEVEL_NONE))
1573 case PROTOCOL_HYBRID:
1586 ENCRYPTION_LEVEL_NONE))
1589 case PROTOCOL_RDSTLS:
1602 ENCRYPTION_LEVEL_NONE))
1618void nego_init(rdpNego* nego)
1621 nego_set_state(nego, NEGO_STATE_INITIAL);
1622 nego->RequestedProtocols = PROTOCOL_RDP;
1623 nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
1624 nego->sendNegoData = FALSE;
1636rdpNego* nego_new(rdpTransport* transport)
1638 rdpNego* nego = (rdpNego*)calloc(1,
sizeof(rdpNego));
1643 nego->log = WLog_Get(NEGO_TAG);
1644 WINPR_ASSERT(nego->log);
1645 nego->transport = transport;
1655void nego_free(rdpNego* nego)
1659 free(nego->RoutingToken);
1674BOOL nego_set_target(rdpNego* nego,
const char* hostname, UINT16 port)
1676 if (!nego || !hostname)
1679 nego->hostname = hostname;
1691void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1693 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling security layer negotiation: %s",
1694 NegotiateSecurityLayer ?
"TRUE" :
"FALSE");
1695 nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1705void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1707 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling restricted admin mode: %s",
1708 RestrictedAdminModeRequired ?
"TRUE" :
"FALSE");
1709 nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1712void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1716 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling remoteCredentialGuards: %s",
1717 enabled ?
"TRUE" :
"FALSE");
1718 nego->RemoteCredsGuardRequired = enabled;
1721void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1725 nego->RemoteCredsGuardSupported = enabled;
1728BOOL nego_get_remoteCredentialGuard(rdpNego* nego)
1732 return nego->RemoteCredsGuardActive;
1735void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1738 nego->ConnectChildSession = ChildSessionEnabled;
1741void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1743 nego->GatewayEnabled = GatewayEnabled;
1746void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1748 nego->GatewayBypassLocal = GatewayBypassLocal;
1757void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1759 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDP security: %s", enable_rdp ?
"TRUE" :
"FALSE");
1760 nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1769void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1771 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling TLS security: %s", enable_tls ?
"TRUE" :
"FALSE");
1772 nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1782void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1784 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA security: %s", enable_nla ?
"TRUE" :
"FALSE");
1785 nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1795void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1797 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDSTLS security: %s",
1798 enable_rdstls ?
"TRUE" :
"FALSE");
1799 nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1809void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1811 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling NLA extended security: %s",
1812 enable_ext ?
"TRUE" :
"FALSE");
1813 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = enable_ext;
1823void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1826 if (aad_is_supported())
1828 WLog_Print(nego->log, WLOG_DEBUG,
"Enabling RDS AAD security: %s",
1829 enable_aad ?
"TRUE" :
"FALSE");
1830 nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1834 WLog_Print(nego->log, WLOG_WARN,
"This build does not support AAD security, disabling.");
1847BOOL nego_set_routing_token(rdpNego* nego,
const void* RoutingToken, DWORD RoutingTokenLength)
1849 if (RoutingTokenLength == 0)
1852 free(nego->RoutingToken);
1853 nego->RoutingTokenLength = RoutingTokenLength;
1854 nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1856 if (!nego->RoutingToken)
1859 CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1871BOOL nego_set_cookie(rdpNego* nego,
const char* cookie)
1876 nego->cookie = NULL;
1882 nego->cookie = _strdup(cookie);
1896void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1898 nego->CookieMaxLength = CookieMaxLength;
1907void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1909 nego->SendPreconnectionPdu = SendPreconnectionPdu;
1918void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1920 nego->PreconnectionId = PreconnectionId;
1929void nego_set_preconnection_blob(rdpNego* nego,
const char* PreconnectionBlob)
1931 nego->PreconnectionBlob = PreconnectionBlob;
1934UINT32 nego_get_selected_protocol(rdpNego* nego)
1939 return nego->SelectedProtocol;
1942BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
1945 nego->SelectedProtocol = SelectedProtocol;
1949UINT32 nego_get_requested_protocols(rdpNego* nego)
1954 return nego->RequestedProtocols;
1957BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
1962 nego->RequestedProtocols = RequestedProtocols;
1966NEGO_STATE nego_get_state(rdpNego* nego)
1969 return NEGO_STATE_FAIL;
1974BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
1979 nego->state = state;
1983SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
1989 nla = transport_get_nla(nego->transport);
1990 return nla_get_identity(nla);
1993void nego_free_nla(rdpNego* nego)
1995 if (!nego || !nego->transport)
1998 transport_set_nla(nego->transport, NULL);
2001const BYTE* nego_get_routing_token(rdpNego* nego, DWORD* RoutingTokenLength)
2005 if (RoutingTokenLength)
2006 *RoutingTokenLength = nego->RoutingTokenLength;
2007 return nego->RoutingToken;
2010const char* nego_protocol_to_str(UINT32 protocol,
char* buffer,
size_t size)
2012 const UINT32 mask = ~(PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_RDSTLS | PROTOCOL_HYBRID_EX |
2013 PROTOCOL_RDSAAD | PROTOCOL_FAILED_NEGO);
2014 char str[48] = { 0 };
2016 if (protocol & PROTOCOL_SSL)
2017 (void)winpr_str_append(
"SSL", str,
sizeof(str),
"|");
2018 if (protocol & PROTOCOL_HYBRID)
2019 (void)winpr_str_append(
"HYBRID", str,
sizeof(str),
"|");
2020 if (protocol & PROTOCOL_RDSTLS)
2021 (void)winpr_str_append(
"RDSTLS", str,
sizeof(str),
"|");
2022 if (protocol & PROTOCOL_HYBRID_EX)
2023 (void)winpr_str_append(
"HYBRID_EX", str,
sizeof(str),
"|");
2024 if (protocol & PROTOCOL_RDSAAD)
2025 (void)winpr_str_append(
"RDSAAD", str,
sizeof(str),
"|");
2026 if (protocol & PROTOCOL_FAILED_NEGO)
2027 (void)winpr_str_append(
"NEGO FAILED", str,
sizeof(str),
"|");
2029 if (protocol == PROTOCOL_RDP)
2030 (void)winpr_str_append(
"RDP", str,
sizeof(str),
"");
2031 else if ((protocol & mask) != 0)
2032 (
void)winpr_str_append(
"UNKNOWN", str,
sizeof(str),
"|");
2034 (void)_snprintf(buffer, size,
"[%s][0x%08" PRIx32
"]", str, protocol);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean 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 BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.