Proxy cleanups (#7568)

* Fixed C++ issues with proxy context

* Added freerdp_settings_get_string_writable

* Define WITH_PROXY_EMULATE_SMARTCARD in config.h
This commit is contained in:
akallabeth 2022-01-20 11:12:36 +01:00 committed by GitHub
parent 02535ea200
commit 724c6f8192
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 374 additions and 127 deletions

View File

@ -177,5 +177,6 @@
/* Proxy */
#cmakedefine WITH_PROXY_MODULES
#cmakedefine WITH_PROXY_EMULATE_SMARTCARD
#endif /* FREERDP_CONFIG_H */

View File

@ -29,123 +29,124 @@
#define PROXY_SESSION_ID_LENGTH 32
typedef struct proxy_data proxyData;
typedef struct proxy_module proxyModule;
typedef struct channel_data_event_info proxyChannelDataEventInfo;
typedef struct _InterceptContextMapEntry
#ifdef __cplusplus
extern "C"
{
void (*free)(struct _InterceptContextMapEntry*);
} InterceptContextMapEntry;
#endif
/* All proxy interception channels derive from this base struct
* and set their cleanup function accordingly. */
static INLINE void intercept_context_entry_free(void* obj)
{
InterceptContextMapEntry* entry = obj;
if (!entry)
return;
if (!entry->free)
return;
entry->free(entry);
}
typedef struct proxy_data proxyData;
typedef struct proxy_module proxyModule;
typedef struct channel_data_event_info proxyChannelDataEventInfo;
/**
* Wraps rdpContext and holds the state for the proxy's server.
*/
struct p_server_context
{
rdpContext context;
proxyData* pdata;
HANDLE vcm;
HANDLE dynvcReady;
wHashTable* interceptContextMap;
};
typedef struct p_server_context pServerContext;
/**
* Wraps rdpContext and holds the state for the proxy's client.
*/
typedef struct p_client_context pClientContext;
struct p_client_context
{
rdpContext context;
proxyData* pdata;
/*
* In a case when freerdp_connect fails,
* 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 allow_next_conn_failure;
BOOL connected; /* Set after client post_connect. */
pReceiveChannelData client_receive_channel_data_original;
wQueue* cached_server_channel_data;
BOOL (*sendChannelData)(pClientContext* pc, const proxyChannelDataEventInfo* ev);
/* X509 specific */
char* remote_hostname;
wStream* remote_pem;
UINT16 remote_port;
UINT32 remote_flags;
BOOL input_state_sync_pending;
UINT32 input_state;
wHashTable* interceptContextMap;
UINT32 computerNameLen;
BOOL computerNameUnicode;
union
typedef struct _InterceptContextMapEntry
{
WCHAR* wc;
char* c;
void* v;
} computerName;
};
void (*free)(struct _InterceptContextMapEntry*);
} InterceptContextMapEntry;
/**
* Holds data common to both sides of a proxy's session.
*/
struct proxy_data
{
proxyModule* module;
const proxyConfig* config;
/* All proxy interception channels derive from this base struct
* and set their cleanup function accordingly. */
FREERDP_API void intercept_context_entry_free(void* obj);
pServerContext* ps;
pClientContext* pc;
/**
* Wraps rdpContext and holds the state for the proxy's server.
*/
struct p_server_context
{
rdpContext context;
HANDLE abort_event;
HANDLE client_thread;
HANDLE gfx_server_ready;
proxyData* pdata;
char session_id[PROXY_SESSION_ID_LENGTH + 1];
HANDLE vcm;
HANDLE dynvcReady;
/* used to external modules to store per-session info */
wHashTable* modules_info;
psPeerReceiveChannelData server_receive_channel_data_original;
};
wHashTable* interceptContextMap;
};
typedef struct p_server_context pServerContext;
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
BOOL pf_context_init_server_context(freerdp_peer* client);
pClientContext* pf_context_create_client_context(rdpSettings* clientSettings);
/**
* Wraps rdpContext and holds the state for the proxy's client.
*/
typedef struct p_client_context pClientContext;
proxyData* proxy_data_new(void);
void proxy_data_set_client_context(proxyData* pdata, pClientContext* context);
void proxy_data_set_server_context(proxyData* pdata, pServerContext* context);
void proxy_data_free(proxyData* pdata);
struct p_client_context
{
rdpContext context;
BOOL proxy_data_shall_disconnect(proxyData* pdata);
void proxy_data_abort_connect(proxyData* pdata);
proxyData* pdata;
/*
* In a case when freerdp_connect fails,
* 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 allow_next_conn_failure;
BOOL connected; /* Set after client post_connect. */
pReceiveChannelData client_receive_channel_data_original;
wQueue* cached_server_channel_data;
BOOL (*sendChannelData)(pClientContext* pc, const proxyChannelDataEventInfo* ev);
/* X509 specific */
char* remote_hostname;
wStream* remote_pem;
UINT16 remote_port;
UINT32 remote_flags;
BOOL input_state_sync_pending;
UINT32 input_state;
wHashTable* interceptContextMap;
UINT32 computerNameLen;
BOOL computerNameUnicode;
union
{
WCHAR* wc;
char* c;
void* v;
} computerName;
};
/**
* Holds data common to both sides of a proxy's session.
*/
struct proxy_data
{
proxyModule* module;
const proxyConfig* config;
pServerContext* ps;
pClientContext* pc;
HANDLE abort_event;
HANDLE client_thread;
HANDLE gfx_server_ready;
char session_id[PROXY_SESSION_ID_LENGTH + 1];
/* used to external modules to store per-session info */
wHashTable* modules_info;
psPeerReceiveChannelData server_receive_channel_data_original;
};
FREERDP_API BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
FREERDP_API BOOL pf_context_init_server_context(freerdp_peer* client);
FREERDP_API pClientContext* pf_context_create_client_context(rdpSettings* clientSettings);
FREERDP_API proxyData* proxy_data_new(void);
FREERDP_API void proxy_data_set_client_context(proxyData* pdata, pClientContext* context);
FREERDP_API void proxy_data_set_server_context(proxyData* pdata, pServerContext* context);
FREERDP_API void proxy_data_free(proxyData* pdata);
FREERDP_API BOOL proxy_data_shall_disconnect(proxyData* pdata);
FREERDP_API void proxy_data_abort_connect(proxyData* pdata);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SERVER_PROXY_PFCONTEXT_H */

View File

@ -1745,13 +1745,14 @@ extern "C"
FREERDP_API BOOL freerdp_settings_set_uint64(rdpSettings* settings, size_t id, UINT64 param);
FREERDP_API const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id);
FREERDP_API char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id);
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings* settings, size_t id,
const char* param, size_t len);
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id,
const char* param);
FREERDP_API const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id);
FREERDP_API void* freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id);
FREERDP_API void* freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id);
FREERDP_API BOOL freerdp_settings_set_pointer(rdpSettings* settings, size_t id,
const void* data);
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id,

View File

@ -2527,6 +2527,231 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
}
}
char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
{
WINPR_ASSERT(settings);
switch (id)
{
case FreeRDP_AcceptedCert:
return settings->AcceptedCert;
case FreeRDP_ActionScript:
return settings->ActionScript;
case FreeRDP_AllowedTlsCiphers:
return settings->AllowedTlsCiphers;
case FreeRDP_AlternateShell:
return settings->AlternateShell;
case FreeRDP_AssistanceFile:
return settings->AssistanceFile;
case FreeRDP_AuthenticationServiceClass:
return settings->AuthenticationServiceClass;
case FreeRDP_CertificateAcceptedFingerprints:
return settings->CertificateAcceptedFingerprints;
case FreeRDP_CertificateContent:
return settings->CertificateContent;
case FreeRDP_CertificateFile:
return settings->CertificateFile;
case FreeRDP_CertificateName:
return settings->CertificateName;
case FreeRDP_ClientAddress:
return settings->ClientAddress;
case FreeRDP_ClientDir:
return settings->ClientDir;
case FreeRDP_ClientHostname:
return settings->ClientHostname;
case FreeRDP_ClientProductId:
return settings->ClientProductId;
case FreeRDP_ComputerName:
return settings->ComputerName;
case FreeRDP_ConfigPath:
return settings->ConfigPath;
case FreeRDP_ConnectionFile:
return settings->ConnectionFile;
case FreeRDP_CurrentPath:
return settings->CurrentPath;
case FreeRDP_Domain:
return settings->Domain;
case FreeRDP_DrivesToRedirect:
return settings->DrivesToRedirect;
case FreeRDP_DumpRemoteFxFile:
return settings->DumpRemoteFxFile;
case FreeRDP_DynamicDSTTimeZoneKeyName:
return settings->DynamicDSTTimeZoneKeyName;
case FreeRDP_GatewayAcceptedCert:
return settings->GatewayAcceptedCert;
case FreeRDP_GatewayAccessToken:
return settings->GatewayAccessToken;
case FreeRDP_GatewayDomain:
return settings->GatewayDomain;
case FreeRDP_GatewayHostname:
return settings->GatewayHostname;
case FreeRDP_GatewayPassword:
return settings->GatewayPassword;
case FreeRDP_GatewayUsername:
return settings->GatewayUsername;
case FreeRDP_HomePath:
return settings->HomePath;
case FreeRDP_ImeFileName:
return settings->ImeFileName;
case FreeRDP_KerberosKdc:
return settings->KerberosKdc;
case FreeRDP_KerberosRealm:
return settings->KerberosRealm;
case FreeRDP_KeyboardRemappingList:
return settings->KeyboardRemappingList;
case FreeRDP_NtlmSamFile:
return settings->NtlmSamFile;
case FreeRDP_Password:
return settings->Password;
case FreeRDP_PasswordHash:
return settings->PasswordHash;
case FreeRDP_PlayRemoteFxFile:
return settings->PlayRemoteFxFile;
case FreeRDP_PreconnectionBlob:
return settings->PreconnectionBlob;
case FreeRDP_PrivateKeyContent:
return settings->PrivateKeyContent;
case FreeRDP_PrivateKeyFile:
return settings->PrivateKeyFile;
case FreeRDP_ProxyHostname:
return settings->ProxyHostname;
case FreeRDP_ProxyPassword:
return settings->ProxyPassword;
case FreeRDP_ProxyUsername:
return settings->ProxyUsername;
case FreeRDP_RDP2TCPArgs:
return settings->RDP2TCPArgs;
case FreeRDP_RdpKeyContent:
return settings->RdpKeyContent;
case FreeRDP_RdpKeyFile:
return settings->RdpKeyFile;
case FreeRDP_RedirectionAcceptedCert:
return settings->RedirectionAcceptedCert;
case FreeRDP_RedirectionDomain:
return settings->RedirectionDomain;
case FreeRDP_RedirectionTargetFQDN:
return settings->RedirectionTargetFQDN;
case FreeRDP_RedirectionTargetNetBiosName:
return settings->RedirectionTargetNetBiosName;
case FreeRDP_RedirectionUsername:
return settings->RedirectionUsername;
case FreeRDP_RemoteApplicationCmdLine:
return settings->RemoteApplicationCmdLine;
case FreeRDP_RemoteApplicationFile:
return settings->RemoteApplicationFile;
case FreeRDP_RemoteApplicationGuid:
return settings->RemoteApplicationGuid;
case FreeRDP_RemoteApplicationIcon:
return settings->RemoteApplicationIcon;
case FreeRDP_RemoteApplicationName:
return settings->RemoteApplicationName;
case FreeRDP_RemoteApplicationProgram:
return settings->RemoteApplicationProgram;
case FreeRDP_RemoteApplicationWorkingDir:
return settings->RemoteApplicationWorkingDir;
case FreeRDP_RemoteAssistancePassStub:
return settings->RemoteAssistancePassStub;
case FreeRDP_RemoteAssistancePassword:
return settings->RemoteAssistancePassword;
case FreeRDP_RemoteAssistanceRCTicket:
return settings->RemoteAssistanceRCTicket;
case FreeRDP_RemoteAssistanceSessionId:
return settings->RemoteAssistanceSessionId;
case FreeRDP_ServerHostname:
return settings->ServerHostname;
case FreeRDP_ShellWorkingDirectory:
return settings->ShellWorkingDirectory;
case FreeRDP_SmartcardCertificate:
return settings->SmartcardCertificate;
case FreeRDP_SmartcardPrivateKey:
return settings->SmartcardPrivateKey;
case FreeRDP_TargetNetAddress:
return settings->TargetNetAddress;
case FreeRDP_TransportDumpFile:
return settings->TransportDumpFile;
case FreeRDP_Username:
return settings->Username;
case FreeRDP_WindowTitle:
return settings->WindowTitle;
case FreeRDP_WmClass:
return settings->WmClass;
default:
WLog_ERR(TAG, "[%s] Invalid key index %" PRIuz, __FUNCTION__, id);
return FALSE;
}
}
BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val, size_t len,
BOOL cleanup)
{
@ -2776,7 +3001,7 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v
return freerdp_settings_set_string_(settings, id, val, len, TRUE);
}
void* freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id)
void* freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id)
{
WINPR_ASSERT(settings);

View File

@ -269,21 +269,7 @@ def write_getter_case(f, val):
f.write('\t\tcase FreeRDP_' + val + ':\n')
f.write('\t\t\treturn settings->' + val + ';\n\n')
def write_getter(f, entry_dict, entry_type, entry_name):
isString = 'string' in entry_name
isPointer = 'pointer' in entry_name
values = get_values(entry_dict, entry_type)
if isPointer:
f.write('void*')
elif isString:
f.write('const ' + entry_type)
else:
f.write(entry_type)
if isPointer:
f.write(' freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id)\n')
else:
f.write(' freerdp_settings_get_' + entry_name.lower() + '(const rdpSettings* settings, size_t id)\n')
def write_getter_body(f, values):
f.write('{\n')
f.write('\tWINPR_ASSERT(settings);\n\n')
f.write('\tswitch (id)\n')
@ -297,6 +283,28 @@ def write_getter(f, entry_dict, entry_type, entry_name):
f.write('\t}\n')
f.write('}\n\n')
def write_getter(f, entry_dict, entry_type, entry_name):
isString = 'string' in entry_name
isPointer = 'pointer' in entry_name
values = get_values(entry_dict, entry_type)
if isPointer:
f.write('void*')
elif isString:
f.write('const ' + entry_type)
else:
f.write(entry_type)
if isPointer:
f.write(' freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id)\n')
else:
f.write(' freerdp_settings_get_' + entry_name.lower() + '(const rdpSettings* settings, size_t id)\n')
write_getter_body(f, values)
if isString:
f.write('char* freerdp_settings_get_' + entry_name.lower() + '_writable(rdpSettings* settings, size_t id)\n')
write_getter_body(f, values)
def write_setter_case(f, val, isString, isPointer):
f.write('\t\tcase FreeRDP_' + val + ':\n')
if isPointer:

View File

@ -41,6 +41,7 @@ set(${MODULE_PREFIX}_SRCS
set(PROXY_APP_SRCS freerdp_proxy.c)
option(WITH_PROXY_EMULATE_SMARTCARD "Compile proxy smartcard emulation" OFF)
add_subdirectory("channels")
# On windows create dll version information.
@ -116,7 +117,3 @@ if (WITH_PROXY_MODULES)
add_subdirectory("modules")
endif()
option(WITH_PROXY_EMULATE_SMARTCARD "Compile proxy smartcard emulation" OFF)
if (WITH_PROXY_EMULATE_SMARTCARD)
add_definitions("-DWITH_PROXY_EMULATE_SMARTCARD")
endif()

View File

@ -18,6 +18,10 @@
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/assert.h>
#include <winpr/string.h>
#include <winpr/print.h>

View File

@ -121,6 +121,16 @@ static BOOL pf_context_revert_str_settings(rdpSettings* dst, const rdpSettings*
return TRUE;
}
void intercept_context_entry_free(void* obj)
{
InterceptContextMapEntry* entry = obj;
if (!entry)
return;
if (!entry->free)
return;
entry->free(entry);
}
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
{
BOOL rc = FALSE;