server/proxy: Add external filters support
This commit is contained in:
parent
3d346b69df
commit
a39658fc2a
@ -43,6 +43,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
pf_config.h
|
||||
pf_graphics.c
|
||||
pf_graphics.h
|
||||
pf_filters.c
|
||||
pf_filters.h
|
||||
pf_log.h)
|
||||
|
||||
# On windows create dll version information.
|
||||
|
@ -31,3 +31,7 @@ RdpSecurity = 1
|
||||
WhitelistMode = 0
|
||||
AllowedChannels = "cliprdr,Microsoft::Windows::RDS::Video::Control"
|
||||
DeniedChannels = "Microsoft::Windows::RDS::Geometry"
|
||||
|
||||
[Filters]
|
||||
; FilterName = FilterPath
|
||||
DemoFilter = "server/proxy/demo.so"
|
||||
|
25
server/proxy/filters/filter_demo.c
Normal file
25
server/proxy/filters/filter_demo.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "filters_api.h"
|
||||
|
||||
static PF_FILTER_RESULT demo_filter_keyboard_event(connectionInfo* info, void* param)
|
||||
{
|
||||
proxyKeyboardEventInfo* event_data = (proxyKeyboardEventInfo*) param;
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
static PF_FILTER_RESULT demo_filter_mouse_event(connectionInfo* info, void* param)
|
||||
{
|
||||
proxyMouseEventInfo* event_data = (proxyMouseEventInfo*) param;
|
||||
|
||||
if (event_data->x % 100 == 0)
|
||||
{
|
||||
return FILTER_DROP;
|
||||
}
|
||||
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
bool filter_init(proxyEvents* events)
|
||||
{
|
||||
events->KeyboardEvent = demo_filter_keyboard_event;
|
||||
events->MouseEvent = demo_filter_mouse_event;
|
||||
}
|
69
server/proxy/filters/filters_api.h
Normal file
69
server/proxy/filters/filters_api.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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_FILTERS_API_H
|
||||
#define FREERDP_SERVER_PROXY_FILTERS_API_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum pf_filter_result {
|
||||
FILTER_PASS = 0,
|
||||
FILTER_DROP,
|
||||
FILTER_IGNORE
|
||||
};
|
||||
|
||||
typedef enum pf_filter_result PF_FILTER_RESULT;
|
||||
typedef struct connection_info connectionInfo;
|
||||
typedef struct proxy_events proxyEvents;
|
||||
typedef struct proxy_keyboard_event_info proxyKeyboardEventInfo;
|
||||
typedef struct proxy_mouse_event_info proxyMouseEventInfo;
|
||||
typedef PF_FILTER_RESULT(*proxyEvent)(connectionInfo* info, void* param);
|
||||
|
||||
struct connection_info {
|
||||
char* TargetHostname;
|
||||
char* ClientHostname;
|
||||
char* Username;
|
||||
};
|
||||
|
||||
struct proxy_events {
|
||||
proxyEvent KeyboardEvent;
|
||||
proxyEvent MouseEvent;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct proxy_keyboard_event_info {
|
||||
uint16_t flags;
|
||||
uint16_t rdp_scan_code;
|
||||
};
|
||||
|
||||
struct proxy_mouse_event_info {
|
||||
uint16_t flags;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/* implement this method */
|
||||
bool filter_init(proxyEvents* events);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_FILTERS_API_H */
|
@ -22,6 +22,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_server.h"
|
||||
#include "pf_config.h"
|
||||
@ -30,39 +32,49 @@
|
||||
|
||||
#define CHANNELS_SEPERATOR ","
|
||||
|
||||
static char** parse_channels_from_str(const char* str, UINT32* length)
|
||||
wArrayList* parse_string_array_from_str(const char* str)
|
||||
{
|
||||
char* s = strdup(str);
|
||||
size_t tokens_alloc = 1;
|
||||
size_t tokens_count = 0;
|
||||
char** tokens = calloc(tokens_alloc, sizeof(char*));
|
||||
wArrayList* list = ArrayList_New(FALSE);
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): ArrayList_New failed!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* s = _strdup(str);
|
||||
char* temp = s;
|
||||
char* token;
|
||||
|
||||
while ((token = StrSep(&s, CHANNELS_SEPERATOR)) != NULL)
|
||||
if (s == NULL)
|
||||
{
|
||||
if (tokens_count == tokens_alloc)
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): strdup failed!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((token = StrSep(&temp, CHANNELS_SEPERATOR)) != NULL)
|
||||
{
|
||||
char* current_token = _strdup(token);
|
||||
|
||||
if (current_token == NULL)
|
||||
{
|
||||
tokens_alloc *= 2;
|
||||
tokens = realloc(tokens, tokens_alloc * sizeof(char*));
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): strdup failed!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
tokens[tokens_count++] = strdup(token);
|
||||
if (ArrayList_Add(list, current_token) < 0)
|
||||
{
|
||||
free(current_token);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tokens_count == 0) || (tokens_count > UINT32_MAX))
|
||||
{
|
||||
free(tokens);
|
||||
tokens = NULL;
|
||||
tokens_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens = realloc(tokens, tokens_count * sizeof(char*));
|
||||
}
|
||||
|
||||
*length = (DWORD)tokens_count;
|
||||
free(s);
|
||||
return tokens;
|
||||
return list;
|
||||
error:
|
||||
free(s);
|
||||
ArrayList_Free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL pf_server_is_config_valid(proxyConfig* config)
|
||||
@ -100,7 +112,9 @@ static BOOL pf_server_is_config_valid(proxyConfig* config)
|
||||
DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
{
|
||||
const char* input;
|
||||
char** filters_names;
|
||||
int rc;
|
||||
int filters_count = 0;
|
||||
DWORD result = CONFIG_PARSE_ERROR;
|
||||
wIniFile* ini = IniFile_New();
|
||||
|
||||
@ -141,10 +155,11 @@ DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
/* channels filtering */
|
||||
config->WhitelistMode = IniFile_GetKeyValueInt(ini, "Channels", "WhitelistMode");
|
||||
input = IniFile_GetKeyValueString(ini, "Channels", "AllowedChannels");
|
||||
/* filters api */
|
||||
|
||||
if (input)
|
||||
{
|
||||
config->AllowedChannels = parse_channels_from_str(input, &config->AllowedChannelsCount);
|
||||
config->AllowedChannels = parse_string_array_from_str(input);
|
||||
|
||||
if (config->AllowedChannels == NULL)
|
||||
goto out;
|
||||
@ -154,13 +169,34 @@ DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
|
||||
if (input)
|
||||
{
|
||||
config->BlockedChannels = parse_channels_from_str(input, &config->BlockedChannelsCount);
|
||||
config->BlockedChannels = parse_string_array_from_str(input);
|
||||
|
||||
if (config->BlockedChannels == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = CONFIG_PARSE_SUCCESS;
|
||||
|
||||
if (!pf_filters_init(&config->Filters))
|
||||
goto out;
|
||||
|
||||
filters_names = IniFile_GetSectionKeyNames(ini, "Filters", &filters_count);
|
||||
|
||||
for (int i = 0; i < filters_count; i++)
|
||||
{
|
||||
char* filter_name = filters_names[i];
|
||||
const char* path = IniFile_GetKeyValueString(ini, "Filters", filter_name);
|
||||
|
||||
if (!pf_filters_register_new(config->Filters, path, filter_name))
|
||||
{
|
||||
WLog_DBG(TAG, "pf_server_load_config(): failed to register %s (%s)", filter_name, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_DBG(TAG, "pf_server_load_config(): registered filter %s (%s) successfully", filter_name, path);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
IniFile_Free(ini);
|
||||
|
||||
@ -172,16 +208,9 @@ out:
|
||||
|
||||
void pf_server_config_free(proxyConfig* config)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
for (i = 0; i < config->AllowedChannelsCount; i++)
|
||||
free(config->AllowedChannels[i]);
|
||||
|
||||
for (i = 0; i < config->BlockedChannelsCount; i++)
|
||||
free(config->BlockedChannels[i]);
|
||||
|
||||
free(config->AllowedChannels);
|
||||
free(config->BlockedChannels);
|
||||
pf_filters_unregister_all(config->Filters);
|
||||
ArrayList_Free(config->AllowedChannels);
|
||||
ArrayList_Free(config->BlockedChannels);
|
||||
free(config->TargetHost);
|
||||
free(config->Host);
|
||||
free(config);
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include <winpr/ini.h>
|
||||
|
||||
#include "pf_filters.h"
|
||||
|
||||
struct proxy_config
|
||||
{
|
||||
/* server */
|
||||
@ -59,8 +61,8 @@ struct proxy_config
|
||||
char** AllowedChannels;
|
||||
UINT32 AllowedChannelsCount;
|
||||
|
||||
char** BlockedChannels;
|
||||
UINT32 BlockedChannelsCount;
|
||||
/* filters */
|
||||
filters_list* Filters;
|
||||
};
|
||||
|
||||
typedef struct proxy_config proxyConfig;
|
||||
|
@ -79,3 +79,37 @@ rdpContext* p_client_context_create(rdpSettings* clientSettings,
|
||||
settings->RedirectClipboard = FALSE;
|
||||
return context;
|
||||
}
|
||||
|
||||
static void pf_context_connection_info_free(connectionInfo* info)
|
||||
{
|
||||
free(info->TargetHostname);
|
||||
free(info->ClientHostname);
|
||||
free(info->Username);
|
||||
free(info);
|
||||
}
|
||||
|
||||
proxyData* pf_context_proxy_data_new()
|
||||
{
|
||||
proxyData* pdata = malloc(sizeof(proxyData));
|
||||
|
||||
if (pdata == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdata->info = pf_context_connection_info_new();
|
||||
|
||||
if (pdata->info == NULL)
|
||||
{
|
||||
free(pdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
void pf_context_proxy_data_free(proxyData* pdata)
|
||||
{
|
||||
pf_context_connection_info_free(pdata->info);
|
||||
free(pdata);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include "pf_config.h"
|
||||
#include "pf_server.h"
|
||||
#include "pf_filters.h"
|
||||
|
||||
|
||||
typedef struct proxy_data proxyData;
|
||||
@ -75,9 +76,16 @@ struct proxy_data
|
||||
pClientContext* pc;
|
||||
|
||||
HANDLE connectionClosed;
|
||||
|
||||
connectionInfo* info;
|
||||
filters_list* filters;
|
||||
};
|
||||
|
||||
BOOL init_p_server_context(freerdp_peer* client);
|
||||
rdpContext* p_client_context_create(rdpSettings* clientSettings, char* host, DWORD port);
|
||||
proxyData* pf_context_proxy_data_new();
|
||||
void pf_context_proxy_data_free(proxyData* pdata);
|
||||
connectionInfo* pf_context_connection_info_new();
|
||||
void pf_context_connection_info_free(connectionInfo* info);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFCONTEXT_H */
|
||||
|
218
server/proxy/pf_filters.c
Normal file
218
server/proxy/pf_filters.c
Normal file
@ -0,0 +1,218 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/library.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_filters.h"
|
||||
|
||||
#define TAG PROXY_TAG("filters")
|
||||
#define FILTER_INIT_METHOD "filter_init"
|
||||
|
||||
static const char* FILTER_RESULT_STRINGS[] =
|
||||
{
|
||||
"FILTER_PASS",
|
||||
"FILTER_DROP",
|
||||
"FILTER_IGNORE",
|
||||
};
|
||||
|
||||
static const char* EVENT_TYPE_STRINGS[] =
|
||||
{
|
||||
"KEYBOARD_EVENT",
|
||||
"MOUSE_EVENT",
|
||||
};
|
||||
|
||||
static const char* pf_filters_get_filter_result_string(PF_FILTER_RESULT result)
|
||||
{
|
||||
if (result >= FILTER_PASS && result <= FILTER_IGNORE)
|
||||
return FILTER_RESULT_STRINGS[result];
|
||||
else
|
||||
return "FILTER_UNKNOWN";
|
||||
}
|
||||
|
||||
static const char* pf_filters_get_event_type_string(PF_FILTER_TYPE result)
|
||||
{
|
||||
if (result >= FILTER_TYPE_KEYBOARD && result <= FILTER_TYPE_MOUSE)
|
||||
return EVENT_TYPE_STRINGS[result];
|
||||
else
|
||||
return "EVENT_UNKNOWN";
|
||||
}
|
||||
|
||||
BOOL pf_filters_init(filters_list** list)
|
||||
{
|
||||
if (list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_init(): list == NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*list = ArrayList_New(FALSE);
|
||||
|
||||
if (*list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_init(): ArrayList_New failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PF_FILTER_RESULT pf_filters_run_by_type(filters_list* list, PF_FILTER_TYPE type,
|
||||
connectionInfo* info,
|
||||
void* param)
|
||||
{
|
||||
proxyFilter* filter;
|
||||
proxyEvents* events;
|
||||
PF_FILTER_RESULT result = FILTER_PASS;
|
||||
const size_t count = (size_t) ArrayList_Count(list);
|
||||
size_t index;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
filter = (proxyFilter*) ArrayList_GetItem(list, index);
|
||||
events = filter->events;
|
||||
WLog_DBG(TAG, "pf_filters_run_by_type(): Running filter: %s", filter->name);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FILTER_TYPE_KEYBOARD:
|
||||
IFCALLRET(events->KeyboardEvent, result, info, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_MOUSE:
|
||||
IFCALLRET(events->MouseEvent, result, info, param);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != FILTER_PASS)
|
||||
{
|
||||
/* Filter returned FILTER_DROP or FILTER_IGNORE. There's no need to call next filters. */
|
||||
WLog_INFO(TAG, "Filter %s [%s] returned %s", filter->name,
|
||||
pf_filters_get_event_type_string(type), pf_filters_get_filter_result_string(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* all filters returned FILTER_PASS */
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
static void pf_filters_filter_free(proxyFilter* filter)
|
||||
{
|
||||
assert(filter != NULL);
|
||||
FreeLibrary(filter->handle);
|
||||
free(filter->name);
|
||||
free(filter->events);
|
||||
free(filter);
|
||||
}
|
||||
|
||||
void pf_filters_unregister_all(filters_list* list)
|
||||
{
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
const size_t count = (size_t) ArrayList_Count(list);
|
||||
size_t index;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
proxyFilter* filter = (proxyFilter*) ArrayList_GetItem(list, index);
|
||||
WLog_DBG(TAG, "pf_filters_unregister_all(): freeing filter: %s", filter->name);
|
||||
pf_filters_filter_free(filter);
|
||||
}
|
||||
|
||||
ArrayList_Free(list);
|
||||
}
|
||||
|
||||
BOOL pf_filters_register_new(filters_list* list, const char* module_path, const char* filter_name)
|
||||
{
|
||||
proxyEvents* events = NULL;
|
||||
proxyFilter* filter = NULL;
|
||||
HMODULE handle = NULL;
|
||||
filterInitFn fn;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): list == NULL");
|
||||
goto error;
|
||||
}
|
||||
|
||||
handle = LoadLibraryA(module_path);
|
||||
|
||||
if (handle == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed loading external module: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(fn = (filterInitFn) GetProcAddress(handle, FILTER_INIT_METHOD)))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): GetProcAddress failed while loading %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
filter = (proxyFilter*) malloc(sizeof(proxyFilter));
|
||||
|
||||
if (filter == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): malloc failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
events = malloc(sizeof(proxyEvents));
|
||||
|
||||
if (events == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed loading external module: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!fn(events))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed calling external filter_init: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
filter->handle = handle;
|
||||
filter->name = _strdup(filter_name);
|
||||
filter->events = events;
|
||||
filter->enabled = TRUE;
|
||||
|
||||
if (ArrayList_Add(list, filter) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed adding filter to list: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
|
||||
if (handle)
|
||||
FreeLibrary(handle);
|
||||
|
||||
free(events);
|
||||
free(filter);
|
||||
return FALSE;
|
||||
}
|
75
server/proxy/pf_filters.h
Normal file
75
server/proxy/pf_filters.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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_FILTERS_H
|
||||
#define FREERDP_SERVER_PROXY_FILTERS_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "filters/filters_api.h"
|
||||
|
||||
/* filter init method */
|
||||
typedef BOOL (*filterInitFn)(proxyEvents* events);
|
||||
|
||||
typedef wArrayList filters_list;
|
||||
typedef struct proxy_filter proxyFilter;
|
||||
|
||||
typedef enum _PF_FILTER_TYPE PF_FILTER_TYPE;
|
||||
enum _PF_FILTER_TYPE
|
||||
{
|
||||
FILTER_TYPE_KEYBOARD,
|
||||
FILTER_TYPE_MOUSE
|
||||
};
|
||||
|
||||
struct proxy_filter
|
||||
{
|
||||
/* Handle to the loaded library. Used for freeing the library */
|
||||
HMODULE handle;
|
||||
|
||||
char* name;
|
||||
BOOL enabled;
|
||||
proxyEvents* events;
|
||||
};
|
||||
|
||||
BOOL pf_filters_init(filters_list** list);
|
||||
BOOL pf_filters_register_new(filters_list* list, const char* module_path, const char* filter_name);
|
||||
PF_FILTER_RESULT pf_filters_run_by_type(filters_list* list, PF_FILTER_TYPE type,
|
||||
connectionInfo* info,
|
||||
void* param);
|
||||
void pf_filters_unregister_all(filters_list* list);
|
||||
|
||||
#define RUN_FILTER(_filters,_type,_conn_info,_event_info,_cb,...) ({ \
|
||||
({ BOOL result; switch(pf_filters_run_by_type(_filters,_type,_conn_info,_event_info)) { \
|
||||
case FILTER_PASS: \
|
||||
result = _cb(__VA_ARGS__); \
|
||||
break; \
|
||||
case FILTER_IGNORE: \
|
||||
result = TRUE; \
|
||||
break; \
|
||||
case FILTER_DROP: \
|
||||
default: \
|
||||
result = FALSE; \
|
||||
}; result; \
|
||||
}); \
|
||||
})
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_FILTERS_H */
|
@ -40,7 +40,13 @@ static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
if (!config->Keyboard)
|
||||
return TRUE;
|
||||
|
||||
return freerdp_input_send_keyboard_event(context->input, flags, code);
|
||||
proxyKeyboardEventInfo info =
|
||||
{
|
||||
.flags = flags,
|
||||
.rdp_scan_code = code
|
||||
};
|
||||
return RUN_FILTER(config->Filters, FILTER_TYPE_KEYBOARD, ps->pdata->info, &info,
|
||||
freerdp_input_send_keyboard_event, context->input, flags, code);
|
||||
}
|
||||
|
||||
static BOOL pf_server_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
@ -66,7 +72,13 @@ static BOOL pf_server_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
|
||||
if (!config->Mouse)
|
||||
return TRUE;
|
||||
|
||||
return freerdp_input_send_mouse_event(context->input, flags, x, y);
|
||||
proxyMouseEventInfo info =
|
||||
{
|
||||
.flags = flags,
|
||||
.x = x, .y = y
|
||||
};
|
||||
return RUN_FILTER(config->Filters, FILTER_TYPE_MOUSE, ps->pdata->info, &info,
|
||||
freerdp_input_send_mouse_event, context->input, flags, x, y);
|
||||
}
|
||||
|
||||
static BOOL pf_server_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
|
||||
|
@ -158,7 +158,9 @@ static BOOL pf_server_post_connect(freerdp_peer* client)
|
||||
connectionClosedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
/* keep both sides of the connection in pdata */
|
||||
pc->pdata = ps->pdata;
|
||||
pdata->pc = (pClientContext*) pc;
|
||||
pdata->info->TargetHostname = _strdup(host);
|
||||
pdata->info->Username = _strdup(client->settings->Username);
|
||||
pdata->pc = pc;
|
||||
pdata->ps = ps;
|
||||
pdata->connectionClosed = connectionClosedEvent;
|
||||
pf_server_rdpgfx_init(ps);
|
||||
@ -206,7 +208,15 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
|
||||
ps = (pServerContext*) client->context;
|
||||
ps->dynvcReady = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
pdata = calloc(1, sizeof(proxyData));
|
||||
pdata = pf_context_proxy_data_new();
|
||||
|
||||
if (pdata == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_context_proxy_data_new failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pdata->info->ClientHostname = _strdup(client->hostname);
|
||||
ps->pdata = pdata;
|
||||
/* keep configuration in proxyData */
|
||||
pdata->config = client->ContextExtra;
|
||||
@ -320,7 +330,7 @@ fail:
|
||||
|
||||
pc = (rdpContext*) pdata->pc;
|
||||
freerdp_client_stop(pc);
|
||||
free(pdata);
|
||||
pf_context_proxy_data_free(pdata);
|
||||
freerdp_client_context_free(pc);
|
||||
client->Disconnect(client);
|
||||
freerdp_peer_context_free(client);
|
||||
|
Loading…
Reference in New Issue
Block a user