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