server: proxy: separate client and server security settings
authorkubistika <kmizrachi18@gmail.com>
Wed, 18 Sep 2019 13:08:25 +0000 (16:08 +0300)
committerakallabeth <akallabeth@users.noreply.github.com>
Mon, 30 Sep 2019 08:07:43 +0000 (10:07 +0200)
server/proxy/config.ini
server/proxy/pf_client.c
server/proxy/pf_config.c
server/proxy/pf_config.h
server/proxy/pf_server.c

index ec5611d..4e8edb6 100644 (file)
@@ -19,9 +19,11 @@ Mouse = 1
 Keyboard = 1
 
 [Security]
-NlaSecurity = 0
-TlsSecurity = 1
-RdpSecurity = 1
+ServerTlsSecurity = 1
+ServerRdpSecurity = 0
+ClientTlsSecurity = 1
+ClientRdpSecurity = 0
+ClientNlaSecurity = 0
 
 [Channels]
 GFX = 1
index 91dc274..7bd2b5c 100644 (file)
@@ -266,47 +266,94 @@ static void pf_client_post_disconnect(freerdp* instance)
                proxy_data_abort_connect(pdata);
 }
 
+/*
+ * pf_client_should_retry_without_nla:
+ *
+ * returns TRUE if in case of connection failure, the client should try again without NLA.
+ * Otherwise, returns FALSE.
+ */
+static BOOL pf_client_should_retry_without_nla(pClientContext* pc)
+{
+       rdpSettings* settings = pc->context.settings;
+       proxyConfig* config = pc->pdata->config;
+
+       if (!settings->NlaSecurity)
+               return FALSE;
+
+       return config->ClientTlsSecurity || config->ClientRdpSecurity;
+}
+
+static void pf_client_set_security_settings(pClientContext* pc)
+{
+       rdpSettings* settings = pc->context.settings;
+       proxyConfig* config = pc->pdata->config;
+
+       settings->RdpSecurity = config->ClientRdpSecurity;
+       settings->TlsSecurity = config->ClientTlsSecurity;
+       settings->NlaSecurity = FALSE;
+
+       if (!config->ClientNlaSecurity)
+               return;
+
+       if (!settings->Username || !settings->Password)
+               return;
+
+       settings->NlaSecurity = TRUE;
+}
+
+static BOOL pf_client_connect_without_nla(pClientContext* pc)
+{
+       freerdp* instance = pc->context.instance;
+       rdpSettings* settings = pc->context.settings;
+
+       /* disable NLA */
+       settings->NlaSecurity = FALSE;
+
+       /* do not allow next connection failure */
+       pc->allow_next_conn_failure = FALSE;
+       return freerdp_connect(instance);
+}
+
 static BOOL pf_client_connect(freerdp* instance)
 {
        pClientContext* pc = (pClientContext*) instance->context;
-       rdpSettings* settings = pc->context.settings;
+       BOOL rc = FALSE;
+       BOOL retry_without_nla = FALSE;
 
-       /* if credentials are available, always try to connect with NLA on first try */
-       if (settings->Username && settings->Password)
-       {
-               settings->NlaSecurity = TRUE;
-               pc->allow_next_conn_failure = TRUE;
-       }
-       else
-               settings->NlaSecurity = FALSE;
+       pf_client_set_security_settings(pc);
+       if (pf_client_should_retry_without_nla(pc))
+               retry_without_nla = pc->allow_next_conn_failure = TRUE;
 
        if (!freerdp_connect(instance))
        {
-               if (settings->NlaSecurity)
-               {
-                       WLog_ERR(TAG, "freerdp_connect() failed, trying to connect without NLA");
+               UINT32 last_error = freerdp_get_last_error(instance->context);
+               UINT32 last_error_type = GET_FREERDP_ERROR_TYPE(last_error);
 
-                       /* disable NLA, enable TLS */
-                       settings->NlaSecurity = FALSE;
-                       settings->RdpSecurity = TRUE;
-                       settings->TlsSecurity = TRUE;
+               /* Do not retry if last error is not ERRCONNECT_LOGON_FAILURE */
+               if (last_error_type != ERRCONNECT_LOGON_FAILURE)
+                       retry_without_nla = FALSE;
 
-                       pc->allow_next_conn_failure = FALSE;
-                       if (!freerdp_connect(instance))
+               if (retry_without_nla)
+               {
+                       WLog_ERR(TAG, "failed to connect with NLA. disabling NLA and retyring...");
+
+                       if (!pf_client_connect_without_nla(pc))
                        {
-                               WLog_ERR(TAG, "connection failure");
-                               return FALSE;
+                               WLog_ERR(TAG, "pf_client_connect_without_nla failed!");
+                               goto out;
                        }
                }
                else
                {
-                       WLog_ERR(TAG, "connection failure");
-                       return FALSE;
+                       WLog_ERR(TAG, "connection failure!");
+                       goto out;
                }
        }
 
+       rc = TRUE;
+out:
        pc->allow_next_conn_failure = FALSE;
-       return TRUE;
+       return rc;
 }
 
 /**
@@ -337,7 +384,10 @@ static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
                return FALSE;
 
        if (!pf_client_connect(instance))
+       {
+               proxy_data_abort_connect(pdata);
                return FALSE;
+       }
 
        while (!freerdp_shall_disconnect(instance))
        {
index 8ccd48f..392da53 100644 (file)
@@ -105,9 +105,12 @@ static BOOL pf_config_load_input(wIniFile* ini, proxyConfig* config)
 
 static BOOL pf_config_load_security(wIniFile* ini, proxyConfig* config)
 {
-       config->TlsSecurity = CONFIG_GET_BOOL(ini, "Security", "TlsSecurity");
-       config->NlaSecurity = CONFIG_GET_BOOL(ini, "Security", "NlaSecurity");
-       config->RdpSecurity = CONFIG_GET_BOOL(ini, "Security", "RdpSecurity");
+       config->ServerTlsSecurity = CONFIG_GET_BOOL(ini, "Security", "ServerTlsSecurity");
+       config->ServerRdpSecurity = CONFIG_GET_BOOL(ini, "Security", "ServerRdpSecurity");
+
+       config->ClientTlsSecurity = CONFIG_GET_BOOL(ini, "Security", "ClientTlsSecurity");
+       config->ClientNlaSecurity = CONFIG_GET_BOOL(ini, "Security", "ClientNlaSecurity");
+       config->ClientRdpSecurity = CONFIG_GET_BOOL(ini, "Security", "ClientRdpSecurity");
        return TRUE;
 }
 
@@ -210,10 +213,14 @@ void pf_server_config_print(proxyConfig* config)
        CONFIG_PRINT_BOOL(config, Keyboard);
        CONFIG_PRINT_BOOL(config, Mouse);
 
-       CONFIG_PRINT_SECTION("Security");
-       CONFIG_PRINT_BOOL(config, NlaSecurity);
-       CONFIG_PRINT_BOOL(config, TlsSecurity);
-       CONFIG_PRINT_BOOL(config, RdpSecurity);
+       CONFIG_PRINT_SECTION("Server Security");
+       CONFIG_PRINT_BOOL(config, ServerTlsSecurity);
+       CONFIG_PRINT_BOOL(config, ServerRdpSecurity);
+
+       CONFIG_PRINT_SECTION("Client Security");
+       CONFIG_PRINT_BOOL(config, ClientNlaSecurity);
+       CONFIG_PRINT_BOOL(config, ClientTlsSecurity);
+       CONFIG_PRINT_BOOL(config, ClientRdpSecurity);
 
        CONFIG_PRINT_SECTION("Channels");
        CONFIG_PRINT_BOOL(config, GFX);
index b42f2f7..553f8bb 100644 (file)
@@ -43,10 +43,14 @@ struct proxy_config
        BOOL Keyboard;
        BOOL Mouse;
 
-       /* security */
-       BOOL NlaSecurity;
-       BOOL TlsSecurity;
-       BOOL RdpSecurity;
+       /* server security */
+       BOOL ServerTlsSecurity;
+       BOOL ServerRdpSecurity;
+
+       /* client security */
+       BOOL ClientNlaSecurity;
+       BOOL ClientTlsSecurity;
+       BOOL ClientRdpSecurity;
 
        /* channels */
        BOOL GFX;
@@ -54,7 +58,7 @@ struct proxy_config
        BOOL Clipboard;
        BOOL AudioOutput;
 
-       /* clipboard specific settings*/
+       /* clipboard specific settings */
        BOOL TextOnly;
        UINT32 MaxTextLength;
 };
index ed36bcd..f3089f3 100644 (file)
@@ -240,9 +240,9 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
                goto out_free_peer;
        }
 
-       client->settings->RdpSecurity = config->RdpSecurity;
-       client->settings->TlsSecurity = config->TlsSecurity;
-       client->settings->NlaSecurity = config->NlaSecurity;
+       client->settings->RdpSecurity = config->ServerRdpSecurity;
+       client->settings->TlsSecurity = config->ServerTlsSecurity;
+       client->settings->NlaSecurity = FALSE; /* currently NLA is not supported in proxy server */
        client->settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
        client->settings->ColorDepth = 32;
        client->settings->SuppressOutput = TRUE;