FreeRDP
Loading...
Searching...
No Matches
utils.c
1
21#include <freerdp/config.h>
22
23#include "settings.h"
24
25#include <winpr/assert.h>
26
27#include <freerdp/freerdp.h>
28#include <freerdp/channels/cliprdr.h>
29#include <freerdp/channels/rdpdr.h>
30
31#include <freerdp/log.h>
32#define TAG FREERDP_TAG("core.gateway.utils")
33
34#include "utils.h"
35
36#if !defined(_WIN32)
37#include <sys/stat.h>
38#endif
39
40#include "../core/rdp.h"
41#include "../core/proxy.h"
42
43BOOL utils_str_copy(const char* value, char** dst)
44{
45 WINPR_ASSERT(dst);
46
47 free(*dst);
48 *dst = nullptr;
49 if (!value)
50 return TRUE;
51
52 (*dst) = _strdup(value);
53 return (*dst) != nullptr;
54}
55
56WINPR_ATTR_NODISCARD
57static BOOL utils_copy_smartcard_settings(const rdpSettings* settings, rdpSettings* origSettings)
58{
59 /* update original settings with provided smart card settings */
60 origSettings->SmartcardLogon = settings->SmartcardLogon;
61 origSettings->PasswordIsSmartcardPin = settings->PasswordIsSmartcardPin;
62 if (!utils_str_copy(settings->ReaderName, &origSettings->ReaderName))
63 return FALSE;
64 if (!utils_str_copy(settings->CspName, &origSettings->CspName))
65 return FALSE;
66 if (!utils_str_copy(settings->ContainerName, &origSettings->ContainerName))
67 return FALSE;
68
69 return TRUE;
70}
71
72WINPR_ATTR_NODISCARD
73static BOOL utils_auth_skip(freerdp* instance, rdp_auth_reason reason, BOOL gateway)
74{
75 WINPR_ASSERT(instance);
76 WINPR_ASSERT(instance->context);
77
78 const char* password = freerdp_settings_get_string(
79 instance->context->settings, gateway ? FreeRDP_GatewayPassword : FreeRDP_Password);
80 const char* username = freerdp_settings_get_string(
81 instance->context->settings, gateway ? FreeRDP_GatewayUsername : FreeRDP_Username);
82
83 switch (reason)
84 {
85 case AUTH_TLS:
86 case AUTH_RDP:
87 case AUTH_SMARTCARD_PIN: /* in this case password is pin code */
88 case AUTH_FIDO_PIN:
89 if (username && password)
90 return TRUE;
91 break;
92 default:
93 break;
94 }
95
96 return FALSE;
97}
98
99auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason)
100{
101 rdpSettings* settings = nullptr;
102 rdpSettings* origSettings = nullptr;
103 BOOL prompt = FALSE;
104 BOOL proceed = 0;
105
106 WINPR_ASSERT(instance);
107 WINPR_ASSERT(instance->context);
108 WINPR_ASSERT(instance->context->settings);
109 WINPR_ASSERT(instance->context->rdp);
110 WINPR_ASSERT(instance->context->rdp->originalSettings);
111
112 settings = instance->context->settings;
113 origSettings = instance->context->rdp->originalSettings;
114
115 if (freerdp_shall_disconnect_context(instance->context))
116 return AUTH_FAILED;
117
118 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayPassword)))
119 prompt = TRUE;
120 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayUsername)))
121 prompt = TRUE;
122
123 if (!prompt)
124 {
125 if (!utils_sync_credentials(settings, FALSE))
126 return AUTH_FAILED;
127 return AUTH_SKIP;
128 }
129 const BOOL skip = utils_auth_skip(instance, reason, TRUE);
130 if (skip)
131 return AUTH_SKIP;
132
133#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
134 WINPR_PRAGMA_DIAG_PUSH
135 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
136#endif
137
138#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
139 if (!instance->AuthenticateEx)
140 return AUTH_NO_CREDENTIALS;
141#else
142 if (!instance->GatewayAuthenticate && !instance->AuthenticateEx)
143 return AUTH_NO_CREDENTIALS;
144
145 if (!instance->GatewayAuthenticate)
146#endif
147 {
148 proceed =
149 instance->AuthenticateEx(instance, &settings->GatewayUsername,
150 &settings->GatewayPassword, &settings->GatewayDomain, reason);
151 if (!proceed)
152 return AUTH_CANCELLED;
153 }
154#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
155 else
156 {
157 proceed =
158 instance->GatewayAuthenticate(instance, &settings->GatewayUsername,
159 &settings->GatewayPassword, &settings->GatewayDomain);
160 if (!proceed)
161 return AUTH_CANCELLED;
162 }
163#endif
164
165#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
166 WINPR_PRAGMA_DIAG_POP
167#endif
168
169 if (utils_str_is_empty(settings->GatewayUsername) ||
170 utils_str_is_empty(settings->GatewayPassword))
171 return AUTH_NO_CREDENTIALS;
172
173 if (!utils_sync_credentials(settings, FALSE))
174 return AUTH_FAILED;
175
176 /* update original settings with provided user credentials */
177 if (!utils_str_copy(settings->GatewayUsername, &origSettings->GatewayUsername))
178 return AUTH_FAILED;
179 if (!utils_str_copy(settings->GatewayDomain, &origSettings->GatewayDomain))
180 return AUTH_FAILED;
181 if (!utils_str_copy(settings->GatewayPassword, &origSettings->GatewayPassword))
182 return AUTH_FAILED;
183 if (!utils_sync_credentials(origSettings, FALSE))
184 return AUTH_FAILED;
185
186 if (!utils_copy_smartcard_settings(settings, origSettings))
187 return AUTH_FAILED;
188
189 return AUTH_SUCCESS;
190}
191
192auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL override)
193{
194 rdpSettings* settings = nullptr;
195 rdpSettings* origSettings = nullptr;
196 BOOL prompt = !override;
197 BOOL proceed = 0;
198
199 WINPR_ASSERT(instance);
200 WINPR_ASSERT(instance->context);
201 WINPR_ASSERT(instance->context->settings);
202 WINPR_ASSERT(instance->context->rdp);
203 WINPR_ASSERT(instance->context->rdp->originalSettings);
204
205 settings = instance->context->settings;
206 origSettings = instance->context->rdp->originalSettings;
207
208 if (freerdp_shall_disconnect_context(instance->context))
209 return AUTH_FAILED;
210
211 if (settings->ConnectChildSession)
212 return AUTH_NO_CREDENTIALS;
213
214 /* Ask for auth data if no or an empty username was specified or no password was given */
215 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_Username)) ||
216 (settings->Password == nullptr && settings->RedirectionPassword == nullptr))
217 prompt = TRUE;
218
219 const BOOL skip = utils_auth_skip(instance, reason, FALSE);
220 if (!prompt || skip)
221 return AUTH_SKIP;
222
223 switch (reason)
224 {
225 case AUTH_RDP:
226 case AUTH_TLS:
227 if (settings->SmartcardLogon)
228 {
229 if (!utils_str_is_empty(settings->Password))
230 {
231 WLog_INFO(TAG, "Authentication via smartcard");
232 return AUTH_SUCCESS;
233 }
234 reason = AUTH_SMARTCARD_PIN;
235 }
236 break;
237 case AUTH_NLA:
238 if (settings->SmartcardLogon)
239 reason = AUTH_SMARTCARD_PIN;
240 break;
241 case AUTH_RDSTLS:
242 default:
243 break;
244 }
245
246#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
247 WINPR_PRAGMA_DIAG_PUSH
248 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
249#endif
250
251 /* If no callback is specified still continue connection */
252#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
253 if (!instance->AuthenticateEx)
254 return AUTH_NO_CREDENTIALS;
255#else
256 if (!instance->Authenticate && !instance->AuthenticateEx)
257 return AUTH_NO_CREDENTIALS;
258 if (!instance->Authenticate)
259#endif
260 {
261 proceed = instance->AuthenticateEx(instance, &settings->Username, &settings->Password,
262 &settings->Domain, reason);
263 if (!proceed)
264 return AUTH_CANCELLED;
265 }
266#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
267 else
268 {
269 proceed = instance->Authenticate(instance, &settings->Username, &settings->Password,
270 &settings->Domain);
271 if (!proceed)
272 return AUTH_NO_CREDENTIALS;
273 }
274#endif
275
276#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
277 WINPR_PRAGMA_DIAG_POP
278#endif
279
280 if (utils_str_is_empty(settings->Username) || utils_str_is_empty(settings->Password))
281 return AUTH_NO_CREDENTIALS;
282
283 if (!utils_sync_credentials(settings, TRUE))
284 return AUTH_FAILED;
285
286 /* update original settings with provided user credentials */
287 if (!utils_str_copy(settings->Username, &origSettings->Username))
288 return AUTH_FAILED;
289 if (!utils_str_copy(settings->Domain, &origSettings->Domain))
290 return AUTH_FAILED;
291 if (!utils_str_copy(settings->Password, &origSettings->Password))
292 return AUTH_FAILED;
293 if (!utils_sync_credentials(origSettings, TRUE))
294 return AUTH_FAILED;
295
296 if (!utils_copy_smartcard_settings(settings, origSettings))
297 return AUTH_FAILED;
298
299 return AUTH_SUCCESS;
300}
301
302BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway)
303{
304 WINPR_ASSERT(settings);
305 if (!settings->GatewayUseSameCredentials)
306 return TRUE;
307
308 if (toGateway)
309 {
310 if (!utils_str_copy(settings->Username, &settings->GatewayUsername))
311 return FALSE;
312 if (!utils_str_copy(settings->Domain, &settings->GatewayDomain))
313 return FALSE;
314 if (!utils_str_copy(settings->Password, &settings->GatewayPassword))
315 return FALSE;
316 }
317 else
318 {
319 if (!utils_str_copy(settings->GatewayUsername, &settings->Username))
320 return FALSE;
321 if (!utils_str_copy(settings->GatewayDomain, &settings->Domain))
322 return FALSE;
323 if (!utils_str_copy(settings->GatewayPassword, &settings->Password))
324 return FALSE;
325 }
326 return TRUE;
327}
328
329BOOL utils_persist_credentials(rdpSettings* settings, const rdpSettings* current)
330{
331 if (!settings || !current)
332 return FALSE;
333
334 const SSIZE_T keys[] = { FreeRDP_GatewayUsername, FreeRDP_GatewayDomain,
335 FreeRDP_GatewayPassword, FreeRDP_Username,
336 FreeRDP_Domain, FreeRDP_Password };
337
338 for (size_t x = 0; x < ARRAYSIZE(keys); x++)
339 {
340 const SSIZE_T key = keys[x];
341 if (!freerdp_settings_copy_item(settings, current, key))
342 {
343 WLog_ERR(TAG, "Failed to copy %s from current to backup settings",
345 return FALSE;
346 }
347 }
348
349 return TRUE;
350}
351
352BOOL utils_str_is_empty(const char* str)
353{
354 if (!str)
355 return TRUE;
356 if (*str == '\0')
357 return TRUE;
358 return FALSE;
359}
360
361BOOL utils_abort_connect(rdpRdp* rdp)
362{
363 if (!rdp)
364 return FALSE;
365
366 return SetEvent(rdp->abortEvent);
367}
368
369BOOL utils_reset_abort(rdpRdp* rdp)
370{
371 WINPR_ASSERT(rdp);
372
373 return ResetEvent(rdp->abortEvent);
374}
375
376HANDLE utils_get_abort_event(rdpRdp* rdp)
377{
378 WINPR_ASSERT(rdp);
379 return rdp->abortEvent;
380}
381
382BOOL utils_abort_event_is_set(const rdpRdp* rdp)
383{
384 DWORD status = 0;
385 WINPR_ASSERT(rdp);
386 status = WaitForSingleObject(rdp->abortEvent, 0);
387 return status == WAIT_OBJECT_0;
388}
389
390const char* utils_is_vsock(const char* hostname)
391{
392 if (!hostname)
393 return nullptr;
394
395 const char vsock[8] = { 'v', 's', 'o', 'c', 'k', ':', '/', '/' };
396 if (strncmp(hostname, vsock, sizeof(vsock)) == 0)
397 return &hostname[sizeof(vsock)];
398 return nullptr;
399}
400
401WINPR_ATTR_NODISCARD
402static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
403{
404 BOOL rc = TRUE;
405 RDPDR_DEVICE* printer = nullptr;
406 do
407 {
408 printer = freerdp_device_collection_find_type(settings, type);
409 if (printer)
410 {
411 if (!freerdp_device_collection_del(settings, printer))
412 rc = FALSE;
413 }
414 freerdp_device_free(printer);
415 } while (printer);
416 return rc;
417}
418
419WINPR_ATTR_NODISCARD
420static BOOL disable_clipboard(rdpSettings* settings)
421{
422 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, FALSE))
423 return FALSE;
424 freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
425 return TRUE;
426}
427
428WINPR_ATTR_NODISCARD
429static BOOL disable_drive(rdpSettings* settings)
430{
431 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, FALSE))
432 return FALSE;
433 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, FALSE))
434 return FALSE;
435
436 return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
437}
438
439WINPR_ATTR_NODISCARD
440static BOOL disable_printers(rdpSettings* settings)
441{
442 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters, FALSE))
443 return FALSE;
444
445 return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
446}
447
448WINPR_ATTR_NODISCARD
449static BOOL disable_port(rdpSettings* settings)
450{
451 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts, FALSE))
452 return FALSE;
453 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts, FALSE))
454 return FALSE;
455 if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
456 return FALSE;
457 return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
458}
459
460WINPR_ATTR_NODISCARD
461static BOOL disable_pnp(WINPR_ATTR_UNUSED rdpSettings* settings)
462{
463 // TODO(akallabeth): [MS-RDPEPNP] related stuff is disabled.
464 return TRUE;
465}
466
467WINPR_ATTR_NODISCARD
468static BOOL apply_gw_policy(rdpContext* context)
469{
470 WINPR_ASSERT(context);
471 return utils_reload_channels(context);
472}
473
474BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module)
475{
476 WINPR_ASSERT(log);
477 WINPR_ASSERT(context);
478
479 rdpSettings* settings = context->settings;
480 WINPR_ASSERT(settings);
481
482 if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
483 {
484 WLog_Print(log, WLOG_DEBUG, "[%s] policy allows all redirections", module);
485 }
486 else if (freerdp_settings_get_bool(settings, FreeRDP_GatewayIgnoreRedirectionPolicy))
487 {
488 char buffer[128] = WINPR_C_ARRAY_INIT;
489 WLog_Print(log, WLOG_INFO, "[%s] policy ignored on user request %s", module,
490 utils_redir_flags_to_string(flags, buffer, sizeof(buffer)));
491 }
492 else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
493 {
494 WLog_Print(log, WLOG_INFO, "[%s] policy denies all redirections", module);
495 if (!disable_drive(settings))
496 return FALSE;
497 if (!disable_printers(settings))
498 return FALSE;
499 if (!disable_clipboard(settings))
500 return FALSE;
501 if (!disable_port(settings))
502 return FALSE;
503 if (!disable_pnp(settings))
504 return FALSE;
505 if (!apply_gw_policy(context))
506 return FALSE;
507 }
508 else
509 {
510 if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
511 {
512 WLog_Print(log, WLOG_INFO, "[%s] policy denies drive redirections", module);
513 if (!disable_drive(settings))
514 return FALSE;
515 }
516 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
517 {
518 WLog_Print(log, WLOG_INFO, "[%s] policy denies printer redirections", module);
519 if (!disable_printers(settings))
520 return FALSE;
521 }
522 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
523 {
524 WLog_Print(log, WLOG_INFO, "[%s] policy denies port redirections", module);
525 if (!disable_port(settings))
526 return FALSE;
527 }
528 if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
529 {
530 WLog_Print(log, WLOG_INFO, "[%s] policy denies clipboard redirections", module);
531 if (!disable_clipboard(settings))
532 return FALSE;
533 }
534 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
535 {
536 WLog_Print(log, WLOG_INFO, "[%s] policy denies PNP redirections", module);
537 if (!disable_pnp(settings))
538 return FALSE;
539 }
540 if (flags != 0)
541 {
542 if (!apply_gw_policy(context))
543 return FALSE;
544 }
545 }
546 return TRUE;
547}
548
549char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size)
550{
551 winpr_str_append("{", buffer, size, "");
552 if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
553 winpr_str_append("ENABLE_ALL", buffer, size, "|");
554 if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
555 winpr_str_append("DISABLE_ALL", buffer, size, "|");
556 if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
557 winpr_str_append("DISABLE_DRIVE", buffer, size, "|");
558 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
559 winpr_str_append("DISABLE_PRINTER", buffer, size, "|");
560 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
561 winpr_str_append("DISABLE_PORT", buffer, size, "|");
562 if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
563 winpr_str_append("DISABLE_CLIPBOARD", buffer, size, "|");
564 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
565 winpr_str_append("DISABLE_PNP", buffer, size, "|");
566
567 char fbuffer[16] = WINPR_C_ARRAY_INIT;
568 (void)_snprintf(fbuffer, sizeof(fbuffer), "[0x%08" PRIx32 "]", flags);
569
570 winpr_str_append(fbuffer, buffer, size, " ");
571 winpr_str_append("{", buffer, size, "}");
572 return buffer;
573}
574
575BOOL utils_reload_channels(rdpContext* context)
576{
577 WINPR_ASSERT(context);
578
579 if (context->channels)
580 {
581 freerdp_channels_disconnect(context->channels, context->instance);
582 freerdp_channels_close(context->channels, context->instance);
583 freerdp_channels_free(context->channels);
584 }
585
586 context->channels = freerdp_channels_new(context->instance);
587 if (!context->channels)
588 return FALSE;
589
590 freerdp_channels_register_instance(context->channels, context->instance);
591
592 BOOL rc = TRUE;
593 IFCALLRET(context->instance->LoadChannels, rc, context->instance);
594 if (rc)
595 return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
596 return rc;
597}
598
599const char* guid2str(const GUID* guid, char* buffer, size_t len)
600{
601 if (!guid)
602 return nullptr;
603 RPC_CSTR strguid = nullptr;
604
605 RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
606
607 if (rpcStatus != RPC_S_OK)
608 return nullptr;
609
610 (void)sprintf_s(buffer, len, "%s", strguid);
611 RpcStringFreeA(&strguid);
612 return buffer;
613}
614
615WINPR_ATTR_NODISCARD
616static BOOL isValidIPv4(const char* ipAddress)
617{
618 if (!ipAddress)
619 return FALSE;
620 const size_t len = strnlen(ipAddress, INET_ADDRSTRLEN + 1);
621 if (len > INET_ADDRSTRLEN)
622 return FALSE;
623
624 struct sockaddr_in sa = WINPR_C_ARRAY_INIT;
625 int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
626 return result != 0;
627}
628
629BOOL utils_is_valid_ipV6(const char* ipAddress)
630{
631 if (!ipAddress)
632 return FALSE;
633 const size_t len = strnlen(ipAddress, INET6_ADDRSTRLEN + 1);
634 if (len > INET6_ADDRSTRLEN)
635 return FALSE;
636 struct sockaddr_in6 sa = WINPR_C_ARRAY_INIT;
637 int result = inet_pton(AF_INET6, ipAddress, &(sa.sin6_addr));
638 return result != 0;
639}
640
641BOOL utils_is_valid_ipV6N(const char* ipAddress, size_t len)
642{
643 if (!ipAddress || (len == 0))
644 return FALSE;
645 if (strnlen(ipAddress, len) > INET6_ADDRSTRLEN)
646 return FALSE;
647 return utils_is_valid_ipV6(ipAddress);
648}
649
650BOOL utils_is_valid_ip(const char* ipAddress)
651{
652 return isValidIPv4(ipAddress) || utils_is_valid_ipV6(ipAddress);
653}
654
655BOOL utils_set_umask(void)
656{
657#if !defined(_WIN32)
658 (void)umask(S_IRWXG | S_IRWXO);
659#endif
660 return TRUE;
661}
662
663BOOL utils_compare_ip_strings(const char* ipAddressA, size_t lenA, const char* ipAddressB,
664 size_t lenB)
665{
666 if (!ipAddressA || (lenA == 0))
667 return FALSE;
668 if (!ipAddressB || (lenB == 0))
669 return FALSE;
670 if (strnlen(ipAddressA, lenA + 1) > lenA)
671 return FALSE;
672 if (strnlen(ipAddressB, lenB + 1) > lenB)
673 return FALSE;
674
675 if (isValidIPv4(ipAddressA) && isValidIPv4(ipAddressB))
676 {
677 struct sockaddr_in sa = WINPR_C_ARRAY_INIT;
678 struct sockaddr_in sb = WINPR_C_ARRAY_INIT;
679 const int resultA = inet_pton(AF_INET, ipAddressA, &(sa.sin_addr));
680 const int resultB = inet_pton(AF_INET, ipAddressB, &(sb.sin_addr));
681 if ((resultA != resultB) || (resultA != 1))
682 return FALSE;
683 return memcmp(&sa, &sb, sizeof(sa)) == 0;
684 }
685 if (utils_is_valid_ipV6(ipAddressA) && utils_is_valid_ipV6(ipAddressB))
686 {
687 struct sockaddr_in6 sa = WINPR_C_ARRAY_INIT;
688 struct sockaddr_in6 sb = WINPR_C_ARRAY_INIT;
689 const int resultA = inet_pton(AF_INET6, ipAddressA, &(sa.sin6_addr));
690 const int resultB = inet_pton(AF_INET6, ipAddressB, &(sb.sin6_addr));
691 if ((resultA != resultB) || (resultA != 1))
692 return FALSE;
693 return memcmp(&sa, &sb, sizeof(sa)) == 0;
694 }
695 return FALSE;
696}
697
698BOOL utils_is_valid_ipN(const char* ipAddress, size_t len)
699{
700 if (!ipAddress || (len == 0))
701 return FALSE;
702 if (strnlen(ipAddress, len) > INET6_ADDRSTRLEN)
703 return FALSE;
704 return utils_is_valid_ip(ipAddress);
705}
706
707WINPR_ATTR_NODISCARD
708static BIO* utils_tls_layer_bio(rdpContext* context, const char* hostname, UINT16 port,
709 UINT32 timeout)
710{
711 WINPR_ASSERT(context);
712 rdpTransport* transport = freerdp_get_transport(context);
713 rdpTransportLayer* layer = transport_connect_layer(transport, hostname, port, timeout);
714
715 if (!layer)
716 return nullptr;
717
718 BIO* layerBio = BIO_new(BIO_s_transport_layer());
719 if (!layerBio)
720 {
721 transport_layer_free(layer);
722 return nullptr;
723 }
724 BIO_set_data(layerBio, layer);
725 return layerBio;
726}
727
728WINPR_ATTR_NODISCARD
729static BIO* utils_tls_socket_bio(rdpContext* context, const char* hostname, UINT16 port,
730 UINT32 timeout)
731{
732 int sockfd = freerdp_tcp_connect(context, hostname, port, timeout);
733
734 if (sockfd < 0)
735 return nullptr;
736
737 BIO* socketBio = BIO_new(BIO_s_simple_socket());
738
739 if (!socketBio)
740 {
741 closesocket((SOCKET)sockfd);
742 return nullptr;
743 }
744
745 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
746 return socketBio;
747}
748
749BOOL utils_tls_connect(rdpContext* context, rdpTls* tls, wLog* log, const char* hostname,
750 UINT16 port, BOOL layerConnect, UINT32 timeout)
751{
752 WINPR_ASSERT(context);
753 WINPR_ASSERT(tls);
754
755 long status = 0;
756 rdpSettings* settings = context->settings;
757 const char* peerHostname = hostname;
758 UINT16 peerPort = port;
759 const char* proxyUsername = nullptr;
760 const char* proxyPassword = nullptr;
761 BOOL isProxyConnection =
762 proxy_prepare(settings, &peerHostname, &peerPort, &proxyUsername, &proxyPassword);
763
764 WLog_Print(log, WLOG_DEBUG, "connecting to %s %d", peerHostname, peerPort);
765 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
766
767 if (!bufferedBio)
768 return FALSE;
769
770 BIO* bio = nullptr;
771 if (layerConnect)
772 bio = utils_tls_layer_bio(context, hostname, port, timeout);
773 else
774 bio = utils_tls_socket_bio(context, hostname, port, timeout);
775 if (!bio)
776 {
777 BIO_free_all(bufferedBio);
778 return FALSE;
779 }
780 bufferedBio = BIO_push(bufferedBio, bio);
781 status = BIO_set_nonblock(bufferedBio, TRUE);
782
783 if (isProxyConnection)
784 {
785 if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword, hostname, port))
786 {
787 BIO_free_all(bufferedBio);
788 return FALSE;
789 }
790 }
791
792 if (!status)
793 {
794 BIO_free_all(bufferedBio);
795 return FALSE;
796 }
797
798 status = freerdp_tls_connect(tls, bufferedBio);
799 if (status < 1)
800 {
801 if (status < 0)
802 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
803 else
804 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
805
806 return FALSE;
807 }
808 return (status >= 1);
809}
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
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_copy_item(rdpSettings *dst, const rdpSettings *src, SSIZE_T id)
copies one setting identified by id from src to dst
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_device_collection_del(rdpSettings *settings, const RDPDR_DEVICE *device)
Removed a device from the settings, returns ownership of the allocated device to caller.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_name_for_key(SSIZE_T key)
Returns the type name for a key.