Added config dump function, improved resource cleanup

This commit is contained in:
Armin Novak 2021-09-07 13:42:33 +02:00 committed by akallabeth
parent 4daa09c3e5
commit 4463e5eda9
6 changed files with 182 additions and 29 deletions

View File

@ -93,6 +93,13 @@ extern "C"
{
#endif
/**
* @brief pf_server_config_dump Dumps a default INI configuration file
* @param file The file to write to. Existing files are truncated.
* @return TRUE for success, FALSE if the file could not be written.
*/
FREERDP_API BOOL pf_server_config_dump(const char* file);
/**
* @brief server_config_load_ini Create a proxyConfig from a already loaded
* INI file.

View File

@ -69,6 +69,16 @@ static void pf_server_register_signal_handlers(void)
#endif
}
static WINPR_NORETURN(void usage(const char* app))
{
printf("Usage:\n");
printf("%s -h Display this help text.\n", app);
printf("%s --help Display this help text.\n", app);
printf("%s <config ini file> Start the proxy with <config.ini>\n", app);
printf("%s --dump-config <config ini file> Create a template <config.ini>\n", app);
exit(0);
}
int main(int argc, char* argv[])
{
proxyConfig* config = NULL;
@ -82,8 +92,27 @@ int main(int argc, char* argv[])
WLog_INFO(TAG, "\tGit commit: %s", FREERDP_GIT_REVISION);
WLog_DBG(TAG, "\tBuild config: %s", freerdp_get_build_config());
if (argc >= 2)
if (argc < 2)
usage(argv[0]);
{
const char* arg = argv[1];
if (_stricmp(arg, "-h") == 0)
usage(argv[0]);
else if (_stricmp(arg, "--help") == 0)
usage(argv[0]);
else if (_stricmp(arg, "--dump-config") == 0)
{
if (argc <= 2)
usage(argv[0]);
pf_server_config_dump(argv[2]);
status = 0;
goto fail;
}
config_path = argv[1];
}
config = pf_server_config_load_file(config_path);
if (!config)

View File

@ -681,18 +681,19 @@ out:
* Connects RDP, loops while running and handles event and dispatch, cleans up
* after the connection ends.
*/
static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
static DWORD WINAPI pf_client_thread_proc(pClientContext* pc)
{
freerdp* instance = (freerdp*)arg;
pClientContext* pc;
freerdp* instance;
proxyData* pdata;
DWORD nCount = 0;
DWORD status;
HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
WINPR_ASSERT(instance);
pc = (pClientContext*)instance->context;
WINPR_ASSERT(pc);
instance = pc->context.instance;
WINPR_ASSERT(instance);
pdata = pc->pdata;
WINPR_ASSERT(pdata);
/*
@ -904,17 +905,6 @@ static int pf_client_client_stop(rdpContext* context)
proxy_data_abort_connect(pdata);
freerdp_abort_connect(context->instance);
if (pdata->client_thread)
{
/*
* Wait for client thread to finish. No need to call CloseHandle() here, as
* it is the responsibility of `proxy_data_free`.
*/
PROXY_LOG_DBG(TAG, pc, "waiting for client thread to finish");
WaitForSingleObject(pdata->client_thread, INFINITE);
PROXY_LOG_DBG(TAG, pc, "thread finished");
}
return 0;
}
@ -938,11 +928,12 @@ int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
*/
DWORD WINAPI pf_client_start(LPVOID arg)
{
rdpContext* context = (rdpContext*)arg;
DWORD rc = 1;
pClientContext* pc = (pClientContext*)arg;
WINPR_ASSERT(context);
if (freerdp_client_start(context) != 0)
return 1;
return pf_client_thread_proc(context->instance);
WINPR_ASSERT(pc);
if (freerdp_client_start(&pc->context) == 0)
rc = pf_client_thread_proc(pc);
freerdp_client_stop(&pc->context);
return rc;
}

View File

@ -437,6 +437,116 @@ out:
return NULL;
}
BOOL pf_server_config_dump(const char* file)
{
BOOL rc = FALSE;
wIniFile* ini = IniFile_New();
if (!ini)
return FALSE;
/* Proxy server configuration */
if (IniFile_SetKeyValueString(ini, "Server", "Host", "0.0.0.0") < 0)
goto fail;
if (IniFile_SetKeyValueInt(ini, "Server", "Port", 3389) < 0)
goto fail;
/* Target configuration */
if (IniFile_SetKeyValueString(ini, "Target", "Host", "somehost.example.com") < 0)
goto fail;
if (IniFile_SetKeyValueInt(ini, "Target", "Port", 3389) < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Target", "FixedTarget", "true") < 0)
goto fail;
/* Channel configuration */
if (IniFile_SetKeyValueString(ini, "Channels", "GFX", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "DisplayControl", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "Clipboard", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "AudioOutput", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "RemoteApp", "false") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "PassthroughIsBlacklist", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Channels", "Passthrough", "") < 0)
goto fail;
/* Input configuration */
if (IniFile_SetKeyValueString(ini, "Input", "Keyboard", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Input", "Mouse", "true") < 0)
goto fail;
/* Security settings */
if (IniFile_SetKeyValueString(ini, "Security", "ServerTlsSecurity", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ServerNlaSecurity", "false") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ServerRdpSecurity", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ClientTlsSecurity", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ClientNlaSecurity", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ClientRdpSecurity", "true") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Security", "ClientAllowFallbackToTls", "true") < 0)
goto fail;
/* Module configuration */
if (IniFile_SetKeyValueString(ini, "Plugins", "Modules", "module1,module2,...") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Plugins", "Required", "module1,module2,...") < 0)
goto fail;
/* Clipboard configuration */
if (IniFile_SetKeyValueString(ini, "Clipboard", "TextOnly", "false") < 0)
goto fail;
if (IniFile_SetKeyValueInt(ini, "Clipboard", "MaxTextLength", 0) < 0)
goto fail;
/* GFX configuration */
if (IniFile_SetKeyValueString(ini, "GFXSettings", "DecodeGFX", "false") < 0)
goto fail;
/* Certificate configuration */
if (IniFile_SetKeyValueString(ini, "Certificates", "CertificateFile",
"<absolute path to some certificate file> OR") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Certificates", "CertificateContent",
"<Contents of some certificate file in PEM format>") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Certificates", "PrivateKeyFile",
"<absolute path to some private key file> OR") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Certificates", "PrivateKeyContent",
"<Contents of some private key file in PEM format>") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Certificates", "RdpKeyFile",
"<absolute path to some private key file> OR") < 0)
goto fail;
if (IniFile_SetKeyValueString(ini, "Certificates", "RdpKeyContent",
"<Contents of some private key file in PEM format>") < 0)
goto fail;
/* store configuration */
if (IniFile_WriteFile(ini, file) < 0)
goto fail;
rc = TRUE;
fail:
IniFile_Free(ini);
return rc;
}
proxyConfig* pf_server_config_load_buffer(const char* buffer)
{
proxyConfig* config = NULL;

View File

@ -259,6 +259,9 @@ void proxy_data_free(proxyData* pdata)
if (pdata->modules_info)
HashTable_Free(pdata->modules_info);
if (pdata->pc)
freerdp_client_context_free(&pdata->pc->context);
free(pdata);
}

View File

@ -127,10 +127,13 @@ static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings
case PROXY_FETCH_TARGET_METHOD_CONFIG:
{
WINPR_ASSERT(config);
settings->ServerPort = config->TargetPort > 0 ? 3389 : settings->ServerPort;
settings->ServerHostname = _strdup(config->TargetHost);
if (!settings->ServerHostname)
if (config->TargetPort > 0)
freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, config->TargetPort);
else
freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, 3389);
if (!freerdp_settings_set_string(settings, FreeRDP_ServerHostname, config->TargetHost))
{
PROXY_LOG_ERR(TAG, ps, "strdup failed!");
return FALSE;
@ -558,16 +561,26 @@ fail:
PROXY_LOG_INFO(TAG, ps, "starting shutdown of connection");
PROXY_LOG_INFO(TAG, ps, "stopping proxy's client");
pc = (rdpContext*)pdata->pc;
freerdp_client_stop(pc);
if (pdata->client_thread)
{
if (pdata->pc)
freerdp_abort_connect(pdata->pc->context.instance);
/*
* Wait for client thread to finish. No need to call CloseHandle() here, as
* it is the responsibility of `proxy_data_free`.
*/
PROXY_LOG_DBG(TAG, pdata->pc, "waiting for client thread to finish");
WaitForSingleObject(pdata->client_thread, INFINITE);
PROXY_LOG_DBG(TAG, pdata->pc, "thread finished");
}
pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_END, pdata, client);
PROXY_LOG_INFO(TAG, ps, "freeing server's channels");
pf_server_channels_free(ps, client);
PROXY_LOG_INFO(TAG, ps, "freeing proxy data");
ArrayList_Remove(server->clients, pdata);
proxy_data_free(pdata);
freerdp_client_context_free(pc);
WINPR_ASSERT(client->Close);
client->Close(client);