summaryrefslogtreecommitdiffstats
path: root/libfreerdp/core/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfreerdp/core/utils.c')
-rw-r--r--libfreerdp/core/utils.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/libfreerdp/core/utils.c b/libfreerdp/core/utils.c
new file mode 100644
index 0000000..1bcb090
--- /dev/null
+++ b/libfreerdp/core/utils.c
@@ -0,0 +1,301 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Terminal Server Gateway (utils)
+ *
+ * Copyright 2021 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2021 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include "settings.h"
+
+#include <winpr/assert.h>
+
+#include <freerdp/freerdp.h>
+
+#include <freerdp/log.h>
+#define TAG FREERDP_TAG("core.gateway.utils")
+
+#include "utils.h"
+
+#include "../core/rdp.h"
+
+BOOL utils_str_copy(const char* value, char** dst)
+{
+ WINPR_ASSERT(dst);
+
+ free(*dst);
+ *dst = NULL;
+ if (!value)
+ return TRUE;
+
+ (*dst) = _strdup(value);
+ return (*dst) != NULL;
+}
+
+static BOOL utils_copy_smartcard_settings(const rdpSettings* settings, rdpSettings* origSettings)
+{
+ /* update original settings with provided smart card settings */
+ origSettings->SmartcardLogon = settings->SmartcardLogon;
+ origSettings->PasswordIsSmartcardPin = settings->PasswordIsSmartcardPin;
+ if (!utils_str_copy(settings->ReaderName, &origSettings->ReaderName))
+ return FALSE;
+ if (!utils_str_copy(settings->CspName, &origSettings->CspName))
+ return FALSE;
+ if (!utils_str_copy(settings->ContainerName, &origSettings->ContainerName))
+ return FALSE;
+
+ return TRUE;
+}
+
+auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason)
+{
+ rdpSettings* settings = NULL;
+ rdpSettings* origSettings = NULL;
+ BOOL prompt = FALSE;
+ BOOL proceed = 0;
+
+ WINPR_ASSERT(instance);
+ WINPR_ASSERT(instance->context);
+ WINPR_ASSERT(instance->context->settings);
+ WINPR_ASSERT(instance->context->rdp);
+ WINPR_ASSERT(instance->context->rdp->originalSettings);
+
+ settings = instance->context->settings;
+ origSettings = instance->context->rdp->originalSettings;
+
+ if (freerdp_shall_disconnect_context(instance->context))
+ return AUTH_FAILED;
+
+ if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayPassword)))
+ prompt = TRUE;
+ if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_GatewayUsername)))
+ prompt = TRUE;
+
+ if (!prompt)
+ return AUTH_SKIP;
+
+ if (!instance->GatewayAuthenticate && !instance->AuthenticateEx)
+ return AUTH_NO_CREDENTIALS;
+
+ if (!instance->GatewayAuthenticate)
+ {
+ proceed =
+ instance->AuthenticateEx(instance, &settings->GatewayUsername,
+ &settings->GatewayPassword, &settings->GatewayDomain, reason);
+ if (!proceed)
+ return AUTH_CANCELLED;
+ }
+ else
+ {
+ proceed =
+ instance->GatewayAuthenticate(instance, &settings->GatewayUsername,
+ &settings->GatewayPassword, &settings->GatewayDomain);
+ if (!proceed)
+ return AUTH_CANCELLED;
+ }
+
+ if (utils_str_is_empty(settings->GatewayUsername) ||
+ utils_str_is_empty(settings->GatewayPassword))
+ return AUTH_NO_CREDENTIALS;
+
+ if (!utils_sync_credentials(settings, FALSE))
+ return AUTH_FAILED;
+
+ /* update original settings with provided user credentials */
+ if (!utils_str_copy(settings->GatewayUsername, &origSettings->GatewayUsername))
+ return AUTH_FAILED;
+ if (!utils_str_copy(settings->GatewayDomain, &origSettings->GatewayDomain))
+ return AUTH_FAILED;
+ if (!utils_str_copy(settings->GatewayPassword, &origSettings->GatewayPassword))
+ return AUTH_FAILED;
+ if (!utils_sync_credentials(origSettings, FALSE))
+ return AUTH_FAILED;
+
+ if (!utils_copy_smartcard_settings(settings, origSettings))
+ return AUTH_FAILED;
+
+ return AUTH_SUCCESS;
+}
+
+auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL override)
+{
+ rdpSettings* settings = NULL;
+ rdpSettings* origSettings = NULL;
+ BOOL prompt = !override;
+ BOOL proceed = 0;
+
+ WINPR_ASSERT(instance);
+ WINPR_ASSERT(instance->context);
+ WINPR_ASSERT(instance->context->settings);
+ WINPR_ASSERT(instance->context->rdp);
+ WINPR_ASSERT(instance->context->rdp->originalSettings);
+
+ settings = instance->context->settings;
+ origSettings = instance->context->rdp->originalSettings;
+
+ if (freerdp_shall_disconnect_context(instance->context))
+ return AUTH_FAILED;
+
+ if (settings->ConnectChildSession)
+ return AUTH_NO_CREDENTIALS;
+
+ /* Ask for auth data if no or an empty username was specified or no password was given */
+ if (utils_str_is_empty(freerdp_settings_get_string(settings, FreeRDP_Username)) ||
+ (settings->Password == NULL && settings->RedirectionPassword == NULL))
+ prompt = TRUE;
+
+ if (!prompt)
+ return AUTH_SKIP;
+
+ switch (reason)
+ {
+ case AUTH_RDP:
+ case AUTH_TLS:
+ if (settings->SmartcardLogon)
+ {
+ if (!utils_str_is_empty(settings->Password))
+ {
+ WLog_INFO(TAG, "Authentication via smartcard");
+ return AUTH_SUCCESS;
+ }
+ reason = AUTH_SMARTCARD_PIN;
+ }
+ break;
+ case AUTH_NLA:
+ if (settings->SmartcardLogon)
+ reason = AUTH_SMARTCARD_PIN;
+ break;
+ default:
+ break;
+ }
+
+ /* If no callback is specified still continue connection */
+ if (!instance->Authenticate && !instance->AuthenticateEx)
+ return AUTH_NO_CREDENTIALS;
+
+ if (!instance->Authenticate)
+ {
+ proceed = instance->AuthenticateEx(instance, &settings->Username, &settings->Password,
+ &settings->Domain, reason);
+ if (!proceed)
+ return AUTH_CANCELLED;
+ }
+ else
+ {
+ proceed = instance->Authenticate(instance, &settings->Username, &settings->Password,
+ &settings->Domain);
+ if (!proceed)
+ return AUTH_NO_CREDENTIALS;
+ }
+
+ if (utils_str_is_empty(settings->Username) || utils_str_is_empty(settings->Password))
+ return AUTH_NO_CREDENTIALS;
+
+ if (!utils_sync_credentials(settings, TRUE))
+ return AUTH_FAILED;
+
+ /* update original settings with provided user credentials */
+ if (!utils_str_copy(settings->Username, &origSettings->Username))
+ return AUTH_FAILED;
+ if (!utils_str_copy(settings->Domain, &origSettings->Domain))
+ return AUTH_FAILED;
+ if (!utils_str_copy(settings->Password, &origSettings->Password))
+ return AUTH_FAILED;
+ if (!utils_sync_credentials(origSettings, TRUE))
+ return AUTH_FAILED;
+
+ if (!utils_copy_smartcard_settings(settings, origSettings))
+ return AUTH_FAILED;
+
+ return AUTH_SUCCESS;
+}
+
+BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway)
+{
+ WINPR_ASSERT(settings);
+ if (!settings->GatewayUseSameCredentials)
+ return TRUE;
+
+ if (toGateway)
+ {
+ if (!utils_str_copy(settings->Username, &settings->GatewayUsername))
+ return FALSE;
+ if (!utils_str_copy(settings->Domain, &settings->GatewayDomain))
+ return FALSE;
+ if (!utils_str_copy(settings->Password, &settings->GatewayPassword))
+ return FALSE;
+ }
+ else
+ {
+ if (!utils_str_copy(settings->GatewayUsername, &settings->Username))
+ return FALSE;
+ if (!utils_str_copy(settings->GatewayDomain, &settings->Domain))
+ return FALSE;
+ if (!utils_str_copy(settings->GatewayPassword, &settings->Password))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL utils_str_is_empty(const char* str)
+{
+ if (!str)
+ return TRUE;
+ if (strlen(str) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+BOOL utils_abort_connect(rdpRdp* rdp)
+{
+ if (!rdp)
+ return FALSE;
+
+ return SetEvent(rdp->abortEvent);
+}
+
+BOOL utils_reset_abort(rdpRdp* rdp)
+{
+ WINPR_ASSERT(rdp);
+
+ return ResetEvent(rdp->abortEvent);
+}
+
+HANDLE utils_get_abort_event(rdpRdp* rdp)
+{
+ WINPR_ASSERT(rdp);
+ return rdp->abortEvent;
+}
+
+BOOL utils_abort_event_is_set(rdpRdp* rdp)
+{
+ DWORD status = 0;
+ WINPR_ASSERT(rdp);
+ status = WaitForSingleObject(rdp->abortEvent, 0);
+ return status == WAIT_OBJECT_0;
+}
+
+const char* utils_is_vsock(const char* hostname)
+{
+ if (!hostname)
+ return NULL;
+
+ const char vsock[8] = "vsock://";
+ if (strncmp(hostname, vsock, sizeof(vsock)) == 0)
+ return &hostname[sizeof(vsock)];
+ return NULL;
+}