summaryrefslogtreecommitdiff
path: root/src/rdp/rdp_impl.c
diff options
context:
space:
mode:
authorsss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
committersss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
commitcc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch)
treeec09d690c7656ab5f2cc72607e05fb359c24d8b2 /src/rdp/rdp_impl.c
added webrdp public code
Diffstat (limited to 'src/rdp/rdp_impl.c')
-rw-r--r--src/rdp/rdp_impl.c637
1 files changed, 637 insertions, 0 deletions
diff --git a/src/rdp/rdp_impl.c b/src/rdp/rdp_impl.c
new file mode 100644
index 0000000..3aa47e2
--- /dev/null
+++ b/src/rdp/rdp_impl.c
@@ -0,0 +1,637 @@
+/* BSD-2-Clause license
+ *
+ * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>.
+ *
+ */
+
+#include <errno.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/select.h>
+
+#include <freerdp/client/channels.h>
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/client/cmdline.h>
+#include <freerdp/client/file.h>
+#include <freerdp/constants.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/gdi/gdi.h>
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <freerdp/log.h>
+
+#include <webrdp_core_api.h>
+#include <webrdp_module_api.h>
+
+#include "rdp_backend_api.h"
+#include "rdp_impl.h"
+#include "rdp_display_output.h"
+#include "rdp_channels.h"
+#include "rdp_clipboard.h"
+#include "rdp_ft.h"
+#include "rdp_user_input.h"
+
+/* from winpr */
+
+typedef BOOL (*pcIsHandled)(HANDLE handle);
+typedef BOOL (*pcCloseHandle)(HANDLE handle);
+typedef int (*pcGetFd)(HANDLE handle);
+typedef DWORD (*pcCleanupHandle)(HANDLE handle);
+typedef BOOL (*pcReadFile)(PVOID Object, LPVOID lpBuffer,
+ DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
+ LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcReadFileEx)(HANDLE hFile, LPVOID lpBuffer,
+ DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped,
+ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+typedef BOOL (*pcReadFileScatter)(HANDLE hFile,
+ FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
+ LPDWORD lpReserved, LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcWriteFile)(PVOID Object, LPCVOID lpBuffer,
+ DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
+ LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcWriteFileEx)(HANDLE hFile, LPCVOID lpBuffer,
+ DWORD nNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped,
+ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+typedef BOOL (*pcWriteFileGather)(HANDLE hFile,
+ FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToWrite,
+ LPDWORD lpReserved, LPOVERLAPPED lpOverlapped);
+typedef DWORD (*pcGetFileSize)(HANDLE handle, LPDWORD lpFileSizeHigh);
+typedef BOOL (*pcFlushFileBuffers)(HANDLE hFile);
+typedef BOOL (*pcSetEndOfFile)(HANDLE handle);
+typedef DWORD (*pcSetFilePointer)(HANDLE handle, LONG lDistanceToMove,
+ PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
+typedef BOOL (*pcSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
+ PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
+typedef BOOL (*pcLockFile)(HANDLE hFile, DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow,
+ DWORD nNumberOfBytesToLockHigh);
+typedef BOOL (*pcLockFileEx)(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
+ DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
+ LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcUnlockFile)(HANDLE hFile, DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh);
+typedef BOOL (*pcUnlockFileEx)(HANDLE hFile, DWORD dwReserved,
+ DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh,
+ LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcSetFileTime)(HANDLE hFile, const FILETIME *lpCreationTime,
+ const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime);
+
+typedef struct _HANDLE_OPS
+{
+ pcIsHandled IsHandled;
+ pcCloseHandle CloseHandle;
+ pcGetFd GetFd;
+ pcCleanupHandle CleanupHandle;
+ pcReadFile ReadFile;
+ pcReadFileEx ReadFileEx;
+ pcReadFileScatter ReadFileScatter;
+ pcWriteFile WriteFile;
+ pcWriteFileEx WriteFileEx;
+ pcWriteFileGather WriteFileGather;
+ pcGetFileSize GetFileSize;
+ pcFlushFileBuffers FlushFileBuffers;
+ pcSetEndOfFile SetEndOfFile;
+ pcSetFilePointer SetFilePointer;
+ pcSetFilePointerEx SetFilePointerEx;
+ pcLockFile LockFile;
+ pcLockFileEx LockFileEx;
+ pcUnlockFile UnlockFile;
+ pcUnlockFileEx UnlockFileEx;
+ pcSetFileTime SetFileTime;
+} HANDLE_OPS;
+
+#define WINPR_HANDLE_DEF() \
+ ULONG Type; \
+ ULONG Mode; \
+ HANDLE_OPS *ops
+
+struct winpr_handle
+{
+ WINPR_HANDLE_DEF();
+};
+typedef struct winpr_handle WINPR_HANDLE;
+
+static INLINE BOOL
+winpr_Handle_GetInfo(HANDLE handle, ULONG *pType, WINPR_HANDLE **pObject)
+{
+ WINPR_HANDLE *wHandle;
+
+ if (handle == NULL || handle == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ wHandle = (WINPR_HANDLE *)handle;
+
+ *pType = wHandle->Type;
+ *pObject = handle;
+
+ return TRUE;
+}
+
+static INLINE int
+winpr_Handle_getFd(HANDLE handle)
+{
+ WINPR_HANDLE *hdl;
+ ULONG type;
+
+ if (!winpr_Handle_GetInfo(handle, &type, &hdl))
+ return -1;
+
+ if (!hdl || !hdl->ops || !hdl->ops->GetFd)
+ return -1;
+
+ return hdl->ops->GetFd(handle);
+}
+
+/* end from winpr */
+
+bool
+rdp_init_internals(void *internals)
+{
+ setlocale(LC_ALL, "");
+#ifdef DEBUG
+ setenv("WLOG_LEVEL", "DEBUG", 1);
+#else
+ setenv("WLOG_LEVEL", "ERROR", 1);
+#endif
+ rdp_internals *i = internals;
+ i->instance = freerdp_new();
+ if (!i->instance)
+ {
+ const char *msg
+ = "rdp_module: Failed to create FreeRDP instance";
+ i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ goto error;
+ }
+ rdp_register_base(i->instance);
+ i->instance->ContextSize = sizeof(my_rdp_context);
+ if (!freerdp_context_new(i->instance))
+ {
+ const char *msg
+ = "rdp_module: Failed to create FreeRDP context";
+ i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ goto error;
+ }
+ i->context = (my_rdp_context *)i->instance->context;
+ ((my_rdp_context *)i->instance->context)->my_internals = internals;
+ {
+ char **argv = malloc(sizeof(char *));
+ if (!argv)
+ {
+ perror("malloc");
+ goto error;
+ }
+ argv[0] = strdup("./core");
+ rdpSettings *settings = i->instance->context->settings;
+ freerdp_client_settings_parse_command_line(
+ settings, 1, argv, FALSE);
+ free(argv[0]);
+ free(argv);
+ if (!settings)
+ {
+ const char *msg
+ = "rdp_module: Failed to create FreeRDP settings";
+ i->core->api_utils->log_msg((const uint8_t *)msg,
+ strlen(msg), wrdp_log_level_error, 0);
+ goto error;
+ }
+ settings->ThreadingFlags = THREADING_FLAGS_DISABLE_THREADS;
+
+ settings->OsMajorType = OSMAJORTYPE_UNIX;
+ settings->OsMinorType = OSMINORTYPE_UNSPECIFIED;
+
+ /* unsupported */
+ settings->RemoteFxCodec = FALSE;
+ settings->NSCodec = FALSE;
+
+ /* turn on clipboard redirect */
+ settings->RedirectClipboard = TRUE;
+ }
+ i->context->ft_to_server = calloc(1, sizeof(my_rdp_ft));
+ if (!i->context->ft_to_server)
+ {
+ perror("calloc");
+ goto error;
+ }
+ i->context->ft_to_client = calloc(1, sizeof(my_rdp_ft));
+ if (!i->context->ft_to_client)
+ {
+ perror("calloc");
+ goto error;
+ }
+ freerdp_register_addin_provider(
+ freerdp_channels_load_static_addin_entry, 0);
+ i->settings = i->instance->context->settings;
+ //i->instance->settings = i->settings;
+ i->settings->instance = i->instance;
+ i->instance->context->settings = i->settings;
+ return true;
+error:
+ if (i->instance)
+ {
+ if (i->instance->context)
+ {
+ freerdp_context_free(i->instance);
+ }
+ freerdp_free(i->instance);
+ i->instance = 0;
+ }
+ if (i->context->ft_to_client)
+ {
+ free(i->context->ft_to_client);
+ }
+ if (i->context->ft_to_server)
+ {
+ free(i->context->ft_to_server);
+ }
+ {
+ const char *msg = "rdp_module: internal error";
+ i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ }
+ i->core->api_msgs->send_error_msg(
+ "rdp_module_internal_error", i->task_info);
+ return false;
+}
+
+static void
+rdp_check_all_fds(struct ev_loop *loop, ev_io *w)
+{
+ rdp_internals *i = w->data;
+ bool failure = false;
+ if (i->backend->stopped)
+ return;
+ if ((freerdp_check_event_handles(i->instance->context)) != TRUE)
+ {
+ uint32_t e;
+ e = freerdp_error_info(i->instance);
+ switch (e)
+ {
+ case 1:
+ case 2:
+ case 7:
+ case 9:
+ /* case 12: */
+ /* No really an error
+ * (Happens when you invoke Disconnect
+ * in Start-Menu) */
+ break;
+ case 5:
+ {
+ const char *msg
+ = "rdp_module: Another user connected to "
+ "the server,\nforcing the "
+ "disconnection of the "
+ "current connection.";
+ i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg),
+ wrdp_log_level_debug, 0);
+ break;
+ }
+ default:
+ {
+ failure = true;
+ }
+ break;
+ }
+ if (failure)
+ {
+ char buf[512];
+ snprintf(buf, 511, "%s",
+ freerdp_get_last_error_name(
+ freerdp_get_last_error(i->instance->context)));
+ i->core->api_msgs->send_error_msg(buf, i->task_info);
+ i->core->api_utils->log_msg((const uint8_t *)buf,
+ strlen(buf), wrdp_log_level_error, 0);
+ goto cleanup;
+ }
+ }
+ if (freerdp_shall_disconnect_context(i->instance->context))
+ {
+ {
+ const char *msg = "rdp_module: disconnect, no error";
+ i->core->api_utils->log_msg((const uint8_t *)msg,
+ strlen(msg), wrdp_log_level_trace, 0);
+ }
+ freerdp_disconnect(i->instance);
+ i->conn_state = rdp_conn_state_offline;
+ i->core->api_msgs->send_error_msg(
+ "rdp_module_disconnect_no_error", i->task_info);
+ goto cleanup;
+ }
+ return;
+cleanup:
+ ev_io_stop(loop, w);
+ if (!failure)
+ {
+ i->core->api_msgs->send_termination_msg(i->task_info);
+ }
+ i->core->api_core->task_finished(true, i->task_info);
+}
+
+static void
+rdp_fd_readable_cb(struct ev_loop *loop, ev_io *w, int revents)
+{
+ rdp_check_all_fds(loop, w);
+}
+
+bool
+rdp_connect(void *internals)
+{
+ rdp_internals *_i = internals;
+#ifdef DEBUG
+ {
+ /* print settings before connect for debug */
+ char buf[512];
+ snprintf(buf, 511,
+ "rdp_module: settings:\n\tfntlm: %ld\n\t"
+ "height: %ld\n\thost: %s\n\tnomani: %ld\n\tnonla: %ld\n\t"
+ "notheme: %ld\n\tnotls: %ld\n\tnowallp: %ld\n\tnowdrag: "
+ "%ld\n\t"
+ "password: %s\n\tpcb: %s\n\tperf: %ld\n\tport: "
+ "%ld\n\tuser: %s\n\t"
+ "width: %ld",
+ _i->my_settings.fntlm.value, _i->my_settings.height.value,
+ _i->my_settings.host.value, _i->my_settings.nomani.value,
+ _i->my_settings.nonla.value, _i->my_settings.notheme.value,
+ _i->my_settings.notls.value, _i->my_settings.nowallp.value,
+ _i->my_settings.nowdrag.value,
+ _i->my_settings.password.value, _i->my_settings.pcb.value,
+ _i->my_settings.perf.value, _i->my_settings.port.value,
+ _i->my_settings.user.value, _i->my_settings.width.value);
+ _i->core->api_utils->log_msg(
+ (const uint8_t *)buf, strlen(buf), wrdp_log_level_trace, 0);
+ }
+#endif /* DEBUG */
+ if (!_i->my_settings.host.value || !_i->my_settings.host.value[0])
+ {
+ const char *msg = "rdp_module: host is not set";
+ _i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ _i->core->api_msgs->send_error_msg(
+ "rdp_module_param_error", _i->task_info);
+ return false;
+ }
+ if (!_i->my_settings.port.value)
+ {
+ const char *msg = "rdp_module: port is not set";
+ _i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ _i->core->api_msgs->send_error_msg(
+ "rdp_module_param_error", _i->task_info);
+ return false;
+ }
+ if (!_i->my_settings.user.value || !_i->my_settings.user.value[0])
+ {
+ const char *msg = "rdp_module: user is not set";
+ _i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ _i->core->api_msgs->send_error_msg(
+ "rdp_module_param_error", _i->task_info);
+ return false;
+ }
+ /* password can be optional ? */
+ if (freerdp_connect(_i->instance))
+ {
+ int fdcount = 0, i;
+ HANDLE *fds[256];
+ ZeroMemory(fds, sizeof(fds));
+
+ struct ev_loop *loop
+ = _i->core->api_core->get_libev_loop(_i->task_info);
+ fdcount = freerdp_get_event_handles(
+ _i->instance->context, (HANDLE *)fds, 256);
+ if (!fdcount)
+ {
+ const char *msg
+ = "Failed to get FreeRDP file descriptors";
+ _i->core->api_utils->log_msg((const uint8_t *)msg,
+ strlen(msg), wrdp_log_level_error, 0);
+ _i->core->api_msgs->send_error_msg(
+ "rdp_module_internal_error", _i->task_info);
+ return false;
+ }
+ _i->rdp_fd_count = fdcount;
+ for (i = 0; i < fdcount; ++i)
+ {
+ ULONG type;
+ WINPR_HANDLE *phandle = 0;
+ int fd = 0;
+ if (!winpr_Handle_GetInfo(fds[i], &type, &phandle))
+ {
+ /* TODO: assume what this is not fatal */
+ const char *msg = "winpr_Handle_GetInfo failed";
+ _i->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg),
+ wrdp_log_level_error, 0);
+ continue;
+ }
+ fd = winpr_Handle_getFd(phandle);
+
+ /* TODO: check type here, and set EV_WRITE if needed
+ * for now watch only for read available event*/
+ ev_io_init(
+ &(_i->rdp_fd[i]), rdp_fd_readable_cb, fd, EV_READ);
+ _i->rdp_fd[i].data = internals;
+ ev_io_start(loop, &(_i->rdp_fd[i]));
+ }
+ return true;
+ }
+ {
+ const char *msg = freerdp_get_last_error_name(
+ freerdp_get_last_error(_i->instance->context));
+ _i->core->api_msgs->send_error_msg(msg, _i->task_info);
+ }
+
+ return false;
+}
+
+static BOOL
+rdp_pre_connect(freerdp *instance)
+{
+ rdpSettings *settings = instance->context->settings;
+ my_rdp_context *c = (my_rdp_context *)instance->context;
+
+ RegisterUpdate(instance);
+ RegisterPrimary(instance);
+
+ /* looks like this settings reducing artifacts level */
+ settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE;
+ settings->OrderSupport[NEG_SCRBLT_INDEX] = FALSE;
+
+ /* causing random disconnects */
+ settings->OrderSupport[NEG_ATEXTOUT_INDEX] = FALSE;
+ settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
+ settings->NoBitmapCompressionHeader = TRUE;
+ settings->BitmapCompressionDisabled = TRUE;
+ settings->BitmapCacheEnabled = FALSE;
+ settings->BrushSupportLevel = 0;
+
+ /* causing connection failure on recent versions of freerdp */
+ settings->OffscreenSupportLevel = 0;
+ settings->OffscreenCacheSize = 0;
+
+ /* following required at least on windows 7 */
+ settings->OrderSupport[NEG_MEMBLT_INDEX] = FALSE;
+ settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE;
+
+ /* following required for windows 2012,2016 */
+ settings->FastPathOutput = 1;
+
+ /* testing */
+ /* wsgate settings */
+ // settings->ColorDepth = 16;
+ // settings->FrameAcknowledge = 1;
+ // settings->LargePointerFlag = 1;
+ // settings->BitmapCacheV3Enabled = FALSE;
+ // settings->BitmapCachePersistEnabled = FALSE;
+ // settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; // XXX
+ // settings->OrderSupport[NEG_SCRBLT_INDEX] = FALSE; // XXX
+ // settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE; //
+ //XXX settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
+ // settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
+ // settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
+ // settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE;
+
+ PubSub_SubscribeChannelConnected(
+ instance->context->pubSub, rdp_on_channel_connected);
+ PubSub_SubscribeChannelDisconnected(
+ instance->context->pubSub, rdp_on_channel_disconnected);
+
+ freerdp_client_load_addins(instance->context->channels, settings);
+ instance->context->cache = cache_new(instance->context);
+
+ c->my_internals->clrconv
+ = freerdp_clrconv_new(CLRCONV_ALPHA | CLRCONV_INVERT);
+
+ if (!instance->context->cache)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL
+rdp_post_connect(freerdp *instance)
+{
+ my_rdp_context *c = (my_rdp_context *)instance->context;
+ my_rdp_clipboard *clip = 0;
+ rdpPointer p;
+ memset(&p, 0, sizeof(p));
+ p.size = sizeof(my_rdp_pointer);
+ register_pointer(&p);
+ graphics_register_pointer(instance->context->graphics, &p);
+ pointer_cache_register_callbacks(instance->context->update);
+
+ clip = rdp_clipboard_new(c);
+ if (!clip)
+ {
+ const char *msg = "rdp_module: \"rdp_clipboard_new\" failed";
+ c->my_internals->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ return FALSE;
+ }
+ c->clipboard = clip;
+
+ c->my_internals->conn_state = rdp_conn_state_connected;
+
+ {
+ const char *msg
+ = "rdp_module: \"C:RDP session connection started.\"";
+ c->my_internals->core->api_utils->log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_trace, 0);
+ }
+
+ c->my_internals->core->api_msgs->send_text_msg(
+ "C:RDP session connection started.", c->my_internals->task_info);
+
+ instance->context->update->DesktopResize(instance->context);
+
+ return TRUE;
+}
+
+static DWORD
+rdp_verify_certificate(freerdp *instance, const char *host, UINT16 port,
+ const char *common_name, const char *subject, const char *issuer,
+ const char *fingerprint, DWORD flags)
+{
+ my_rdp_context *c = (my_rdp_context *)instance->context;
+ char buf[512];
+ snprintf(buf, 511,
+ "Certificate details:\n\tSubject: %s\n\tIssuer:"
+ " %s\n\tThumbprint: %s\n"
+ "The above X.509 certificate could not be verified, possibly "
+ "because you do not have "
+ "the CA certificate in your certificate store, or the "
+ "certificate has expired. "
+ "Please look at the OpenSSL documentation on how to add a "
+ "private CA to the store.",
+ subject, issuer, fingerprint);
+ c->my_internals->core->api_utils->log_msg(
+ (const uint8_t *)buf, strlen(buf), wrdp_log_level_debug, 0);
+
+ return TRUE; /* ?? */
+}
+
+/*static int
+rdp_receive_channel_data (freerdp* instance,
+ UINT16 channelId,
+ BYTE* data,
+ int size,
+ int flags,
+ int total_size)
+{
+ return freerdp_channels_data (
+ instance, channelId, data, size, flags, total_size);
+}*/
+
+static BOOL
+rdp_context_new(freerdp *instance, rdpContext *context)
+{
+ return TRUE;
+}
+
+static void
+rdp_context_free(freerdp *instance, rdpContext *context)
+{
+ my_rdp_context *c = (my_rdp_context *)context;
+ if (context->cache)
+ {
+ cache_free(context->cache);
+ context->cache = NULL;
+ }
+ if (c->my_internals->clrconv)
+ {
+ freerdp_clrconv_free(c->my_internals->clrconv);
+ c->my_internals->clrconv = NULL;
+ }
+}
+
+void
+rdp_register_base(freerdp *r)
+{
+ r->PreConnect = rdp_pre_connect;
+ r->PostConnect = rdp_post_connect;
+ r->VerifyCertificateEx = rdp_verify_certificate;
+ // r->ReceiveChannelData = rdp_receive_channel_data;
+ r->ContextNew = rdp_context_new;
+ r->ContextFree = rdp_context_free;
+}