Coverage Report

Created: 2026-10-15 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/core/utils.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Terminal Server Gateway (utils)
4
 *
5
 * Copyright 2021 Armin Novak <armin.novak@thincast.com>
6
 * Copyright 2021 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
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
42
BOOL utils_str_copy(const char* value, char** dst)
43
0
{
44
0
  WINPR_ASSERT(dst);
45
46
0
  free(*dst);
47
0
  *dst = nullptr;
48
0
  if (!value)
49
0
    return TRUE;
50
51
0
  (*dst) = _strdup(value);
52
0
  return (*dst) != nullptr;
53
0
}
54
55
WINPR_ATTR_NODISCARD
56
static BOOL utils_copy_smartcard_settings(const rdpSettings* settings, rdpSettings* origSettings)
57
0
{
58
  /* update original settings with provided smart card settings */
59
0
  origSettings->SmartcardLogon = settings->SmartcardLogon;
60
0
  origSettings->PasswordIsSmartcardPin = settings->PasswordIsSmartcardPin;
61
0
  if (!utils_str_copy(settings->ReaderName, &origSettings->ReaderName))
62
0
    return FALSE;
63
0
  if (!utils_str_copy(settings->CspName, &origSettings->CspName))
64
0
    return FALSE;
65
0
  if (!utils_str_copy(settings->ContainerName, &origSettings->ContainerName))
66
0
    return FALSE;
67
68
0
  return TRUE;
69
0
}
70
71
WINPR_ATTR_NODISCARD
72
static BOOL utils_auth_skip(freerdp* instance, rdp_auth_reason reason, BOOL gateway)
73
0
{
74
0
  WINPR_ASSERT(instance);
75
0
  WINPR_ASSERT(instance->context);
76
77
0
  const char* password = freerdp_settings_get_string(
78
0
      instance->context->settings, gateway ? FreeRDP_GatewayPassword : FreeRDP_Password);
79
0
  const char* username = freerdp_settings_get_string(
80
0
      instance->context->settings, gateway ? FreeRDP_GatewayUsername : FreeRDP_Username);
81
82
0
  switch (reason)
83
0
  {
84
0
    case AUTH_TLS:
85
0
    case AUTH_RDP:
86
0
    case AUTH_SMARTCARD_PIN: /* in this case password is pin code */
87
0
    case AUTH_FIDO_PIN:
88
0
      if (username && password)
89
0
        return TRUE;
90
0
      break;
91
0
    default:
92
0
      break;
93
0
  }
94
95
0
  return FALSE;
96
0
}
97
98
auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason)
99
0
{
100
0
  rdpSettings* settings = nullptr;
101
0
  rdpSettings* origSettings = nullptr;
102
0
  BOOL prompt = FALSE;
103
0
  BOOL proceed = 0;
104
105
0
  WINPR_ASSERT(instance);
106
0
  WINPR_ASSERT(instance->context);
107
0
  WINPR_ASSERT(instance->context->settings);
108
0
  WINPR_ASSERT(instance->context->rdp);
109
0
  WINPR_ASSERT(instance->context->rdp->originalSettings);
110
111
0
  settings = instance->context->settings;
112
0
  origSettings = instance->context->rdp->originalSettings;
113
114
0
  if (freerdp_shall_disconnect_context(instance->context))
115
0
    return AUTH_FAILED;
116
117
0
  if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayPassword)))
118
0
    prompt = TRUE;
119
0
  if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayUsername)))
120
0
    prompt = TRUE;
121
122
0
  if (!prompt)
123
0
  {
124
0
    if (!utils_sync_credentials(settings, FALSE))
125
0
      return AUTH_FAILED;
126
0
    return AUTH_SKIP;
127
0
  }
128
0
  const BOOL skip = utils_auth_skip(instance, reason, TRUE);
129
0
  if (skip)
130
0
    return AUTH_SKIP;
131
132
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
133
0
  WINPR_PRAGMA_DIAG_PUSH
134
0
  WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
135
0
#endif
136
137
#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
138
  if (!instance->AuthenticateEx)
139
    return AUTH_NO_CREDENTIALS;
140
#else
141
0
  if (!instance->GatewayAuthenticate && !instance->AuthenticateEx)
142
0
    return AUTH_NO_CREDENTIALS;
143
144
0
  if (!instance->GatewayAuthenticate)
145
0
#endif
146
0
  {
147
0
    proceed =
148
0
        instance->AuthenticateEx(instance, &settings->GatewayUsername,
149
0
                                 &settings->GatewayPassword, &settings->GatewayDomain, reason);
150
0
    if (!proceed)
151
0
      return AUTH_CANCELLED;
152
0
  }
153
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
154
0
  else
155
0
  {
156
0
    proceed =
157
0
        instance->GatewayAuthenticate(instance, &settings->GatewayUsername,
158
0
                                      &settings->GatewayPassword, &settings->GatewayDomain);
159
0
    if (!proceed)
160
0
      return AUTH_CANCELLED;
161
0
  }
162
0
#endif
163
164
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
165
0
  WINPR_PRAGMA_DIAG_POP
166
0
#endif
167
168
0
  if (utils_str_is_empty(settings->GatewayUsername) ||
169
0
      utils_str_is_empty(settings->GatewayPassword))
170
0
    return AUTH_NO_CREDENTIALS;
171
172
0
  if (!utils_sync_credentials(settings, FALSE))
173
0
    return AUTH_FAILED;
174
175
  /* update original settings with provided user credentials */
176
0
  if (!utils_str_copy(settings->GatewayUsername, &origSettings->GatewayUsername))
177
0
    return AUTH_FAILED;
178
0
  if (!utils_str_copy(settings->GatewayDomain, &origSettings->GatewayDomain))
179
0
    return AUTH_FAILED;
180
0
  if (!utils_str_copy(settings->GatewayPassword, &origSettings->GatewayPassword))
181
0
    return AUTH_FAILED;
182
0
  if (!utils_sync_credentials(origSettings, FALSE))
183
0
    return AUTH_FAILED;
184
185
0
  if (!utils_copy_smartcard_settings(settings, origSettings))
186
0
    return AUTH_FAILED;
187
188
0
  return AUTH_SUCCESS;
189
0
}
190
191
auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL override)
192
0
{
193
0
  rdpSettings* settings = nullptr;
194
0
  rdpSettings* origSettings = nullptr;
195
0
  BOOL prompt = !override;
196
0
  BOOL proceed = 0;
197
198
0
  WINPR_ASSERT(instance);
199
0
  WINPR_ASSERT(instance->context);
200
0
  WINPR_ASSERT(instance->context->settings);
201
0
  WINPR_ASSERT(instance->context->rdp);
202
0
  WINPR_ASSERT(instance->context->rdp->originalSettings);
203
204
0
  settings = instance->context->settings;
205
0
  origSettings = instance->context->rdp->originalSettings;
206
207
0
  if (freerdp_shall_disconnect_context(instance->context))
208
0
    return AUTH_FAILED;
209
210
0
  if (settings->ConnectChildSession)
211
0
    return AUTH_NO_CREDENTIALS;
212
213
  /* Ask for auth data if no or an empty username was specified or no password was given */
214
0
  if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_Username)) ||
215
0
      (settings->Password == nullptr && settings->RedirectionPassword == nullptr))
216
0
    prompt = TRUE;
217
218
0
  const BOOL skip = utils_auth_skip(instance, reason, FALSE);
219
0
  if (!prompt || skip)
220
0
    return AUTH_SKIP;
221
222
0
  switch (reason)
223
0
  {
224
0
    case AUTH_RDP:
225
0
    case AUTH_TLS:
226
0
      if (settings->SmartcardLogon)
227
0
      {
228
0
        if (!utils_str_is_empty(settings->Password))
229
0
        {
230
0
          WLog_INFO(TAG, "Authentication via smartcard");
231
0
          return AUTH_SUCCESS;
232
0
        }
233
0
        reason = AUTH_SMARTCARD_PIN;
234
0
      }
235
0
      break;
236
0
    case AUTH_NLA:
237
0
      if (settings->SmartcardLogon)
238
0
        reason = AUTH_SMARTCARD_PIN;
239
0
      break;
240
0
    case AUTH_RDSTLS:
241
0
    default:
242
0
      break;
243
0
  }
244
245
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
246
0
  WINPR_PRAGMA_DIAG_PUSH
247
0
  WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
248
0
#endif
249
250
  /* If no callback is specified still continue connection */
251
#if defined(WITHOUT_FREERDP_3x_DEPRECATED)
252
  if (!instance->AuthenticateEx)
253
    return AUTH_NO_CREDENTIALS;
254
#else
255
0
  if (!instance->Authenticate && !instance->AuthenticateEx)
256
0
    return AUTH_NO_CREDENTIALS;
257
0
  if (!instance->Authenticate)
258
0
#endif
259
0
  {
260
0
    proceed = instance->AuthenticateEx(instance, &settings->Username, &settings->Password,
261
0
                                       &settings->Domain, reason);
262
0
    if (!proceed)
263
0
      return AUTH_CANCELLED;
264
0
  }
265
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
266
0
  else
267
0
  {
268
0
    proceed = instance->Authenticate(instance, &settings->Username, &settings->Password,
269
0
                                     &settings->Domain);
270
0
    if (!proceed)
271
0
      return AUTH_NO_CREDENTIALS;
272
0
  }
273
0
#endif
274
275
0
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
276
0
  WINPR_PRAGMA_DIAG_POP
277
0
#endif
278
279
0
  if (utils_str_is_empty(settings->Username) || utils_str_is_empty(settings->Password))
280
0
    return AUTH_NO_CREDENTIALS;
281
282
0
  if (!utils_sync_credentials(settings, TRUE))
283
0
    return AUTH_FAILED;
284
285
  /* update original settings with provided user credentials */
286
0
  if (!utils_str_copy(settings->Username, &origSettings->Username))
287
0
    return AUTH_FAILED;
288
0
  if (!utils_str_copy(settings->Domain, &origSettings->Domain))
289
0
    return AUTH_FAILED;
290
0
  if (!utils_str_copy(settings->Password, &origSettings->Password))
291
0
    return AUTH_FAILED;
292
0
  if (!utils_sync_credentials(origSettings, TRUE))
293
0
    return AUTH_FAILED;
294
295
0
  if (!utils_copy_smartcard_settings(settings, origSettings))
296
0
    return AUTH_FAILED;
297
298
0
  return AUTH_SUCCESS;
299
0
}
300
301
BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway)
302
0
{
303
0
  WINPR_ASSERT(settings);
304
0
  if (!settings->GatewayUseSameCredentials)
305
0
    return TRUE;
306
307
0
  if (toGateway)
308
0
  {
309
0
    if (!utils_str_copy(settings->Username, &settings->GatewayUsername))
310
0
      return FALSE;
311
0
    if (!utils_str_copy(settings->Domain, &settings->GatewayDomain))
312
0
      return FALSE;
313
0
    if (!utils_str_copy(settings->Password, &settings->GatewayPassword))
314
0
      return FALSE;
315
0
  }
316
0
  else
317
0
  {
318
0
    if (!utils_str_copy(settings->GatewayUsername, &settings->Username))
319
0
      return FALSE;
320
0
    if (!utils_str_copy(settings->GatewayDomain, &settings->Domain))
321
0
      return FALSE;
322
0
    if (!utils_str_copy(settings->GatewayPassword, &settings->Password))
323
0
      return FALSE;
324
0
  }
325
0
  return TRUE;
326
0
}
327
328
BOOL utils_persist_credentials(rdpSettings* settings, const rdpSettings* current)
329
0
{
330
0
  if (!settings || !current)
331
0
    return FALSE;
332
333
0
  const SSIZE_T keys[] = { FreeRDP_GatewayUsername, FreeRDP_GatewayDomain,
334
0
                         FreeRDP_GatewayPassword, FreeRDP_Username,
335
0
                         FreeRDP_Domain,          FreeRDP_Password };
336
337
0
  for (size_t x = 0; x < ARRAYSIZE(keys); x++)
338
0
  {
339
0
    const SSIZE_T key = keys[x];
340
0
    if (!freerdp_settings_copy_item(settings, current, key))
341
0
    {
342
0
      WLog_ERR(TAG, "Failed to copy %s from current to backup settings",
343
0
               freerdp_settings_get_name_for_key(key));
344
0
      return FALSE;
345
0
    }
346
0
  }
347
348
0
  return TRUE;
349
0
}
350
351
BOOL utils_str_is_empty(const char* str)
352
0
{
353
0
  if (!str)
354
0
    return TRUE;
355
0
  if (*str == '\0')
356
0
    return TRUE;
357
0
  return FALSE;
358
0
}
359
360
BOOL utils_abort_connect(rdpRdp* rdp)
361
894
{
362
894
  if (!rdp)
363
0
    return FALSE;
364
365
894
  return SetEvent(rdp->abortEvent);
366
894
}
367
368
BOOL utils_reset_abort(rdpRdp* rdp)
369
0
{
370
0
  WINPR_ASSERT(rdp);
371
372
0
  return ResetEvent(rdp->abortEvent);
373
0
}
374
375
HANDLE utils_get_abort_event(rdpRdp* rdp)
376
21.4k
{
377
21.4k
  WINPR_ASSERT(rdp);
378
21.4k
  return rdp->abortEvent;
379
21.4k
}
380
381
BOOL utils_abort_event_is_set(const rdpRdp* rdp)
382
26
{
383
26
  DWORD status = 0;
384
26
  WINPR_ASSERT(rdp);
385
26
  status = WaitForSingleObject(rdp->abortEvent, 0);
386
26
  return status == WAIT_OBJECT_0;
387
26
}
388
389
const char* utils_is_vsock(const char* hostname)
390
0
{
391
0
  if (!hostname)
392
0
    return nullptr;
393
394
0
  const char vsock[8] = { 'v', 's', 'o', 'c', 'k', ':', '/', '/' };
395
0
  if (strncmp(hostname, vsock, sizeof(vsock)) == 0)
396
0
    return &hostname[sizeof(vsock)];
397
0
  return nullptr;
398
0
}
399
400
WINPR_ATTR_NODISCARD
401
static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
402
0
{
403
0
  BOOL rc = TRUE;
404
0
  RDPDR_DEVICE* printer = nullptr;
405
0
  do
406
0
  {
407
0
    printer = freerdp_device_collection_find_type(settings, type);
408
0
    if (printer)
409
0
    {
410
0
      if (!freerdp_device_collection_del(settings, printer))
411
0
        rc = FALSE;
412
0
    }
413
0
    freerdp_device_free(printer);
414
0
  } while (printer);
415
0
  return rc;
416
0
}
417
418
WINPR_ATTR_NODISCARD
419
static BOOL disable_clipboard(rdpSettings* settings)
420
0
{
421
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, FALSE))
422
0
    return FALSE;
423
0
  freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
424
0
  return TRUE;
425
0
}
426
427
WINPR_ATTR_NODISCARD
428
static BOOL disable_drive(rdpSettings* settings)
429
0
{
430
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, FALSE))
431
0
    return FALSE;
432
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, FALSE))
433
0
    return FALSE;
434
435
0
  return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
436
0
}
437
438
WINPR_ATTR_NODISCARD
439
static BOOL disable_printers(rdpSettings* settings)
440
0
{
441
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters, FALSE))
442
0
    return FALSE;
443
444
0
  return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
445
0
}
446
447
WINPR_ATTR_NODISCARD
448
static BOOL disable_port(rdpSettings* settings)
449
0
{
450
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts, FALSE))
451
0
    return FALSE;
452
0
  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts, FALSE))
453
0
    return FALSE;
454
0
  if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
455
0
    return FALSE;
456
0
  return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
457
0
}
458
459
WINPR_ATTR_NODISCARD
460
static BOOL disable_pnp(WINPR_ATTR_UNUSED rdpSettings* settings)
461
0
{
462
  // TODO(akallabeth): [MS-RDPEPNP] related stuff is disabled.
463
0
  return TRUE;
464
0
}
465
466
WINPR_ATTR_NODISCARD
467
static BOOL apply_gw_policy(rdpContext* context)
468
0
{
469
0
  WINPR_ASSERT(context);
470
0
  return utils_reload_channels(context);
471
0
}
472
473
BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module)
474
0
{
475
0
  WINPR_ASSERT(log);
476
0
  WINPR_ASSERT(context);
477
478
0
  rdpSettings* settings = context->settings;
479
0
  WINPR_ASSERT(settings);
480
481
0
  if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
482
0
  {
483
0
    WLog_Print(log, WLOG_DEBUG, "[%s] policy allows all redirections", module);
484
0
  }
485
0
  else if (freerdp_settings_get_bool(settings, FreeRDP_GatewayIgnoreRedirectionPolicy))
486
0
  {
487
0
    char buffer[128] = WINPR_C_ARRAY_INIT;
488
0
    WLog_Print(log, WLOG_INFO, "[%s] policy ignored on user request %s", module,
489
0
               utils_redir_flags_to_string(flags, buffer, sizeof(buffer)));
490
0
  }
491
0
  else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
492
0
  {
493
0
    WLog_Print(log, WLOG_INFO, "[%s] policy denies all redirections", module);
494
0
    if (!disable_drive(settings))
495
0
      return FALSE;
496
0
    if (!disable_printers(settings))
497
0
      return FALSE;
498
0
    if (!disable_clipboard(settings))
499
0
      return FALSE;
500
0
    if (!disable_port(settings))
501
0
      return FALSE;
502
0
    if (!disable_pnp(settings))
503
0
      return FALSE;
504
0
    if (!apply_gw_policy(context))
505
0
      return FALSE;
506
0
  }
507
0
  else
508
0
  {
509
0
    if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
510
0
    {
511
0
      WLog_Print(log, WLOG_INFO, "[%s] policy denies drive redirections", module);
512
0
      if (!disable_drive(settings))
513
0
        return FALSE;
514
0
    }
515
0
    if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
516
0
    {
517
0
      WLog_Print(log, WLOG_INFO, "[%s] policy denies printer redirections", module);
518
0
      if (!disable_printers(settings))
519
0
        return FALSE;
520
0
    }
521
0
    if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
522
0
    {
523
0
      WLog_Print(log, WLOG_INFO, "[%s] policy denies port redirections", module);
524
0
      if (!disable_port(settings))
525
0
        return FALSE;
526
0
    }
527
0
    if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
528
0
    {
529
0
      WLog_Print(log, WLOG_INFO, "[%s] policy denies clipboard redirections", module);
530
0
      if (!disable_clipboard(settings))
531
0
        return FALSE;
532
0
    }
533
0
    if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
534
0
    {
535
0
      WLog_Print(log, WLOG_INFO, "[%s] policy denies PNP redirections", module);
536
0
      if (!disable_pnp(settings))
537
0
        return FALSE;
538
0
    }
539
0
    if (flags != 0)
540
0
    {
541
0
      if (!apply_gw_policy(context))
542
0
        return FALSE;
543
0
    }
544
0
  }
545
0
  return TRUE;
546
0
}
547
548
char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size)
549
0
{
550
0
  winpr_str_append("{", buffer, size, "");
551
0
  if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
552
0
    winpr_str_append("ENABLE_ALL", buffer, size, "|");
553
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
554
0
    winpr_str_append("DISABLE_ALL", buffer, size, "|");
555
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
556
0
    winpr_str_append("DISABLE_DRIVE", buffer, size, "|");
557
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
558
0
    winpr_str_append("DISABLE_PRINTER", buffer, size, "|");
559
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
560
0
    winpr_str_append("DISABLE_PORT", buffer, size, "|");
561
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
562
0
    winpr_str_append("DISABLE_CLIPBOARD", buffer, size, "|");
563
0
  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
564
0
    winpr_str_append("DISABLE_PNP", buffer, size, "|");
565
566
0
  char fbuffer[16] = WINPR_C_ARRAY_INIT;
567
0
  (void)_snprintf(fbuffer, sizeof(fbuffer), "[0x%08" PRIx32 "]", flags);
568
569
0
  winpr_str_append(fbuffer, buffer, size, " ");
570
0
  winpr_str_append("{", buffer, size, "}");
571
0
  return buffer;
572
0
}
573
574
BOOL utils_reload_channels(rdpContext* context)
575
0
{
576
0
  WINPR_ASSERT(context);
577
578
0
  if (context->channels)
579
0
  {
580
0
    freerdp_channels_disconnect(context->channels, context->instance);
581
0
    freerdp_channels_close(context->channels, context->instance);
582
0
    freerdp_channels_free(context->channels);
583
0
  }
584
585
0
  context->channels = freerdp_channels_new(context->instance);
586
0
  if (!context->channels)
587
0
    return FALSE;
588
589
0
  freerdp_channels_register_instance(context->channels, context->instance);
590
591
0
  BOOL rc = TRUE;
592
0
  IFCALLRET(context->instance->LoadChannels, rc, context->instance);
593
0
  if (rc)
594
0
    return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
595
0
  return rc;
596
0
}
597
598
const char* guid2str(const GUID* guid, char* buffer, size_t len)
599
98.4k
{
600
98.4k
  if (!guid)
601
0
    return nullptr;
602
98.4k
  RPC_CSTR strguid = nullptr;
603
604
98.4k
  RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
605
606
98.4k
  if (rpcStatus != RPC_S_OK)
607
0
    return nullptr;
608
609
98.4k
  (void)sprintf_s(buffer, len, "%s", strguid);
610
98.4k
  RpcStringFreeA(&strguid);
611
98.4k
  return buffer;
612
98.4k
}
613
614
WINPR_ATTR_NODISCARD
615
static BOOL isValidIPv4(const char* ipAddress)
616
8
{
617
8
  struct sockaddr_in sa = WINPR_C_ARRAY_INIT;
618
8
  int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
619
8
  return result != 0;
620
8
}
621
622
WINPR_ATTR_NODISCARD
623
static BOOL isValidIPv6(const char* ipAddress)
624
8
{
625
8
  struct sockaddr_in6 sa = WINPR_C_ARRAY_INIT;
626
8
  int result = inet_pton(AF_INET6, ipAddress, &(sa.sin6_addr));
627
8
  return result != 0;
628
8
}
629
630
BOOL utils_is_valid_ip(const char* ipAddress)
631
8
{
632
8
  return isValidIPv4(ipAddress) || isValidIPv6(ipAddress);
633
8
}
634
635
BOOL utils_set_umask(void)
636
14.3k
{
637
14.3k
#if !defined(_WIN32)
638
14.3k
  (void)umask(S_IRWXG | S_IRWXO);
639
14.3k
#endif
640
14.3k
  return TRUE;
641
14.3k
}
642
643
BOOL utils_compare_ip_strings(const char* ipAddressA, size_t lenA, const char* ipAddressB,
644
                              size_t lenB)
645
0
{
646
0
  if (!ipAddressA || (lenA == 0))
647
0
    return FALSE;
648
0
  if (!ipAddressB || (lenB == 0))
649
0
    return FALSE;
650
0
  if (strnlen(ipAddressA, lenA + 1) > lenA)
651
0
    return FALSE;
652
0
  if (strnlen(ipAddressB, lenB + 1) > lenB)
653
0
    return FALSE;
654
655
0
  if (isValidIPv4(ipAddressA) && isValidIPv4(ipAddressB))
656
0
  {
657
0
    struct sockaddr_in sa = WINPR_C_ARRAY_INIT;
658
0
    struct sockaddr_in sb = WINPR_C_ARRAY_INIT;
659
0
    const int resultA = inet_pton(AF_INET, ipAddressA, &(sa.sin_addr));
660
0
    const int resultB = inet_pton(AF_INET, ipAddressB, &(sb.sin_addr));
661
0
    if ((resultA != resultB) || (resultA != 0))
662
0
      return FALSE;
663
0
    return memcmp(&sa, &sb, sizeof(sa)) == 0;
664
0
  }
665
0
  if (isValidIPv6(ipAddressA) && isValidIPv6(ipAddressB))
666
0
  {
667
0
    struct sockaddr_in6 sa = WINPR_C_ARRAY_INIT;
668
0
    struct sockaddr_in6 sb = WINPR_C_ARRAY_INIT;
669
0
    const int resultA = inet_pton(AF_INET6, ipAddressA, &(sa.sin6_addr));
670
0
    const int resultB = inet_pton(AF_INET6, ipAddressB, &(sb.sin6_addr));
671
0
    if ((resultA != resultB) || (resultA != 0))
672
0
      return FALSE;
673
0
    return memcmp(&sa, &sb, sizeof(sa)) == 0;
674
0
  }
675
0
  return FALSE;
676
0
}