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