FreeRDP
Loading...
Searching...
No Matches
peer.c
1
23#include <freerdp/config.h>
24
25#include "settings.h"
26
27#include <winpr/assert.h>
28#include <winpr/cast.h>
29#include <winpr/crt.h>
30#include <winpr/winsock.h>
31
32#include "info.h"
33#include "display.h"
34
35#include <freerdp/log.h>
36#include <freerdp/streamdump.h>
37#include <freerdp/redirection.h>
38#include <freerdp/crypto/certificate.h>
39
40#include "rdp.h"
41#include "peer.h"
42#include "multitransport.h"
43
44#define TAG FREERDP_TAG("core.peer")
45
46static state_run_t peer_recv_pdu(freerdp_peer* client, wStream* s);
47
48static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char* name,
49 UINT32 flags)
50{
51 WINPR_ASSERT(client);
52 WINPR_ASSERT(client->context);
53 WINPR_ASSERT(client->context->rdp);
54 WINPR_ASSERT(name);
55 rdpMcs* mcs = client->context->rdp->mcs;
56 WINPR_ASSERT(mcs);
57
58 if (flags & WTS_CHANNEL_OPTION_DYNAMIC)
59 return nullptr; /* not yet supported */
60
61 const size_t length = strnlen(name, 9);
62
63 if (length > 8)
64 return nullptr; /* SVC maximum name length is 8 */
65
66 BOOL joined = FALSE;
67 UINT32 index = 0;
68 rdpMcsChannel* mcsChannel = nullptr;
69 for (; index < mcs->channelCount; index++)
70 {
71 mcsChannel = &(mcs->channels[index]);
72
73 if (!mcsChannel->joined)
74 continue;
75
76 if (_strnicmp(name, mcsChannel->Name, length) == 0)
77 {
78 joined = TRUE;
79 break;
80 }
81 }
82
83 if (!joined)
84 return nullptr; /* channel is not joined */
85
86 rdpPeerChannel* peerChannel = (rdpPeerChannel*)mcsChannel->handle;
87
88 if (peerChannel)
89 {
90 /* channel is already open */
91 return (HANDLE)peerChannel;
92 }
93
94 WINPR_ASSERT(index <= UINT16_MAX);
95 peerChannel =
96 server_channel_common_new(client, (UINT16)index, mcsChannel->ChannelId, 128, nullptr, name);
97
98 if (peerChannel)
99 {
100 peerChannel->channelFlags = flags;
101 peerChannel->mcsChannel = mcsChannel;
102 mcsChannel->handle = (void*)peerChannel;
103 }
104
105 return (HANDLE)peerChannel;
106}
107
108static BOOL freerdp_peer_virtual_channel_close(WINPR_ATTR_UNUSED freerdp_peer* client,
109 HANDLE hChannel)
110{
111 rdpMcsChannel* mcsChannel = nullptr;
112 rdpPeerChannel* peerChannel = nullptr;
113
114 WINPR_ASSERT(client);
115
116 if (!hChannel)
117 return FALSE;
118
119 peerChannel = (rdpPeerChannel*)hChannel;
120 mcsChannel = peerChannel->mcsChannel;
121 WINPR_ASSERT(mcsChannel);
122 mcsChannel->handle = nullptr;
123 server_channel_common_free(peerChannel);
124 return TRUE;
125}
126
127static int freerdp_peer_virtual_channel_write(freerdp_peer* client, HANDLE hChannel,
128 const BYTE* buffer, UINT32 length)
129{
130 wStream* s = nullptr;
131 UINT32 flags = 0;
132 UINT32 chunkSize = 0;
133 UINT32 maxChunkSize = 0;
134 UINT32 totalLength = 0;
135 rdpPeerChannel* peerChannel = nullptr;
136 rdpMcsChannel* mcsChannel = nullptr;
137 rdpRdp* rdp = nullptr;
138
139 WINPR_ASSERT(client);
140 WINPR_ASSERT(client->context);
141
142 rdp = client->context->rdp;
143 WINPR_ASSERT(rdp);
144 WINPR_ASSERT(rdp->settings);
145
146 if (!hChannel)
147 return -1;
148
149 peerChannel = (rdpPeerChannel*)hChannel;
150 mcsChannel = peerChannel->mcsChannel;
151 WINPR_ASSERT(peerChannel);
152 WINPR_ASSERT(mcsChannel);
153 if (peerChannel->channelFlags & WTS_CHANNEL_OPTION_DYNAMIC)
154 return -1; /* not yet supported */
155
156 maxChunkSize = rdp->settings->VCChunkSize;
157 totalLength = length;
158 flags = CHANNEL_FLAG_FIRST;
159
160 while (length > 0)
161 {
162 UINT16 sec_flags = 0;
163 s = rdp_send_stream_init(rdp, &sec_flags);
164
165 if (!s)
166 return -1;
167
168 if (length > maxChunkSize)
169 {
170 chunkSize = rdp->settings->VCChunkSize;
171 }
172 else
173 {
174 chunkSize = length;
175 flags |= CHANNEL_FLAG_LAST;
176 }
177
178 if (mcsChannel->options & CHANNEL_OPTION_SHOW_PROTOCOL)
179 flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
180
181 Stream_Write_UINT32(s, totalLength);
182 Stream_Write_UINT32(s, flags);
183
184 if (!Stream_EnsureRemainingCapacity(s, chunkSize))
185 {
186 Stream_Release(s);
187 return -1;
188 }
189
190 Stream_Write(s, buffer, chunkSize);
191
192 WINPR_ASSERT(peerChannel->channelId <= UINT16_MAX);
193 if (!rdp_send(rdp, s, (UINT16)peerChannel->channelId, sec_flags))
194 return -1;
195
196 buffer += chunkSize;
197 length -= chunkSize;
198 flags = 0;
199 }
200
201 return 1;
202}
203
204static void* freerdp_peer_virtual_channel_get_data(WINPR_ATTR_UNUSED freerdp_peer* client,
205 HANDLE hChannel)
206{
207 rdpPeerChannel* peerChannel = (rdpPeerChannel*)hChannel;
208
209 WINPR_ASSERT(client);
210 if (!hChannel)
211 return nullptr;
212
213 return peerChannel->extra;
214}
215
216static int freerdp_peer_virtual_channel_set_data(WINPR_ATTR_UNUSED freerdp_peer* client,
217 HANDLE hChannel, void* data)
218{
219 rdpPeerChannel* peerChannel = (rdpPeerChannel*)hChannel;
220
221 WINPR_ASSERT(client);
222 if (!hChannel)
223 return -1;
224
225 peerChannel->extra = data;
226 return 1;
227}
228
229static BOOL freerdp_peer_set_state(freerdp_peer* client, CONNECTION_STATE state)
230{
231 WINPR_ASSERT(client);
232 WINPR_ASSERT(client->context);
233 return rdp_server_transition_to_state(client->context->rdp, state);
234}
235
236static BOOL freerdp_peer_initialize(freerdp_peer* client)
237{
238 rdpRdp* rdp = nullptr;
239 rdpSettings* settings = nullptr;
240
241 WINPR_ASSERT(client);
242 WINPR_ASSERT(client->context);
243
244 rdp = client->context->rdp;
245 WINPR_ASSERT(rdp);
246
247 settings = rdp->settings;
248 WINPR_ASSERT(settings);
249
250 settings->ServerMode = TRUE;
251 settings->FrameAcknowledge = 0;
252 settings->LocalConnection = client->local;
253
254 const rdpCertificate* cert =
255 freerdp_settings_get_pointer(settings, FreeRDP_RdpServerCertificate);
256 if (!cert)
257 {
258 WLog_ERR(TAG, "Missing server certificate, can not continue.");
259 return FALSE;
260 }
261
262 if (freerdp_settings_get_bool(settings, FreeRDP_RdpSecurity))
263 {
264
265 if (!freerdp_certificate_is_rdp_security_compatible(cert))
266 {
267 if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
268 return FALSE;
269 if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
270 return FALSE;
271 }
272 }
273
274 nego_set_RCG_supported(rdp->nego, settings->RemoteCredentialGuard);
275 nego_set_restricted_admin_mode_supported(rdp->nego, settings->RestrictedAdminModeSupported);
276
277 return (rdp_server_transition_to_state(rdp, CONNECTION_STATE_INITIAL));
278}
279
280#if defined(WITH_FREERDP_DEPRECATED)
281static BOOL freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
282{
283 rdpTransport* transport = nullptr;
284 WINPR_ASSERT(client);
285 WINPR_ASSERT(client->context);
286 WINPR_ASSERT(client->context->rdp);
287
288 transport = client->context->rdp->transport;
289 WINPR_ASSERT(transport);
290 transport_get_fds(transport, rfds, rcount);
291 return TRUE;
292}
293#endif
294
295static HANDLE freerdp_peer_get_event_handle(freerdp_peer* client)
296{
297 HANDLE hEvent = nullptr;
298 rdpTransport* transport = nullptr;
299 WINPR_ASSERT(client);
300 WINPR_ASSERT(client->context);
301 WINPR_ASSERT(client->context->rdp);
302
303 transport = client->context->rdp->transport;
304 hEvent = transport_get_front_bio(transport);
305 return hEvent;
306}
307
308static DWORD freerdp_peer_get_event_handles(freerdp_peer* client, HANDLE* events, DWORD count)
309{
310 WINPR_ASSERT(client);
311 WINPR_ASSERT(client->context);
312 WINPR_ASSERT(client->context->rdp);
313 return transport_get_event_handles(client->context->rdp->transport, events, count);
314}
315
316static BOOL freerdp_peer_check_fds(freerdp_peer* peer)
317{
318 int status = 0;
319 rdpRdp* rdp = nullptr;
320
321 WINPR_ASSERT(peer);
322 WINPR_ASSERT(peer->context);
323
324 rdp = peer->context->rdp;
325 status = rdp_check_fds(rdp);
326
327 return (status >= 0);
328}
329
330WINPR_ATTR_NODISCARD
331static state_run_t peer_recv_data_pdu(freerdp_peer* client, wStream* s,
332 WINPR_ATTR_UNUSED UINT16 totalLength)
333{
334 BYTE type = 0;
335 UINT16 length = 0;
336 UINT32 share_id = 0;
337 BYTE compressed_type = 0;
338 UINT16 compressed_len = 0;
339 rdpUpdate* update = nullptr;
340
341 WINPR_ASSERT(s);
342 WINPR_ASSERT(client);
343 WINPR_ASSERT(client->context);
344 rdpRdp* rdp = client->context->rdp;
345 WINPR_ASSERT(rdp);
346 WINPR_ASSERT(rdp->mcs);
347
348 update = client->context->update;
349 WINPR_ASSERT(update);
350
351 if (!rdp_read_share_data_header(rdp, s, &length, &type, &share_id, &compressed_type,
352 &compressed_len))
353 return STATE_RUN_FAILED;
354
355#ifdef WITH_DEBUG_RDP
356 WLog_Print(rdp->log, WLOG_DEBUG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "",
357 data_pdu_type_to_string(type), type, length);
358#endif
359
360 switch (type)
361 {
362 case DATA_PDU_TYPE_SYNCHRONIZE:
363 if (!rdp_recv_client_synchronize_pdu(rdp, s))
364 return STATE_RUN_FAILED;
365
366 break;
367
368 case DATA_PDU_TYPE_CONTROL:
369 if (!rdp_server_accept_client_control_pdu(rdp, s))
370 return STATE_RUN_FAILED;
371
372 break;
373
374 case DATA_PDU_TYPE_INPUT:
375 if (!input_recv(rdp->input, s))
376 return STATE_RUN_FAILED;
377
378 break;
379
380 case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
381 if (!rdp_server_accept_client_persistent_key_list_pdu(rdp, s))
382 return STATE_RUN_FAILED;
383 break;
384
385 case DATA_PDU_TYPE_FONT_LIST:
386 if (!rdp_server_accept_client_font_list_pdu(rdp, s))
387 return STATE_RUN_FAILED;
388
389 return STATE_RUN_CONTINUE; // State changed, trigger rerun
390
391 case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
392 mcs_send_disconnect_provider_ultimatum(rdp->mcs,
393 Disconnect_Ultimatum_provider_initiated);
394 WLog_WARN(TAG, "disconnect provider ultimatum sent to peer, closing connection");
395 return STATE_RUN_QUIT_SESSION;
396
397 case DATA_PDU_TYPE_FRAME_ACKNOWLEDGE:
398 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
399 return STATE_RUN_FAILED;
400
401 Stream_Read_UINT32(s, client->ack_frame_id);
402 if (update->SurfaceFrameAcknowledge)
403 {
404 if (!update->SurfaceFrameAcknowledge(update->context, client->ack_frame_id))
405 return STATE_RUN_FAILED;
406 }
407 break;
408
409 case DATA_PDU_TYPE_REFRESH_RECT:
410 if (!update_read_refresh_rect(update, s))
411 return STATE_RUN_FAILED;
412
413 break;
414
415 case DATA_PDU_TYPE_SUPPRESS_OUTPUT:
416 if (!update_read_suppress_output(update, s))
417 return STATE_RUN_FAILED;
418
419 break;
420
421 default:
422 WLog_ERR(TAG, "Data PDU type %" PRIu8 "", type);
423 break;
424 }
425
426 return STATE_RUN_SUCCESS;
427}
428
429static state_run_t peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
430{
431 state_run_t rc = STATE_RUN_SUCCESS;
432 UINT16 length = 0;
433 UINT16 pduType = 0;
434 UINT16 pduSource = 0;
435 UINT16 channelId = 0;
436 UINT16 securityFlags = 0;
437
438 WINPR_ASSERT(s);
439 WINPR_ASSERT(client);
440 WINPR_ASSERT(client->context);
441
442 rdpRdp* rdp = client->context->rdp;
443 WINPR_ASSERT(rdp);
444 WINPR_ASSERT(rdp->mcs);
445
446 rdpSettings* settings = client->context->settings;
447 WINPR_ASSERT(settings);
448
449 if (!rdp_read_header(rdp, s, &length, &channelId))
450 return STATE_RUN_FAILED;
451
452 rdp->inPackets++;
453 if (freerdp_shall_disconnect_context(rdp->context))
454 return STATE_RUN_SUCCESS;
455
456 if (rdp_get_state(rdp) <= CONNECTION_STATE_LICENSING)
457 {
458 return rdp_handle_message_channel(rdp, s, channelId, length);
459 }
460
461 if (!rdp_handle_optional_rdp_decryption(rdp, s, &length, &securityFlags))
462 return STATE_RUN_FAILED;
463
464 if (channelId == MCS_GLOBAL_CHANNEL_ID)
465 {
466 char buffer[256] = WINPR_C_ARRAY_INIT;
467 UINT16 pduLength = 0;
468 UINT16 remain = 0;
469 if (!rdp_read_share_control_header(rdp, s, &pduLength, &remain, &pduType, &pduSource))
470 return STATE_RUN_FAILED;
471
472 settings->PduSource = pduSource;
473
474 WLog_DBG(TAG, "Received %s", pdu_type_to_str(pduType, buffer, sizeof(buffer)));
475 switch (pduType)
476 {
477 case PDU_TYPE_DATA:
478 rc = peer_recv_data_pdu(client, s, pduLength);
479 break;
480
481 case PDU_TYPE_CONFIRM_ACTIVE:
482 if (!rdp_server_accept_confirm_active(rdp, s, pduLength))
483 return STATE_RUN_FAILED;
484
485 break;
486
487 case PDU_TYPE_FLOW_RESPONSE:
488 case PDU_TYPE_FLOW_STOP:
489 case PDU_TYPE_FLOW_TEST:
490 if (!Stream_SafeSeek(s, remain))
491 {
492 WLog_WARN(TAG, "Short PDU, need %" PRIu16 " bytes, got %" PRIuz, remain,
493 Stream_GetRemainingLength(s));
494 return STATE_RUN_FAILED;
495 }
496 break;
497
498 default:
499 WLog_ERR(TAG, "Client sent unknown pduType %" PRIu16 "", pduType);
500 return STATE_RUN_FAILED;
501 }
502 }
503 else if ((rdp->mcs->messageChannelId > 0) && (channelId == rdp->mcs->messageChannelId))
504 {
505 if (!settings->UseRdpSecurityLayer)
506 {
507 if (!rdp_read_security_header(rdp, s, &securityFlags, nullptr))
508 return STATE_RUN_FAILED;
509 }
510
511 return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
512 }
513 else
514 {
515 if (!freerdp_channel_peer_process(client, s, channelId))
516 return STATE_RUN_FAILED;
517 }
518 if (!tpkt_ensure_stream_consumed(rdp->log, s, length))
519 return STATE_RUN_FAILED;
520
521 return rc;
522}
523
524static state_run_t peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
525{
526 state_run_t ret = STATE_RUN_FAILED;
527 rdpRdp* rdp = nullptr;
528
529 WINPR_ASSERT(client);
530 WINPR_ASSERT(s);
531 WINPR_ASSERT(client->context);
532
533 rdp = client->context->rdp;
534 WINPR_ASSERT(rdp);
535
536 const rdpSettings* settings = client->context->settings;
537 WINPR_ASSERT(settings);
538
539 if (freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
540 {
541 switch (rdp_get_state(rdp))
542 {
543 case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
544 autodetect_on_connect_time_auto_detect_begin(rdp->autodetect);
545 switch (autodetect_get_state(rdp->autodetect))
546 {
547 case FREERDP_AUTODETECT_STATE_REQUEST:
548 ret = STATE_RUN_SUCCESS;
549 if (!rdp_server_transition_to_state(
550 rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE))
551 return STATE_RUN_FAILED;
552 break;
553 case FREERDP_AUTODETECT_STATE_COMPLETE:
554 ret = STATE_RUN_CONTINUE; /* Rerun in next state */
555 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING))
556 return STATE_RUN_FAILED;
557 break;
558 default:
559 break;
560 }
561 break;
562 case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
563 ret = peer_recv_pdu(client, s);
564 if (state_run_success(ret))
565 {
566 autodetect_on_connect_time_auto_detect_progress(rdp->autodetect);
567 switch (autodetect_get_state(rdp->autodetect))
568 {
569 case FREERDP_AUTODETECT_STATE_REQUEST:
570 ret = STATE_RUN_SUCCESS;
571 break;
572 case FREERDP_AUTODETECT_STATE_COMPLETE:
573 ret = STATE_RUN_CONTINUE; /* Rerun in next state */
574 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING))
575 return STATE_RUN_FAILED;
576 break;
577 default:
578 break;
579 }
580 }
581 break;
582 default:
583 WINPR_ASSERT(FALSE);
584 break;
585 }
586 }
587 else
588 {
589 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING))
590 return STATE_RUN_FAILED;
591
592 ret = STATE_RUN_CONTINUE; /* Rerun in next state */
593 }
594
595 return ret;
596}
597
598static state_run_t peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
599{
600 state_run_t ret = STATE_RUN_FAILED;
601 rdpRdp* rdp = nullptr;
602 rdpSettings* settings = nullptr;
603
604 WINPR_ASSERT(client);
605 WINPR_ASSERT(s);
606 WINPR_ASSERT(client->context);
607
608 rdp = client->context->rdp;
609 WINPR_ASSERT(rdp);
610
611 settings = rdp->settings;
612 WINPR_ASSERT(settings);
613
614 switch (license_get_state(rdp->license))
615 {
616 case LICENSE_STATE_INITIAL:
617 {
618 const BOOL required =
619 freerdp_settings_get_bool(settings, FreeRDP_ServerLicenseRequired);
620
621 if (required)
622 {
623 if (!license_server_configure(rdp->license))
624 ret = STATE_RUN_FAILED;
625 else if (!license_server_send_request(rdp->license))
626 ret = STATE_RUN_FAILED;
627 else
628 ret = STATE_RUN_SUCCESS;
629 }
630 else
631 {
632 if (license_send_valid_client_error_packet(rdp))
633 ret = STATE_RUN_CONTINUE; /* Rerun in next state, might be capabilities */
634 }
635 }
636 break;
637 case LICENSE_STATE_COMPLETED:
638 ret = STATE_RUN_CONTINUE; /* Licensing completed, continue in next state */
639 break;
640 case LICENSE_STATE_ABORTED:
641 ret = STATE_RUN_FAILED;
642 break;
643 default:
644 ret = peer_recv_pdu(client, s);
645 break;
646 }
647
648 return ret;
649}
650
651static state_run_t peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
652{
653 rdpRdp* rdp = nullptr;
654 UINT16 length = 0;
655 BOOL rc = 0;
656 rdpFastPath* fastpath = nullptr;
657
658 WINPR_ASSERT(s);
659 WINPR_ASSERT(client);
660 WINPR_ASSERT(client->context);
661
662 rdp = client->context->rdp;
663 WINPR_ASSERT(rdp);
664
665 fastpath = rdp->fastpath;
666 WINPR_ASSERT(fastpath);
667
668 rc = fastpath_read_header_rdp(fastpath, s, &length);
669
670 if (!rc || (length == 0))
671 {
672 WLog_ERR(TAG, "incorrect FastPath PDU header length %" PRIu16 "", length);
673 return STATE_RUN_FAILED;
674 }
675 if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
676 return STATE_RUN_FAILED;
677
678 if (!fastpath_decrypt(fastpath, s, &length))
679 return STATE_RUN_FAILED;
680
681 rdp->inPackets++;
682
683 return fastpath_recv_inputs(fastpath, s);
684}
685
686state_run_t peer_recv_pdu(freerdp_peer* client, wStream* s)
687{
688 int rc = tpkt_verify_header(s);
689
690 if (rc > 0)
691 return peer_recv_tpkt_pdu(client, s);
692 else if (rc == 0)
693 return peer_recv_fastpath_pdu(client, s);
694 else
695 return STATE_RUN_FAILED;
696}
697
698static state_run_t peer_unexpected_client_message(rdpRdp* rdp, UINT32 flag)
699{
700 char buffer[1024] = WINPR_C_ARRAY_INIT;
701 WLog_WARN(TAG, "Unexpected client message in state %s, missing flag %s",
702 rdp_get_state_string(rdp), rdp_finalize_flags_to_str(flag, buffer, sizeof(buffer)));
703 return STATE_RUN_SUCCESS; /* we ignore this as per spec input PDU are already allowed */
704}
705
706state_run_t rdp_peer_handle_state_demand_active(freerdp_peer* client)
707{
708 state_run_t ret = STATE_RUN_FAILED;
709
710 WINPR_ASSERT(client);
711 WINPR_ASSERT(client->context);
712
713 rdpRdp* rdp = client->context->rdp;
714 WINPR_ASSERT(rdp);
715
716 if (client->Capabilities && !client->Capabilities(client))
717 {
718 WLog_ERR(TAG, "[%s] freerdp_peer::Capabilities() callback failed",
719 rdp_get_state_string(rdp));
720 }
721 else if (!rdp_send_demand_active(rdp))
722 {
723 WLog_ERR(TAG, "[%s] rdp_send_demand_active() fail", rdp_get_state_string(rdp));
724 }
725 else
726 {
727 if (!rdp_server_transition_to_state(rdp,
728 CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT))
729 return STATE_RUN_FAILED;
730 ret = STATE_RUN_CONTINUE;
731 }
732 return ret;
733}
734
741static state_run_t rdp_peer_handle_state_active(freerdp_peer* client)
742{
743 state_run_t ret = STATE_RUN_FAILED;
744
745 WINPR_ASSERT(client);
746 WINPR_ASSERT(client->context);
747
748 if (!client->connected)
749 {
754 IFCALLRET(client->PostConnect, client->connected, client);
755 }
756 if (!client->connected)
757 {
758 WLog_ERR(TAG, "PostConnect for peer %p failed", WINPR_CXX_COMPAT_CAST(const void*, client));
759 ret = STATE_RUN_FAILED;
760 }
761 else if (!client->activated)
762 {
763 BOOL activated = TRUE;
764
765 /* Set client->activated TRUE before calling the Activate callback.
766 * the Activate callback might reset the client->activated flag even if it returns success
767 * (e.g. deactivate/reactivate sequence) */
768 client->activated = TRUE;
769 IFCALLRET(client->Activate, activated, client);
770
771 if (!activated)
772 {
773 WLog_ERR(TAG, "Activate for peer %p failed",
774 WINPR_CXX_COMPAT_CAST(const void*, client));
775 ret = STATE_RUN_FAILED;
776 }
777 else
778 ret = STATE_RUN_SUCCESS;
779 }
780 else
781 ret = STATE_RUN_ACTIVE;
782 return ret;
783}
784
785static state_run_t peer_recv_callback_internal(WINPR_ATTR_UNUSED rdpTransport* transport,
786 wStream* s, void* extra)
787{
788 freerdp_peer* client = (freerdp_peer*)extra;
789 state_run_t ret = STATE_RUN_FAILED;
790
791 WINPR_ASSERT(transport);
792 WINPR_ASSERT(client);
793 WINPR_ASSERT(client->context);
794
795 rdpRdp* rdp = client->context->rdp;
796 WINPR_ASSERT(rdp);
797
798 rdpSettings* settings = client->context->settings;
799 WINPR_ASSERT(settings);
800
801 if (client->ReachedState)
802 {
803 if (!client->ReachedState(client, rdp_get_state(rdp)))
804 return STATE_RUN_FAILED;
805 }
806 switch (rdp_get_state(rdp))
807 {
808 case CONNECTION_STATE_INITIAL:
809 if (!freerdp_settings_enforce_consistency(settings))
810 ret = STATE_RUN_FAILED;
811 else if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO))
812 ret = STATE_RUN_CONTINUE;
813 break;
814
815 case CONNECTION_STATE_NEGO:
816 if (!rdp_server_accept_nego(rdp, s))
817 {
818 WLog_ERR(TAG, "%s - rdp_server_accept_nego() fail", rdp_get_state_string(rdp));
819 }
820 else
821 {
822 const UINT32 SelectedProtocol = nego_get_selected_protocol(rdp->nego);
823
824 settings->RdstlsSecurity = (SelectedProtocol & PROTOCOL_RDSTLS) != 0;
825 settings->NlaSecurity = (SelectedProtocol & PROTOCOL_HYBRID) != 0;
826 settings->ExtSecurity = (SelectedProtocol & PROTOCOL_HYBRID_EX) != 0;
827 settings->TlsSecurity = (SelectedProtocol & PROTOCOL_SSL) != 0;
828 settings->RdpSecurity = (SelectedProtocol == PROTOCOL_RDP) != 0;
829
830 client->authenticated = FALSE;
831 if (SelectedProtocol & PROTOCOL_HYBRID)
832 {
834 (SEC_WINNT_AUTH_IDENTITY_INFO*)nego_get_identity(rdp->nego);
835 if (sspi_CopyAuthIdentity(&client->identity, identity) >= 0)
836 {
837 client->authenticated =
838 IFCALLRESULT(TRUE, client->Logon, client, &client->identity, TRUE);
839 }
840 nego_free_nla(rdp->nego);
841 }
842 else
843 {
844 client->authenticated =
845 IFCALLRESULT(TRUE, client->Logon, client, &client->identity, FALSE);
846 }
847 if (!client->authenticated)
848 ret = STATE_RUN_FAILED;
849 else
850 {
851 if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
852 ret = STATE_RUN_SUCCESS;
853 }
854 }
855 break;
856
857 case CONNECTION_STATE_NLA:
858 WINPR_ASSERT(FALSE); // TODO
859 break;
860
861 case CONNECTION_STATE_MCS_CREATE_REQUEST:
862 if (!rdp_server_accept_mcs_connect_initial(rdp, s))
863 {
864 WLog_ERR(TAG,
865 "%s - "
866 "rdp_server_accept_mcs_connect_initial() fail",
867 rdp_get_state_string(rdp));
868 }
869 else
870 ret = STATE_RUN_SUCCESS;
871
872 break;
873
874 case CONNECTION_STATE_MCS_ERECT_DOMAIN:
875 if (!rdp_server_accept_mcs_erect_domain_request(rdp, s))
876 {
877 WLog_ERR(TAG,
878 "%s - "
879 "rdp_server_accept_mcs_erect_domain_request() fail",
880 rdp_get_state_string(rdp));
881 }
882 else
883 ret = STATE_RUN_SUCCESS;
884
885 break;
886
887 case CONNECTION_STATE_MCS_ATTACH_USER:
888 if (!rdp_server_accept_mcs_attach_user_request(rdp, s))
889 {
890 WLog_ERR(TAG,
891 "%s - "
892 "rdp_server_accept_mcs_attach_user_request() fail",
893 rdp_get_state_string(rdp));
894 }
895 else
896 ret = STATE_RUN_SUCCESS;
897
898 break;
899
900 case CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST:
901 if (!rdp_server_accept_mcs_channel_join_request(rdp, s))
902 {
903 WLog_ERR(TAG,
904 "%s - "
905 "rdp_server_accept_mcs_channel_join_request() fail",
906 rdp_get_state_string(rdp));
907 }
908 else
909 ret = STATE_RUN_SUCCESS;
910 break;
911
912 case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
913 ret = STATE_RUN_SUCCESS;
914
915 if (!rdp_server_establish_keys(rdp, s))
916 {
917 WLog_ERR(TAG,
918 "%s - "
919 "rdp_server_establish_keys() fail",
920 rdp_get_state_string(rdp));
921 ret = STATE_RUN_FAILED;
922 }
923
924 if (state_run_success(ret))
925 {
926 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE))
927 ret = STATE_RUN_FAILED;
928 else if (Stream_GetRemainingLength(s) > 0)
929 ret = STATE_RUN_CONTINUE; /* Rerun function */
930 }
931 break;
932
933 case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
934 if (rdp_recv_client_info(rdp, s))
935 {
936 if (rdp_server_transition_to_state(
937 rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST))
938 ret = STATE_RUN_CONTINUE;
939 }
940 break;
941
942 case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
943 case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
944 ret = peer_recv_handle_auto_detect(client, s);
945 break;
946
947 case CONNECTION_STATE_LICENSING:
948 ret = peer_recv_handle_licensing(client, s);
949 if (ret == STATE_RUN_CONTINUE)
950 {
951 if (!rdp_server_transition_to_state(
952 rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST))
953 ret = STATE_RUN_FAILED;
954 }
955 break;
956
957 case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST:
958 if (settings->SupportMultitransport &&
959 ((settings->MultitransportFlags & INITIATE_REQUEST_PROTOCOL_UDPFECR) != 0))
960 {
961 /* only UDP reliable for now, nobody does lossy UDP (MS-RDPUDP only) these days */
962 ret = multitransport_server_request(rdp->multitransport,
963 INITIATE_REQUEST_PROTOCOL_UDPFECR);
964 switch (ret)
965 {
966 case STATE_RUN_SUCCESS:
967 if (!rdp_server_transition_to_state(
968 rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE))
969 ret = STATE_RUN_FAILED;
970 break;
971 case STATE_RUN_CONTINUE:
972 /* mismatch on the supported kind of UDP transports */
973 if (!rdp_server_transition_to_state(
974 rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE))
975 ret = STATE_RUN_FAILED;
976 break;
977 default:
978 break;
979 }
980 }
981 else
982 {
983 if (rdp_server_transition_to_state(
984 rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE))
985 ret = STATE_RUN_CONTINUE; /* Rerun, initialize next state */
986 }
987 break;
988 case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE:
989 ret = peer_recv_pdu(client, s);
990 break;
991
992 case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
993 ret = rdp_peer_handle_state_demand_active(client);
994 break;
995
996 case CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT:
997 if (freerdp_settings_get_bool(settings, FreeRDP_SupportMonitorLayoutPdu))
998 {
999 MONITOR_DEF* monitors = nullptr;
1000
1001 if (client->AdjustMonitorsLayout)
1002 {
1003 if (!client->AdjustMonitorsLayout(client))
1004 return STATE_RUN_FAILED;
1005 }
1006
1007 /* client supports the monitorLayout PDU, let's send him the monitors if any */
1008 ret = STATE_RUN_SUCCESS;
1009 if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) == 0)
1010 {
1011 const UINT32 w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1012 const UINT32 h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1013 const rdpMonitor primary = { .x = 0,
1014 .y = 0,
1015 .width = WINPR_ASSERTING_INT_CAST(int32_t, w),
1016 .height = WINPR_ASSERTING_INT_CAST(int32_t, h),
1017 .is_primary = TRUE,
1018 .orig_screen = 0,
1019 .attributes = { .physicalWidth = w,
1020 .physicalHeight = h,
1021 .orientation =
1022 ORIENTATION_LANDSCAPE,
1023 .desktopScaleFactor = 100,
1024 .deviceScaleFactor = 100 } };
1025 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorDefArray, 0,
1026 &primary))
1027 ret = STATE_RUN_FAILED;
1028 else if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1))
1029 ret = STATE_RUN_FAILED;
1030 }
1031 if (state_run_failed(ret))
1032 {
1033 }
1034 else if (!display_convert_rdp_monitor_to_monitor_def(
1035 settings->MonitorCount, settings->MonitorDefArray, &monitors))
1036 {
1037 ret = STATE_RUN_FAILED;
1038 }
1039 else if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount,
1040 monitors))
1041 {
1042 ret = STATE_RUN_FAILED;
1043 }
1044 else
1045 ret = STATE_RUN_SUCCESS;
1046 free(monitors);
1047
1048 const size_t len = Stream_GetRemainingLength(s);
1049 if (!state_run_failed(ret) && (len > 0))
1050 ret = STATE_RUN_CONTINUE;
1051 }
1052 else
1053 {
1054 const size_t len = Stream_GetRemainingLength(s);
1055 if (len > 0)
1056 ret = STATE_RUN_CONTINUE;
1057 else
1058 ret = STATE_RUN_SUCCESS;
1059 }
1060 if (state_run_success(ret))
1061 {
1062 if (!rdp_server_transition_to_state(
1063 rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE))
1064 ret = STATE_RUN_FAILED;
1065 }
1066 break;
1067
1068 case CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE:
1073 ret = peer_recv_pdu(client, s);
1074 break;
1075
1076 case CONNECTION_STATE_FINALIZATION_SYNC:
1077 ret = peer_recv_pdu(client, s);
1078 if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
1079 {
1080 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_COOPERATE))
1081 ret = STATE_RUN_FAILED;
1082 }
1083 else
1084 ret = peer_unexpected_client_message(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
1085 break;
1086 case CONNECTION_STATE_FINALIZATION_COOPERATE:
1087 ret = peer_recv_pdu(client, s);
1088 if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
1089 {
1090 if (!rdp_server_transition_to_state(rdp,
1091 CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL))
1092 ret = STATE_RUN_FAILED;
1093 }
1094 else
1095 ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
1096 break;
1097 case CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL:
1098 ret = peer_recv_pdu(client, s);
1099 if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU))
1100 {
1101 if (!rdp_send_server_control_granted_pdu(rdp))
1102 ret = STATE_RUN_FAILED;
1103 else if (!rdp_server_transition_to_state(
1104 rdp, CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST))
1105 ret = STATE_RUN_FAILED;
1106 }
1107 else
1108 ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
1109 break;
1110 case CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST:
1111 if (freerdp_settings_get_bool(settings, FreeRDP_BitmapCachePersistEnabled) &&
1112 !rdp_finalize_is_flag_set(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
1113 {
1114 ret = peer_recv_pdu(client, s);
1115
1116 if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU))
1117 {
1118 if (!rdp_server_transition_to_state(rdp,
1119 CONNECTION_STATE_FINALIZATION_FONT_LIST))
1120 ret = STATE_RUN_FAILED;
1121 }
1122 else
1123 ret = peer_unexpected_client_message(rdp,
1124 CONNECTION_STATE_FINALIZATION_FONT_LIST);
1125 }
1126 else
1127 {
1128 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_FONT_LIST))
1129 ret = STATE_RUN_FAILED;
1130 else
1131 ret = STATE_RUN_CONTINUE;
1132 }
1133 break;
1134 case CONNECTION_STATE_FINALIZATION_FONT_LIST:
1135 ret = peer_recv_pdu(client, s);
1136 if (state_run_success(ret))
1137 {
1138 if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_FONT_LIST_PDU))
1139 {
1140 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
1141 ret = STATE_RUN_FAILED;
1142 else
1143 {
1144 update_reset_state(rdp->update);
1145 ret = STATE_RUN_CONTINUE;
1146 }
1147 }
1148 else
1149 ret = peer_unexpected_client_message(rdp, FINALIZE_CS_FONT_LIST_PDU);
1150 }
1151 break;
1152
1153 case CONNECTION_STATE_ACTIVE:
1154 ret = rdp_peer_handle_state_active(client);
1155 if (ret >= STATE_RUN_ACTIVE)
1156 ret = peer_recv_pdu(client, s);
1157 break;
1158
1159 /* States that must not happen in server state machine */
1160 case CONNECTION_STATE_FINALIZATION_CLIENT_SYNC:
1161 case CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE:
1162 case CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL:
1163 case CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP:
1164 default:
1165 WLog_ERR(TAG, "%s state %" PRId32, rdp_get_state_string(rdp),
1166 WINPR_CXX_COMPAT_CAST(int32_t, rdp_get_state(rdp)));
1167 break;
1168 }
1169
1170 return ret;
1171}
1172
1173static state_run_t peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
1174{
1175 char buffer[64] = WINPR_C_ARRAY_INIT;
1176 state_run_t rc = STATE_RUN_FAILED;
1177 const size_t start = Stream_GetPosition(s);
1178 const rdpContext* context = transport_get_context(transport);
1179 DWORD level = WLOG_TRACE;
1180 static wLog* log = nullptr;
1181 if (!log)
1182 log = WLog_Get(TAG);
1183
1184 WINPR_ASSERT(context);
1185 do
1186 {
1187 const rdpRdp* rdp = context->rdp;
1188 const char* old = rdp_get_state_string(rdp);
1189
1190 if (rc == STATE_RUN_TRY_AGAIN)
1191 {
1192 if (!Stream_SetPosition(s, start))
1193 return STATE_RUN_FAILED;
1194 }
1195 rc = peer_recv_callback_internal(transport, s, extra);
1196
1197 const size_t len = Stream_GetRemainingLength(s);
1198 if ((len > 0) && !state_run_continue(rc))
1199 level = WLOG_WARN;
1200 WLog_Print(log, level,
1201 "(server)[%s -> %s] current return %s [%" PRIuz " bytes not processed]", old,
1202 rdp_get_state_string(rdp), state_run_result_string(rc, buffer, sizeof(buffer)),
1203 len);
1204 } while (state_run_continue(rc));
1205
1206 return rc;
1207}
1208
1209static BOOL freerdp_peer_close(freerdp_peer* client)
1210{
1211 UINT32 SelectedProtocol = 0;
1212 rdpContext* context = nullptr;
1213
1214 WINPR_ASSERT(client);
1215
1216 context = client->context;
1217 WINPR_ASSERT(context);
1218 WINPR_ASSERT(context->settings);
1219 WINPR_ASSERT(context->rdp);
1220
1224 SelectedProtocol = nego_get_selected_protocol(context->rdp->nego);
1225
1226 if (SelectedProtocol & PROTOCOL_FAILED_NEGO)
1227 return TRUE;
1228
1237 if (rdp_get_state(context->rdp) < CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM)
1238 return TRUE;
1239
1245 if (!rdp_send_deactivate_all(context->rdp))
1246 return FALSE;
1247
1248 if (freerdp_settings_get_bool(context->settings, FreeRDP_SupportErrorInfoPdu))
1249 {
1250 if (!rdp_send_error_info(context->rdp))
1251 return FALSE;
1252 }
1253
1254 return mcs_send_disconnect_provider_ultimatum(context->rdp->mcs,
1255 Disconnect_Ultimatum_provider_initiated);
1256}
1257
1258static void freerdp_peer_disconnect(freerdp_peer* client)
1259{
1260 rdpTransport* transport = nullptr;
1261 WINPR_ASSERT(client);
1262
1263 transport = freerdp_get_transport(client->context);
1264 transport_disconnect(transport);
1265}
1266
1267static BOOL freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelId, const BYTE* data,
1268 size_t size)
1269{
1270 WINPR_ASSERT(client);
1271 WINPR_ASSERT(client->context);
1272 WINPR_ASSERT(client->context->rdp);
1273 return rdp_send_channel_data(client->context->rdp, channelId, data, size);
1274}
1275
1276static BOOL freerdp_peer_send_server_redirection_pdu(freerdp_peer* peer,
1277 const rdpRedirection* redirection)
1278{
1279 BOOL rc = FALSE;
1280 WINPR_ASSERT(peer);
1281 WINPR_ASSERT(peer->context);
1282
1283 UINT16 sec_flags = 0;
1284 wStream* s = rdp_send_stream_pdu_init(peer->context->rdp, &sec_flags);
1285 if (!s)
1286 return FALSE;
1287 if (!rdp_write_enhanced_security_redirection_packet(s, redirection))
1288 goto fail;
1289 if (!rdp_send_pdu(peer->context->rdp, s, PDU_TYPE_SERVER_REDIRECTION, 0, sec_flags))
1290 goto fail;
1291 rc = rdp_reset_runtime_settings(peer->context->rdp);
1292fail:
1293 Stream_Release(s);
1294 return rc;
1295}
1296
1297static BOOL freerdp_peer_send_channel_packet(freerdp_peer* client, UINT16 channelId,
1298 size_t totalSize, UINT32 flags, const BYTE* data,
1299 size_t chunkSize)
1300{
1301 WINPR_ASSERT(client);
1302 WINPR_ASSERT(client->context);
1303 WINPR_ASSERT(client->context->rdp);
1304 return rdp_channel_send_packet(client->context->rdp, channelId, totalSize, flags, data,
1305 chunkSize);
1306}
1307
1308static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
1309{
1310 rdpTransport* transport = nullptr;
1311 WINPR_ASSERT(peer);
1312 WINPR_ASSERT(peer->context);
1313 WINPR_ASSERT(peer->context->rdp);
1314 WINPR_ASSERT(peer->context->rdp->transport);
1315 transport = peer->context->rdp->transport;
1316 return transport_is_write_blocked(transport);
1317}
1318
1319static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
1320{
1321 rdpTransport* transport = nullptr;
1322 WINPR_ASSERT(peer);
1323 WINPR_ASSERT(peer->context);
1324 WINPR_ASSERT(peer->context->rdp);
1325 WINPR_ASSERT(peer->context->rdp->transport);
1326 transport = peer->context->rdp->transport;
1327 return transport_drain_output_buffer(transport);
1328}
1329
1330static BOOL freerdp_peer_has_more_to_read(freerdp_peer* peer)
1331{
1332 WINPR_ASSERT(peer);
1333 WINPR_ASSERT(peer->context);
1334 WINPR_ASSERT(peer->context->rdp);
1335 return transport_have_more_bytes_to_read(peer->context->rdp->transport);
1336}
1337
1338static LicenseCallbackResult freerdp_peer_nolicense(freerdp_peer* peer,
1339 WINPR_ATTR_UNUSED wStream* s)
1340{
1341 rdpRdp* rdp = nullptr;
1342
1343 WINPR_ASSERT(peer);
1344 WINPR_ASSERT(peer->context);
1345
1346 rdp = peer->context->rdp;
1347
1348 if (!license_send_valid_client_error_packet(rdp))
1349 {
1350 WLog_ERR(TAG, "freerdp_peer_nolicense: license_send_valid_client_error_packet() failed");
1351 return LICENSE_CB_ABORT;
1352 }
1353
1354 return LICENSE_CB_COMPLETED;
1355}
1356
1357BOOL freerdp_peer_context_new(freerdp_peer* client)
1358{
1359 return freerdp_peer_context_new_ex(client, nullptr);
1360}
1361
1362void freerdp_peer_context_free(freerdp_peer* client)
1363{
1364 if (!client)
1365 return;
1366
1367 IFCALL(client->ContextFree, client, client->context);
1368
1369 if (client->context)
1370 {
1371 rdpContext* ctx = client->context;
1372
1373 (void)CloseHandle(ctx->channelErrorEvent);
1374 ctx->channelErrorEvent = nullptr;
1375 free(ctx->errorDescription);
1376 ctx->errorDescription = nullptr;
1377 rdp_free(ctx->rdp);
1378 ctx->rdp = nullptr;
1379 metrics_free(ctx->metrics);
1380 ctx->metrics = nullptr;
1381 stream_dump_free(ctx->dump);
1382 ctx->dump = nullptr;
1383 free(ctx);
1384 }
1385 client->context = nullptr;
1386}
1387
1388static const char* os_major_type_to_string(UINT16 osMajorType)
1389{
1390 switch (osMajorType)
1391 {
1392 case OSMAJORTYPE_UNSPECIFIED:
1393 return "Unspecified platform";
1394 case OSMAJORTYPE_WINDOWS:
1395 return "Windows platform";
1396 case OSMAJORTYPE_OS2:
1397 return "OS/2 platform";
1398 case OSMAJORTYPE_MACINTOSH:
1399 return "Macintosh platform";
1400 case OSMAJORTYPE_UNIX:
1401 return "UNIX platform";
1402 case OSMAJORTYPE_IOS:
1403 return "iOS platform";
1404 case OSMAJORTYPE_OSX:
1405 return "OS X platform";
1406 case OSMAJORTYPE_ANDROID:
1407 return "Android platform";
1408 case OSMAJORTYPE_CHROME_OS:
1409 return "Chrome OS platform";
1410 default:
1411 break;
1412 }
1413
1414 return "Unknown platform";
1415}
1416
1417const char* freerdp_peer_os_major_type_string(freerdp_peer* client)
1418{
1419 WINPR_ASSERT(client);
1420
1421 rdpContext* context = client->context;
1422 WINPR_ASSERT(context);
1423 WINPR_ASSERT(context->settings);
1424
1425 const UINT32 osMajorType = freerdp_settings_get_uint32(context->settings, FreeRDP_OsMajorType);
1426 WINPR_ASSERT(osMajorType <= UINT16_MAX);
1427 return os_major_type_to_string((UINT16)osMajorType);
1428}
1429
1430static const char* os_minor_type_to_string(UINT16 osMinorType)
1431{
1432 switch (osMinorType)
1433 {
1434 case OSMINORTYPE_UNSPECIFIED:
1435 return "Unspecified version";
1436 case OSMINORTYPE_WINDOWS_31X:
1437 return "Windows 3.1x";
1438 case OSMINORTYPE_WINDOWS_95:
1439 return "Windows 95";
1440 case OSMINORTYPE_WINDOWS_NT:
1441 return "Windows NT";
1442 case OSMINORTYPE_OS2_V21:
1443 return "OS/2 2.1";
1444 case OSMINORTYPE_POWER_PC:
1445 return "PowerPC";
1446 case OSMINORTYPE_MACINTOSH:
1447 return "Macintosh";
1448 case OSMINORTYPE_NATIVE_XSERVER:
1449 return "Native X Server";
1450 case OSMINORTYPE_PSEUDO_XSERVER:
1451 return "Pseudo X Server";
1452 case OSMINORTYPE_WINDOWS_RT:
1453 return "Windows RT";
1454 default:
1455 break;
1456 }
1457
1458 return "Unknown version";
1459}
1460
1461const char* freerdp_peer_os_minor_type_string(freerdp_peer* client)
1462{
1463 WINPR_ASSERT(client);
1464
1465 rdpContext* context = client->context;
1466 WINPR_ASSERT(context);
1467 WINPR_ASSERT(context->settings);
1468
1469 const UINT32 osMinorType = freerdp_settings_get_uint32(context->settings, FreeRDP_OsMinorType);
1470 WINPR_ASSERT(osMinorType <= UINT16_MAX);
1471 return os_minor_type_to_string((UINT16)osMinorType);
1472}
1473
1474freerdp_peer* freerdp_peer_new(int sockfd)
1475{
1476 freerdp_peer* client = (freerdp_peer*)calloc(1, sizeof(freerdp_peer));
1477
1478 if (!client)
1479 return nullptr;
1480
1481 if (sockfd >= 0)
1482 {
1483 (void)freerdp_tcp_set_nodelay(WLog_Get(TAG), WLOG_DEBUG, sockfd);
1484 }
1485
1486 client->sockfd = sockfd;
1487 client->ContextSize = sizeof(rdpContext);
1488 client->Initialize = freerdp_peer_initialize;
1489#if defined(WITH_FREERDP_DEPRECATED)
1490 client->GetFileDescriptor = freerdp_peer_get_fds;
1491#endif
1492 client->GetEventHandle = freerdp_peer_get_event_handle;
1493 client->GetEventHandles = freerdp_peer_get_event_handles;
1494 client->CheckFileDescriptor = freerdp_peer_check_fds;
1495 client->Close = freerdp_peer_close;
1496 client->Disconnect = freerdp_peer_disconnect;
1497 client->SendChannelData = freerdp_peer_send_channel_data;
1498 client->SendChannelPacket = freerdp_peer_send_channel_packet;
1499 client->SendServerRedirection = freerdp_peer_send_server_redirection_pdu;
1500 client->IsWriteBlocked = freerdp_peer_is_write_blocked;
1501 client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
1502 client->HasMoreToRead = freerdp_peer_has_more_to_read;
1503 client->VirtualChannelOpen = freerdp_peer_virtual_channel_open;
1504 client->VirtualChannelClose = freerdp_peer_virtual_channel_close;
1505 client->VirtualChannelWrite = freerdp_peer_virtual_channel_write;
1506 client->VirtualChannelRead = nullptr; /* must be defined by server application */
1507 client->VirtualChannelGetData = freerdp_peer_virtual_channel_get_data;
1508 client->VirtualChannelSetData = freerdp_peer_virtual_channel_set_data;
1509 client->SetState = freerdp_peer_set_state;
1510
1511 return client;
1512}
1513
1514void freerdp_peer_free(freerdp_peer* client)
1515{
1516 if (!client)
1517 return;
1518
1519 sspi_FreeAuthIdentity(&client->identity);
1520 if (client->sockfd >= 0)
1521 closesocket((SOCKET)client->sockfd);
1522 free(client);
1523}
1524
1525static BOOL freerdp_peer_transport_setup(freerdp_peer* client)
1526{
1527 rdpRdp* rdp = nullptr;
1528
1529 WINPR_ASSERT(client);
1530 WINPR_ASSERT(client->context);
1531
1532 rdp = client->context->rdp;
1533 WINPR_ASSERT(rdp);
1534
1535 if (!transport_attach(rdp->transport, client->sockfd))
1536 return FALSE;
1537 client->sockfd = -1;
1538
1539 if (!transport_set_recv_callbacks(rdp->transport, peer_recv_callback, client))
1540 return FALSE;
1541
1542 if (!transport_set_blocking_mode(rdp->transport, FALSE))
1543 return FALSE;
1544
1545 return TRUE;
1546}
1547
1548BOOL freerdp_peer_context_new_ex(freerdp_peer* client, const rdpSettings* settings)
1549{
1550 rdpRdp* rdp = nullptr;
1551 rdpContext* context = nullptr;
1552 BOOL ret = TRUE;
1553
1554 if (!client)
1555 return FALSE;
1556
1557 WINPR_ASSERT(client->ContextSize >= sizeof(rdpContext));
1558 if (!(context = (rdpContext*)calloc(1, client->ContextSize)))
1559 goto fail;
1560
1561 client->context = context;
1562 context->peer = client;
1563 context->ServerMode = TRUE;
1564 context->log = WLog_Get(TAG);
1565 if (!context->log)
1566 goto fail;
1567
1568 if (settings)
1569 {
1570 context->settings = freerdp_settings_clone(settings);
1571 if (!context->settings)
1572 goto fail;
1573 }
1574
1575 context->dump = stream_dump_new();
1576 if (!context->dump)
1577 goto fail;
1578 if (!(context->metrics = metrics_new(context)))
1579 goto fail;
1580
1581 if (!(rdp = rdp_new(context)))
1582 goto fail;
1583
1584 rdp_log_build_warnings(rdp);
1585
1586#if defined(WITH_FREERDP_DEPRECATED)
1587 client->update = rdp->update;
1588 client->settings = rdp->settings;
1589 client->autodetect = rdp->autodetect;
1590#endif
1591 context->rdp = rdp;
1592 context->input = rdp->input;
1593 context->update = rdp->update;
1594 context->settings = rdp->settings;
1595 context->autodetect = rdp->autodetect;
1596 update_register_server_callbacks(rdp->update);
1597 autodetect_register_server_callbacks(rdp->autodetect);
1598
1599 if (!(context->channelErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
1600 {
1601 WLog_ERR(TAG, "CreateEvent failed!");
1602 goto fail;
1603 }
1604
1605 if (!(context->errorDescription = calloc(1, 500)))
1606 {
1607 WLog_ERR(TAG, "calloc failed!");
1608 goto fail;
1609 }
1610
1611 if (!freerdp_peer_transport_setup(client))
1612 goto fail;
1613
1614 client->IsWriteBlocked = freerdp_peer_is_write_blocked;
1615 client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
1616 client->HasMoreToRead = freerdp_peer_has_more_to_read;
1617 client->LicenseCallback = freerdp_peer_nolicense;
1618 IFCALLRET(client->ContextNew, ret, client, client->context);
1619
1620 if (!ret)
1621 goto fail;
1622 return TRUE;
1623
1624fail:
1625 WLog_ERR(TAG, "ContextNew callback failed");
1626 freerdp_peer_context_free(client);
1627 return FALSE;
1628}
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 rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.