FreeRDP
Loading...
Searching...
No Matches
nego.c
1
23#include <freerdp/config.h>
24
25#include <winpr/crt.h>
26#include <winpr/assert.h>
27#include <winpr/stream.h>
28
29#include <freerdp/log.h>
30
31#include "tpkt.h"
32
33#include "nego.h"
34#include "aad.h"
35
36#include "transport.h"
37
38#define NEGO_TAG FREERDP_TAG("core.nego")
39
40struct rdp_nego
41{
42 UINT16 port;
43 UINT32 flags;
44 const char* hostname;
45 char* cookie;
46 BYTE* RoutingToken;
47 DWORD RoutingTokenLength;
48 BOOL SendPreconnectionPdu;
49 UINT32 PreconnectionId;
50 const char* PreconnectionBlob;
51
52 NEGO_STATE state;
53 BOOL TcpConnected;
54 BOOL SecurityConnected;
55 UINT32 CookieMaxLength;
56
57 BOOL sendNegoData;
58 UINT32 SelectedProtocol;
59 UINT32 RequestedProtocols;
60 BOOL NegotiateSecurityLayer;
61 BOOL EnabledProtocols[32];
62 BOOL RestrictedAdminModeRequired; /* Client-side */
63 BOOL RestrictedAdminModeSupported; /* Server-side */
64 BOOL RemoteCredsGuardRequired;
65 BOOL RemoteCredsGuardActive;
66 BOOL RemoteCredsGuardSupported;
67 BOOL GatewayEnabled;
68 BOOL GatewayBypassLocal;
69 BOOL ConnectChildSession;
70
71 rdpTransport* transport;
72 wLog* log;
73};
74
75static const char* nego_state_string(NEGO_STATE state)
76{
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];
85}
86
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);
97
98BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
99{
100 WINPR_ASSERT(nego);
101
102 /* update settings with negotiated protocol security */
103 return freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
104 nego->RequestedProtocols) &&
105 freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
106 nego->SelectedProtocol) &&
107 freerdp_settings_set_uint32(settings, FreeRDP_NegotiationFlags, nego->flags);
108}
109
118BOOL nego_connect(rdpNego* nego)
119{
120 rdpContext* context = nullptr;
121 rdpSettings* settings = nullptr;
122 WINPR_ASSERT(nego);
123 context = transport_get_context(nego->transport);
124 WINPR_ASSERT(context);
125 settings = context->settings;
126 WINPR_ASSERT(settings);
127
128 if (nego_get_state(nego) == NEGO_STATE_INITIAL)
129 {
130 if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
131 {
132 nego_set_state(nego, NEGO_STATE_AAD);
133 }
134 else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
135 {
136 nego_set_state(nego, NEGO_STATE_RDSTLS);
137 }
138 else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
139 {
140 nego_set_state(nego, NEGO_STATE_EXT);
141 }
142 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
143 {
144 nego_set_state(nego, NEGO_STATE_NLA);
145 }
146 else if (nego->EnabledProtocols[PROTOCOL_SSL])
147 {
148 nego_set_state(nego, NEGO_STATE_TLS);
149 }
150 else if (nego->EnabledProtocols[PROTOCOL_RDP])
151 {
152 nego_set_state(nego, NEGO_STATE_RDP);
153 }
154 else
155 {
156 WLog_Print(nego->log, WLOG_ERROR, "No security protocol is enabled");
157 nego_set_state(nego, NEGO_STATE_FAIL);
158 return FALSE;
159 }
160
161 if (!nego->NegotiateSecurityLayer)
162 {
163 WLog_Print(nego->log, WLOG_DEBUG, "Security Layer Negotiation is disabled");
164 /* attempt only the highest enabled protocol (see nego_attempt_*) */
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;
171
172 UINT32 SelectedProtocol = 0;
173 switch (nego_get_state(nego))
174 {
175 case NEGO_STATE_AAD:
176 nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
177 SelectedProtocol = PROTOCOL_RDSAAD;
178 break;
179 case NEGO_STATE_RDSTLS:
180 nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
181 SelectedProtocol = PROTOCOL_RDSTLS;
182 break;
183 case NEGO_STATE_EXT:
184 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
185 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
186 SelectedProtocol = PROTOCOL_HYBRID_EX;
187 break;
188 case NEGO_STATE_NLA:
189 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
190 SelectedProtocol = PROTOCOL_HYBRID;
191 break;
192 case NEGO_STATE_TLS:
193 nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
194 SelectedProtocol = PROTOCOL_SSL;
195 break;
196 case NEGO_STATE_RDP:
197 nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
198 SelectedProtocol = PROTOCOL_RDP;
199 break;
200 default:
201 WLog_Print(nego->log, WLOG_ERROR, "Invalid NEGO state 0x%08" PRIx32,
202 nego_get_state(nego));
203 return FALSE;
204 }
205 if (!nego_set_selected_protocol(nego, SelectedProtocol))
206 return FALSE;
207 }
208
209 if (!nego_tcp_connect(nego))
210 {
211 WLog_Print(nego->log, WLOG_ERROR, "Failed to connect");
212 return FALSE;
213 }
214
215 if (nego->SendPreconnectionPdu)
216 {
217 if (!nego_send_preconnection_pdu(nego))
218 {
219 WLog_Print(nego->log, WLOG_ERROR, "Failed to send preconnection pdu");
220 nego_set_state(nego, NEGO_STATE_FINAL);
221 return FALSE;
222 }
223 }
224 }
225
226 if (!nego->NegotiateSecurityLayer)
227 {
228 nego_set_state(nego, NEGO_STATE_FINAL);
229 }
230 else
231 {
232 do
233 {
234 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
235 nego_send(nego);
236
237 if (nego_get_state(nego) == NEGO_STATE_FAIL)
238 {
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");
242
243 nego_set_state(nego, NEGO_STATE_FINAL);
244 return FALSE;
245 }
246 } while (nego_get_state(nego) != NEGO_STATE_FINAL);
247 }
248
249 {
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)));
253 }
254
255 /* update settings with negotiated protocol security */
256 if (!nego_update_settings_from_state(nego, settings))
257 return FALSE;
258
259 if (nego->SelectedProtocol == PROTOCOL_RDP)
260 {
261 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
262 return FALSE;
263
264 if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionMethods) == 0)
265 {
270 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods,
271 ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
272 ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
273 return FALSE;
274 }
275 }
276
277 /* finally connect security layer (if not already done) */
278 if (!nego_security_connect(nego))
279 {
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)));
283 return FALSE;
284 }
285
286 return TRUE;
287}
288
289BOOL nego_disconnect(rdpNego* nego)
290{
291 WINPR_ASSERT(nego);
292 nego_set_state(nego, NEGO_STATE_INITIAL);
293 return nego_transport_disconnect(nego);
294}
295
296static BOOL nego_try_connect(rdpNego* nego)
297{
298 WINPR_ASSERT(nego);
299
300 switch (nego->SelectedProtocol)
301 {
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);
305 break;
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);
309 break;
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);
313 break;
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);
317 break;
318 case PROTOCOL_SSL:
319 WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_SSL");
320 nego->SecurityConnected = transport_connect_tls(nego->transport);
321 break;
322 case PROTOCOL_RDP:
323 WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_RDP");
324 nego->SecurityConnected = transport_connect_rdp(nego->transport);
325 break;
326 default:
327 WLog_Print(nego->log, WLOG_ERROR,
328 "cannot connect security layer because no protocol has been selected yet.");
329 return FALSE;
330 }
331 return nego->SecurityConnected;
332}
333
334/* connect to selected security layer */
335BOOL nego_security_connect(rdpNego* nego)
336{
337 WINPR_ASSERT(nego);
338 if (!nego->TcpConnected)
339 {
340 nego->SecurityConnected = FALSE;
341 }
342 else if (!nego->SecurityConnected)
343 {
344 if (!nego_try_connect(nego))
345 return FALSE;
346 }
347
348 return nego->SecurityConnected;
349}
350
351static BOOL nego_tcp_connect(rdpNego* nego)
352{
353 rdpContext* context = nullptr;
354 WINPR_ASSERT(nego);
355 if (!nego->TcpConnected)
356 {
357 UINT32 TcpConnectTimeout = 0;
358
359 context = transport_get_context(nego->transport);
360 WINPR_ASSERT(context);
361
362 TcpConnectTimeout =
363 freerdp_settings_get_uint32(context->settings, FreeRDP_TcpConnectTimeout);
364
365 if (nego->GatewayEnabled)
366 {
367 if (nego->GatewayBypassLocal)
368 {
369 /* Attempt a direct connection first, and then fallback to using the gateway */
370 WLog_Print(
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,
377 TcpConnectTimeout);
378 }
379
380 if (!nego->TcpConnected)
381 {
382 transport_set_gateway_enabled(nego->transport, TRUE);
383 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
384 TcpConnectTimeout);
385 }
386 }
387 else if (nego->ConnectChildSession)
388 {
389 nego->TcpConnected = transport_connect_childsession(nego->transport);
390 }
391 else
392 {
393 nego->TcpConnected =
394 transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
395 }
396 }
397
398 return nego->TcpConnected;
399}
400
409BOOL nego_transport_connect(rdpNego* nego)
410{
411 WINPR_ASSERT(nego);
412 if (!nego_tcp_connect(nego))
413 return FALSE;
414
415 if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
416 return nego_security_connect(nego);
417
418 return nego->TcpConnected;
419}
420
429BOOL nego_transport_disconnect(rdpNego* nego)
430{
431 WINPR_ASSERT(nego);
432 if (nego->TcpConnected)
433 transport_disconnect(nego->transport);
434
435 nego->TcpConnected = FALSE;
436 nego->SecurityConnected = FALSE;
437 return TRUE;
438}
439
448BOOL nego_send_preconnection_pdu(rdpNego* nego)
449{
450 wStream* s = nullptr;
451 UINT32 cbSize = 0;
452 UINT16 cchPCB = 0;
453 WCHAR* wszPCB = nullptr;
454
455 WINPR_ASSERT(nego);
456
457 WLog_Print(nego->log, WLOG_DEBUG, "Sending preconnection PDU");
458
459 if (!nego_tcp_connect(nego))
460 return FALSE;
461
462 /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
463 cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
464
465 if (nego->PreconnectionBlob)
466 {
467 size_t len = 0;
468 wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
469 if (len > UINT16_MAX - 1)
470 {
471 free(wszPCB);
472 return FALSE;
473 }
474 cchPCB = (UINT16)len;
475 cchPCB += 1; /* zero-termination */
476 cbSize += cchPCB * sizeof(WCHAR);
477 }
478
479 s = Stream_New(nullptr, cbSize);
480
481 if (!s)
482 {
483 free(wszPCB);
484 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
485 return FALSE;
486 }
487
488 Stream_Write_UINT32(s, cbSize); /* cbSize */
489 Stream_Write_UINT32(s, 0); /* Flags */
490 Stream_Write_UINT32(s, PRECONNECTION_PDU_V2); /* Version */
491 Stream_Write_UINT32(s, nego->PreconnectionId); /* Id */
492 Stream_Write_UINT16(s, cchPCB); /* cchPCB */
493
494 if (wszPCB)
495 {
496 Stream_Write(s, wszPCB, cchPCB * sizeof(WCHAR)); /* wszPCB */
497 free(wszPCB);
498 }
499
500 Stream_SealLength(s);
501
502 if (transport_write(nego->transport, s) < 0)
503 {
504 Stream_Free(s, TRUE);
505 return FALSE;
506 }
507
508 Stream_Free(s, TRUE);
509 return TRUE;
510}
511
512static void nego_attempt_rdstls(rdpNego* nego)
513{
514 WINPR_ASSERT(nego);
515 nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
516 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDSTLS security");
517
518 if (!nego_transport_connect(nego))
519 {
520 nego_set_state(nego, NEGO_STATE_FAIL);
521 return;
522 }
523
524 if (!nego_send_negotiation_request(nego))
525 {
526 nego_set_state(nego, NEGO_STATE_FAIL);
527 return;
528 }
529
530 if (!nego_recv_response(nego))
531 {
532 nego_set_state(nego, NEGO_STATE_FAIL);
533 return;
534 }
535
536 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
537
538 if (nego_get_state(nego) != NEGO_STATE_FINAL)
539 {
540 nego_transport_disconnect(nego);
541
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);
550 else
551 nego_set_state(nego, NEGO_STATE_FAIL);
552 }
553}
554
555static void nego_attempt_rdsaad(rdpNego* nego)
556{
557 WINPR_ASSERT(nego);
558 nego->RequestedProtocols = PROTOCOL_RDSAAD;
559 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDS AAD Auth security");
560
561 if (!nego_transport_connect(nego))
562 {
563 nego_set_state(nego, NEGO_STATE_FAIL);
564 return;
565 }
566
567 if (!nego_send_negotiation_request(nego))
568 {
569 nego_set_state(nego, NEGO_STATE_FAIL);
570 return;
571 }
572
573 if (!nego_recv_response(nego))
574 {
575 nego_set_state(nego, NEGO_STATE_FAIL);
576 return;
577 }
578
579 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
580
581 if (nego_get_state(nego) != NEGO_STATE_FINAL)
582 {
583 nego_transport_disconnect(nego);
584
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);
593 else
594 nego_set_state(nego, NEGO_STATE_FAIL);
595 }
596}
597
598static void nego_attempt_ext(rdpNego* nego)
599{
600 WINPR_ASSERT(nego);
601 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
602 WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA extended security");
603
604 if (!nego_transport_connect(nego))
605 {
606 nego_set_state(nego, NEGO_STATE_FAIL);
607 return;
608 }
609
610 if (!nego_send_negotiation_request(nego))
611 {
612 nego_set_state(nego, NEGO_STATE_FAIL);
613 return;
614 }
615
616 if (!nego_recv_response(nego))
617 {
618 nego_set_state(nego, NEGO_STATE_FAIL);
619 return;
620 }
621
622 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
623
624 if (nego_get_state(nego) != NEGO_STATE_FINAL)
625 {
626 nego_transport_disconnect(nego);
627
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);
634 else
635 nego_set_state(nego, NEGO_STATE_FAIL);
636 }
637}
638
639static void nego_attempt_nla(rdpNego* nego)
640{
641 WINPR_ASSERT(nego);
642 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
643 WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA security");
644
645 if (!nego_transport_connect(nego))
646 {
647 nego_set_state(nego, NEGO_STATE_FAIL);
648 return;
649 }
650
651 if (!nego_send_negotiation_request(nego))
652 {
653 nego_set_state(nego, NEGO_STATE_FAIL);
654 return;
655 }
656
657 if (!nego_recv_response(nego))
658 {
659 nego_set_state(nego, NEGO_STATE_FAIL);
660 return;
661 }
662
663 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
664
665 if (nego_get_state(nego) != NEGO_STATE_FINAL)
666 {
667 nego_transport_disconnect(nego);
668
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);
673 else
674 nego_set_state(nego, NEGO_STATE_FAIL);
675 }
676}
677
678static void nego_attempt_tls(rdpNego* nego)
679{
680 WINPR_ASSERT(nego);
681 nego->RequestedProtocols = PROTOCOL_SSL;
682 WLog_Print(nego->log, WLOG_DEBUG, "Attempting TLS security");
683
684 if (!nego_transport_connect(nego))
685 {
686 nego_set_state(nego, NEGO_STATE_FAIL);
687 return;
688 }
689
690 if (!nego_send_negotiation_request(nego))
691 {
692 nego_set_state(nego, NEGO_STATE_FAIL);
693 return;
694 }
695
696 if (!nego_recv_response(nego))
697 {
698 nego_set_state(nego, NEGO_STATE_FAIL);
699 return;
700 }
701
702 if (nego_get_state(nego) != NEGO_STATE_FINAL)
703 {
704 nego_transport_disconnect(nego);
705
706 if (nego->EnabledProtocols[PROTOCOL_RDP])
707 nego_set_state(nego, NEGO_STATE_RDP);
708 else
709 nego_set_state(nego, NEGO_STATE_FAIL);
710 }
711}
712
713static void nego_attempt_rdp(rdpNego* nego)
714{
715 WINPR_ASSERT(nego);
716 nego->RequestedProtocols = PROTOCOL_RDP;
717 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDP security");
718
719 if (!nego_transport_connect(nego))
720 {
721 nego_set_state(nego, NEGO_STATE_FAIL);
722 return;
723 }
724
725 if (!nego_send_negotiation_request(nego))
726 {
727 nego_set_state(nego, NEGO_STATE_FAIL);
728 return;
729 }
730
731 if (!nego_recv_response(nego))
732 {
733 nego_set_state(nego, NEGO_STATE_FAIL);
734 return;
735 }
736}
737
746BOOL nego_recv_response(rdpNego* nego)
747{
748 int status = 0;
749 wStream* s = nullptr;
750
751 WINPR_ASSERT(nego);
752 s = Stream_New(nullptr, 1024);
753
754 if (!s)
755 {
756 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
757 return FALSE;
758 }
759
760 status = transport_read_pdu(nego->transport, s);
761
762 if (status < 0)
763 {
764 Stream_Free(s, TRUE);
765 return FALSE;
766 }
767
768 status = nego_recv(nego->transport, s, nego);
769 Stream_Free(s, TRUE);
770
771 return (status >= 0);
772}
773
785int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport, wStream* s, void* extra)
786{
787 BYTE li = 0;
788 BYTE type = 0;
789 UINT16 length = 0;
790 rdpNego* nego = (rdpNego*)extra;
791
792 WINPR_ASSERT(nego);
793 if (!tpkt_read_header(s, &length))
794 return -1;
795
796 if (!tpdu_read_connection_confirm(s, &li, length))
797 return -1;
798
799 if (li > 6)
800 {
801 /* rdpNegData (optional) */
802 Stream_Read_UINT8(s, type); /* Type */
803
804 switch (type)
805 {
806 case TYPE_RDP_NEG_RSP:
807 if (!nego_process_negotiation_response(nego, s))
808 return -1;
809 {
810 char buffer[64] = WINPR_C_ARRAY_INIT;
811 WLog_Print(
812 nego->log, WLOG_DEBUG, "selected_protocol: %s",
813 nego_protocol_to_str(nego->SelectedProtocol, buffer, sizeof(buffer)));
814 }
815
816 /* enhanced security selected ? */
817
818 if (nego->SelectedProtocol)
819 {
820 if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
821 (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
822 {
823 nego_set_state(nego, NEGO_STATE_FAIL);
824 }
825 if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
826 (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
827 {
828 nego_set_state(nego, NEGO_STATE_FAIL);
829 }
830
831 if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
832 (!nego->EnabledProtocols[PROTOCOL_SSL]))
833 {
834 nego_set_state(nego, NEGO_STATE_FAIL);
835 }
836 }
837 else if (!nego->EnabledProtocols[PROTOCOL_RDP])
838 {
839 nego_set_state(nego, NEGO_STATE_FAIL);
840 }
841
842 break;
843
844 case TYPE_RDP_NEG_FAILURE:
845 if (!nego_process_negotiation_failure(nego, s))
846 return -1;
847 break;
848 default:
849 return -1;
850 }
851 }
852 else if (li == 6)
853 {
854 WLog_Print(nego->log, WLOG_DEBUG, "no rdpNegData");
855
856 if (!nego->EnabledProtocols[PROTOCOL_RDP])
857 nego_set_state(nego, NEGO_STATE_FAIL);
858 else
859 nego_set_state(nego, NEGO_STATE_FINAL);
860 }
861 else
862 {
863 WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation response");
864 nego_set_state(nego, NEGO_STATE_FAIL);
865 }
866
867 if (!tpkt_ensure_stream_consumed(nego->log, s, length))
868 return -1;
869 return 0;
870}
871
877static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
878{
879 /* routingToken and cookie are optional and mutually exclusive!
880 *
881 * routingToken (variable): An optional and variable-length routing
882 * token (used for load balancing) terminated by a 0x0D0A two-byte
883 * sequence: (check [MSFT-SDLBTS] for details!)
884 * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A]
885 * tsv://MS Terminal Services Plugin.1.[\x0D\x0A]
886 *
887 * cookie (variable): An optional and variable-length ANSI character
888 * string terminated by a 0x0D0A two-byte sequence:
889 * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A]
890 */
891 UINT16 crlf = 0;
892 BOOL result = FALSE;
893 BOOL isToken = FALSE;
894 size_t remain = Stream_GetRemainingLength(s);
895
896 WINPR_ASSERT(nego);
897
898 const char* str = Stream_ConstPointer(s);
899 const size_t pos = Stream_GetPosition(s);
900
901 /* minimum length for token is 15 */
902 if (remain < 15)
903 return TRUE;
904
905 if (memcmp(Stream_ConstPointer(s), "Cookie: mstshash=", 17) != 0)
906 {
907 if (memcmp(Stream_ConstPointer(s), "Cookie: msts=", 13) != 0)
908 {
909 if (memcmp(Stream_ConstPointer(s), "tsv:", 4) != 0)
910 {
911 if (memcmp(Stream_ConstPointer(s), "mth://", 6) != 0)
912 {
913 /* remaining bytes are neither a token nor a cookie */
914 return TRUE;
915 }
916 }
917 }
918 isToken = TRUE;
919 }
920 else
921 {
922 /* not a token, minimum length for cookie is 19 */
923 if (remain < 19)
924 return TRUE;
925
926 Stream_Seek(s, 17);
927 }
928
929 while (Stream_GetRemainingLength(s) >= 2)
930 {
931 Stream_Read_UINT16(s, crlf);
932
933 if (crlf == 0x0A0D)
934 break;
935
936 Stream_Rewind(s, 1);
937 }
938
939 if (crlf == 0x0A0D)
940 {
941 Stream_Rewind(s, 2);
942 const size_t len = Stream_GetPosition(s) - pos;
943 Stream_Write_UINT16(s, 0);
944
945 if (len > UINT32_MAX)
946 return FALSE;
947
948 if (strnlen(str, len) == len)
949 {
950 if (isToken)
951 result = nego_set_routing_token(nego, str, (UINT32)len);
952 else
953 result = nego_set_cookie(nego, str);
954 }
955 }
956
957 if (!result)
958 {
959 if (!Stream_SetPosition(s, pos))
960 return FALSE;
961 WLog_Print(nego->log, WLOG_ERROR, "invalid %s received",
962 isToken ? "routing token" : "cookie");
963 }
964 else
965 {
966 WLog_Print(nego->log, WLOG_DEBUG, "received %s [%s]", isToken ? "routing token" : "cookie",
967 str);
968 }
969
970 return result;
971}
972
982BOOL nego_read_request(rdpNego* nego, wStream* s)
983{
984 BYTE li = 0;
985 BYTE type = 0;
986 UINT16 length = 0;
987
988 WINPR_ASSERT(nego);
989 WINPR_ASSERT(s);
990
991 if (!tpkt_read_header(s, &length))
992 return FALSE;
993
994 if (!tpdu_read_connection_request(s, &li, length))
995 return FALSE;
996
997 if (li != Stream_GetRemainingLength(s) + 6)
998 {
999 WLog_Print(nego->log, WLOG_ERROR, "Incorrect TPDU length indicator.");
1000 return FALSE;
1001 }
1002
1003 if (!nego_read_request_token_or_cookie(nego, s))
1004 {
1005 WLog_Print(nego->log, WLOG_ERROR, "Failed to parse routing token or cookie.");
1006 return FALSE;
1007 }
1008
1009 if (Stream_GetRemainingLength(s) >= 8)
1010 {
1011 /* rdpNegData (optional) */
1012 Stream_Read_UINT8(s, type); /* Type */
1013
1014 if (type != TYPE_RDP_NEG_REQ)
1015 {
1016 WLog_Print(nego->log, WLOG_ERROR, "Incorrect negotiation request type %" PRIu8 "",
1017 type);
1018 return FALSE;
1019 }
1020
1021 if (!nego_process_negotiation_request(nego, s))
1022 return FALSE;
1023 }
1024
1025 return tpkt_ensure_stream_consumed(nego->log, s, length);
1026}
1027
1034void nego_send(rdpNego* nego)
1035{
1036 WINPR_ASSERT(nego);
1037
1038 switch (nego_get_state(nego))
1039 {
1040 case NEGO_STATE_AAD:
1041 nego_attempt_rdsaad(nego);
1042 break;
1043 case NEGO_STATE_RDSTLS:
1044 nego_attempt_rdstls(nego);
1045 break;
1046 case NEGO_STATE_EXT:
1047 nego_attempt_ext(nego);
1048 break;
1049 case NEGO_STATE_NLA:
1050 nego_attempt_nla(nego);
1051 break;
1052 case NEGO_STATE_TLS:
1053 nego_attempt_tls(nego);
1054 break;
1055 case NEGO_STATE_RDP:
1056 nego_attempt_rdp(nego);
1057 break;
1058 default:
1059 WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation state for sending");
1060 break;
1061 }
1062}
1063
1074BOOL nego_send_negotiation_request(rdpNego* nego)
1075{
1076 BOOL rc = FALSE;
1077 wStream* s = nullptr;
1078 size_t length = 0;
1079 size_t bm = 0;
1080 size_t em = 0;
1081 BYTE flags = 0;
1082 size_t cookie_length = 0;
1083 s = Stream_New(nullptr, 512);
1084
1085 WINPR_ASSERT(nego);
1086 if (!s)
1087 {
1088 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1089 return FALSE;
1090 }
1091
1092 length = TPDU_CONNECTION_REQUEST_LENGTH;
1093 bm = Stream_GetPosition(s);
1094 Stream_Seek(s, length);
1095
1096 if (nego->RoutingToken)
1097 {
1098 Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1099
1100 /* Ensure Routing Token is correctly terminated - may already be present in string */
1101
1102 if ((nego->RoutingTokenLength > 2) &&
1103 (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1104 (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1105 {
1106 WLog_Print(nego->log, WLOG_DEBUG,
1107 "Routing token looks correctly terminated - use verbatim");
1108 length += nego->RoutingTokenLength;
1109 }
1110 else
1111 {
1112 WLog_Print(nego->log, WLOG_DEBUG, "Adding terminating CRLF to routing token");
1113 Stream_Write_UINT8(s, 0x0D); /* CR */
1114 Stream_Write_UINT8(s, 0x0A); /* LF */
1115 length += nego->RoutingTokenLength + 2;
1116 }
1117 }
1118 else if (nego->cookie)
1119 {
1120 cookie_length = strlen(nego->cookie);
1121
1122 if (cookie_length > nego->CookieMaxLength)
1123 cookie_length = nego->CookieMaxLength;
1124
1125 Stream_Write(s, "Cookie: mstshash=", 17);
1126 Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1127 Stream_Write_UINT8(s, 0x0D); /* CR */
1128 Stream_Write_UINT8(s, 0x0A); /* LF */
1129 length += cookie_length + 19;
1130 }
1131
1132 {
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)));
1136 }
1137
1138 if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1139 {
1140 /* RDP_NEG_DATA must be present for TLS and NLA */
1141 if (nego->RestrictedAdminModeRequired)
1142 flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1143
1144 if (nego->RemoteCredsGuardRequired)
1145 flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1146
1147 Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1148 Stream_Write_UINT8(s, flags);
1149 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1150 Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
1151 length += 8;
1152 }
1153
1154 if (length > UINT16_MAX)
1155 goto fail;
1156
1157 em = Stream_GetPosition(s);
1158 if (!Stream_SetPosition(s, bm))
1159 goto fail;
1160 if (!tpkt_write_header(s, (UINT16)length))
1161 goto fail;
1162 if (!tpdu_write_connection_request(s, (UINT16)length - 5))
1163 goto fail;
1164 if (!Stream_SetPosition(s, em))
1165 goto fail;
1166 Stream_SealLength(s);
1167 rc = (transport_write(nego->transport, s) >= 0);
1168fail:
1169 Stream_Free(s, TRUE);
1170 return rc;
1171}
1172
1173static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego, wStream* s)
1174{
1175 UINT8 type = 0;
1176 UINT8 flags = 0;
1177 UINT16 length = 0;
1178 BYTE correlationId[16] = WINPR_C_ARRAY_INIT;
1179
1180 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1181 {
1182 WLog_Print(nego->log, WLOG_ERROR,
1183 "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1184 return FALSE;
1185 }
1186
1187 Stream_Read_UINT8(s, type);
1188 if (type != TYPE_RDP_CORRELATION_INFO)
1189 {
1190 WLog_Print(nego->log, WLOG_ERROR,
1191 "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1192 return FALSE;
1193 }
1194 Stream_Read_UINT8(s, flags);
1195 if (flags != 0)
1196 {
1197 WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::flags != 0");
1198 return FALSE;
1199 }
1200 Stream_Read_UINT16(s, length);
1201 if (length != 36)
1202 {
1203 WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::length != 36");
1204 return FALSE;
1205 }
1206
1207 Stream_Read(s, correlationId, sizeof(correlationId));
1208 if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1209 {
1210 WLog_Print(nego->log, WLOG_ERROR,
1211 "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1212 correlationId[0]);
1213 return FALSE;
1214 }
1215 for (size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1216 {
1217 if (correlationId[x] == 0x0D)
1218 {
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]);
1223 return FALSE;
1224 }
1225 }
1226 Stream_Seek(s, 16); /* skip reserved bytes */
1227
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
1232 ", %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]);
1237 return TRUE;
1238}
1239
1240BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
1241{
1242 BYTE flags = 0;
1243 UINT16 length = 0;
1244
1245 WINPR_ASSERT(nego);
1246 WINPR_ASSERT(s);
1247
1248 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1249 return FALSE;
1250 Stream_Read_UINT8(s, flags);
1251 if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1252 CORRELATION_INFO_PRESENT)) != 0)
1253 {
1254 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1255 return FALSE;
1256 }
1257 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1258 {
1259 if (nego->RestrictedAdminModeSupported)
1260 {
1261 WLog_Print(nego->log, WLOG_INFO, "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1262 }
1263 else
1264 {
1265 WLog_Print(nego->log, WLOG_ERROR,
1266 "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED but disabled");
1267 return FALSE;
1268 }
1269 }
1270
1271 if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1272 {
1273 if (nego->RemoteCredsGuardSupported)
1274 {
1275 WLog_Print(nego->log, WLOG_INFO,
1276 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1277 nego->RemoteCredsGuardActive = TRUE;
1278 }
1279 else
1280 {
1281 /* If both RESTRICTED_ADMIN_MODE_REQUIRED and REDIRECTED_AUTHENTICATION_MODE_REQUIRED
1282 * are set, it means one or the other. In this case, don't fail if Remote Guard isn't
1283 * available. */
1284 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1285 {
1286 WLog_Print(nego->log, WLOG_INFO,
1287 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED ignored.");
1288 }
1289 else
1290 {
1291 WLog_Print(
1292 nego->log, WLOG_ERROR,
1293 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1294 return FALSE;
1295 }
1296 }
1297 }
1298
1299 Stream_Read_UINT16(s, length);
1300 if (length != 8)
1301 {
1302 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::length != 8");
1303 return FALSE;
1304 }
1305 Stream_Read_UINT32(s, nego->RequestedProtocols);
1306
1307 if (flags & CORRELATION_INFO_PRESENT)
1308 {
1309 if (!nego_process_correlation_info(nego, s))
1310 return FALSE;
1311 }
1312
1313 {
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)));
1317 }
1318 nego_set_state(nego, NEGO_STATE_FINAL);
1319 return TRUE;
1320}
1321
1322static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1323{
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;
1328
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), "|");
1340 if (flags & ~mask)
1341 {
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), "|");
1345 }
1346
1347 return buffer;
1348}
1349
1350BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
1351{
1352 UINT16 length = 0;
1353
1354 WINPR_ASSERT(nego);
1355 WINPR_ASSERT(s);
1356
1357 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1358 {
1359 nego_set_state(nego, NEGO_STATE_FAIL);
1360 return FALSE;
1361 }
1362
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));
1366
1367 Stream_Read_UINT16(s, length);
1368 if (length != 8)
1369 {
1370 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_RSP::length != 8");
1371 nego_set_state(nego, NEGO_STATE_FAIL);
1372 return FALSE;
1373 }
1374 UINT32 SelectedProtocol = 0;
1375 Stream_Read_UINT32(s, SelectedProtocol);
1376
1377 if (!nego_set_selected_protocol(nego, SelectedProtocol))
1378 return FALSE;
1379 return nego_set_state(nego, NEGO_STATE_FINAL);
1380}
1381
1382static const char* nego_rdp_neg_fail_str(uint32_t what)
1383{
1384 switch (what)
1385 {
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";
1398 default:
1399 return "UNKNOWN";
1400 }
1401}
1402
1403static void nego_disable_all_except(rdpNego* nego, uint32_t what)
1404{
1405 WINPR_ASSERT(nego);
1406
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)));
1410
1411 for (size_t x = 0; x < ARRAYSIZE(nego->EnabledProtocols); x++)
1412 {
1413 if (x == what)
1414 continue;
1415 nego->EnabledProtocols[x] = FALSE;
1416 }
1417}
1418
1427BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
1428{
1429 BYTE flags = 0;
1430 UINT16 length = 0;
1431
1432 WINPR_ASSERT(nego);
1433 WINPR_ASSERT(s);
1434
1435 WLog_Print(nego->log, WLOG_DEBUG, "RDP_NEG_FAILURE");
1436 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1437 return FALSE;
1438
1439 Stream_Read_UINT8(s, flags);
1440 if (flags != 0)
1441 {
1442 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1443 return FALSE;
1444 }
1445 Stream_Read_UINT16(s, length);
1446 if (length != 8)
1447 {
1448 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::length != 8");
1449 return FALSE;
1450 }
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)
1455 {
1456 case SSL_REQUIRED_BY_SERVER:
1457 nego_disable_all_except(nego, PROTOCOL_SSL);
1458 break;
1459
1460 case SSL_NOT_ALLOWED_BY_SERVER:
1461 nego_disable_all_except(nego, PROTOCOL_RDP);
1462 nego->sendNegoData = TRUE;
1463 break;
1464
1465 case SSL_CERT_NOT_ON_SERVER:
1466 level = WLOG_ERROR;
1467 nego->sendNegoData = TRUE;
1468 break;
1469
1470 case INCONSISTENT_FLAGS:
1471 level = WLOG_ERROR;
1472 break;
1473
1474 case HYBRID_REQUIRED_BY_SERVER:
1475 nego_disable_all_except(nego, PROTOCOL_HYBRID);
1476 break;
1477
1478 default:
1479 level = WLOG_ERROR;
1480 break;
1481 }
1482
1483 WLog_Print(nego->log, level, "Error: %s [0x%08" PRIx32 "]", failureStr, failureCode);
1484 nego_set_state(nego, NEGO_STATE_FAIL);
1485 return TRUE;
1486}
1487
1493BOOL nego_send_negotiation_response(rdpNego* nego)
1494{
1495 BOOL status = FALSE;
1496 BYTE flags = 0;
1497 rdpContext* context = nullptr;
1498 rdpSettings* settings = nullptr;
1499
1500 WINPR_ASSERT(nego);
1501 context = transport_get_context(nego->transport);
1502 WINPR_ASSERT(context);
1503
1504 settings = context->settings;
1505 WINPR_ASSERT(settings);
1506
1507 wStream* s = Stream_New(nullptr, 512);
1508
1509 if (!s)
1510 {
1511 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1512 return FALSE;
1513 }
1514
1515 UINT16 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1516 const size_t bm = Stream_GetPosition(s);
1517 if (!Stream_SafeSeek(s, length))
1518 goto fail;
1519
1520 if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1521 {
1522 UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1523 flags = 0;
1524 Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1525 Stream_Write_UINT8(s, flags); /* flags */
1526 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1527 Stream_Write_UINT32(s, errorCode);
1528 length += 8;
1529 }
1530 else
1531 {
1532 flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1533
1534 if (freerdp_settings_get_bool(settings, FreeRDP_SupportGraphicsPipeline))
1535 flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1536
1537 if (nego->RestrictedAdminModeSupported)
1538 flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1539
1540 if (nego->RemoteCredsGuardSupported)
1541 flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1542
1543 /* RDP_NEG_DATA must be present for TLS, NLA, RDP and RDSTLS */
1544 Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1545 Stream_Write_UINT8(s, flags); /* flags */
1546 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1547 Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
1548 length += 8;
1549 }
1550
1551 const size_t em = Stream_GetPosition(s);
1552 if (!Stream_SetPosition(s, bm))
1553 goto fail;
1554 if (!tpkt_write_header(s, length))
1555 goto fail;
1556
1557 if (!tpdu_write_connection_confirm(s, length - 5))
1558 goto fail;
1559
1560 if (!Stream_SetPosition(s, em))
1561 goto fail;
1562 Stream_SealLength(s);
1563
1564 status = (transport_write(nego->transport, s) >= 0);
1565
1566fail:
1567 Stream_Free(s, TRUE);
1568
1569 if (status)
1570 {
1571 /* update settings with negotiated protocol security */
1572 if (!freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
1573 nego->RequestedProtocols))
1574 return FALSE;
1575 if (!freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
1576 nego->SelectedProtocol))
1577 return FALSE;
1578
1579 switch (nego->SelectedProtocol)
1580 {
1581 case PROTOCOL_RDP:
1582 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, FALSE))
1583 return FALSE;
1584 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1585 return FALSE;
1586 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE))
1587 return FALSE;
1588 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
1589 return FALSE;
1590
1591 if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionLevel) ==
1592 ENCRYPTION_LEVEL_NONE)
1593 {
1598 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1599 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1600 return FALSE;
1601 }
1602
1603 if (freerdp_settings_get_bool(settings, FreeRDP_LocalConnection))
1604 {
1611 WLog_Print(nego->log, WLOG_INFO,
1612 "Turning off encryption for local peer with standard rdp security");
1613 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1614 return FALSE;
1615 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1616 ENCRYPTION_LEVEL_NONE))
1617 return FALSE;
1618 }
1619 else if (!freerdp_settings_get_pointer(settings, FreeRDP_RdpServerRsaKey))
1620 {
1621 WLog_Print(nego->log, WLOG_ERROR, "Missing server certificate");
1622 return FALSE;
1623 }
1624 break;
1625 case PROTOCOL_SSL:
1626 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1627 return FALSE;
1628 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1629 return FALSE;
1630 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1631 return FALSE;
1632 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1633 return FALSE;
1634 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1635 return FALSE;
1636
1637 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1638 ENCRYPTION_LEVEL_NONE))
1639 return FALSE;
1640 break;
1641 case PROTOCOL_HYBRID:
1642 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1643 return FALSE;
1644 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE))
1645 return FALSE;
1646 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1647 return FALSE;
1648 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1649 return FALSE;
1650 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1651 return FALSE;
1652
1653 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1654 ENCRYPTION_LEVEL_NONE))
1655 return FALSE;
1656 break;
1657 case PROTOCOL_RDSTLS:
1658 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1659 return FALSE;
1660 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1661 return FALSE;
1662 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, TRUE))
1663 return FALSE;
1664 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1665 return FALSE;
1666 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1667 return FALSE;
1668
1669 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1670 ENCRYPTION_LEVEL_NONE))
1671 return FALSE;
1672 break;
1673 default:
1674 break;
1675 }
1676 }
1677
1678 return status;
1679}
1680
1686void nego_init(rdpNego* nego)
1687{
1688 WINPR_ASSERT(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;
1693 nego->flags = 0;
1694}
1695
1704rdpNego* nego_new(rdpTransport* transport)
1705{
1706 rdpNego* nego = (rdpNego*)calloc(1, sizeof(rdpNego));
1707
1708 if (!nego)
1709 return nullptr;
1710
1711 nego->log = WLog_Get(NEGO_TAG);
1712 WINPR_ASSERT(nego->log);
1713 nego->transport = transport;
1714 nego_init(nego);
1715 return nego;
1716}
1717
1723void nego_free(rdpNego* nego)
1724{
1725 if (nego)
1726 {
1727 free(nego->RoutingToken);
1728 free(nego->cookie);
1729 free(nego);
1730 }
1731}
1732
1742BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 port)
1743{
1744 WINPR_ASSERT(nego);
1745 WINPR_ASSERT(hostname);
1746
1747 nego->hostname = hostname;
1748 nego->port = port;
1749 return TRUE;
1750}
1751
1759void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1760{
1761 WLog_Print(nego->log, WLOG_DEBUG, "Enabling security layer negotiation: %s",
1762 NegotiateSecurityLayer ? "TRUE" : "FALSE");
1763 nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1764}
1765
1773void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1774{
1775 WLog_Print(nego->log, WLOG_DEBUG, "Enabling restricted admin mode: %s",
1776 RestrictedAdminModeRequired ? "TRUE" : "FALSE");
1777 nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1778}
1779
1780void nego_set_restricted_admin_mode_supported(rdpNego* nego, BOOL enabled)
1781{
1782 WINPR_ASSERT(nego);
1783
1784 nego->RestrictedAdminModeSupported = enabled;
1785}
1786
1787void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1788{
1789 WINPR_ASSERT(nego);
1790
1791 WLog_Print(nego->log, WLOG_DEBUG, "Enabling remoteCredentialGuards: %s",
1792 enabled ? "TRUE" : "FALSE");
1793 nego->RemoteCredsGuardRequired = enabled;
1794}
1795
1796void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1797{
1798 WINPR_ASSERT(nego);
1799
1800 nego->RemoteCredsGuardSupported = enabled;
1801}
1802
1803BOOL nego_get_remoteCredentialGuard(const rdpNego* nego)
1804{
1805 WINPR_ASSERT(nego);
1806
1807 return nego->RemoteCredsGuardActive;
1808}
1809
1810void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1811{
1812 WINPR_ASSERT(nego);
1813 nego->ConnectChildSession = ChildSessionEnabled;
1814}
1815
1816void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1817{
1818 nego->GatewayEnabled = GatewayEnabled;
1819}
1820
1821void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1822{
1823 nego->GatewayBypassLocal = GatewayBypassLocal;
1824}
1825
1832void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1833{
1834 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
1835 nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1836}
1837
1844void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1845{
1846 WLog_Print(nego->log, WLOG_DEBUG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
1847 nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1848}
1849
1857void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1858{
1859 WLog_Print(nego->log, WLOG_DEBUG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
1860 nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1861}
1862
1870void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1871{
1872 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDSTLS security: %s",
1873 enable_rdstls ? "TRUE" : "FALSE");
1874 nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1875}
1876
1884void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1885{
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;
1889}
1890
1898void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1899{
1900 WINPR_ASSERT(nego);
1901 if (aad_is_supported())
1902 {
1903 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDS AAD security: %s",
1904 enable_aad ? "TRUE" : "FALSE");
1905 nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1906 }
1907 else
1908 {
1909 WLog_Print(nego->log, WLOG_WARN, "This build does not support AAD security, disabling.");
1910 }
1911}
1912
1922BOOL nego_set_routing_token(rdpNego* nego, const void* RoutingToken, DWORD RoutingTokenLength)
1923{
1924 if (RoutingTokenLength == 0)
1925 return FALSE;
1926
1927 free(nego->RoutingToken);
1928 nego->RoutingTokenLength = RoutingTokenLength;
1929 nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1930
1931 if (!nego->RoutingToken)
1932 return FALSE;
1933
1934 CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1935 return TRUE;
1936}
1937
1946BOOL nego_set_cookie(rdpNego* nego, const char* cookie)
1947{
1948 if (nego->cookie)
1949 {
1950 free(nego->cookie);
1951 nego->cookie = nullptr;
1952 }
1953
1954 if (!cookie)
1955 return TRUE;
1956
1957 nego->cookie = _strdup(cookie);
1958
1959 return (nego->cookie != nullptr);
1960}
1961
1968void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1969{
1970 nego->CookieMaxLength = CookieMaxLength;
1971}
1972
1979void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1980{
1981 nego->SendPreconnectionPdu = SendPreconnectionPdu;
1982}
1983
1990void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1991{
1992 nego->PreconnectionId = PreconnectionId;
1993}
1994
2001void nego_set_preconnection_blob(rdpNego* nego, const char* PreconnectionBlob)
2002{
2003 nego->PreconnectionBlob = PreconnectionBlob;
2004}
2005
2006UINT32 nego_get_selected_protocol(const rdpNego* nego)
2007{
2008 if (!nego)
2009 return 0;
2010
2011 return nego->SelectedProtocol;
2012}
2013
2014BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
2015{
2016 WINPR_ASSERT(nego);
2017 nego->SelectedProtocol = SelectedProtocol;
2018 return TRUE;
2019}
2020
2021UINT32 nego_get_requested_protocols(const rdpNego* nego)
2022{
2023 if (!nego)
2024 return 0;
2025
2026 return nego->RequestedProtocols;
2027}
2028
2029BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
2030{
2031 if (!nego)
2032 return FALSE;
2033
2034 nego->RequestedProtocols = RequestedProtocols;
2035 return TRUE;
2036}
2037
2038NEGO_STATE nego_get_state(const rdpNego* nego)
2039{
2040 if (!nego)
2041 return NEGO_STATE_FAIL;
2042
2043 return nego->state;
2044}
2045
2046BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
2047{
2048 WINPR_ASSERT(nego);
2049 nego->state = state;
2050 return TRUE;
2051}
2052
2053SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
2054{
2055 rdpNla* nla = nullptr;
2056 if (!nego)
2057 return nullptr;
2058
2059 nla = transport_get_nla(nego->transport);
2060 return nla_get_identity(nla);
2061}
2062
2063void nego_free_nla(rdpNego* nego)
2064{
2065 if (!nego || !nego->transport)
2066 return;
2067
2068 transport_set_nla(nego->transport, nullptr);
2069}
2070
2071const BYTE* nego_get_routing_token(const rdpNego* nego, DWORD* RoutingTokenLength)
2072{
2073 if (!nego)
2074 return nullptr;
2075 if (RoutingTokenLength)
2076 *RoutingTokenLength = nego->RoutingTokenLength;
2077 return nego->RoutingToken;
2078}
2079
2080const char* nego_protocol_to_str(UINT32 protocol, char* buffer, size_t size)
2081{
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;
2085
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), "|");
2098
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), "|");
2103
2104 (void)_snprintf(buffer, size, "[%s][0x%08" PRIx32 "]", str, protocol);
2105 return buffer;
2106}
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.