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