server: proxy: implement NLA fallback
authorkubistika <kmizrachi18@gmail.com>
Mon, 15 Jul 2019 07:55:57 +0000 (10:55 +0300)
committerakallabeth <akallabeth@users.noreply.github.com>
Mon, 15 Jul 2019 09:52:30 +0000 (11:52 +0200)
server/proxy/pf_client.c
server/proxy/pf_context.h

index a313105..31ea8aa 100644 (file)
@@ -208,7 +208,14 @@ static void pf_client_post_disconnect(freerdp* instance)
        PubSub_UnsubscribeErrorInfo(instance->context->pubSub, pf_OnErrorInfo);
        gdi_free(instance);
 
-       SetEvent(pdata->connectionClosed);
+       if (!context->during_connect_process)
+       {
+               /* proxy's client failed to connect, and now it's trying to connect without NLA, no need to shutdown
+                * the connection between proxy's server and the original client.
+                */
+               SetEvent(pdata->connectionClosed);
+       }
+
        /* It's important to avoid calling `freerdp_peer_context_free` and `freerdp_peer_free` here,
         * in order to avoid double-free. Those objects will be freed by the server when needed.
         */
@@ -222,16 +229,38 @@ static void pf_client_post_disconnect(freerdp* instance)
 static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
 {
        freerdp* instance = (freerdp*)arg;
+       pClientContext* pc = (pClientContext*)instance->context;
        DWORD nCount;
        DWORD status;
        HANDLE handles[64];
 
+       pc->during_connect_process = TRUE;
        if (!freerdp_connect(instance))
        {
-               WLog_ERR(TAG, "connection failure");
-               return 0;
+               if (instance->settings->NlaSecurity)
+               {
+                       WLog_ERR(TAG, "freerdp_connect() failed, trying to connect without NLA");
+                       /* disable NLA, enable TLS */
+                       instance->settings->NlaSecurity = FALSE;
+                       instance->settings->RdpSecurity = TRUE;
+                       instance->settings->TlsSecurity = TRUE;
+
+                       pc->during_connect_process = FALSE;
+                       if (!freerdp_connect(instance))
+                       {
+                               WLog_ERR(TAG, "connection failure");
+                               return 0;
+                       }
+               }
+               else
+               {
+                       WLog_ERR(TAG, "connection failure");
+                       return 0;
+               }
        }
 
+       pc->during_connect_process = FALSE;
+
        while (!freerdp_shall_disconnect(instance))
        {
                nCount = freerdp_get_event_handles(instance->context, &handles[0], 64);
index 2cd7fe6..b8ef9c8 100644 (file)
@@ -68,6 +68,15 @@ struct p_client_context
        RdpeiClientContext* rdpei;
        RdpgfxClientContext* gfx;
        DispClientContext* disp;
+
+       /*
+        * Used for NLA fallback feature, to check if the server should close the connection.
+        * When it is set to TRUE, proxy's client knows it shouldn't signal the server thread to closed
+        * the connection when pf_client_post_disconnect is called, because it is trying to connect reconnect without NLA.
+        * It must be set to TRUE before the first try, and to FALSE after the connection fully established,
+        * to ensure graceful shutdown of the connection when it will be closed.
+        */
+       BOOL during_connect_process;
 };
 typedef struct p_client_context pClientContext;