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#include "../core/rdp.h"
37
38BOOL utils_str_copy(const char* value, char** dst)
39{
40 WINPR_ASSERT(dst);
41
42 free(*dst);
43 *dst = nullptr;
44 if (!value)
45 return TRUE;
46
47 (*dst) = _strdup(value);
48 return (*dst) != nullptr;
49}
50
51static BOOL utils_copy_smartcard_settings(const rdpSettings* settings, rdpSettings* origSettings)
52{
53 /* update original settings with provided smart card settings */
54 origSettings->SmartcardLogon = settings->SmartcardLogon;
55 origSettings->PasswordIsSmartcardPin = settings->PasswordIsSmartcardPin;
56 if (!utils_str_copy(settings->ReaderName, &origSettings->ReaderName))
57 return FALSE;
58 if (!utils_str_copy(settings->CspName, &origSettings->CspName))
59 return FALSE;
60 if (!utils_str_copy(settings->ContainerName, &origSettings->ContainerName))
61 return FALSE;
62
63 return TRUE;
64}
65
66auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason)
67{
68 rdpSettings* settings = nullptr;
69 rdpSettings* origSettings = nullptr;
70 BOOL prompt = FALSE;
71 BOOL proceed = 0;
72
73 WINPR_ASSERT(instance);
74 WINPR_ASSERT(instance->context);
75 WINPR_ASSERT(instance->context->settings);
76 WINPR_ASSERT(instance->context->rdp);
77 WINPR_ASSERT(instance->context->rdp->originalSettings);
78
79 settings = instance->context->settings;
80 origSettings = instance->context->rdp->originalSettings;
81
82 if (freerdp_shall_disconnect_context(instance->context))
83 return AUTH_FAILED;
84
85 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayPassword)))
86 prompt = TRUE;
87 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayUsername)))
88 prompt = TRUE;
89
90 if (!prompt)
91 {
92 if (!utils_sync_credentials(settings, FALSE))
93 return AUTH_FAILED;
94 return AUTH_SKIP;
95 }
96
97#if !defined(WITH_FREERDP_DEPRECATED)
98 if (!instance->AuthenticateEx)
99 return AUTH_NO_CREDENTIALS;
100#else
101 if (!instance->GatewayAuthenticate && !instance->AuthenticateEx)
102 return AUTH_NO_CREDENTIALS;
103
104 if (!instance->GatewayAuthenticate)
105#endif
106 {
107 proceed =
108 instance->AuthenticateEx(instance, &settings->GatewayUsername,
109 &settings->GatewayPassword, &settings->GatewayDomain, reason);
110 if (!proceed)
111 return AUTH_CANCELLED;
112 }
113#if defined(WITH_FREERDP_DEPRECATED)
114 else
115 {
116 proceed =
117 instance->GatewayAuthenticate(instance, &settings->GatewayUsername,
118 &settings->GatewayPassword, &settings->GatewayDomain);
119 if (!proceed)
120 return AUTH_CANCELLED;
121 }
122#endif
123
124 if (utils_str_is_empty(settings->GatewayUsername) ||
125 utils_str_is_empty(settings->GatewayPassword))
126 return AUTH_NO_CREDENTIALS;
127
128 if (!utils_sync_credentials(settings, FALSE))
129 return AUTH_FAILED;
130
131 /* update original settings with provided user credentials */
132 if (!utils_str_copy(settings->GatewayUsername, &origSettings->GatewayUsername))
133 return AUTH_FAILED;
134 if (!utils_str_copy(settings->GatewayDomain, &origSettings->GatewayDomain))
135 return AUTH_FAILED;
136 if (!utils_str_copy(settings->GatewayPassword, &origSettings->GatewayPassword))
137 return AUTH_FAILED;
138 if (!utils_sync_credentials(origSettings, FALSE))
139 return AUTH_FAILED;
140
141 if (!utils_copy_smartcard_settings(settings, origSettings))
142 return AUTH_FAILED;
143
144 return AUTH_SUCCESS;
145}
146
147auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL override)
148{
149 rdpSettings* settings = nullptr;
150 rdpSettings* origSettings = nullptr;
151 BOOL prompt = !override;
152 BOOL proceed = 0;
153
154 WINPR_ASSERT(instance);
155 WINPR_ASSERT(instance->context);
156 WINPR_ASSERT(instance->context->settings);
157 WINPR_ASSERT(instance->context->rdp);
158 WINPR_ASSERT(instance->context->rdp->originalSettings);
159
160 settings = instance->context->settings;
161 origSettings = instance->context->rdp->originalSettings;
162
163 if (freerdp_shall_disconnect_context(instance->context))
164 return AUTH_FAILED;
165
166 if (settings->ConnectChildSession)
167 return AUTH_NO_CREDENTIALS;
168
169 /* Ask for auth data if no or an empty username was specified or no password was given */
170 if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_Username)) ||
171 (settings->Password == nullptr && settings->RedirectionPassword == nullptr))
172 prompt = TRUE;
173
174 if (!prompt)
175 return AUTH_SKIP;
176
177 switch (reason)
178 {
179 case AUTH_RDP:
180 case AUTH_TLS:
181 if (settings->SmartcardLogon)
182 {
183 if (!utils_str_is_empty(settings->Password))
184 {
185 WLog_INFO(TAG, "Authentication via smartcard");
186 return AUTH_SUCCESS;
187 }
188 reason = AUTH_SMARTCARD_PIN;
189 }
190 break;
191 case AUTH_NLA:
192 if (settings->SmartcardLogon)
193 reason = AUTH_SMARTCARD_PIN;
194 break;
195 case AUTH_RDSTLS:
196 default:
197 break;
198 }
199
200 /* If no callback is specified still continue connection */
201#if !defined(WITH_FREERDP_DEPRECATED)
202 if (!instance->AuthenticateEx)
203 return AUTH_NO_CREDENTIALS;
204#else
205 if (!instance->Authenticate && !instance->AuthenticateEx)
206 return AUTH_NO_CREDENTIALS;
207 if (!instance->Authenticate)
208#endif
209 {
210 proceed = instance->AuthenticateEx(instance, &settings->Username, &settings->Password,
211 &settings->Domain, reason);
212 if (!proceed)
213 return AUTH_CANCELLED;
214 }
215#if defined(WITH_FREERDP_DEPRECATED)
216 else
217 {
218 proceed = instance->Authenticate(instance, &settings->Username, &settings->Password,
219 &settings->Domain);
220 if (!proceed)
221 return AUTH_NO_CREDENTIALS;
222 }
223#endif
224
225 if (utils_str_is_empty(settings->Username) || utils_str_is_empty(settings->Password))
226 return AUTH_NO_CREDENTIALS;
227
228 if (!utils_sync_credentials(settings, TRUE))
229 return AUTH_FAILED;
230
231 /* update original settings with provided user credentials */
232 if (!utils_str_copy(settings->Username, &origSettings->Username))
233 return AUTH_FAILED;
234 if (!utils_str_copy(settings->Domain, &origSettings->Domain))
235 return AUTH_FAILED;
236 if (!utils_str_copy(settings->Password, &origSettings->Password))
237 return AUTH_FAILED;
238 if (!utils_sync_credentials(origSettings, TRUE))
239 return AUTH_FAILED;
240
241 if (!utils_copy_smartcard_settings(settings, origSettings))
242 return AUTH_FAILED;
243
244 return AUTH_SUCCESS;
245}
246
247BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway)
248{
249 WINPR_ASSERT(settings);
250 if (!settings->GatewayUseSameCredentials)
251 return TRUE;
252
253 if (toGateway)
254 {
255 if (!utils_str_copy(settings->Username, &settings->GatewayUsername))
256 return FALSE;
257 if (!utils_str_copy(settings->Domain, &settings->GatewayDomain))
258 return FALSE;
259 if (!utils_str_copy(settings->Password, &settings->GatewayPassword))
260 return FALSE;
261 }
262 else
263 {
264 if (!utils_str_copy(settings->GatewayUsername, &settings->Username))
265 return FALSE;
266 if (!utils_str_copy(settings->GatewayDomain, &settings->Domain))
267 return FALSE;
268 if (!utils_str_copy(settings->GatewayPassword, &settings->Password))
269 return FALSE;
270 }
271 return TRUE;
272}
273
274BOOL utils_persist_credentials(rdpSettings* settings, const rdpSettings* current)
275{
276 if (!settings || !current)
277 return FALSE;
278
279 const SSIZE_T keys[] = { FreeRDP_GatewayUsername, FreeRDP_GatewayDomain,
280 FreeRDP_GatewayPassword, FreeRDP_Username,
281 FreeRDP_Domain, FreeRDP_Password };
282
283 for (size_t x = 0; x < ARRAYSIZE(keys); x++)
284 {
285 const SSIZE_T key = keys[x];
286 if (!freerdp_settings_copy_item(settings, current, key))
287 {
288 WLog_ERR(TAG, "Failed to copy %s from current to backup settings",
290 return FALSE;
291 }
292 }
293
294 return TRUE;
295}
296
297BOOL utils_str_is_empty(const char* str)
298{
299 if (!str)
300 return TRUE;
301 if (*str == '\0')
302 return TRUE;
303 return FALSE;
304}
305
306BOOL utils_abort_connect(rdpRdp* rdp)
307{
308 if (!rdp)
309 return FALSE;
310
311 return SetEvent(rdp->abortEvent);
312}
313
314BOOL utils_reset_abort(rdpRdp* rdp)
315{
316 WINPR_ASSERT(rdp);
317
318 return ResetEvent(rdp->abortEvent);
319}
320
321HANDLE utils_get_abort_event(rdpRdp* rdp)
322{
323 WINPR_ASSERT(rdp);
324 return rdp->abortEvent;
325}
326
327BOOL utils_abort_event_is_set(const rdpRdp* rdp)
328{
329 DWORD status = 0;
330 WINPR_ASSERT(rdp);
331 status = WaitForSingleObject(rdp->abortEvent, 0);
332 return status == WAIT_OBJECT_0;
333}
334
335const char* utils_is_vsock(const char* hostname)
336{
337 if (!hostname)
338 return nullptr;
339
340 const char vsock[8] = { 'v', 's', 'o', 'c', 'k', ':', '/', '/' };
341 if (strncmp(hostname, vsock, sizeof(vsock)) == 0)
342 return &hostname[sizeof(vsock)];
343 return nullptr;
344}
345
346static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
347{
348 BOOL rc = TRUE;
349 RDPDR_DEVICE* printer = nullptr;
350 do
351 {
352 printer = freerdp_device_collection_find_type(settings, type);
353 if (printer)
354 {
355 if (!freerdp_device_collection_del(settings, printer))
356 rc = FALSE;
357 }
358 freerdp_device_free(printer);
359 } while (printer);
360 return rc;
361}
362
363static BOOL disable_clipboard(rdpSettings* settings)
364{
365 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, FALSE))
366 return FALSE;
367 freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
368 return TRUE;
369}
370
371static BOOL disable_drive(rdpSettings* settings)
372{
373 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, FALSE))
374 return FALSE;
375 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, FALSE))
376 return FALSE;
377
378 return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
379}
380
381static BOOL disable_printers(rdpSettings* settings)
382{
383 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters, FALSE))
384 return FALSE;
385
386 return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
387}
388
389static BOOL disable_port(rdpSettings* settings)
390{
391 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts, FALSE))
392 return FALSE;
393 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts, FALSE))
394 return FALSE;
395 if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
396 return FALSE;
397 return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
398}
399
400static BOOL disable_pnp(WINPR_ATTR_UNUSED rdpSettings* settings)
401{
402 // TODO(akallabeth): [MS-RDPEPNP] related stuff is disabled.
403 return TRUE;
404}
405
406static BOOL apply_gw_policy(rdpContext* context)
407{
408 WINPR_ASSERT(context);
409 return utils_reload_channels(context);
410}
411
412BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module)
413{
414 WINPR_ASSERT(log);
415 WINPR_ASSERT(context);
416
417 rdpSettings* settings = context->settings;
418 WINPR_ASSERT(settings);
419
420 if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
421 {
422 WLog_Print(log, WLOG_DEBUG, "[%s] policy allows all redirections", module);
423 }
424 else if (freerdp_settings_get_bool(settings, FreeRDP_GatewayIgnoreRedirectionPolicy))
425 {
426 char buffer[128] = WINPR_C_ARRAY_INIT;
427 WLog_Print(log, WLOG_INFO, "[%s] policy ignored on user request %s", module,
428 utils_redir_flags_to_string(flags, buffer, sizeof(buffer)));
429 }
430 else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
431 {
432 WLog_Print(log, WLOG_INFO, "[%s] policy denies all redirections", module);
433 if (!disable_drive(settings))
434 return FALSE;
435 if (!disable_printers(settings))
436 return FALSE;
437 if (!disable_clipboard(settings))
438 return FALSE;
439 if (!disable_port(settings))
440 return FALSE;
441 if (!disable_pnp(settings))
442 return FALSE;
443 if (!apply_gw_policy(context))
444 return FALSE;
445 }
446 else
447 {
448 if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
449 {
450 WLog_Print(log, WLOG_INFO, "[%s] policy denies drive redirections", module);
451 if (!disable_drive(settings))
452 return FALSE;
453 }
454 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
455 {
456 WLog_Print(log, WLOG_INFO, "[%s] policy denies printer redirections", module);
457 if (!disable_printers(settings))
458 return FALSE;
459 }
460 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
461 {
462 WLog_Print(log, WLOG_INFO, "[%s] policy denies port redirections", module);
463 if (!disable_port(settings))
464 return FALSE;
465 }
466 if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
467 {
468 WLog_Print(log, WLOG_INFO, "[%s] policy denies clipboard redirections", module);
469 if (!disable_clipboard(settings))
470 return FALSE;
471 }
472 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
473 {
474 WLog_Print(log, WLOG_INFO, "[%s] policy denies PNP redirections", module);
475 if (!disable_pnp(settings))
476 return FALSE;
477 }
478 if (flags != 0)
479 {
480 if (!apply_gw_policy(context))
481 return FALSE;
482 }
483 }
484 return TRUE;
485}
486
487char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size)
488{
489 winpr_str_append("{", buffer, size, "");
490 if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
491 winpr_str_append("ENABLE_ALL", buffer, size, "|");
492 if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
493 winpr_str_append("DISABLE_ALL", buffer, size, "|");
494 if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
495 winpr_str_append("DISABLE_DRIVE", buffer, size, "|");
496 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
497 winpr_str_append("DISABLE_PRINTER", buffer, size, "|");
498 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
499 winpr_str_append("DISABLE_PORT", buffer, size, "|");
500 if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
501 winpr_str_append("DISABLE_CLIPBOARD", buffer, size, "|");
502 if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
503 winpr_str_append("DISABLE_PNP", buffer, size, "|");
504
505 char fbuffer[16] = WINPR_C_ARRAY_INIT;
506 (void)_snprintf(fbuffer, sizeof(fbuffer), "[0x%08" PRIx32 "]", flags);
507
508 winpr_str_append(fbuffer, buffer, size, " ");
509 winpr_str_append("{", buffer, size, "}");
510 return buffer;
511}
512
513BOOL utils_reload_channels(rdpContext* context)
514{
515 WINPR_ASSERT(context);
516
517 if (context->channels)
518 {
519 freerdp_channels_disconnect(context->channels, context->instance);
520 freerdp_channels_close(context->channels, context->instance);
521 freerdp_channels_free(context->channels);
522 }
523
524 context->channels = freerdp_channels_new(context->instance);
525 if (!context->channels)
526 return FALSE;
527
528 freerdp_channels_register_instance(context->channels, context->instance);
529
530 BOOL rc = TRUE;
531 IFCALLRET(context->instance->LoadChannels, rc, context->instance);
532 if (rc)
533 return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
534 return rc;
535}
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.