21#include <freerdp/config.h>
25#include <winpr/assert.h>
27#include <freerdp/freerdp.h>
28#include <freerdp/channels/cliprdr.h>
29#include <freerdp/channels/rdpdr.h>
31#include <freerdp/log.h>
32#define TAG FREERDP_TAG("core.gateway.utils")
40#include "../core/rdp.h"
41#include "../core/proxy.h"
43BOOL utils_str_copy(
const char* value,
char** dst)
52 (*dst) = _strdup(value);
53 return (*dst) !=
nullptr;
57static BOOL utils_copy_smartcard_settings(
const rdpSettings* settings, rdpSettings* origSettings)
60 origSettings->SmartcardLogon = settings->SmartcardLogon;
61 origSettings->PasswordIsSmartcardPin = settings->PasswordIsSmartcardPin;
62 if (!utils_str_copy(settings->ReaderName, &origSettings->ReaderName))
64 if (!utils_str_copy(settings->CspName, &origSettings->CspName))
66 if (!utils_str_copy(settings->ContainerName, &origSettings->ContainerName))
73static BOOL utils_auth_skip(freerdp* instance, rdp_auth_reason reason, BOOL gateway)
75 WINPR_ASSERT(instance);
76 WINPR_ASSERT(instance->context);
79 instance->context->settings, gateway ? FreeRDP_GatewayPassword : FreeRDP_Password);
81 instance->context->settings, gateway ? FreeRDP_GatewayUsername : FreeRDP_Username);
87 case AUTH_SMARTCARD_PIN:
89 if (username && password)
99auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason)
101 rdpSettings* settings =
nullptr;
102 rdpSettings* origSettings =
nullptr;
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);
112 settings = instance->context->settings;
113 origSettings = instance->context->rdp->originalSettings;
115 if (freerdp_shall_disconnect_context(instance->context))
125 if (!utils_sync_credentials(settings, FALSE))
129 const BOOL skip = utils_auth_skip(instance, reason, TRUE);
133#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
134 WINPR_PRAGMA_DIAG_PUSH
135 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
138#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
139 if (!instance->AuthenticateEx)
140 return AUTH_NO_CREDENTIALS;
142 if (!instance->GatewayAuthenticate && !instance->AuthenticateEx)
143 return AUTH_NO_CREDENTIALS;
145 if (!instance->GatewayAuthenticate)
149 instance->AuthenticateEx(instance, &settings->GatewayUsername,
150 &settings->GatewayPassword, &settings->GatewayDomain, reason);
152 return AUTH_CANCELLED;
154#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
158 instance->GatewayAuthenticate(instance, &settings->GatewayUsername,
159 &settings->GatewayPassword, &settings->GatewayDomain);
161 return AUTH_CANCELLED;
165#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
166 WINPR_PRAGMA_DIAG_POP
169 if (utils_str_is_empty(settings->GatewayUsername) ||
170 utils_str_is_empty(settings->GatewayPassword))
171 return AUTH_NO_CREDENTIALS;
173 if (!utils_sync_credentials(settings, FALSE))
177 if (!utils_str_copy(settings->GatewayUsername, &origSettings->GatewayUsername))
179 if (!utils_str_copy(settings->GatewayDomain, &origSettings->GatewayDomain))
181 if (!utils_str_copy(settings->GatewayPassword, &origSettings->GatewayPassword))
183 if (!utils_sync_credentials(origSettings, FALSE))
186 if (!utils_copy_smartcard_settings(settings, origSettings))
192auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL
override)
194 rdpSettings* settings =
nullptr;
195 rdpSettings* origSettings =
nullptr;
196 BOOL prompt = !
override;
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);
205 settings = instance->context->settings;
206 origSettings = instance->context->rdp->originalSettings;
208 if (freerdp_shall_disconnect_context(instance->context))
211 if (settings->ConnectChildSession)
212 return AUTH_NO_CREDENTIALS;
216 (settings->Password ==
nullptr && settings->RedirectionPassword ==
nullptr))
219 const BOOL skip = utils_auth_skip(instance, reason, FALSE);
227 if (settings->SmartcardLogon)
229 if (!utils_str_is_empty(settings->Password))
231 WLog_INFO(TAG,
"Authentication via smartcard");
234 reason = AUTH_SMARTCARD_PIN;
238 if (settings->SmartcardLogon)
239 reason = AUTH_SMARTCARD_PIN;
246#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
247 WINPR_PRAGMA_DIAG_PUSH
248 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
252#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
253 if (!instance->AuthenticateEx)
254 return AUTH_NO_CREDENTIALS;
256 if (!instance->Authenticate && !instance->AuthenticateEx)
257 return AUTH_NO_CREDENTIALS;
258 if (!instance->Authenticate)
261 proceed = instance->AuthenticateEx(instance, &settings->Username, &settings->Password,
262 &settings->Domain, reason);
264 return AUTH_CANCELLED;
266#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
269 proceed = instance->Authenticate(instance, &settings->Username, &settings->Password,
272 return AUTH_NO_CREDENTIALS;
276#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
277 WINPR_PRAGMA_DIAG_POP
280 if (utils_str_is_empty(settings->Username) || utils_str_is_empty(settings->Password))
281 return AUTH_NO_CREDENTIALS;
283 if (!utils_sync_credentials(settings, TRUE))
287 if (!utils_str_copy(settings->Username, &origSettings->Username))
289 if (!utils_str_copy(settings->Domain, &origSettings->Domain))
291 if (!utils_str_copy(settings->Password, &origSettings->Password))
293 if (!utils_sync_credentials(origSettings, TRUE))
296 if (!utils_copy_smartcard_settings(settings, origSettings))
302BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway)
304 WINPR_ASSERT(settings);
305 if (!settings->GatewayUseSameCredentials)
310 if (!utils_str_copy(settings->Username, &settings->GatewayUsername))
312 if (!utils_str_copy(settings->Domain, &settings->GatewayDomain))
314 if (!utils_str_copy(settings->Password, &settings->GatewayPassword))
319 if (!utils_str_copy(settings->GatewayUsername, &settings->Username))
321 if (!utils_str_copy(settings->GatewayDomain, &settings->Domain))
323 if (!utils_str_copy(settings->GatewayPassword, &settings->Password))
329BOOL utils_persist_credentials(rdpSettings* settings,
const rdpSettings* current)
331 if (!settings || !current)
334 const SSIZE_T keys[] = { FreeRDP_GatewayUsername, FreeRDP_GatewayDomain,
335 FreeRDP_GatewayPassword, FreeRDP_Username,
336 FreeRDP_Domain, FreeRDP_Password };
338 for (
size_t x = 0; x < ARRAYSIZE(keys); x++)
340 const SSIZE_T key = keys[x];
343 WLog_ERR(TAG,
"Failed to copy %s from current to backup settings",
352BOOL utils_str_is_empty(
const char* str)
361BOOL utils_abort_connect(rdpRdp* rdp)
366 return SetEvent(rdp->abortEvent);
369BOOL utils_reset_abort(rdpRdp* rdp)
373 return ResetEvent(rdp->abortEvent);
376HANDLE utils_get_abort_event(rdpRdp* rdp)
379 return rdp->abortEvent;
382BOOL utils_abort_event_is_set(
const rdpRdp* rdp)
386 status = WaitForSingleObject(rdp->abortEvent, 0);
387 return status == WAIT_OBJECT_0;
390const char* utils_is_vsock(
const char* hostname)
395 const char vsock[8] = {
'v',
's',
'o',
'c',
'k',
':',
'/',
'/' };
396 if (strncmp(hostname, vsock,
sizeof(vsock)) == 0)
397 return &hostname[
sizeof(vsock)];
402static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
408 printer = freerdp_device_collection_find_type(settings, type);
414 freerdp_device_free(printer);
420static BOOL disable_clipboard(rdpSettings* settings)
424 freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
429static BOOL disable_drive(rdpSettings* settings)
436 return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
440static BOOL disable_printers(rdpSettings* settings)
445 return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
449static BOOL disable_port(rdpSettings* settings)
455 if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
457 return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
461static BOOL disable_pnp(WINPR_ATTR_UNUSED rdpSettings* settings)
468static BOOL apply_gw_policy(rdpContext* context)
470 WINPR_ASSERT(context);
471 return utils_reload_channels(context);
474BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags,
const char* module)
477 WINPR_ASSERT(context);
479 rdpSettings* settings = context->settings;
480 WINPR_ASSERT(settings);
482 if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
484 WLog_Print(log, WLOG_DEBUG,
"[%s] policy allows all redirections", module);
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)));
492 else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
494 WLog_Print(log, WLOG_INFO,
"[%s] policy denies all redirections", module);
495 if (!disable_drive(settings))
497 if (!disable_printers(settings))
499 if (!disable_clipboard(settings))
501 if (!disable_port(settings))
503 if (!disable_pnp(settings))
505 if (!apply_gw_policy(context))
510 if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
512 WLog_Print(log, WLOG_INFO,
"[%s] policy denies drive redirections", module);
513 if (!disable_drive(settings))
516 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
518 WLog_Print(log, WLOG_INFO,
"[%s] policy denies printer redirections", module);
519 if (!disable_printers(settings))
522 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
524 WLog_Print(log, WLOG_INFO,
"[%s] policy denies port redirections", module);
525 if (!disable_port(settings))
528 if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
530 WLog_Print(log, WLOG_INFO,
"[%s] policy denies clipboard redirections", module);
531 if (!disable_clipboard(settings))
534 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
536 WLog_Print(log, WLOG_INFO,
"[%s] policy denies PNP redirections", module);
537 if (!disable_pnp(settings))
542 if (!apply_gw_policy(context))
549char* utils_redir_flags_to_string(UINT32 flags,
char* buffer,
size_t size)
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,
"|");
567 char fbuffer[16] = WINPR_C_ARRAY_INIT;
568 (void)_snprintf(fbuffer,
sizeof(fbuffer),
"[0x%08" PRIx32
"]", flags);
570 winpr_str_append(fbuffer, buffer, size,
" ");
571 winpr_str_append(
"{", buffer, size,
"}");
575BOOL utils_reload_channels(rdpContext* context)
577 WINPR_ASSERT(context);
579 if (context->channels)
581 freerdp_channels_disconnect(context->channels, context->instance);
582 freerdp_channels_close(context->channels, context->instance);
583 freerdp_channels_free(context->channels);
586 context->channels = freerdp_channels_new(context->instance);
587 if (!context->channels)
590 freerdp_channels_register_instance(context->channels, context->instance);
593 IFCALLRET(context->instance->LoadChannels, rc, context->instance);
595 return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
599const char* guid2str(
const GUID* guid,
char* buffer,
size_t len)
603 RPC_CSTR strguid =
nullptr;
605 RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
607 if (rpcStatus != RPC_S_OK)
610 (void)sprintf_s(buffer, len,
"%s", strguid);
611 RpcStringFreeA(&strguid);
616static BOOL isValidIPv4(
const char* ipAddress)
620 const size_t len = strnlen(ipAddress, INET_ADDRSTRLEN + 1);
621 if (len > INET_ADDRSTRLEN)
624 struct sockaddr_in sa = WINPR_C_ARRAY_INIT;
625 int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
629BOOL utils_is_valid_ipV6(
const char* ipAddress)
633 const size_t len = strnlen(ipAddress, INET6_ADDRSTRLEN + 1);
634 if (len > INET6_ADDRSTRLEN)
636 struct sockaddr_in6 sa = WINPR_C_ARRAY_INIT;
637 int result = inet_pton(AF_INET6, ipAddress, &(sa.sin6_addr));
641BOOL utils_is_valid_ipV6N(
const char* ipAddress,
size_t len)
643 if (!ipAddress || (len == 0))
645 if (strnlen(ipAddress, len) > INET6_ADDRSTRLEN)
647 return utils_is_valid_ipV6(ipAddress);
650BOOL utils_is_valid_ip(
const char* ipAddress)
652 return isValidIPv4(ipAddress) || utils_is_valid_ipV6(ipAddress);
655BOOL utils_set_umask(
void)
658 (void)umask(S_IRWXG | S_IRWXO);
663BOOL utils_compare_ip_strings(
const char* ipAddressA,
size_t lenA,
const char* ipAddressB,
666 if (!ipAddressA || (lenA == 0))
668 if (!ipAddressB || (lenB == 0))
670 if (strnlen(ipAddressA, lenA + 1) > lenA)
672 if (strnlen(ipAddressB, lenB + 1) > lenB)
675 if (isValidIPv4(ipAddressA) && isValidIPv4(ipAddressB))
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))
683 return memcmp(&sa, &sb,
sizeof(sa)) == 0;
685 if (utils_is_valid_ipV6(ipAddressA) && utils_is_valid_ipV6(ipAddressB))
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))
693 return memcmp(&sa, &sb,
sizeof(sa)) == 0;
698BOOL utils_is_valid_ipN(
const char* ipAddress,
size_t len)
700 if (!ipAddress || (len == 0))
702 if (strnlen(ipAddress, len) > INET6_ADDRSTRLEN)
704 return utils_is_valid_ip(ipAddress);
708static BIO* utils_tls_layer_bio(rdpContext* context,
const char* hostname, UINT16 port,
711 WINPR_ASSERT(context);
712 rdpTransport* transport = freerdp_get_transport(context);
713 rdpTransportLayer* layer = transport_connect_layer(transport, hostname, port, timeout);
718 BIO* layerBio = BIO_new(BIO_s_transport_layer());
721 transport_layer_free(layer);
724 BIO_set_data(layerBio, layer);
729static BIO* utils_tls_socket_bio(rdpContext* context,
const char* hostname, UINT16 port,
732 int sockfd = freerdp_tcp_connect(context, hostname, port, timeout);
737 BIO* socketBio = BIO_new(BIO_s_simple_socket());
741 closesocket((SOCKET)sockfd);
745 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
749BOOL utils_tls_connect(rdpContext* context, rdpTls* tls, wLog* log,
const char* hostname,
750 UINT16 port, BOOL layerConnect, UINT32 timeout)
752 WINPR_ASSERT(context);
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);
764 WLog_Print(log, WLOG_DEBUG,
"connecting to %s %d", peerHostname, peerPort);
765 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
772 bio = utils_tls_layer_bio(context, hostname, port, timeout);
774 bio = utils_tls_socket_bio(context, hostname, port, timeout);
777 BIO_free_all(bufferedBio);
780 bufferedBio = BIO_push(bufferedBio, bio);
781 status = BIO_set_nonblock(bufferedBio, TRUE);
783 if (isProxyConnection)
785 if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword, hostname, port))
787 BIO_free_all(bufferedBio);
794 BIO_free_all(bufferedBio);
798 status = freerdp_tls_connect(tls, bufferedBio);
802 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
804 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
808 return (status >= 1);
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.