FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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;
63 BOOL RemoteCredsGuardRequired;
64 BOOL RemoteCredsGuardActive;
65 BOOL RemoteCredsGuardSupported;
66 BOOL GatewayEnabled;
67 BOOL GatewayBypassLocal;
68 BOOL ConnectChildSession;
69
70 rdpTransport* transport;
71 wLog* log;
72};
73
74static const char* nego_state_string(NEGO_STATE state)
75{
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];
84}
85
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);
96
97BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
98{
99 WINPR_ASSERT(nego);
100
101 /* update settings with negotiated protocol security */
102 return freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
103 nego->RequestedProtocols) &&
104 freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
105 nego->SelectedProtocol) &&
106 freerdp_settings_set_uint32(settings, FreeRDP_NegotiationFlags, nego->flags);
107}
108
117BOOL nego_connect(rdpNego* nego)
118{
119 rdpContext* context = NULL;
120 rdpSettings* settings = NULL;
121 WINPR_ASSERT(nego);
122 context = transport_get_context(nego->transport);
123 WINPR_ASSERT(context);
124 settings = context->settings;
125 WINPR_ASSERT(settings);
126
127 if (nego_get_state(nego) == NEGO_STATE_INITIAL)
128 {
129 if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
130 {
131 nego_set_state(nego, NEGO_STATE_AAD);
132 }
133 else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
134 {
135 nego_set_state(nego, NEGO_STATE_RDSTLS);
136 }
137 else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
138 {
139 nego_set_state(nego, NEGO_STATE_EXT);
140 }
141 else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
142 {
143 nego_set_state(nego, NEGO_STATE_NLA);
144 }
145 else if (nego->EnabledProtocols[PROTOCOL_SSL])
146 {
147 nego_set_state(nego, NEGO_STATE_TLS);
148 }
149 else if (nego->EnabledProtocols[PROTOCOL_RDP])
150 {
151 nego_set_state(nego, NEGO_STATE_RDP);
152 }
153 else
154 {
155 WLog_Print(nego->log, WLOG_ERROR, "No security protocol is enabled");
156 nego_set_state(nego, NEGO_STATE_FAIL);
157 return FALSE;
158 }
159
160 if (!nego->NegotiateSecurityLayer)
161 {
162 WLog_Print(nego->log, WLOG_DEBUG, "Security Layer Negotiation is disabled");
163 /* attempt only the highest enabled protocol (see nego_attempt_*) */
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;
170
171 UINT32 SelectedProtocol = 0;
172 switch (nego_get_state(nego))
173 {
174 case NEGO_STATE_AAD:
175 nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
176 SelectedProtocol = PROTOCOL_RDSAAD;
177 break;
178 case NEGO_STATE_RDSTLS:
179 nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
180 SelectedProtocol = PROTOCOL_RDSTLS;
181 break;
182 case NEGO_STATE_EXT:
183 nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
184 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
185 SelectedProtocol = PROTOCOL_HYBRID_EX;
186 break;
187 case NEGO_STATE_NLA:
188 nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
189 SelectedProtocol = PROTOCOL_HYBRID;
190 break;
191 case NEGO_STATE_TLS:
192 nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
193 SelectedProtocol = PROTOCOL_SSL;
194 break;
195 case NEGO_STATE_RDP:
196 nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
197 SelectedProtocol = PROTOCOL_RDP;
198 break;
199 default:
200 WLog_Print(nego->log, WLOG_ERROR, "Invalid NEGO state 0x%08" PRIx32,
201 nego_get_state(nego));
202 return FALSE;
203 }
204 if (!nego_set_selected_protocol(nego, SelectedProtocol))
205 return FALSE;
206 }
207
208 if (!nego_tcp_connect(nego))
209 {
210 WLog_Print(nego->log, WLOG_ERROR, "Failed to connect");
211 return FALSE;
212 }
213
214 if (nego->SendPreconnectionPdu)
215 {
216 if (!nego_send_preconnection_pdu(nego))
217 {
218 WLog_Print(nego->log, WLOG_ERROR, "Failed to send preconnection pdu");
219 nego_set_state(nego, NEGO_STATE_FINAL);
220 return FALSE;
221 }
222 }
223 }
224
225 if (!nego->NegotiateSecurityLayer)
226 {
227 nego_set_state(nego, NEGO_STATE_FINAL);
228 }
229 else
230 {
231 do
232 {
233 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
234 nego_send(nego);
235
236 if (nego_get_state(nego) == NEGO_STATE_FAIL)
237 {
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");
241
242 nego_set_state(nego, NEGO_STATE_FINAL);
243 return FALSE;
244 }
245 } while (nego_get_state(nego) != NEGO_STATE_FINAL);
246 }
247
248 {
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)));
252 }
253
254 /* update settings with negotiated protocol security */
255 if (!nego_update_settings_from_state(nego, settings))
256 return FALSE;
257
258 if (nego->SelectedProtocol == PROTOCOL_RDP)
259 {
260 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
261 return FALSE;
262
263 if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionMethods) == 0)
264 {
269 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods,
270 ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
271 ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
272 return FALSE;
273 }
274 }
275
276 /* finally connect security layer (if not already done) */
277 if (!nego_security_connect(nego))
278 {
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)));
282 return FALSE;
283 }
284
285 return TRUE;
286}
287
288BOOL nego_disconnect(rdpNego* nego)
289{
290 WINPR_ASSERT(nego);
291 nego_set_state(nego, NEGO_STATE_INITIAL);
292 return nego_transport_disconnect(nego);
293}
294
295static BOOL nego_try_connect(rdpNego* nego)
296{
297 WINPR_ASSERT(nego);
298
299 switch (nego->SelectedProtocol)
300 {
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);
304 break;
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);
308 break;
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);
312 break;
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);
316 break;
317 case PROTOCOL_SSL:
318 WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_SSL");
319 nego->SecurityConnected = transport_connect_tls(nego->transport);
320 break;
321 case PROTOCOL_RDP:
322 WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_RDP");
323 nego->SecurityConnected = transport_connect_rdp(nego->transport);
324 break;
325 default:
326 WLog_Print(nego->log, WLOG_ERROR,
327 "cannot connect security layer because no protocol has been selected yet.");
328 return FALSE;
329 }
330 return nego->SecurityConnected;
331}
332
333/* connect to selected security layer */
334BOOL nego_security_connect(rdpNego* nego)
335{
336 WINPR_ASSERT(nego);
337 if (!nego->TcpConnected)
338 {
339 nego->SecurityConnected = FALSE;
340 }
341 else if (!nego->SecurityConnected)
342 {
343 if (!nego_try_connect(nego))
344 return FALSE;
345 }
346
347 return nego->SecurityConnected;
348}
349
350static BOOL nego_tcp_connect(rdpNego* nego)
351{
352 rdpContext* context = NULL;
353 WINPR_ASSERT(nego);
354 if (!nego->TcpConnected)
355 {
356 UINT32 TcpConnectTimeout = 0;
357
358 context = transport_get_context(nego->transport);
359 WINPR_ASSERT(context);
360
361 TcpConnectTimeout =
362 freerdp_settings_get_uint32(context->settings, FreeRDP_TcpConnectTimeout);
363
364 if (nego->GatewayEnabled)
365 {
366 if (nego->GatewayBypassLocal)
367 {
368 /* Attempt a direct connection first, and then fallback to using the gateway */
369 WLog_Print(
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,
376 TcpConnectTimeout);
377 }
378
379 if (!nego->TcpConnected)
380 {
381 transport_set_gateway_enabled(nego->transport, TRUE);
382 nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
383 TcpConnectTimeout);
384 }
385 }
386 else if (nego->ConnectChildSession)
387 {
388 nego->TcpConnected = transport_connect_childsession(nego->transport);
389 }
390 else
391 {
392 nego->TcpConnected =
393 transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
394 }
395 }
396
397 return nego->TcpConnected;
398}
399
408BOOL nego_transport_connect(rdpNego* nego)
409{
410 WINPR_ASSERT(nego);
411 if (!nego_tcp_connect(nego))
412 return FALSE;
413
414 if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
415 return nego_security_connect(nego);
416
417 return nego->TcpConnected;
418}
419
428BOOL nego_transport_disconnect(rdpNego* nego)
429{
430 WINPR_ASSERT(nego);
431 if (nego->TcpConnected)
432 transport_disconnect(nego->transport);
433
434 nego->TcpConnected = FALSE;
435 nego->SecurityConnected = FALSE;
436 return TRUE;
437}
438
447BOOL nego_send_preconnection_pdu(rdpNego* nego)
448{
449 wStream* s = NULL;
450 UINT32 cbSize = 0;
451 UINT16 cchPCB = 0;
452 WCHAR* wszPCB = NULL;
453
454 WINPR_ASSERT(nego);
455
456 WLog_Print(nego->log, WLOG_DEBUG, "Sending preconnection PDU");
457
458 if (!nego_tcp_connect(nego))
459 return FALSE;
460
461 /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
462 cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
463
464 if (nego->PreconnectionBlob)
465 {
466 size_t len = 0;
467 wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
468 if (len > UINT16_MAX - 1)
469 {
470 free(wszPCB);
471 return FALSE;
472 }
473 cchPCB = (UINT16)len;
474 cchPCB += 1; /* zero-termination */
475 cbSize += cchPCB * sizeof(WCHAR);
476 }
477
478 s = Stream_New(NULL, cbSize);
479
480 if (!s)
481 {
482 free(wszPCB);
483 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
484 return FALSE;
485 }
486
487 Stream_Write_UINT32(s, cbSize); /* cbSize */
488 Stream_Write_UINT32(s, 0); /* Flags */
489 Stream_Write_UINT32(s, PRECONNECTION_PDU_V2); /* Version */
490 Stream_Write_UINT32(s, nego->PreconnectionId); /* Id */
491 Stream_Write_UINT16(s, cchPCB); /* cchPCB */
492
493 if (wszPCB)
494 {
495 Stream_Write(s, wszPCB, cchPCB * sizeof(WCHAR)); /* wszPCB */
496 free(wszPCB);
497 }
498
499 Stream_SealLength(s);
500
501 if (transport_write(nego->transport, s) < 0)
502 {
503 Stream_Free(s, TRUE);
504 return FALSE;
505 }
506
507 Stream_Free(s, TRUE);
508 return TRUE;
509}
510
511static void nego_attempt_rdstls(rdpNego* nego)
512{
513 WINPR_ASSERT(nego);
514 nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
515 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDSTLS security");
516
517 if (!nego_transport_connect(nego))
518 {
519 nego_set_state(nego, NEGO_STATE_FAIL);
520 return;
521 }
522
523 if (!nego_send_negotiation_request(nego))
524 {
525 nego_set_state(nego, NEGO_STATE_FAIL);
526 return;
527 }
528
529 if (!nego_recv_response(nego))
530 {
531 nego_set_state(nego, NEGO_STATE_FAIL);
532 return;
533 }
534
535 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
536
537 if (nego_get_state(nego) != NEGO_STATE_FINAL)
538 {
539 nego_transport_disconnect(nego);
540
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);
549 else
550 nego_set_state(nego, NEGO_STATE_FAIL);
551 }
552}
553
554static void nego_attempt_rdsaad(rdpNego* nego)
555{
556 WINPR_ASSERT(nego);
557 nego->RequestedProtocols = PROTOCOL_RDSAAD;
558 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDS AAD Auth security");
559
560 if (!nego_transport_connect(nego))
561 {
562 nego_set_state(nego, NEGO_STATE_FAIL);
563 return;
564 }
565
566 if (!nego_send_negotiation_request(nego))
567 {
568 nego_set_state(nego, NEGO_STATE_FAIL);
569 return;
570 }
571
572 if (!nego_recv_response(nego))
573 {
574 nego_set_state(nego, NEGO_STATE_FAIL);
575 return;
576 }
577
578 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
579
580 if (nego_get_state(nego) != NEGO_STATE_FINAL)
581 {
582 nego_transport_disconnect(nego);
583
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);
592 else
593 nego_set_state(nego, NEGO_STATE_FAIL);
594 }
595}
596
597static void nego_attempt_ext(rdpNego* nego)
598{
599 WINPR_ASSERT(nego);
600 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
601 WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA extended security");
602
603 if (!nego_transport_connect(nego))
604 {
605 nego_set_state(nego, NEGO_STATE_FAIL);
606 return;
607 }
608
609 if (!nego_send_negotiation_request(nego))
610 {
611 nego_set_state(nego, NEGO_STATE_FAIL);
612 return;
613 }
614
615 if (!nego_recv_response(nego))
616 {
617 nego_set_state(nego, NEGO_STATE_FAIL);
618 return;
619 }
620
621 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
622
623 if (nego_get_state(nego) != NEGO_STATE_FINAL)
624 {
625 nego_transport_disconnect(nego);
626
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);
633 else
634 nego_set_state(nego, NEGO_STATE_FAIL);
635 }
636}
637
638static void nego_attempt_nla(rdpNego* nego)
639{
640 WINPR_ASSERT(nego);
641 nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
642 WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA security");
643
644 if (!nego_transport_connect(nego))
645 {
646 nego_set_state(nego, NEGO_STATE_FAIL);
647 return;
648 }
649
650 if (!nego_send_negotiation_request(nego))
651 {
652 nego_set_state(nego, NEGO_STATE_FAIL);
653 return;
654 }
655
656 if (!nego_recv_response(nego))
657 {
658 nego_set_state(nego, NEGO_STATE_FAIL);
659 return;
660 }
661
662 WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
663
664 if (nego_get_state(nego) != NEGO_STATE_FINAL)
665 {
666 nego_transport_disconnect(nego);
667
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);
672 else
673 nego_set_state(nego, NEGO_STATE_FAIL);
674 }
675}
676
677static void nego_attempt_tls(rdpNego* nego)
678{
679 WINPR_ASSERT(nego);
680 nego->RequestedProtocols = PROTOCOL_SSL;
681 WLog_Print(nego->log, WLOG_DEBUG, "Attempting TLS security");
682
683 if (!nego_transport_connect(nego))
684 {
685 nego_set_state(nego, NEGO_STATE_FAIL);
686 return;
687 }
688
689 if (!nego_send_negotiation_request(nego))
690 {
691 nego_set_state(nego, NEGO_STATE_FAIL);
692 return;
693 }
694
695 if (!nego_recv_response(nego))
696 {
697 nego_set_state(nego, NEGO_STATE_FAIL);
698 return;
699 }
700
701 if (nego_get_state(nego) != NEGO_STATE_FINAL)
702 {
703 nego_transport_disconnect(nego);
704
705 if (nego->EnabledProtocols[PROTOCOL_RDP])
706 nego_set_state(nego, NEGO_STATE_RDP);
707 else
708 nego_set_state(nego, NEGO_STATE_FAIL);
709 }
710}
711
712static void nego_attempt_rdp(rdpNego* nego)
713{
714 WINPR_ASSERT(nego);
715 nego->RequestedProtocols = PROTOCOL_RDP;
716 WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDP security");
717
718 if (!nego_transport_connect(nego))
719 {
720 nego_set_state(nego, NEGO_STATE_FAIL);
721 return;
722 }
723
724 if (!nego_send_negotiation_request(nego))
725 {
726 nego_set_state(nego, NEGO_STATE_FAIL);
727 return;
728 }
729
730 if (!nego_recv_response(nego))
731 {
732 nego_set_state(nego, NEGO_STATE_FAIL);
733 return;
734 }
735}
736
745BOOL nego_recv_response(rdpNego* nego)
746{
747 int status = 0;
748 wStream* s = NULL;
749
750 WINPR_ASSERT(nego);
751 s = Stream_New(NULL, 1024);
752
753 if (!s)
754 {
755 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
756 return FALSE;
757 }
758
759 status = transport_read_pdu(nego->transport, s);
760
761 if (status < 0)
762 {
763 Stream_Free(s, TRUE);
764 return FALSE;
765 }
766
767 status = nego_recv(nego->transport, s, nego);
768 Stream_Free(s, TRUE);
769
770 if (status < 0)
771 return FALSE;
772
773 return TRUE;
774}
775
787int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport, wStream* s, void* extra)
788{
789 BYTE li = 0;
790 BYTE type = 0;
791 UINT16 length = 0;
792 rdpNego* nego = (rdpNego*)extra;
793
794 WINPR_ASSERT(nego);
795 if (!tpkt_read_header(s, &length))
796 return -1;
797
798 if (!tpdu_read_connection_confirm(s, &li, length))
799 return -1;
800
801 if (li > 6)
802 {
803 /* rdpNegData (optional) */
804 Stream_Read_UINT8(s, type); /* Type */
805
806 switch (type)
807 {
808 case TYPE_RDP_NEG_RSP:
809 if (!nego_process_negotiation_response(nego, s))
810 return -1;
811 {
812 char buffer[64] = { 0 };
813 WLog_Print(
814 nego->log, WLOG_DEBUG, "selected_protocol: %s",
815 nego_protocol_to_str(nego->SelectedProtocol, buffer, sizeof(buffer)));
816 }
817
818 /* enhanced security selected ? */
819
820 if (nego->SelectedProtocol)
821 {
822 if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
823 (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
824 {
825 nego_set_state(nego, NEGO_STATE_FAIL);
826 }
827 if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
828 (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
829 {
830 nego_set_state(nego, NEGO_STATE_FAIL);
831 }
832
833 if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
834 (!nego->EnabledProtocols[PROTOCOL_SSL]))
835 {
836 nego_set_state(nego, NEGO_STATE_FAIL);
837 }
838 }
839 else if (!nego->EnabledProtocols[PROTOCOL_RDP])
840 {
841 nego_set_state(nego, NEGO_STATE_FAIL);
842 }
843
844 break;
845
846 case TYPE_RDP_NEG_FAILURE:
847 if (!nego_process_negotiation_failure(nego, s))
848 return -1;
849 break;
850 default:
851 return -1;
852 }
853 }
854 else if (li == 6)
855 {
856 WLog_Print(nego->log, WLOG_DEBUG, "no rdpNegData");
857
858 if (!nego->EnabledProtocols[PROTOCOL_RDP])
859 nego_set_state(nego, NEGO_STATE_FAIL);
860 else
861 nego_set_state(nego, NEGO_STATE_FINAL);
862 }
863 else
864 {
865 WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation response");
866 nego_set_state(nego, NEGO_STATE_FAIL);
867 }
868
869 if (!tpkt_ensure_stream_consumed(nego->log, s, length))
870 return -1;
871 return 0;
872}
873
879static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
880{
881 /* routingToken and cookie are optional and mutually exclusive!
882 *
883 * routingToken (variable): An optional and variable-length routing
884 * token (used for load balancing) terminated by a 0x0D0A two-byte
885 * sequence: (check [MSFT-SDLBTS] for details!)
886 * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A]
887 * tsv://MS Terminal Services Plugin.1.[\x0D\x0A]
888 *
889 * cookie (variable): An optional and variable-length ANSI character
890 * string terminated by a 0x0D0A two-byte sequence:
891 * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A]
892 */
893 UINT16 crlf = 0;
894 BOOL result = FALSE;
895 BOOL isToken = FALSE;
896 size_t remain = Stream_GetRemainingLength(s);
897
898 WINPR_ASSERT(nego);
899
900 const char* str = Stream_ConstPointer(s);
901 const size_t pos = Stream_GetPosition(s);
902
903 /* minimum length for token is 15 */
904 if (remain < 15)
905 return TRUE;
906
907 if (memcmp(Stream_ConstPointer(s), "Cookie: mstshash=", 17) != 0)
908 {
909 if (memcmp(Stream_ConstPointer(s), "Cookie: msts=", 13) != 0)
910 {
911 if (memcmp(Stream_ConstPointer(s), "tsv:", 4) != 0)
912 {
913 if (memcmp(Stream_ConstPointer(s), "mth://", 6) != 0)
914 {
915 /* remaining bytes are neither a token nor a cookie */
916 return TRUE;
917 }
918 }
919 }
920 isToken = TRUE;
921 }
922 else
923 {
924 /* not a token, minimum length for cookie is 19 */
925 if (remain < 19)
926 return TRUE;
927
928 Stream_Seek(s, 17);
929 }
930
931 while (Stream_GetRemainingLength(s) >= 2)
932 {
933 Stream_Read_UINT16(s, crlf);
934
935 if (crlf == 0x0A0D)
936 break;
937
938 Stream_Rewind(s, 1);
939 }
940
941 if (crlf == 0x0A0D)
942 {
943 Stream_Rewind(s, 2);
944 const size_t len = Stream_GetPosition(s) - pos;
945 Stream_Write_UINT16(s, 0);
946
947 if (len > UINT32_MAX)
948 return FALSE;
949
950 if (strnlen(str, len) == len)
951 {
952 if (isToken)
953 result = nego_set_routing_token(nego, str, (UINT32)len);
954 else
955 result = nego_set_cookie(nego, str);
956 }
957 }
958
959 if (!result)
960 {
961 Stream_SetPosition(s, pos);
962 WLog_Print(nego->log, WLOG_ERROR, "invalid %s received",
963 isToken ? "routing token" : "cookie");
964 }
965 else
966 {
967 WLog_Print(nego->log, WLOG_DEBUG, "received %s [%s]", isToken ? "routing token" : "cookie",
968 str);
969 }
970
971 return result;
972}
973
983BOOL nego_read_request(rdpNego* nego, wStream* s)
984{
985 BYTE li = 0;
986 BYTE type = 0;
987 UINT16 length = 0;
988
989 WINPR_ASSERT(nego);
990 WINPR_ASSERT(s);
991
992 if (!tpkt_read_header(s, &length))
993 return FALSE;
994
995 if (!tpdu_read_connection_request(s, &li, length))
996 return FALSE;
997
998 if (li != Stream_GetRemainingLength(s) + 6)
999 {
1000 WLog_Print(nego->log, WLOG_ERROR, "Incorrect TPDU length indicator.");
1001 return FALSE;
1002 }
1003
1004 if (!nego_read_request_token_or_cookie(nego, s))
1005 {
1006 WLog_Print(nego->log, WLOG_ERROR, "Failed to parse routing token or cookie.");
1007 return FALSE;
1008 }
1009
1010 if (Stream_GetRemainingLength(s) >= 8)
1011 {
1012 /* rdpNegData (optional) */
1013 Stream_Read_UINT8(s, type); /* Type */
1014
1015 if (type != TYPE_RDP_NEG_REQ)
1016 {
1017 WLog_Print(nego->log, WLOG_ERROR, "Incorrect negotiation request type %" PRIu8 "",
1018 type);
1019 return FALSE;
1020 }
1021
1022 if (!nego_process_negotiation_request(nego, s))
1023 return FALSE;
1024 }
1025
1026 return tpkt_ensure_stream_consumed(nego->log, s, length);
1027}
1028
1035void nego_send(rdpNego* nego)
1036{
1037 WINPR_ASSERT(nego);
1038
1039 switch (nego_get_state(nego))
1040 {
1041 case NEGO_STATE_AAD:
1042 nego_attempt_rdsaad(nego);
1043 break;
1044 case NEGO_STATE_RDSTLS:
1045 nego_attempt_rdstls(nego);
1046 break;
1047 case NEGO_STATE_EXT:
1048 nego_attempt_ext(nego);
1049 break;
1050 case NEGO_STATE_NLA:
1051 nego_attempt_nla(nego);
1052 break;
1053 case NEGO_STATE_TLS:
1054 nego_attempt_tls(nego);
1055 break;
1056 case NEGO_STATE_RDP:
1057 nego_attempt_rdp(nego);
1058 break;
1059 default:
1060 WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation state for sending");
1061 break;
1062 }
1063}
1064
1075BOOL nego_send_negotiation_request(rdpNego* nego)
1076{
1077 BOOL rc = FALSE;
1078 wStream* s = NULL;
1079 size_t length = 0;
1080 size_t bm = 0;
1081 size_t em = 0;
1082 BYTE flags = 0;
1083 size_t cookie_length = 0;
1084 s = Stream_New(NULL, 512);
1085
1086 WINPR_ASSERT(nego);
1087 if (!s)
1088 {
1089 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1090 return FALSE;
1091 }
1092
1093 length = TPDU_CONNECTION_REQUEST_LENGTH;
1094 bm = Stream_GetPosition(s);
1095 Stream_Seek(s, length);
1096
1097 if (nego->RoutingToken)
1098 {
1099 Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1100
1101 /* Ensure Routing Token is correctly terminated - may already be present in string */
1102
1103 if ((nego->RoutingTokenLength > 2) &&
1104 (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1105 (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1106 {
1107 WLog_Print(nego->log, WLOG_DEBUG,
1108 "Routing token looks correctly terminated - use verbatim");
1109 length += nego->RoutingTokenLength;
1110 }
1111 else
1112 {
1113 WLog_Print(nego->log, WLOG_DEBUG, "Adding terminating CRLF to routing token");
1114 Stream_Write_UINT8(s, 0x0D); /* CR */
1115 Stream_Write_UINT8(s, 0x0A); /* LF */
1116 length += nego->RoutingTokenLength + 2;
1117 }
1118 }
1119 else if (nego->cookie)
1120 {
1121 cookie_length = strlen(nego->cookie);
1122
1123 if (cookie_length > nego->CookieMaxLength)
1124 cookie_length = nego->CookieMaxLength;
1125
1126 Stream_Write(s, "Cookie: mstshash=", 17);
1127 Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1128 Stream_Write_UINT8(s, 0x0D); /* CR */
1129 Stream_Write_UINT8(s, 0x0A); /* LF */
1130 length += cookie_length + 19;
1131 }
1132
1133 {
1134 char buffer[64] = { 0 };
1135 WLog_Print(nego->log, WLOG_DEBUG, "RequestedProtocols: %s",
1136 nego_protocol_to_str(nego->RequestedProtocols, buffer, sizeof(buffer)));
1137 }
1138
1139 if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1140 {
1141 /* RDP_NEG_DATA must be present for TLS and NLA */
1142 if (nego->RestrictedAdminModeRequired)
1143 flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1144
1145 if (nego->RemoteCredsGuardRequired)
1146 flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1147
1148 Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1149 Stream_Write_UINT8(s, flags);
1150 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1151 Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
1152 length += 8;
1153 }
1154
1155 if (length > UINT16_MAX)
1156 goto fail;
1157
1158 em = Stream_GetPosition(s);
1159 Stream_SetPosition(s, bm);
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 Stream_SetPosition(s, em);
1165 Stream_SealLength(s);
1166 rc = (transport_write(nego->transport, s) >= 0);
1167fail:
1168 Stream_Free(s, TRUE);
1169 return rc;
1170}
1171
1172static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego, wStream* s)
1173{
1174 UINT8 type = 0;
1175 UINT8 flags = 0;
1176 UINT16 length = 0;
1177 BYTE correlationId[16] = { 0 };
1178
1179 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1180 {
1181 WLog_Print(nego->log, WLOG_ERROR,
1182 "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1183 return FALSE;
1184 }
1185
1186 Stream_Read_UINT8(s, type);
1187 if (type != TYPE_RDP_CORRELATION_INFO)
1188 {
1189 WLog_Print(nego->log, WLOG_ERROR,
1190 "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1191 return FALSE;
1192 }
1193 Stream_Read_UINT8(s, flags);
1194 if (flags != 0)
1195 {
1196 WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::flags != 0");
1197 return FALSE;
1198 }
1199 Stream_Read_UINT16(s, length);
1200 if (length != 36)
1201 {
1202 WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::length != 36");
1203 return FALSE;
1204 }
1205
1206 Stream_Read(s, correlationId, sizeof(correlationId));
1207 if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1208 {
1209 WLog_Print(nego->log, WLOG_ERROR,
1210 "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1211 correlationId[0]);
1212 return FALSE;
1213 }
1214 for (size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1215 {
1216 if (correlationId[x] == 0x0D)
1217 {
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]);
1222 return FALSE;
1223 }
1224 }
1225 Stream_Seek(s, 16); /* skip reserved bytes */
1226
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
1231 ", %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]);
1236 return TRUE;
1237}
1238
1239BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
1240{
1241 BYTE flags = 0;
1242 UINT16 length = 0;
1243
1244 WINPR_ASSERT(nego);
1245 WINPR_ASSERT(s);
1246
1247 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1248 return FALSE;
1249 Stream_Read_UINT8(s, flags);
1250 if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1251 CORRELATION_INFO_PRESENT)) != 0)
1252 {
1253 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1254 return FALSE;
1255 }
1256 if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1257 WLog_Print(nego->log, WLOG_INFO, "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1258
1259 if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1260 {
1261 if (!nego->RemoteCredsGuardSupported)
1262 {
1263 WLog_Print(nego->log, WLOG_ERROR,
1264 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1265 return FALSE;
1266 }
1267 else
1268 {
1269 WLog_Print(nego->log, WLOG_INFO,
1270 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1271 }
1272 nego->RemoteCredsGuardActive = TRUE;
1273 }
1274
1275 Stream_Read_UINT16(s, length);
1276 if (length != 8)
1277 {
1278 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::length != 8");
1279 return FALSE;
1280 }
1281 Stream_Read_UINT32(s, nego->RequestedProtocols);
1282
1283 if (flags & CORRELATION_INFO_PRESENT)
1284 {
1285 if (!nego_process_correlation_info(nego, s))
1286 return FALSE;
1287 }
1288
1289 {
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)));
1293 }
1294 nego_set_state(nego, NEGO_STATE_FINAL);
1295 return TRUE;
1296}
1297
1298static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1299{
1300 static char buffer[1024] = { 0 };
1301
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), "|");
1317
1318 return buffer;
1319}
1320
1321BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
1322{
1323 UINT16 length = 0;
1324
1325 WINPR_ASSERT(nego);
1326 WINPR_ASSERT(s);
1327
1328 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1329 {
1330 nego_set_state(nego, NEGO_STATE_FAIL);
1331 return FALSE;
1332 }
1333
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));
1337
1338 Stream_Read_UINT16(s, length);
1339 if (length != 8)
1340 {
1341 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_RSP::length != 8");
1342 nego_set_state(nego, NEGO_STATE_FAIL);
1343 return FALSE;
1344 }
1345 UINT32 SelectedProtocol = 0;
1346 Stream_Read_UINT32(s, SelectedProtocol);
1347
1348 if (!nego_set_selected_protocol(nego, SelectedProtocol))
1349 return FALSE;
1350 return nego_set_state(nego, NEGO_STATE_FINAL);
1351}
1352
1361BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
1362{
1363 BYTE flags = 0;
1364 UINT16 length = 0;
1365 UINT32 failureCode = 0;
1366
1367 WINPR_ASSERT(nego);
1368 WINPR_ASSERT(s);
1369
1370 WLog_Print(nego->log, WLOG_DEBUG, "RDP_NEG_FAILURE");
1371 if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1372 return FALSE;
1373
1374 Stream_Read_UINT8(s, flags);
1375 if (flags != 0)
1376 {
1377 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1378 return FALSE;
1379 }
1380 Stream_Read_UINT16(s, length);
1381 if (length != 8)
1382 {
1383 WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::length != 8");
1384 return FALSE;
1385 }
1386 Stream_Read_UINT32(s, failureCode);
1387
1388 switch (failureCode)
1389 {
1390 case SSL_REQUIRED_BY_SERVER:
1391 WLog_Print(nego->log, WLOG_WARN, "Error: SSL_REQUIRED_BY_SERVER");
1392 break;
1393
1394 case SSL_NOT_ALLOWED_BY_SERVER:
1395 WLog_Print(nego->log, WLOG_WARN, "Error: SSL_NOT_ALLOWED_BY_SERVER");
1396 nego->sendNegoData = TRUE;
1397 break;
1398
1399 case SSL_CERT_NOT_ON_SERVER:
1400 WLog_Print(nego->log, WLOG_ERROR, "Error: SSL_CERT_NOT_ON_SERVER");
1401 nego->sendNegoData = TRUE;
1402 break;
1403
1404 case INCONSISTENT_FLAGS:
1405 WLog_Print(nego->log, WLOG_ERROR, "Error: INCONSISTENT_FLAGS");
1406 break;
1407
1408 case HYBRID_REQUIRED_BY_SERVER:
1409 WLog_Print(nego->log, WLOG_WARN, "Error: HYBRID_REQUIRED_BY_SERVER");
1410 break;
1411
1412 default:
1413 WLog_Print(nego->log, WLOG_ERROR, "Error: Unknown protocol security error %" PRIu32 "",
1414 failureCode);
1415 break;
1416 }
1417
1418 nego_set_state(nego, NEGO_STATE_FAIL);
1419 return TRUE;
1420}
1421
1427BOOL nego_send_negotiation_response(rdpNego* nego)
1428{
1429 UINT16 length = 0;
1430 size_t bm = 0;
1431 size_t em = 0;
1432 BOOL status = 0;
1433 wStream* s = NULL;
1434 BYTE flags = 0;
1435 rdpContext* context = NULL;
1436 rdpSettings* settings = NULL;
1437
1438 WINPR_ASSERT(nego);
1439 context = transport_get_context(nego->transport);
1440 WINPR_ASSERT(context);
1441
1442 settings = context->settings;
1443 WINPR_ASSERT(settings);
1444
1445 s = Stream_New(NULL, 512);
1446
1447 if (!s)
1448 {
1449 WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1450 return FALSE;
1451 }
1452
1453 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1454 bm = Stream_GetPosition(s);
1455 Stream_Seek(s, length);
1456
1457 if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1458 {
1459 UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1460 flags = 0;
1461 Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1462 Stream_Write_UINT8(s, flags); /* flags */
1463 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1464 Stream_Write_UINT32(s, errorCode);
1465 length += 8;
1466 }
1467 else
1468 {
1469 flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1470
1471 if (freerdp_settings_get_bool(settings, FreeRDP_SupportGraphicsPipeline))
1472 flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1473
1474 if (freerdp_settings_get_bool(settings, FreeRDP_RestrictedAdminModeRequired))
1475 flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1476
1477 if (nego->RemoteCredsGuardSupported)
1478 flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1479
1480 /* RDP_NEG_DATA must be present for TLS, NLA, RDP and RDSTLS */
1481 Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1482 Stream_Write_UINT8(s, flags); /* flags */
1483 Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
1484 Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
1485 length += 8;
1486 }
1487
1488 em = Stream_GetPosition(s);
1489 Stream_SetPosition(s, bm);
1490 status = tpkt_write_header(s, length);
1491 if (status)
1492 {
1493 tpdu_write_connection_confirm(s, length - 5);
1494 Stream_SetPosition(s, em);
1495 Stream_SealLength(s);
1496
1497 status = (transport_write(nego->transport, s) >= 0);
1498 }
1499 Stream_Free(s, TRUE);
1500
1501 if (status)
1502 {
1503 /* update settings with negotiated protocol security */
1504 if (!freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
1505 nego->RequestedProtocols))
1506 return FALSE;
1507 if (!freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
1508 nego->SelectedProtocol))
1509 return FALSE;
1510
1511 switch (nego->SelectedProtocol)
1512 {
1513 case PROTOCOL_RDP:
1514 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, FALSE))
1515 return FALSE;
1516 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1517 return FALSE;
1518 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE))
1519 return FALSE;
1520 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
1521 return FALSE;
1522
1523 if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionLevel) ==
1524 ENCRYPTION_LEVEL_NONE)
1525 {
1530 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1531 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1532 return FALSE;
1533 }
1534
1535 if (freerdp_settings_get_bool(settings, FreeRDP_LocalConnection))
1536 {
1543 WLog_Print(nego->log, WLOG_INFO,
1544 "Turning off encryption for local peer with standard rdp security");
1545 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1546 return FALSE;
1547 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1548 ENCRYPTION_LEVEL_NONE))
1549 return FALSE;
1550 }
1551 else if (!freerdp_settings_get_pointer(settings, FreeRDP_RdpServerRsaKey))
1552 {
1553 WLog_Print(nego->log, WLOG_ERROR, "Missing server certificate");
1554 return FALSE;
1555 }
1556 break;
1557 case PROTOCOL_SSL:
1558 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1559 return FALSE;
1560 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1561 return FALSE;
1562 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1563 return FALSE;
1564 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1565 return FALSE;
1566 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1567 return FALSE;
1568
1569 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1570 ENCRYPTION_LEVEL_NONE))
1571 return FALSE;
1572 break;
1573 case PROTOCOL_HYBRID:
1574 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1575 return FALSE;
1576 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE))
1577 return FALSE;
1578 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1579 return FALSE;
1580 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1581 return FALSE;
1582 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1583 return FALSE;
1584
1585 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1586 ENCRYPTION_LEVEL_NONE))
1587 return FALSE;
1588 break;
1589 case PROTOCOL_RDSTLS:
1590 if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1591 return FALSE;
1592 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1593 return FALSE;
1594 if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, TRUE))
1595 return FALSE;
1596 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1597 return FALSE;
1598 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1599 return FALSE;
1600
1601 if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1602 ENCRYPTION_LEVEL_NONE))
1603 return FALSE;
1604 break;
1605 default:
1606 break;
1607 }
1608 }
1609
1610 return status;
1611}
1612
1618void nego_init(rdpNego* nego)
1619{
1620 WINPR_ASSERT(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;
1625 nego->flags = 0;
1626}
1627
1636rdpNego* nego_new(rdpTransport* transport)
1637{
1638 rdpNego* nego = (rdpNego*)calloc(1, sizeof(rdpNego));
1639
1640 if (!nego)
1641 return NULL;
1642
1643 nego->log = WLog_Get(NEGO_TAG);
1644 WINPR_ASSERT(nego->log);
1645 nego->transport = transport;
1646 nego_init(nego);
1647 return nego;
1648}
1649
1655void nego_free(rdpNego* nego)
1656{
1657 if (nego)
1658 {
1659 free(nego->RoutingToken);
1660 free(nego->cookie);
1661 free(nego);
1662 }
1663}
1664
1674BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 port)
1675{
1676 if (!nego || !hostname)
1677 return FALSE;
1678
1679 nego->hostname = hostname;
1680 nego->port = port;
1681 return TRUE;
1682}
1683
1691void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1692{
1693 WLog_Print(nego->log, WLOG_DEBUG, "Enabling security layer negotiation: %s",
1694 NegotiateSecurityLayer ? "TRUE" : "FALSE");
1695 nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1696}
1697
1705void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1706{
1707 WLog_Print(nego->log, WLOG_DEBUG, "Enabling restricted admin mode: %s",
1708 RestrictedAdminModeRequired ? "TRUE" : "FALSE");
1709 nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1710}
1711
1712void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1713{
1714 WINPR_ASSERT(nego);
1715
1716 WLog_Print(nego->log, WLOG_DEBUG, "Enabling remoteCredentialGuards: %s",
1717 enabled ? "TRUE" : "FALSE");
1718 nego->RemoteCredsGuardRequired = enabled;
1719}
1720
1721void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1722{
1723 WINPR_ASSERT(nego);
1724
1725 nego->RemoteCredsGuardSupported = enabled;
1726}
1727
1728BOOL nego_get_remoteCredentialGuard(rdpNego* nego)
1729{
1730 WINPR_ASSERT(nego);
1731
1732 return nego->RemoteCredsGuardActive;
1733}
1734
1735void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1736{
1737 WINPR_ASSERT(nego);
1738 nego->ConnectChildSession = ChildSessionEnabled;
1739}
1740
1741void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1742{
1743 nego->GatewayEnabled = GatewayEnabled;
1744}
1745
1746void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1747{
1748 nego->GatewayBypassLocal = GatewayBypassLocal;
1749}
1750
1757void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1758{
1759 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
1760 nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1761}
1762
1769void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1770{
1771 WLog_Print(nego->log, WLOG_DEBUG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
1772 nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1773}
1774
1782void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1783{
1784 WLog_Print(nego->log, WLOG_DEBUG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
1785 nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1786}
1787
1795void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1796{
1797 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDSTLS security: %s",
1798 enable_rdstls ? "TRUE" : "FALSE");
1799 nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1800}
1801
1809void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1810{
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;
1814}
1815
1823void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1824{
1825 WINPR_ASSERT(nego);
1826 if (aad_is_supported())
1827 {
1828 WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDS AAD security: %s",
1829 enable_aad ? "TRUE" : "FALSE");
1830 nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1831 }
1832 else
1833 {
1834 WLog_Print(nego->log, WLOG_WARN, "This build does not support AAD security, disabling.");
1835 }
1836}
1837
1847BOOL nego_set_routing_token(rdpNego* nego, const void* RoutingToken, DWORD RoutingTokenLength)
1848{
1849 if (RoutingTokenLength == 0)
1850 return FALSE;
1851
1852 free(nego->RoutingToken);
1853 nego->RoutingTokenLength = RoutingTokenLength;
1854 nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1855
1856 if (!nego->RoutingToken)
1857 return FALSE;
1858
1859 CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1860 return TRUE;
1861}
1862
1871BOOL nego_set_cookie(rdpNego* nego, const char* cookie)
1872{
1873 if (nego->cookie)
1874 {
1875 free(nego->cookie);
1876 nego->cookie = NULL;
1877 }
1878
1879 if (!cookie)
1880 return TRUE;
1881
1882 nego->cookie = _strdup(cookie);
1883
1884 if (!nego->cookie)
1885 return FALSE;
1886
1887 return TRUE;
1888}
1889
1896void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1897{
1898 nego->CookieMaxLength = CookieMaxLength;
1899}
1900
1907void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1908{
1909 nego->SendPreconnectionPdu = SendPreconnectionPdu;
1910}
1911
1918void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1919{
1920 nego->PreconnectionId = PreconnectionId;
1921}
1922
1929void nego_set_preconnection_blob(rdpNego* nego, const char* PreconnectionBlob)
1930{
1931 nego->PreconnectionBlob = PreconnectionBlob;
1932}
1933
1934UINT32 nego_get_selected_protocol(rdpNego* nego)
1935{
1936 if (!nego)
1937 return 0;
1938
1939 return nego->SelectedProtocol;
1940}
1941
1942BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
1943{
1944 WINPR_ASSERT(nego);
1945 nego->SelectedProtocol = SelectedProtocol;
1946 return TRUE;
1947}
1948
1949UINT32 nego_get_requested_protocols(rdpNego* nego)
1950{
1951 if (!nego)
1952 return 0;
1953
1954 return nego->RequestedProtocols;
1955}
1956
1957BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
1958{
1959 if (!nego)
1960 return FALSE;
1961
1962 nego->RequestedProtocols = RequestedProtocols;
1963 return TRUE;
1964}
1965
1966NEGO_STATE nego_get_state(rdpNego* nego)
1967{
1968 if (!nego)
1969 return NEGO_STATE_FAIL;
1970
1971 return nego->state;
1972}
1973
1974BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
1975{
1976 if (!nego)
1977 return FALSE;
1978
1979 nego->state = state;
1980 return TRUE;
1981}
1982
1983SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
1984{
1985 rdpNla* nla = NULL;
1986 if (!nego)
1987 return NULL;
1988
1989 nla = transport_get_nla(nego->transport);
1990 return nla_get_identity(nla);
1991}
1992
1993void nego_free_nla(rdpNego* nego)
1994{
1995 if (!nego || !nego->transport)
1996 return;
1997
1998 transport_set_nla(nego->transport, NULL);
1999}
2000
2001const BYTE* nego_get_routing_token(rdpNego* nego, DWORD* RoutingTokenLength)
2002{
2003 if (!nego)
2004 return NULL;
2005 if (RoutingTokenLength)
2006 *RoutingTokenLength = nego->RoutingTokenLength;
2007 return nego->RoutingToken;
2008}
2009
2010const char* nego_protocol_to_str(UINT32 protocol, char* buffer, size_t size)
2011{
2012 const UINT32 mask = ~(PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_RDSTLS | PROTOCOL_HYBRID_EX |
2013 PROTOCOL_RDSAAD | PROTOCOL_FAILED_NEGO);
2014 char str[48] = { 0 };
2015
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), "|");
2028
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), "|");
2033
2034 (void)_snprintf(buffer, size, "[%s][0x%08" PRIx32 "]", str, protocol);
2035 return buffer;
2036}
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.