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