Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,259 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server
*
* Copyright 2021-2023 Armin Novak <armin.novak@thincast.com>
* Copyright 2021-2023 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.
*/
#ifndef FREERDP_SERVER_PROXY_CONFIG_H
#define FREERDP_SERVER_PROXY_CONFIG_H
#include <winpr/wtypes.h>
#include <winpr/ini.h>
#include <freerdp/api.h>
#include <freerdp/server/proxy/proxy_modules_api.h>
/** @defgroup proxy_config Proxy Configuration
* @ingroup proxy
* @{
*/
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct proxy_config proxyConfig;
struct proxy_config
{
/* server */
char* Host;
UINT16 Port;
/* target */
BOOL FixedTarget;
char* TargetHost;
UINT16 TargetPort;
char* TargetUser;
char* TargetDomain;
char* TargetPassword;
/* input */
BOOL Keyboard;
BOOL Mouse;
BOOL Multitouch;
/* server security */
BOOL ServerTlsSecurity;
BOOL ServerRdpSecurity;
BOOL ServerNlaSecurity;
/* client security */
BOOL ClientNlaSecurity;
BOOL ClientTlsSecurity;
BOOL ClientRdpSecurity;
BOOL ClientAllowFallbackToTls;
/* channels */
BOOL GFX;
BOOL DisplayControl;
BOOL Clipboard;
BOOL AudioOutput;
BOOL AudioInput;
BOOL RemoteApp;
BOOL DeviceRedirection;
BOOL VideoRedirection;
BOOL CameraRedirection;
BOOL PassthroughIsBlacklist;
char** Passthrough;
size_t PassthroughCount;
char** Intercept;
size_t InterceptCount;
/* clipboard specific settings */
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
WINPR_DEPRECATED_VAR("[since 3.6.0] Unused, ignore", BOOL TextOnly);
WINPR_DEPRECATED_VAR("[since 3.6.0] Unused, ignore", UINT32 MaxTextLength);
/* gfx settings */
WINPR_DEPRECATED_VAR("[since 3.6.0] Unused, ignore", BOOL DecodeGFX);
#endif
/* modules */
char** Modules; /* module file names to load */
size_t ModulesCount;
char** RequiredPlugins; /* required plugin names */
size_t RequiredPluginsCount;
char* CertificateFile;
char* CertificateContent;
char* PrivateKeyFile;
char* PrivateKeyContent;
/* Data extracted from CertificateContent or CertificateFile (evaluation in this order) */
char* CertificatePEM;
size_t CertificatePEMLength;
/* Data extracted from PrivateKeyContent or PrivateKeyFile (evaluation in this order) */
char* PrivateKeyPEM;
size_t PrivateKeyPEMLength;
wIniFile* ini;
/* target continued */
UINT32 TargetTlsSecLevel; /** @since version 3.2.0 */
};
/**
* @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.
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_config_dump(const char* file);
/**
* @brief pf_server_config_free Releases all resources associated with proxyConfig
*
* @param config A pointer to the proxyConfig to clean up. Might be nullptr.
*/
FREERDP_API void pf_server_config_free(proxyConfig* config);
/**
* @brief server_config_load_ini Create a proxyConfig from a already loaded
* INI file.
*
* @param ini A pointer to the parsed INI file. Must NOT be nullptr.
*
* @return A proxyConfig or nullptr in case of failure.
*/
WINPR_ATTR_MALLOC(pf_server_config_free, 1)
WINPR_ATTR_NODISCARD
FREERDP_API proxyConfig* server_config_load_ini(wIniFile* ini);
/**
* @brief pf_server_config_load_file Create a proxyConfig from a INI file found at path.
*
* @param path The path of the INI file
*
* @return A proxyConfig or nullptr in case of failure.
*/
WINPR_ATTR_MALLOC(pf_server_config_free, 1)
WINPR_ATTR_NODISCARD
FREERDP_API proxyConfig* pf_server_config_load_file(const char* path);
/**
* @brief pf_server_config_load_buffer Create a proxyConfig from a memory string buffer in INI
* file format
*
* @param buffer A pointer to the '\0' terminated INI string.
*
* @return A proxyConfig or nullptr in case of failure.
*/
WINPR_ATTR_MALLOC(pf_server_config_free, 1)
WINPR_ATTR_NODISCARD
FREERDP_API proxyConfig* pf_server_config_load_buffer(const char* buffer);
/**
* @brief pf_server_config_print Print the configuration to stdout
*
* @param config A pointer to the configuration to print. Must NOT be nullptr.
*/
FREERDP_API void pf_server_config_print(const proxyConfig* config);
/**
* @brief pf_config_required_plugins_count
*
* @param config A pointer to the proxyConfig. Must NOT be nullptr.
*
* @return The number of required plugins configured.
*/
WINPR_ATTR_NODISCARD
FREERDP_API size_t pf_config_required_plugins_count(const proxyConfig* config);
/**
* @brief pf_config_required_plugin
* @param config A pointer to the proxyConfig. Must NOT be nullptr.
* @param index The index of the plugin to return
*
* @return The name of the plugin or nullptr.
*/
WINPR_ATTR_NODISCARD
FREERDP_API const char* pf_config_required_plugin(const proxyConfig* config, size_t index);
/**
* @brief pf_config_modules_count
*
* @param config A pointer to the proxyConfig. Must NOT be nullptr.
*
* @return The number of proxy modules configured.
*/
WINPR_ATTR_NODISCARD
FREERDP_API size_t pf_config_modules_count(const proxyConfig* config);
/**
* @brief pf_config_modules
* @param config A pointer to the proxyConfig. Must NOT be nullptr.
*
* @return An array of strings of size pf_config_modules_count with the module names.
*/
WINPR_ATTR_NODISCARD
FREERDP_API const char** pf_config_modules(const proxyConfig* config);
/**
* @brief pf_config_clone Create a copy of the configuration
* @param dst A pointer that receives the newly allocated copy
* @param config The source configuration to copy
*
* @return TRUE for success, FALSE otherwise
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config);
/**
* @brief pf_config_plugin Register a proxy plugin handling event filtering
* defined in the configuration.
*
* @param plugins_manager The plugin manager
* @param userdata A proxyConfig* to use as reference
*
* @return TRUE for success, FALSE for failure
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_config_plugin(proxyPluginsManager* plugins_manager, void* userdata);
/**
* @brief pf_config_get get a value for a section/key
* @param config A pointer to the proxyConfig. Must NOT be nullptr.
* @param section The name of the section the key is in, must not be \b nullptr
* @param key The name of the key to look for. Must not be \b nullptr
*
* @return A pointer to the value for \b section/key or \b nullptr if not found
*/
WINPR_ATTR_NODISCARD
FREERDP_API const char* pf_config_get(const proxyConfig* config, const char* section,
const char* key);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* FREERDP_SERVER_PROXY_CONFIG_H */

View File

@@ -0,0 +1,195 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server
*
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
*
* 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.
*/
#ifndef FREERDP_SERVER_PROXY_PFCONTEXT_H
#define FREERDP_SERVER_PROXY_PFCONTEXT_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/freerdp.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/proxy/proxy_config.h>
#include <freerdp/server/proxy/proxy_types.h>
#define PROXY_SESSION_ID_LENGTH 32
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct proxy_data proxyData;
typedef struct proxy_module proxyModule;
typedef struct p_server_static_channel_context pServerStaticChannelContext;
typedef struct s_InterceptContextMapEntry
{
void (*free)(struct s_InterceptContextMapEntry*);
} InterceptContextMapEntry;
/* All proxy interception channels derive from this base struct
* and set their cleanup function accordingly. */
FREERDP_API void intercept_context_entry_free(void* obj);
typedef PfChannelResult (*proxyChannelDataFn)(proxyData* pdata,
const pServerStaticChannelContext* channel,
const BYTE* xdata, size_t xsize, UINT32 flags,
size_t totalSizepServer);
typedef void (*proxyChannelContextDtor)(void* context);
/** @brief per channel configuration */
struct p_server_static_channel_context
{
char* channel_name;
UINT32 front_channel_id;
UINT32 back_channel_id;
pf_utils_channel_mode channelMode;
WINPR_ATTR_NODISCARD proxyChannelDataFn onFrontData;
WINPR_ATTR_NODISCARD proxyChannelDataFn onBackData;
proxyChannelContextDtor contextDtor;
void* context;
};
FREERDP_API void StaticChannelContext_free(pServerStaticChannelContext* ctx);
/**
* 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;
wHashTable* channelsByFrontId;
wHashTable* channelsByBackId;
};
typedef struct p_server_context pServerContext;
WINPR_ATTR_MALLOC(StaticChannelContext_free, 1)
WINPR_ATTR_NODISCARD
pServerStaticChannelContext* StaticChannelContext_new(pServerContext* ps, const char* name,
UINT32 id);
/**
* 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;
WINPR_ATTR_NODISCARD 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;
};
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_context_init_server_context(freerdp_peer* client);
WINPR_ATTR_MALLOC(freerdp_client_context_free, 1)
WINPR_ATTR_NODISCARD
FREERDP_API pClientContext* pf_context_create_client_context(const rdpSettings* clientSettings);
FREERDP_API void proxy_data_free(proxyData* pdata);
WINPR_ATTR_MALLOC(proxy_data_free, 1)
WINPR_ATTR_NODISCARD
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);
WINPR_ATTR_NODISCARD
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

@@ -0,0 +1,53 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server
*
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
* Copyright 2021 Armin Novak <anovak@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.
*/
#ifndef FREERDP_SERVER_PROXY_LOG_H
#define FREERDP_SERVER_PROXY_LOG_H
#include <winpr/wlog.h>
#include <freerdp/log.h>
#define PROXY_TAG(tag) FREERDP_TAG("proxy." tag)
/*
* log format in proxy is:
* "[SessionID=%s]: Log message"
* SessionID is optional, but if they should be written to the log,
* that's the format.
*/
/* log macros that prepends session id and function name tp the log message */
#define PROXY_LOG_INFO(_tag, _context, _format, ...) \
WLog_INFO(TAG, "[SessionID=%s]: " _format, \
(_context && _context->pdata) ? _context->pdata->session_id : "null", ##__VA_ARGS__)
#define PROXY_LOG_ERR(_tag, _context, _format, ...) \
WLog_ERR(TAG, "[SessionID=%s]: " _format, \
(_context && _context->pdata) ? _context->pdata->session_id : "null", ##__VA_ARGS__)
#define PROXY_LOG_DBG(_tag, _context, _format, ...) \
WLog_DBG(TAG, "[SessionID=%s]: " _format, \
(_context && _context->pdata) ? _context->pdata->session_id : "null", ##__VA_ARGS__)
#define PROXY_LOG_WARN(_tag, _context, _format, ...) \
WLog_WARN(TAG, "[SessionID=%s]: " _format, \
(_context && _context->pdata) ? _context->pdata->session_id : "null", ##__VA_ARGS__)
#endif /* FREERDP_SERVER_PROXY_LOG_H */

View File

@@ -0,0 +1,246 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
* Copyright 2021 Armin Novak <anovak@thincast.com>
* Copyright 2021 Thincast Technologies GmbH
* Copyright 2023 Armin Novak <anovak@thincast.com>
* Copyright 2023 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.
*/
#ifndef FREERDP_SERVER_PROXY_MODULES_API_H
#define FREERDP_SERVER_PROXY_MODULES_API_H
#include <winpr/winpr.h>
#include <winpr/stream.h>
#include <winpr/sspi.h>
#include <freerdp/server/proxy/proxy_types.h>
#define MODULE_TAG(module) "proxy.modules." module
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct proxy_data proxyData;
typedef struct proxy_module proxyModule;
typedef struct proxy_plugin proxyPlugin;
typedef struct proxy_plugins_manager proxyPluginsManager;
/* hook callback. should return TRUE on success or FALSE on error. */
typedef BOOL (*proxyHookFn)(proxyPlugin*, proxyData*, void*);
/*
* Filter callback:
* It MUST return TRUE if the related event should be proxied,
* or FALSE if it should be ignored.
*/
typedef BOOL (*proxyFilterFn)(proxyPlugin*, proxyData*, void*);
/* describes a plugin: name, description and callbacks to execute.
*
* This is public API, so always add new fields at the end of the struct to keep
* some backward compatibility.
*/
struct proxy_plugin
{
const char* name; /* 0: unique module name */
const char* description; /* 1: module description */
UINT64 reserved1[32 - 2]; /* 2-32 */
WINPR_ATTR_NODISCARD BOOL (*PluginUnload)(proxyPlugin* plugin); /* 33 */
UINT64 reserved2[66 - 34]; /* 34 - 65 */
/* proxy hooks. a module can set these function pointers to register hooks */
WINPR_ATTR_NODISCARD proxyHookFn ClientInitConnect; /* 66 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientUninitConnect; /* 67 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientPreConnect; /* 68 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientPostConnect; /* 69 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientPostDisconnect; /* 70 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientX509Certificate; /* 71 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientLoginFailure; /* 72 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientEndPaint; /* 73 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientRedirect; /* 74 custom=rdpContext* */
WINPR_ATTR_NODISCARD proxyHookFn ClientLoadChannels; /* 75 custom=rdpContext* */
UINT64 reserved3[96 - 76]; /* 76-95 */
WINPR_ATTR_NODISCARD proxyHookFn ServerPostConnect; /* 96 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerPeerActivate; /* 97 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerChannelsInit; /* 98 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerChannelsFree; /* 99 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerSessionEnd; /* 100 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerSessionInitialize; /* 101 custom=freerdp_peer* */
WINPR_ATTR_NODISCARD proxyHookFn ServerSessionStarted; /* 102 custom=freerdp_peer* */
UINT64 reserved4[128 - 103]; /* 103 - 127 */
/* proxy filters. a module can set these function pointers to register filters */
WINPR_ATTR_NODISCARD proxyFilterFn KeyboardEvent; /* 128 */
WINPR_ATTR_NODISCARD proxyFilterFn MouseEvent; /* 129 */
WINPR_ATTR_NODISCARD proxyFilterFn ClientChannelData; /* 130 passthrough channels data */
WINPR_ATTR_NODISCARD proxyFilterFn ServerChannelData; /* 131 passthrough channels data */
WINPR_ATTR_NODISCARD proxyFilterFn
DynamicChannelCreate; /* 132 passthrough drdynvc channel create data */
WINPR_ATTR_NODISCARD proxyFilterFn ServerFetchTargetAddr; /* 133 */
WINPR_ATTR_NODISCARD proxyFilterFn ServerPeerLogon; /* 134 */
WINPR_ATTR_NODISCARD proxyFilterFn
ChannelCreate; /* 135 passthrough drdynvc channel create data */
WINPR_ATTR_NODISCARD proxyFilterFn UnicodeEvent; /* 136 */
WINPR_ATTR_NODISCARD proxyFilterFn MouseExEvent; /* 137 */
/* proxy dynamic channel filters:
*
* - a function that returns the list of channels to intercept
* - a function to call with the data received
*/
WINPR_ATTR_NODISCARD proxyFilterFn DynChannelToIntercept; /* 138 */
WINPR_ATTR_NODISCARD proxyFilterFn DynChannelIntercept; /* 139 */
WINPR_ATTR_NODISCARD proxyFilterFn StaticChannelToIntercept; /* 140 */
UINT64 reserved5[160 - 141]; /* 141-159 */
/* Runtime data fields */
proxyPluginsManager* mgr; /* 160 */ /** Set during plugin registration */
void* userdata; /* 161 */ /** Custom data provided with RegisterPlugin, memory managed
outside of plugin. */
void* custom; /* 162 */ /** Custom configuration data, must be allocated in RegisterPlugin
and freed in PluginUnload */
UINT64 reserved6[192 - 163]; /* 163-191 Add some filler data to allow for new callbacks or
* fields without breaking API */
};
/*
* Main API for use by external modules.
* Supports:
* - Registering a plugin.
* - Setting/getting plugin's per-session specific data.
* - Aborting a session.
*/
struct proxy_plugins_manager
{
/* 0 used for registering a fresh new proxy plugin. */
WINPR_ATTR_NODISCARD BOOL (*RegisterPlugin)(struct proxy_plugins_manager* mgr,
const proxyPlugin* plugin);
/* 1 used for setting plugin's per-session info. */
WINPR_ATTR_NODISCARD BOOL (*SetPluginData)(struct proxy_plugins_manager* mgr, const char*,
proxyData*, void*);
/* 2 used for getting plugin's per-session info. */
WINPR_ATTR_NODISCARD void* (*GetPluginData)(struct proxy_plugins_manager* mgr, const char*,
proxyData*);
/* 3 used for aborting a session. */
void (*AbortConnect)(struct proxy_plugins_manager* mgr, proxyData*);
UINT64 reserved[128 - 4]; /* 4-127 reserved fields */
};
typedef BOOL (*proxyModuleEntryPoint)(proxyPluginsManager* plugins_manager, void* userdata);
/* filter events parameters */
#define WINPR_PACK_PUSH
#include <winpr/pack.h>
typedef struct proxy_keyboard_event_info
{
UINT16 flags;
UINT16 rdp_scan_code;
} proxyKeyboardEventInfo;
typedef struct proxy_unicode_event_info
{
UINT16 flags;
UINT16 code;
} proxyUnicodeEventInfo;
typedef struct proxy_mouse_event_info
{
UINT16 flags;
UINT16 x;
UINT16 y;
} proxyMouseEventInfo;
typedef struct proxy_mouse_ex_event_info
{
UINT16 flags;
UINT16 x;
UINT16 y;
} proxyMouseExEventInfo;
typedef struct
{
/* channel metadata */
const char* channel_name;
UINT16 channel_id;
/* actual data */
const BYTE* data;
size_t data_len;
size_t total_size;
UINT32 flags;
} proxyChannelDataEventInfo;
typedef struct
{
/* out values */
char* target_address;
UINT16 target_port;
/*
* If this value is set to true by a plugin, target info will be fetched from config and proxy
* will connect any client to the same remote server.
*/
ProxyFetchTargetMethod fetch_method;
} proxyFetchTargetEventInfo;
typedef struct server_peer_logon
{
const SEC_WINNT_AUTH_IDENTITY* identity;
BOOL automatic;
} proxyServerPeerLogon;
typedef struct dyn_channel_intercept_data
{
const char* name;
UINT32 channelId;
wStream* data;
BOOL isBackData;
BOOL first;
BOOL last;
BOOL rewritten;
size_t packetSize;
PfChannelResult result;
} proxyDynChannelInterceptData;
typedef struct dyn_channel_to_intercept_data
{
const char* name;
UINT32 channelId;
BOOL intercept;
} proxyChannelToInterceptData;
#define WINPR_PACK_POP
#include <winpr/pack.h>
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SERVER_PROXY_MODULES_API_H */

View File

@@ -0,0 +1,121 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server
*
* 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.
*/
#ifndef FREERDP_SERVER_PROXY_SERVER_H
#define FREERDP_SERVER_PROXY_SERVER_H
#include <freerdp/api.h>
#include <freerdp/server/proxy/proxy_config.h>
#include <freerdp/server/proxy/proxy_modules_api.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct proxy_server proxyServer;
/**
* @brief pf_server_free Cleans up a (stopped) proxy server instance.
*
* @param server The proxy server to clean up. Might be nullptr.
*/
FREERDP_API void pf_server_free(proxyServer* server);
/**
* @brief pf_server_new Creates a new proxy server instance
*
* @param config The proxy server configuration to use. Must NOT be nullptr.
*
* @return A new proxy server instance or nullptr on failure.
*/
WINPR_ATTR_MALLOC(pf_server_free, 1)
WINPR_ATTR_NODISCARD
FREERDP_API proxyServer* pf_server_new(const proxyConfig* config);
/**
* @brief pf_server_add_module Allows registering proxy modules that are
* built-in instead of shipped as separate
* module loaded at runtime.
*
* @param server A proxy instance to add the module to. Must NOT be nullptr
* @param ep The proxy entry function to add. Must NOT be nullptr
* @param userdata Custom data for the module. May be nullptr
*
* @return TRUE for success, FALSE otherwise.
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep,
void* userdata);
/**
* @brief pf_server_start Starts the proxy, binding the configured port.
*
* @param server The server instance. Must NOT be nullptr.
*
* @return TRUE for success, FALSE on error
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_start(proxyServer* server);
/**
* @brief pf_server_start_from_socket Starts the proxy using an existing bound socket
*
* @param server The server instance. Must NOT be nullptr.
* @param socket The bound socket to wait for events on.
*
* @return TRUE for success, FALSE on error
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_start_from_socket(proxyServer* server, int socket);
/**
* @brief pf_server_start_with_peer_socket Use existing peer socket
*
* @param server The server instance. Must NOT be nullptr.
* @param socket Ready to use peer socket
*
* @return TRUE for success, FALSE on error
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_start_with_peer_socket(proxyServer* server, int socket);
/**
* @brief pf_server_stop Stops a server instance asynchronously.
* Can be called from any thread to stop a running server instance.
* @param server A pointer to the server instance to stop. May be nullptr.
*/
FREERDP_API void pf_server_stop(proxyServer* server);
/**
* @brief pf_server_run This (blocking) function runs the main loop of the
* proxy.
*
* @param server The server instance. Must NOT be nullptr.
*
* @return TRUE for successful termination, FALSE otherwise.
*/
WINPR_ATTR_NODISCARD
FREERDP_API BOOL pf_server_run(proxyServer* server);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SERVER_PROXY_SERVER_H */

View File

@@ -0,0 +1,57 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy enum types
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
* Copyright 2023 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.
*/
#ifndef FREERDP_SERVER_PROXY_TYPES_H
#define FREERDP_SERVER_PROXY_TYPES_H
#ifdef __cplusplus
extern "C"
{
#endif
/** @brief how is handled a channel */
typedef enum
{
PF_UTILS_CHANNEL_NOT_HANDLED, /*!< channel not handled */
PF_UTILS_CHANNEL_BLOCK, /*!< block and drop traffic on this channel */
PF_UTILS_CHANNEL_PASSTHROUGH, /*!< pass traffic from this channel */
PF_UTILS_CHANNEL_INTERCEPT /*!< inspect traffic from this channel */
} pf_utils_channel_mode;
/** @brief result of a channel treatment */
typedef enum
{
PF_CHANNEL_RESULT_PASS, /*!< pass the packet as is */
PF_CHANNEL_RESULT_DROP, /*!< drop the packet */
PF_CHANNEL_RESULT_ERROR /*!< error during packet treatment */
} PfChannelResult;
typedef enum
{
PROXY_FETCH_TARGET_METHOD_DEFAULT,
PROXY_FETCH_TARGET_METHOD_CONFIG,
PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO,
PROXY_FETCH_TARGET_USE_CUSTOM_ADDR
} ProxyFetchTargetMethod;
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SERVER_PROXY_TYPES_H */