FreeRDP
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 
38 BOOL 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 
51 static 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 
66 auth_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 
136 auth_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 
229 BOOL 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 
256 BOOL utils_str_is_empty(const char* str)
257 {
258  if (!str)
259  return TRUE;
260  if (*str == '\0')
261  return TRUE;
262  return FALSE;
263 }
264 
265 BOOL utils_abort_connect(rdpRdp* rdp)
266 {
267  if (!rdp)
268  return FALSE;
269 
270  return SetEvent(rdp->abortEvent);
271 }
272 
273 BOOL utils_reset_abort(rdpRdp* rdp)
274 {
275  WINPR_ASSERT(rdp);
276 
277  return ResetEvent(rdp->abortEvent);
278 }
279 
280 HANDLE utils_get_abort_event(rdpRdp* rdp)
281 {
282  WINPR_ASSERT(rdp);
283  return rdp->abortEvent;
284 }
285 
286 BOOL utils_abort_event_is_set(const rdpRdp* rdp)
287 {
288  DWORD status = 0;
289  WINPR_ASSERT(rdp);
290  status = WaitForSingleObject(rdp->abortEvent, 0);
291  return status == WAIT_OBJECT_0;
292 }
293 
294 const char* utils_is_vsock(const char* hostname)
295 {
296  if (!hostname)
297  return NULL;
298 
299  const char vsock[8] = "vsock://";
300  if (strncmp(hostname, vsock, sizeof(vsock)) == 0)
301  return &hostname[sizeof(vsock)];
302  return NULL;
303 }
304 
305 static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
306 {
307  RDPDR_DEVICE* printer = NULL;
308  do
309  {
310  printer = freerdp_device_collection_find_type(settings, type);
311  freerdp_device_collection_del(settings, printer);
312  freerdp_device_free(printer);
313  } while (printer);
314  return TRUE;
315 }
316 
317 static BOOL disable_clipboard(rdpSettings* settings)
318 {
319  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, FALSE))
320  return FALSE;
321  freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
322  return TRUE;
323 }
324 
325 static BOOL disable_drive(rdpSettings* settings)
326 {
327  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, FALSE))
328  return FALSE;
329  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, FALSE))
330  return FALSE;
331 
332  return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
333 }
334 
335 static BOOL disable_printers(rdpSettings* settings)
336 {
337  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters, FALSE))
338  return FALSE;
339 
340  return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
341 }
342 
343 static BOOL disable_port(rdpSettings* settings)
344 {
345  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts, FALSE))
346  return FALSE;
347  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts, FALSE))
348  return FALSE;
349  if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
350  return FALSE;
351  return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
352 }
353 
354 static BOOL disable_pnp(rdpSettings* settings)
355 {
356  // TODO(akallabeth): [MS-RDPEPNP] related stuff is disabled.
357  return TRUE;
358 }
359 
360 static BOOL apply_gw_policy(rdpContext* context)
361 {
362  WINPR_ASSERT(context);
363  return utils_reload_channels(context);
364 }
365 
366 BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module)
367 {
368  WINPR_ASSERT(log);
369  WINPR_ASSERT(context);
370 
371  rdpSettings* settings = context->settings;
372  WINPR_ASSERT(settings);
373 
374  if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
375  {
376  WLog_Print(log, WLOG_DEBUG, "[%s] policy allows all redirections", module);
377  }
378  else if (freerdp_settings_get_bool(settings, FreeRDP_GatewayIgnoreRedirectionPolicy))
379  {
380  char buffer[128] = { 0 };
381  WLog_Print(log, WLOG_INFO, "[%s] policy ignored on user request %s", module,
382  utils_redir_flags_to_string(flags, buffer, sizeof(buffer)));
383  }
384  else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
385  {
386  WLog_Print(log, WLOG_INFO, "[%s] policy denies all redirections", module);
387  if (!disable_drive(settings))
388  return FALSE;
389  if (!disable_printers(settings))
390  return FALSE;
391  if (!disable_clipboard(settings))
392  return FALSE;
393  if (!disable_port(settings))
394  return FALSE;
395  if (!disable_pnp(settings))
396  return FALSE;
397  if (!apply_gw_policy(context))
398  return FALSE;
399  }
400  else
401  {
402  if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
403  {
404  WLog_Print(log, WLOG_INFO, "[%s] policy denies drive redirections", module);
405  if (!disable_drive(settings))
406  return FALSE;
407  }
408  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
409  {
410  WLog_Print(log, WLOG_INFO, "[%s] policy denies printer redirections", module);
411  if (!disable_printers(settings))
412  return FALSE;
413  }
414  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
415  {
416  WLog_Print(log, WLOG_INFO, "[%s] policy denies port redirections", module);
417  if (!disable_port(settings))
418  return FALSE;
419  }
420  if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
421  {
422  WLog_Print(log, WLOG_INFO, "[%s] policy denies clipboard redirections", module);
423  if (!disable_clipboard(settings))
424  return FALSE;
425  }
426  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
427  {
428  WLog_Print(log, WLOG_INFO, "[%s] policy denies PNP redirections", module);
429  if (!disable_pnp(settings))
430  return FALSE;
431  }
432  if (flags != 0)
433  {
434  if (!apply_gw_policy(context))
435  return FALSE;
436  }
437  }
438  return TRUE;
439 }
440 
441 char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size)
442 {
443  winpr_str_append("{", buffer, size, "");
444  if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
445  winpr_str_append("ENABLE_ALL", buffer, size, "|");
446  if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
447  winpr_str_append("DISABLE_ALL", buffer, size, "|");
448  if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
449  winpr_str_append("DISABLE_DRIVE", buffer, size, "|");
450  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
451  winpr_str_append("DISABLE_PRINTER", buffer, size, "|");
452  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
453  winpr_str_append("DISABLE_PORT", buffer, size, "|");
454  if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
455  winpr_str_append("DISABLE_CLIPBOARD", buffer, size, "|");
456  if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
457  winpr_str_append("DISABLE_PNP", buffer, size, "|");
458 
459  char fbuffer[16] = { 0 };
460  (void)_snprintf(fbuffer, sizeof(fbuffer), "[0x%08" PRIx32 "]", flags);
461 
462  winpr_str_append(fbuffer, buffer, size, " ");
463  winpr_str_append("{", buffer, size, "}");
464  return buffer;
465 }
466 
467 BOOL utils_reload_channels(rdpContext* context)
468 {
469  WINPR_ASSERT(context);
470 
471  freerdp_channels_disconnect(context->channels, context->instance);
472  freerdp_channels_close(context->channels, context->instance);
473  freerdp_channels_free(context->channels);
474  context->channels = freerdp_channels_new(context->instance);
475  WINPR_ASSERT(context->channels);
476 
477  BOOL rc = TRUE;
478  IFCALLRET(context->instance->LoadChannels, rc, context->instance);
479  if (rc)
480  return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
481  return rc;
482 }
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
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_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 BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.