2011-08-18 12:06:32 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-08-18 12:06:32 +04:00
|
|
|
* FreeRDP Test Server
|
|
|
|
*
|
|
|
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
2011-08-24 17:59:32 +04:00
|
|
|
* Copyright 2011 Vic Lee
|
Standard RDP Security Layer Levels/Method Overhaul
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
2014-12-12 04:17:12 +03:00
|
|
|
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
|
2011-08-18 12:06:32 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
#include <freerdp/config.h>
|
2012-08-15 01:20:53 +04:00
|
|
|
|
2011-08-18 12:06:32 +04:00
|
|
|
#include <errno.h>
|
2011-08-25 09:18:01 +04:00
|
|
|
#include <signal.h>
|
2012-08-15 01:20:53 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
#include <winpr/winpr.h>
|
2012-10-09 07:42:01 +04:00
|
|
|
#include <winpr/crt.h>
|
2021-06-16 13:59:25 +03:00
|
|
|
#include <winpr/assert.h>
|
2017-04-11 20:04:25 +03:00
|
|
|
#include <winpr/ssl.h>
|
2012-11-27 05:15:48 +04:00
|
|
|
#include <winpr/synch.h>
|
2021-05-31 12:42:03 +03:00
|
|
|
#include <winpr/file.h>
|
2015-07-03 13:38:19 +03:00
|
|
|
#include <winpr/string.h>
|
2015-07-03 10:56:43 +03:00
|
|
|
#include <winpr/path.h>
|
2014-11-12 22:06:34 +03:00
|
|
|
#include <winpr/winsock.h>
|
2014-06-25 23:21:02 +04:00
|
|
|
|
2021-09-23 15:52:03 +03:00
|
|
|
#include <freerdp/streamdump.h>
|
|
|
|
#include <freerdp/transport_io.h>
|
|
|
|
|
2014-03-03 21:10:06 +04:00
|
|
|
#include <freerdp/channels/wtsvc.h>
|
|
|
|
#include <freerdp/channels/channels.h>
|
2021-08-25 11:02:46 +03:00
|
|
|
#include <freerdp/channels/drdynvc.h>
|
2014-09-12 19:38:12 +04:00
|
|
|
|
2011-08-23 19:28:54 +04:00
|
|
|
#include <freerdp/constants.h>
|
2012-10-09 00:12:03 +04:00
|
|
|
#include <freerdp/server/rdpsnd.h>
|
2023-02-03 17:56:16 +03:00
|
|
|
#include <freerdp/settings.h>
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2022-01-19 11:26:57 +03:00
|
|
|
#include "sf_ainput.h"
|
2012-10-09 00:12:03 +04:00
|
|
|
#include "sf_audin.h"
|
|
|
|
#include "sf_rdpsnd.h"
|
2014-06-25 23:21:02 +04:00
|
|
|
#include "sf_encomsp.h"
|
2012-10-09 00:12:03 +04:00
|
|
|
|
|
|
|
#include "sfreerdp.h"
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2014-09-12 19:38:12 +04:00
|
|
|
#include <freerdp/log.h>
|
|
|
|
#define TAG SERVER_TAG("sample")
|
|
|
|
|
2013-06-24 20:02:21 +04:00
|
|
|
#define SAMPLE_SERVER_USE_CLIENT_RESOLUTION 1
|
2013-06-21 18:46:46 +04:00
|
|
|
#define SAMPLE_SERVER_DEFAULT_WIDTH 1024
|
|
|
|
#define SAMPLE_SERVER_DEFAULT_HEIGHT 768
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
struct server_info
|
2011-10-18 11:10:12 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
BOOL test_dump_rfx_realtime;
|
|
|
|
const char* test_pcap_file;
|
2021-09-23 15:52:03 +03:00
|
|
|
const char* replay_dump;
|
2021-09-06 13:50:08 +03:00
|
|
|
const char* cert;
|
|
|
|
const char* key;
|
2021-09-03 09:26:07 +03:00
|
|
|
};
|
2011-08-24 17:59:32 +04:00
|
|
|
|
2019-11-22 12:41:09 +03:00
|
|
|
static void test_peer_context_free(freerdp_peer* client, rdpContext* ctx)
|
2011-08-24 17:59:32 +04:00
|
|
|
{
|
2019-11-22 12:41:09 +03:00
|
|
|
testPeerContext* context = (testPeerContext*)ctx;
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(client);
|
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
if (context)
|
2011-08-24 17:59:32 +04:00
|
|
|
{
|
2011-12-12 18:37:48 +04:00
|
|
|
if (context->debug_channel_thread)
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(context->stopEvent);
|
2013-03-22 01:49:10 +04:00
|
|
|
SetEvent(context->stopEvent);
|
|
|
|
WaitForSingleObject(context->debug_channel_thread, INFINITE);
|
|
|
|
CloseHandle(context->debug_channel_thread);
|
2011-12-12 18:37:48 +04:00
|
|
|
}
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2013-05-09 01:48:30 +04:00
|
|
|
Stream_Free(context->s, TRUE);
|
2012-10-09 07:21:26 +04:00
|
|
|
free(context->icon_data);
|
|
|
|
free(context->bg_data);
|
2011-10-18 11:10:12 +04:00
|
|
|
rfx_context_free(context->rfx_context);
|
2012-03-18 12:36:38 +04:00
|
|
|
nsc_context_free(context->nsc_context);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2011-12-12 12:42:42 +04:00
|
|
|
if (context->debug_channel)
|
|
|
|
WTSVirtualChannelClose(context->debug_channel);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2019-11-22 12:41:09 +03:00
|
|
|
sf_peer_audin_uninit(context);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2022-01-19 11:26:57 +03:00
|
|
|
#if defined(CHANNEL_AINPUT_SERVER)
|
|
|
|
sf_peer_ainput_uninit(context);
|
|
|
|
#endif
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
rdpsnd_server_context_free(context->rdpsnd);
|
|
|
|
encomsp_server_context_free(context->encomsp);
|
2014-06-25 23:21:02 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
WTSCloseServer((HANDLE)context->vcm);
|
2011-08-24 17:59:32 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
static BOOL test_peer_context_new(freerdp_peer* client, rdpContext* ctx)
|
|
|
|
{
|
|
|
|
testPeerContext* context = (testPeerContext*)ctx;
|
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
WINPR_ASSERT(context);
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(ctx->settings);
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (!(context->rfx_context = rfx_context_new_ex(TRUE, ctx->settings->ThreadingFlags)))
|
2021-09-03 09:26:07 +03:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!rfx_context_reset(context->rfx_context, SAMPLE_SERVER_DEFAULT_WIDTH,
|
|
|
|
SAMPLE_SERVER_DEFAULT_HEIGHT))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
context->rfx_context->mode = RLGR3;
|
|
|
|
rfx_context_set_pixel_format(context->rfx_context, PIXEL_FORMAT_RGB24);
|
|
|
|
|
|
|
|
if (!(context->nsc_context = nsc_context_new()))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, PIXEL_FORMAT_RGB24))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!(context->s = Stream_New(NULL, 65536)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
context->icon_x = UINT32_MAX;
|
|
|
|
context->icon_y = UINT32_MAX;
|
|
|
|
context->vcm = WTSOpenServerA((LPSTR)client->context);
|
|
|
|
|
|
|
|
if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
|
|
test_peer_context_free(client, ctx);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-04-28 18:00:41 +03:00
|
|
|
static BOOL test_peer_init(freerdp_peer* client)
|
2011-10-18 11:10:12 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
2013-06-14 05:34:46 +04:00
|
|
|
client->ContextSize = sizeof(testPeerContext);
|
2019-11-22 12:41:09 +03:00
|
|
|
client->ContextNew = test_peer_context_new;
|
|
|
|
client->ContextFree = test_peer_context_free;
|
2015-04-28 18:00:41 +03:00
|
|
|
return freerdp_peer_context_new(client);
|
2011-10-18 11:10:12 +04:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
static wStream* test_peer_stream_init(testPeerContext* context)
|
2011-08-24 17:59:32 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(context);
|
|
|
|
WINPR_ASSERT(context->s);
|
|
|
|
|
2013-05-02 02:15:55 +04:00
|
|
|
Stream_Clear(context->s);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(context->s, 0);
|
2011-10-18 11:10:12 +04:00
|
|
|
return context->s;
|
2011-08-24 17:59:32 +04:00
|
|
|
}
|
2011-08-24 12:25:18 +04:00
|
|
|
|
2012-05-11 12:35:11 +04:00
|
|
|
static void test_peer_begin_frame(freerdp_peer* client)
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
rdpUpdate* update;
|
2020-03-19 11:04:59 +03:00
|
|
|
SURFACE_FRAME_MARKER fm = { 0 };
|
2021-09-03 09:26:07 +03:00
|
|
|
testPeerContext* context;
|
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(client->context);
|
|
|
|
|
|
|
|
update = client->context->update;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update);
|
|
|
|
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2018-04-03 18:17:45 +03:00
|
|
|
fm.frameAction = SURFACECMD_FRAMEACTION_BEGIN;
|
|
|
|
fm.frameId = context->frame_id;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->SurfaceFrameMarker);
|
2018-04-03 18:17:45 +03:00
|
|
|
update->SurfaceFrameMarker(update->context, &fm);
|
2012-05-11 12:35:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_peer_end_frame(freerdp_peer* client)
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
rdpUpdate* update;
|
2020-03-19 11:04:59 +03:00
|
|
|
SURFACE_FRAME_MARKER fm = { 0 };
|
2021-09-03 09:26:07 +03:00
|
|
|
testPeerContext* context;
|
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
update = client->context->update;
|
|
|
|
WINPR_ASSERT(update);
|
|
|
|
|
2018-04-03 18:17:45 +03:00
|
|
|
fm.frameAction = SURFACECMD_FRAMEACTION_END;
|
|
|
|
fm.frameId = context->frame_id;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->SurfaceFrameMarker);
|
2018-04-03 18:17:45 +03:00
|
|
|
update->SurfaceFrameMarker(update->context, &fm);
|
2012-05-11 12:35:11 +04:00
|
|
|
context->frame_id++;
|
|
|
|
}
|
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
static BOOL test_peer_draw_background(freerdp_peer* client)
|
2011-08-23 19:28:54 +04:00
|
|
|
{
|
2021-06-16 12:28:53 +03:00
|
|
|
size_t size;
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2011-08-24 17:59:32 +04:00
|
|
|
RFX_RECT rect;
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE* rgb_data;
|
2021-06-16 13:59:25 +03:00
|
|
|
const rdpSettings* settings;
|
2021-09-03 09:26:07 +03:00
|
|
|
rdpUpdate* update;
|
2018-04-03 18:17:45 +03:00
|
|
|
SURFACE_BITS_COMMAND cmd = { 0 };
|
2021-06-16 13:59:25 +03:00
|
|
|
testPeerContext* context;
|
2016-04-05 18:07:45 +03:00
|
|
|
BOOL ret = FALSE;
|
2011-08-24 12:25:18 +04:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(client);
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = client->context->settings;
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
update = client->context->update;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update);
|
|
|
|
|
2021-07-01 12:40:41 +03:00
|
|
|
if (!settings->RemoteFxCodec && !freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
|
2015-06-17 23:08:02 +03:00
|
|
|
return FALSE;
|
2011-08-23 19:28:54 +04:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(settings->DesktopWidth <= UINT16_MAX);
|
|
|
|
WINPR_ASSERT(settings->DesktopHeight <= UINT16_MAX);
|
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
s = test_peer_stream_init(context);
|
2011-08-24 17:59:32 +04:00
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
2021-06-16 13:59:25 +03:00
|
|
|
rect.width = (UINT16)settings->DesktopWidth;
|
|
|
|
rect.height = (UINT16)settings->DesktopHeight;
|
|
|
|
size = rect.width * rect.height * 3ULL;
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-23 16:42:21 +03:00
|
|
|
if (!(rgb_data = malloc(size)))
|
2015-06-17 23:08:02 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Problem allocating memory");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2015-04-23 16:42:21 +03:00
|
|
|
|
2011-08-24 17:59:32 +04:00
|
|
|
memset(rgb_data, 0xA0, size);
|
2011-08-23 19:28:54 +04:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
if (settings->RemoteFxCodec)
|
2012-03-18 12:36:38 +04:00
|
|
|
{
|
2020-04-03 15:04:12 +03:00
|
|
|
WLog_DBG(TAG, "Using RemoteFX codec");
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!rfx_compose_message(context->rfx_context, s, &rect, 1, rgb_data, rect.width,
|
|
|
|
rect.height, rect.width * 3))
|
2015-04-23 16:42:21 +03:00
|
|
|
{
|
|
|
|
goto out;
|
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(settings->RemoteFxCodecId <= UINT16_MAX);
|
|
|
|
cmd.bmp.codecID = (UINT16)settings->RemoteFxCodecId;
|
2020-04-03 15:04:12 +03:00
|
|
|
cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
|
2012-03-18 12:36:38 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-03 15:04:12 +03:00
|
|
|
WLog_DBG(TAG, "Using NSCodec");
|
2019-11-06 17:24:51 +03:00
|
|
|
nsc_compose_message(context->nsc_context, s, rgb_data, rect.width, rect.height,
|
2021-06-16 13:59:25 +03:00
|
|
|
rect.width * 3ULL);
|
|
|
|
WINPR_ASSERT(settings->NSCodecId <= UINT16_MAX);
|
|
|
|
cmd.bmp.codecID = (UINT16)settings->NSCodecId;
|
2020-04-03 15:04:12 +03:00
|
|
|
cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
|
2012-03-18 12:36:38 +04:00
|
|
|
}
|
2011-08-23 19:28:54 +04:00
|
|
|
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.destLeft = 0;
|
|
|
|
cmd.destTop = 0;
|
|
|
|
cmd.destRight = rect.width;
|
|
|
|
cmd.destBottom = rect.height;
|
|
|
|
cmd.bmp.bpp = 32;
|
|
|
|
cmd.bmp.flags = 0;
|
|
|
|
cmd.bmp.width = rect.width;
|
|
|
|
cmd.bmp.height = rect.height;
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
|
|
|
|
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.bmp.bitmapData = Stream_Buffer(s);
|
2015-04-23 16:42:21 +03:00
|
|
|
test_peer_begin_frame(client);
|
2018-04-03 18:17:45 +03:00
|
|
|
update->SurfaceBits(update->context, &cmd);
|
2015-04-23 16:42:21 +03:00
|
|
|
test_peer_end_frame(client);
|
2015-06-17 23:08:02 +03:00
|
|
|
ret = TRUE;
|
2015-04-23 16:42:21 +03:00
|
|
|
out:
|
2012-10-09 07:21:26 +04:00
|
|
|
free(rgb_data);
|
2015-06-17 23:08:02 +03:00
|
|
|
return ret;
|
2011-08-23 19:28:54 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
static BOOL test_peer_load_icon(freerdp_peer* client)
|
2011-08-24 19:10:23 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
testPeerContext* context;
|
2011-08-24 19:10:23 +04:00
|
|
|
FILE* fp;
|
|
|
|
int i;
|
2022-10-13 17:25:36 +03:00
|
|
|
char line[50] = { 0 };
|
2015-06-23 13:09:42 +03:00
|
|
|
BYTE* rgb_data = NULL;
|
2011-08-24 19:10:23 +04:00
|
|
|
int c;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpSettings* settings;
|
2011-08-24 19:10:23 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = client->context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
|
|
|
if (!settings->RemoteFxCodec && !freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
|
2015-06-17 23:08:02 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Client doesn't support RemoteFX or NSCodec");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-08-24 19:10:23 +04:00
|
|
|
|
2021-05-31 12:42:03 +03:00
|
|
|
if ((fp = winpr_fopen("test_icon.ppm", "r")) == NULL)
|
2015-06-17 23:08:02 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Unable to open test icon");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-08-24 19:10:23 +04:00
|
|
|
|
|
|
|
/* P3 */
|
|
|
|
fgets(line, sizeof(line), fp);
|
|
|
|
/* Creater comment */
|
|
|
|
fgets(line, sizeof(line), fp);
|
|
|
|
/* width height */
|
|
|
|
fgets(line, sizeof(line), fp);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
if (sscanf(line, "%hu %hu", &context->icon_width, &context->icon_height) < 2)
|
2015-06-17 23:08:02 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Problem while extracting width/height from the icon file");
|
|
|
|
goto out_fail;
|
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2011-08-24 19:10:23 +04:00
|
|
|
/* Max */
|
|
|
|
fgets(line, sizeof(line), fp);
|
|
|
|
|
2017-05-30 11:46:43 +03:00
|
|
|
if (!(rgb_data = calloc(context->icon_height, context->icon_width * 3)))
|
2015-06-17 23:08:02 +03:00
|
|
|
goto out_fail;
|
2011-08-24 19:10:23 +04:00
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
for (i = 0; i < context->icon_width * context->icon_height * 3; i++)
|
2011-08-24 19:10:23 +04:00
|
|
|
{
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!fgets(line, sizeof(line), fp) || (sscanf(line, "%d", &c) != 1))
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
rgb_data[i] = (BYTE)c;
|
2011-08-24 19:10:23 +04:00
|
|
|
}
|
|
|
|
|
2011-08-25 13:38:51 +04:00
|
|
|
/* background with same size, which will be used to erase the icon from old position */
|
2017-05-30 11:46:43 +03:00
|
|
|
if (!(context->bg_data = calloc(context->icon_height, context->icon_width * 3)))
|
2015-06-17 23:08:02 +03:00
|
|
|
goto out_fail;
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
memset(context->bg_data, 0xA0, context->icon_width * context->icon_height * 3);
|
2015-06-17 23:08:02 +03:00
|
|
|
context->icon_data = rgb_data;
|
|
|
|
fclose(fp);
|
|
|
|
return TRUE;
|
|
|
|
out_fail:
|
|
|
|
free(rgb_data);
|
2019-11-06 17:24:51 +03:00
|
|
|
context->bg_data = NULL;
|
2015-06-17 23:08:02 +03:00
|
|
|
fclose(fp);
|
|
|
|
return FALSE;
|
2011-08-24 19:10:23 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
|
2011-08-24 19:10:23 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2012-10-09 00:12:03 +04:00
|
|
|
RFX_RECT rect;
|
2021-09-03 09:26:07 +03:00
|
|
|
rdpUpdate* update;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpSettings* settings;
|
2018-04-03 18:17:45 +03:00
|
|
|
SURFACE_BITS_COMMAND cmd = { 0 };
|
2021-06-16 13:59:25 +03:00
|
|
|
testPeerContext* context;
|
2011-08-24 19:10:23 +04:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
WINPR_ASSERT(client);
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
update = client->context->update;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = client->context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
|
|
|
if (freerdp_settings_get_bool(settings, FreeRDP_DumpRemoteFx))
|
2011-08-24 19:10:23 +04:00
|
|
|
return;
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
if (context->icon_width < 1 || !context->activated)
|
2011-08-24 19:10:23 +04:00
|
|
|
return;
|
|
|
|
|
2012-05-11 12:35:11 +04:00
|
|
|
test_peer_begin_frame(client);
|
2011-08-25 13:38:51 +04:00
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
2011-10-18 11:10:12 +04:00
|
|
|
rect.width = context->icon_width;
|
|
|
|
rect.height = context->icon_height;
|
2011-08-24 19:10:23 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (settings->RemoteFxCodec)
|
2020-04-03 15:04:12 +03:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(settings->RemoteFxCodecId <= UINT16_MAX);
|
|
|
|
cmd.bmp.codecID = (UINT16)settings->RemoteFxCodecId;
|
2020-04-03 15:04:12 +03:00
|
|
|
cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(settings->NSCodecId <= UINT16_MAX);
|
|
|
|
cmd.bmp.codecID = (UINT16)settings->NSCodecId;
|
2020-04-03 15:04:12 +03:00
|
|
|
cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
if (context->icon_x != UINT32_MAX)
|
2011-08-24 19:10:23 +04:00
|
|
|
{
|
2011-10-18 11:10:12 +04:00
|
|
|
s = test_peer_stream_init(context);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (settings->RemoteFxCodec)
|
2019-11-06 17:24:51 +03:00
|
|
|
rfx_compose_message(context->rfx_context, s, &rect, 1, context->bg_data, rect.width,
|
|
|
|
rect.height, rect.width * 3);
|
2012-03-18 12:36:38 +04:00
|
|
|
else
|
2019-11-06 17:24:51 +03:00
|
|
|
nsc_compose_message(context->nsc_context, s, context->bg_data, rect.width, rect.height,
|
|
|
|
rect.width * 3);
|
2011-10-18 11:10:12 +04:00
|
|
|
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.destLeft = context->icon_x;
|
|
|
|
cmd.destTop = context->icon_y;
|
|
|
|
cmd.destRight = context->icon_x + context->icon_width;
|
|
|
|
cmd.destBottom = context->icon_y + context->icon_height;
|
|
|
|
cmd.bmp.bpp = 32;
|
|
|
|
cmd.bmp.flags = 0;
|
|
|
|
cmd.bmp.width = context->icon_width;
|
|
|
|
cmd.bmp.height = context->icon_height;
|
2021-06-16 13:59:25 +03:00
|
|
|
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.bmp.bitmapData = Stream_Buffer(s);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->SurfaceBits);
|
2018-04-03 18:17:45 +03:00
|
|
|
update->SurfaceBits(update->context, &cmd);
|
2011-08-24 19:10:23 +04:00
|
|
|
}
|
|
|
|
|
2011-10-18 11:10:12 +04:00
|
|
|
s = test_peer_stream_init(context);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (settings->RemoteFxCodec)
|
2019-11-06 17:24:51 +03:00
|
|
|
rfx_compose_message(context->rfx_context, s, &rect, 1, context->icon_data, rect.width,
|
|
|
|
rect.height, rect.width * 3);
|
2012-03-18 12:36:38 +04:00
|
|
|
else
|
2019-11-06 17:24:51 +03:00
|
|
|
nsc_compose_message(context->nsc_context, s, context->icon_data, rect.width, rect.height,
|
|
|
|
rect.width * 3);
|
2011-08-25 13:38:51 +04:00
|
|
|
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.destLeft = x;
|
|
|
|
cmd.destTop = y;
|
|
|
|
cmd.destRight = x + context->icon_width;
|
|
|
|
cmd.destBottom = y + context->icon_height;
|
|
|
|
cmd.bmp.bpp = 32;
|
|
|
|
cmd.bmp.width = context->icon_width;
|
|
|
|
cmd.bmp.height = context->icon_height;
|
2021-06-16 13:59:25 +03:00
|
|
|
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
|
2018-04-03 18:17:45 +03:00
|
|
|
cmd.bmp.bitmapData = Stream_Buffer(s);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->SurfaceBits);
|
2018-04-03 18:17:45 +03:00
|
|
|
update->SurfaceBits(update->context, &cmd);
|
2011-10-18 11:10:12 +04:00
|
|
|
context->icon_x = x;
|
|
|
|
context->icon_y = y;
|
2012-05-11 12:35:11 +04:00
|
|
|
test_peer_end_frame(client);
|
2011-08-24 19:10:23 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL test_sleep_tsdiff(UINT32* old_sec, UINT32* old_usec, UINT32 new_sec, UINT32 new_usec)
|
2011-10-18 20:36:34 +04:00
|
|
|
{
|
2021-06-16 12:28:53 +03:00
|
|
|
INT64 sec, usec;
|
2011-10-18 20:36:34 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(old_sec);
|
|
|
|
WINPR_ASSERT(old_usec);
|
|
|
|
|
2014-04-21 05:28:09 +04:00
|
|
|
if ((*old_sec == 0) && (*old_usec == 0))
|
2011-10-18 20:36:34 +04:00
|
|
|
{
|
|
|
|
*old_sec = new_sec;
|
|
|
|
*old_usec = new_usec;
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-10-18 20:36:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
sec = new_sec - *old_sec;
|
|
|
|
usec = new_usec - *old_usec;
|
|
|
|
|
2014-04-21 05:28:09 +04:00
|
|
|
if ((sec < 0) || ((sec == 0) && (usec < 0)))
|
2011-10-18 20:36:34 +04:00
|
|
|
{
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_ERR(TAG, "Invalid time stamp detected.");
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2011-10-18 20:36:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
*old_sec = new_sec;
|
|
|
|
*old_usec = new_usec;
|
Standard RDP Security Layer Levels/Method Overhaul
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
2014-12-12 04:17:12 +03:00
|
|
|
|
|
|
|
while (usec < 0)
|
2011-10-18 20:36:34 +04:00
|
|
|
{
|
|
|
|
usec += 1000000;
|
|
|
|
sec--;
|
|
|
|
}
|
Standard RDP Security Layer Levels/Method Overhaul
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
2014-12-12 04:17:12 +03:00
|
|
|
|
2011-10-18 20:36:34 +04:00
|
|
|
if (sec > 0)
|
2021-06-16 12:28:53 +03:00
|
|
|
Sleep((DWORD)sec * 1000);
|
Standard RDP Security Layer Levels/Method Overhaul
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
2014-12-12 04:17:12 +03:00
|
|
|
|
2011-10-18 20:36:34 +04:00
|
|
|
if (usec > 0)
|
2021-06-16 12:28:53 +03:00
|
|
|
USleep((DWORD)usec);
|
Standard RDP Security Layer Levels/Method Overhaul
[MS-RDPBCGR] Section 5.3 describes the encryption level and method values for
standard RDP security.
Looking at the current usage of these values in the FreeRDP code gives me
reason to believe that there is a certain lack of understanding of how these
values should be handled.
The encryption level is only configured on the server side in the "Encryption
Level" setting found in the Remote Desktop Session Host Configuration RDP-Tcp
properties dialog and this value is never transferred from the client to the
server over the wire.
The possible options are "None", "Low", "Client Compatible", "High" and
"FIPS Compliant". The client receices this value in the Server Security Data
block (TS_UD_SC_SEC1), probably only for informational purposes and maybe to
give the client the possibility to verify if the server's decision for the
encryption method confirms to the server's encryption level.
The possible encryption methods are "NONE", "40BIT", "56BIT", "128BIT" and
"FIPS" and the RDP client advertises the ones it supports to the server in the
Client Security Data block (TS_UD_CS_SEC).
The server's configured encryption level value restricts the possible final
encryption method.
Something that I was not able to find in the documentation is the priority
level of the individual encryption methods based on which the server makes its
final method decision if there are several options.
My analysis with Windows Servers reveiled that the order is 128, 56, 40, FIPS.
The server only chooses FIPS if the level is "FIPS Comliant" or if it is the
only method advertised by the client.
Bottom line:
* FreeRDP's client side does not need to set settings->EncryptionLevel
(which was done quite frequently).
* FreeRDP's server side does not have to set the supported encryption methods
list in settings->EncryptionMethods
Changes in this commit:
Removed unnecessary/confusing changes of EncryptionLevel/Methods settings
Refactor settings->DisableEncryption
* This value actually means "Advanced RDP Encryption (NLA/TLS) is NOT used"
* The old name caused lots of confusion among developers
* Renamed it to "UseRdpSecurityLayer" (the compare logic stays untouched)
Any client's setting of settings->EncryptionMethods were annihilated
* All clients "want" to set all supported methods
* Some clients forgot 56bit because 56bit was not supported at the time the
code was written
* settings->EncryptionMethods was overwritten anyways in nego_connect()
* Removed all client side settings of settings->EncryptionMethods
The default is "None" (0)
* Changed nego_connect() to advertise all supported methods if
settings->EncryptionMethods is 0 (None)
* Added a commandline option /encryption-methods:comma separated list of the
values "40", "56", "128", "FIPS". E.g. /encryption-methods:56,128
* Print warning if server chooses non-advertised method
Verify received level and method in client's gcc_read_server_security_data
* Only accept valid/known encryption methods
* Verify encryption level/method combinations according to MS-RDPBCGR 5.3.2
Server implementations can now set settings->EncryptionLevel
* The default for settings->EncryptionLevel is 0 (None)
* nego_send_negotiation_response() changes it to ClientCompatible in that case
* default to ClientCompatible if the server implementation set an invalid level
Fix server's gcc_write_server_security_data
* Verify server encryption level value set by server implementations
* Choose rdp encryption method based on level and supported client methods
* Moved FIPS to the lowest priority (only used if other methods are possible)
Updated sample server
* Support RDP Security (RdpKeyFile was not set)
* Added commented sample code for setting the security level
2014-12-12 04:17:12 +03:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-10-18 20:36:34 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_dump_rfx(freerdp_peer* client)
|
2011-08-27 05:44:37 +04:00
|
|
|
{
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 prev_seconds;
|
|
|
|
UINT32 prev_useconds;
|
2011-08-27 05:44:37 +04:00
|
|
|
rdpUpdate* update;
|
|
|
|
rdpPcap* pcap_rfx;
|
2022-06-22 13:06:54 +03:00
|
|
|
pcap_record record = { 0 };
|
2021-09-03 09:26:07 +03:00
|
|
|
struct server_info* info;
|
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
WINPR_ASSERT(client->context);
|
|
|
|
|
|
|
|
info = client->ContextExtra;
|
|
|
|
WINPR_ASSERT(info);
|
|
|
|
|
2013-05-09 01:48:30 +04:00
|
|
|
s = Stream_New(NULL, 512);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!s)
|
|
|
|
return FALSE;
|
2011-08-27 05:44:37 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
update = client->context->update;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
if (!(pcap_rfx = pcap_open(info->test_pcap_file, FALSE)))
|
2015-06-17 23:08:02 +03:00
|
|
|
return FALSE;
|
2011-10-20 16:25:25 +04:00
|
|
|
|
2011-10-18 20:36:34 +04:00
|
|
|
prev_seconds = prev_useconds = 0;
|
2011-09-01 04:56:17 +04:00
|
|
|
|
2011-08-27 05:44:37 +04:00
|
|
|
while (pcap_has_next_record(pcap_rfx))
|
|
|
|
{
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!pcap_get_next_record_header(pcap_rfx, &record))
|
|
|
|
break;
|
|
|
|
|
2016-02-29 14:54:31 +03:00
|
|
|
if (!Stream_EnsureCapacity(s, record.length))
|
2015-06-17 23:08:02 +03:00
|
|
|
break;
|
2011-08-27 05:44:37 +04:00
|
|
|
|
2013-05-15 20:14:26 +04:00
|
|
|
record.data = Stream_Buffer(s);
|
2011-08-27 05:44:37 +04:00
|
|
|
pcap_get_next_record_content(pcap_rfx, &record);
|
2021-10-04 09:48:38 +03:00
|
|
|
Stream_SetPosition(s, Stream_Capacity(s));
|
2011-08-27 05:44:37 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
if (info->test_dump_rfx_realtime &&
|
2019-11-06 17:24:51 +03:00
|
|
|
test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec,
|
|
|
|
record.header.ts_usec) == FALSE)
|
2011-10-18 20:36:34 +04:00
|
|
|
break;
|
2011-09-01 04:56:17 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->SurfaceCommand);
|
2011-11-22 04:41:49 +04:00
|
|
|
update->SurfaceCommand(update->context, s);
|
2014-04-21 05:28:09 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client->CheckFileDescriptor);
|
2014-04-21 05:28:09 +04:00
|
|
|
if (client->CheckFileDescriptor(client) != TRUE)
|
|
|
|
break;
|
2011-08-27 05:44:37 +04:00
|
|
|
}
|
2015-06-17 23:08:02 +03:00
|
|
|
|
|
|
|
Stream_Free(s, TRUE);
|
|
|
|
pcap_close(pcap_rfx);
|
|
|
|
return TRUE;
|
2011-08-27 05:44:37 +04:00
|
|
|
}
|
|
|
|
|
2018-03-07 14:03:10 +03:00
|
|
|
static DWORD WINAPI tf_debug_channel_thread_func(LPVOID arg)
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
|
|
|
void* fd;
|
2013-03-21 23:19:33 +04:00
|
|
|
wStream* s;
|
2011-12-12 18:37:48 +04:00
|
|
|
void* buffer;
|
2013-08-21 03:26:36 +04:00
|
|
|
DWORD BytesReturned = 0;
|
2014-05-28 19:04:24 +04:00
|
|
|
ULONG written;
|
2019-11-06 17:24:51 +03:00
|
|
|
testPeerContext* context = (testPeerContext*)arg;
|
2011-12-12 18:37:48 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(context);
|
2019-11-06 17:24:51 +03:00
|
|
|
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer,
|
|
|
|
&BytesReturned) == TRUE)
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
fd = *((void**)buffer);
|
2011-12-12 18:37:48 +04:00
|
|
|
WTSFreeMemory(buffer);
|
2013-03-22 01:49:10 +04:00
|
|
|
|
2015-05-05 14:55:48 +03:00
|
|
|
if (!(context->event = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd)))
|
2018-03-07 14:03:10 +03:00
|
|
|
return 0;
|
2011-12-12 18:37:48 +04:00
|
|
|
}
|
|
|
|
|
2013-05-09 01:48:30 +04:00
|
|
|
s = Stream_New(NULL, 4096);
|
2014-05-28 19:04:24 +04:00
|
|
|
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, &written);
|
2011-12-12 18:37:48 +04:00
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
2022-12-06 12:32:08 +03:00
|
|
|
DWORD status;
|
|
|
|
DWORD nCount = 0;
|
|
|
|
HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
|
|
|
|
|
|
|
|
handles[nCount++] = context->event;
|
|
|
|
handles[nCount++] = freerdp_abort_event(&context->_p);
|
|
|
|
handles[nCount++] = context->stopEvent;
|
|
|
|
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
|
|
|
switch (status)
|
|
|
|
{
|
|
|
|
case WAIT_OBJECT_0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto fail;
|
|
|
|
}
|
2011-12-12 18:37:48 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(s, 0);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR)Stream_Buffer(s),
|
2021-06-16 13:59:25 +03:00
|
|
|
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
2013-08-21 03:26:36 +04:00
|
|
|
if (BytesReturned == 0)
|
2011-12-12 18:37:48 +04:00
|
|
|
break;
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2013-08-21 03:26:36 +04:00
|
|
|
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR)Stream_Buffer(s),
|
2021-06-16 13:59:25 +03:00
|
|
|
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
|
|
|
/* should not happen */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2013-08-21 03:26:36 +04:00
|
|
|
Stream_SetPosition(s, BytesReturned);
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "got %" PRIu32 " bytes", BytesReturned);
|
2011-12-12 18:37:48 +04:00
|
|
|
}
|
2022-12-06 12:32:08 +03:00
|
|
|
fail:
|
2013-05-09 01:48:30 +04:00
|
|
|
Stream_Free(s, TRUE);
|
2011-12-12 18:37:48 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_post_connect(freerdp_peer* client)
|
2011-08-22 19:02:56 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
testPeerContext* context;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpSettings* settings;
|
2021-09-03 09:26:07 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = client->context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
2011-08-22 19:02:56 +04:00
|
|
|
/**
|
|
|
|
* This callback is called when the entire connection sequence is done, i.e. we've received the
|
|
|
|
* Font List PDU from the client and sent out the Font Map PDU.
|
|
|
|
* The server may start sending graphics output and receiving keyboard/mouse input after this
|
|
|
|
* callback returns.
|
|
|
|
*/
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "Client %s is activated (osMajorType %" PRIu32 " osMinorType %" PRIu32 ")",
|
2022-03-23 15:18:35 +03:00
|
|
|
client->local ? "(local)" : client->hostname, settings->OsMajorType,
|
|
|
|
settings->OsMinorType);
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (settings->AutoLogonEnabled)
|
2011-08-22 19:02:56 +04:00
|
|
|
{
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, " and wants to login automatically as %s\\%s",
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->Domain ? settings->Domain : "", settings->Username);
|
2011-08-22 19:02:56 +04:00
|
|
|
/* A real server may perform OS login here if NLA is not executed previously. */
|
|
|
|
}
|
2011-08-23 11:51:51 +04:00
|
|
|
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, "");
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "Client requested desktop: %" PRIu32 "x%" PRIu32 "x%" PRIu32 "",
|
2022-06-22 13:42:48 +03:00
|
|
|
settings->DesktopWidth, settings->DesktopHeight,
|
|
|
|
freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth));
|
2013-06-21 18:46:46 +04:00
|
|
|
#if (SAMPLE_SERVER_USE_CLIENT_RESOLUTION == 1)
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (!rfx_context_reset(context->rfx_context, settings->DesktopWidth, settings->DesktopHeight))
|
2016-03-01 19:14:35 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, "Using resolution requested by client.");
|
2013-06-21 18:46:46 +04:00
|
|
|
#else
|
|
|
|
client->settings->DesktopWidth = context->rfx_context->width;
|
|
|
|
client->settings->DesktopHeight = context->rfx_context->height;
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "Resizing client to %" PRIu32 "x%" PRIu32 "", client->settings->DesktopWidth,
|
2016-10-13 23:02:25 +03:00
|
|
|
client->settings->DesktopHeight);
|
2013-06-21 18:46:46 +04:00
|
|
|
client->update->DesktopResize(client->update->context);
|
|
|
|
#endif
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
/* A real server should tag the peer as activated here and start sending updates in main loop.
|
|
|
|
*/
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!test_peer_load_icon(client))
|
|
|
|
{
|
|
|
|
WLog_DBG(TAG, "Unable to load icon");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-02-28 21:07:22 +04:00
|
|
|
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpdbg"))
|
2011-12-12 10:12:16 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
context->debug_channel = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpdbg");
|
2012-10-09 00:12:03 +04:00
|
|
|
|
2014-02-28 21:07:22 +04:00
|
|
|
if (context->debug_channel != NULL)
|
|
|
|
{
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, "Open channel rdpdbg.");
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-28 18:00:41 +03:00
|
|
|
if (!(context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Failed to create stop event");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2013-03-22 01:49:10 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(context->debug_channel_thread =
|
|
|
|
CreateThread(NULL, 0, tf_debug_channel_thread_func, (void*)context, 0, NULL)))
|
2015-04-28 18:00:41 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Failed to create debug channel thread");
|
|
|
|
CloseHandle(context->stopEvent);
|
|
|
|
context->stopEvent = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-12-12 10:12:16 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-25 13:10:48 +03:00
|
|
|
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, RDPSND_CHANNEL_NAME))
|
2014-02-28 21:07:22 +04:00
|
|
|
{
|
|
|
|
sf_peer_rdpsnd_init(context); /* Audio Output */
|
|
|
|
}
|
|
|
|
|
2019-11-22 12:41:09 +03:00
|
|
|
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, ENCOMSP_SVC_CHANNEL_NAME))
|
2014-06-25 23:21:02 +04:00
|
|
|
{
|
|
|
|
sf_peer_encomsp_init(context); /* Lync Multiparty */
|
|
|
|
}
|
|
|
|
|
2012-10-09 00:29:40 +04:00
|
|
|
/* Dynamic Virtual Channels */
|
2012-10-09 00:12:03 +04:00
|
|
|
sf_peer_audin_init(context); /* Audio Input */
|
2022-01-19 11:26:57 +03:00
|
|
|
|
|
|
|
#if defined(CHANNEL_AINPUT_SERVER)
|
|
|
|
sf_peer_ainput_init(context);
|
|
|
|
#endif
|
|
|
|
|
2012-11-27 07:42:40 +04:00
|
|
|
/* Return FALSE here would stop the execution of the peer main loop. */
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-09-06 14:55:11 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_activate(freerdp_peer* client)
|
2011-09-06 14:55:11 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
testPeerContext* context;
|
|
|
|
struct server_info* info;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpSettings* settings;
|
2021-09-03 09:26:07 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
context = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = client->context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
info = client->ContextExtra;
|
|
|
|
WINPR_ASSERT(info);
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
context->activated = TRUE;
|
2019-11-06 17:24:51 +03:00
|
|
|
// client->settings->CompressionLevel = PACKET_COMPR_TYPE_8K;
|
|
|
|
// client->settings->CompressionLevel = PACKET_COMPR_TYPE_64K;
|
|
|
|
// client->settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->CompressionLevel = PACKET_COMPR_TYPE_RDP8;
|
2014-04-21 05:28:09 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
if (info->test_pcap_file != NULL)
|
2011-08-27 05:44:37 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
freerdp_settings_set_bool(settings, FreeRDP_DumpRemoteFx, TRUE);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!tf_peer_dump_rfx(client))
|
|
|
|
return FALSE;
|
2011-08-27 05:44:37 +04:00
|
|
|
}
|
2011-08-29 07:39:04 +04:00
|
|
|
else
|
|
|
|
test_peer_draw_background(client);
|
2011-08-27 05:44:37 +04:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-08-22 19:02:56 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_synchronize_event(rdpInput* input, UINT32 flags)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(input);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(input);
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "Client sent a synchronize event (flags:0x%" PRIX32 ")", flags);
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
static BOOL tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
freerdp_peer* client;
|
|
|
|
rdpUpdate* update;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpContext* context;
|
|
|
|
testPeerContext* tcontext;
|
|
|
|
rdpSettings* settings;
|
2021-09-03 09:26:07 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(input);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
context = input->context;
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
|
|
|
client = context->peer;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings = context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
|
|
|
update = context->update;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update);
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
tcontext = (testPeerContext*)context;
|
|
|
|
WINPR_ASSERT(tcontext);
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2022-04-13 10:34:05 +03:00
|
|
|
WLog_DBG(TAG, "Client sent a keyboard event (flags:0x%04" PRIX16 " code:0x%04" PRIX8 ")", flags,
|
|
|
|
code);
|
2011-09-06 13:19:59 +04:00
|
|
|
|
2022-12-12 12:42:03 +03:00
|
|
|
if (((flags & KBD_FLAGS_RELEASE) == 0) && (code == RDP_SCANCODE_KEY_G)) /* 'g' key */
|
2011-09-06 13:19:59 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
if (settings->DesktopWidth != 800)
|
2011-09-06 13:19:59 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->DesktopWidth = 800;
|
|
|
|
settings->DesktopHeight = 600;
|
2011-09-06 13:19:59 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->DesktopWidth = SAMPLE_SERVER_DEFAULT_WIDTH;
|
|
|
|
settings->DesktopHeight = SAMPLE_SERVER_DEFAULT_HEIGHT;
|
2011-09-06 13:19:59 +04:00
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
if (!rfx_context_reset(tcontext->rfx_context, settings->DesktopWidth,
|
|
|
|
settings->DesktopHeight))
|
2016-03-01 19:14:35 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(update->DesktopResize);
|
2011-11-22 04:41:49 +04:00
|
|
|
update->DesktopResize(update->context);
|
2022-03-23 15:18:35 +03:00
|
|
|
tcontext->activated = FALSE;
|
2011-09-06 13:19:59 +04:00
|
|
|
}
|
2022-12-12 12:42:03 +03:00
|
|
|
else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_C) /* 'c' key */
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
if (tcontext->debug_channel)
|
2011-12-12 18:37:48 +04:00
|
|
|
{
|
2014-05-28 19:04:24 +04:00
|
|
|
ULONG written;
|
2022-03-23 15:18:35 +03:00
|
|
|
WTSVirtualChannelWrite(tcontext->debug_channel, (PCHAR) "test2", 5, &written);
|
2011-12-12 18:37:48 +04:00
|
|
|
}
|
|
|
|
}
|
2022-12-12 12:42:03 +03:00
|
|
|
else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_X) /* 'x' key */
|
2012-04-13 11:58:28 +04:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client->Close);
|
2012-04-13 11:58:28 +04:00
|
|
|
client->Close(client);
|
|
|
|
}
|
2022-12-12 12:42:03 +03:00
|
|
|
else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_R) /* 'r' key */
|
2012-06-25 12:41:59 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
tcontext->audin_open = !tcontext->audin_open;
|
2012-06-25 12:41:59 +04:00
|
|
|
}
|
2022-01-19 11:26:57 +03:00
|
|
|
#if defined(CHANNEL_AINPUT_SERVER)
|
2022-12-12 12:42:03 +03:00
|
|
|
else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_I) /* 'i' key */
|
2022-01-19 11:26:57 +03:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
tcontext->ainput_open = !tcontext->ainput_open;
|
2022-01-19 11:26:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
2022-12-12 12:42:03 +03:00
|
|
|
else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_S) /* 's' key */
|
2012-10-09 00:12:03 +04:00
|
|
|
{
|
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(input);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG,
|
|
|
|
"Client sent a unicode keyboard event (flags:0x%04" PRIX16 " code:0x%04" PRIX16 ")",
|
2016-10-13 23:02:25 +03:00
|
|
|
flags, code);
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(flags);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Client sent a mouse event (flags:0x%04"PRIX16" pos:%"PRIu16",%"PRIu16")",
|
|
|
|
// flags, x, y);
|
2011-10-18 11:10:12 +04:00
|
|
|
test_peer_draw_icon(input->context->peer, x + 10, y);
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2021-06-16 12:28:53 +03:00
|
|
|
static BOOL tf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
2011-08-23 07:50:41 +04:00
|
|
|
{
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(flags);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(input);
|
|
|
|
WINPR_ASSERT(input->context);
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Client sent an extended mouse event (flags:0x%04"PRIX16"
|
|
|
|
// pos:%"PRIu16",%"PRIu16")", flags, x, y);
|
2019-02-07 19:41:34 +03:00
|
|
|
test_peer_draw_icon(input->context->peer, x + 10, y);
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2011-08-23 07:50:41 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL tf_peer_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas)
|
2012-05-26 17:34:09 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE i;
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(context);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(context);
|
|
|
|
WINPR_ASSERT(areas || (count == 0));
|
|
|
|
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, "Client requested to refresh:");
|
2012-05-26 17:34:09 +04:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, " (%" PRIu16 ", %" PRIu16 ") (%" PRIu16 ", %" PRIu16 ")", areas[i].left,
|
|
|
|
areas[i].top, areas[i].right, areas[i].bottom);
|
2012-05-26 17:34:09 +04:00
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2012-05-26 17:34:09 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL tf_peer_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
|
2012-05-26 17:34:09 +04:00
|
|
|
{
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(context);
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(area);
|
2019-02-07 19:41:34 +03:00
|
|
|
|
2012-05-26 17:34:09 +04:00
|
|
|
if (allow > 0)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG,
|
|
|
|
"Client restore output (%" PRIu16 ", %" PRIu16 ") (%" PRIu16 ", %" PRIu16 ").",
|
|
|
|
area->left, area->top, area->right, area->bottom);
|
2012-05-26 17:34:09 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_DBG(TAG, "Client minimized and suppress output.");
|
2012-05-26 17:34:09 +04:00
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2012-05-26 17:34:09 +04:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:52:03 +03:00
|
|
|
static int hook_peer_write_pdu(rdpTransport* transport, wStream* s)
|
|
|
|
{
|
|
|
|
UINT64 ts = 0;
|
|
|
|
wStream* ls = NULL;
|
|
|
|
UINT64 last_ts = 0;
|
|
|
|
const struct server_info* info;
|
|
|
|
freerdp_peer* client;
|
|
|
|
CONNECTION_STATE state;
|
|
|
|
testPeerContext* peerCtx;
|
|
|
|
size_t offset = 0;
|
2022-10-06 17:03:31 +03:00
|
|
|
UINT32 flags = 0;
|
2021-09-23 15:52:03 +03:00
|
|
|
rdpContext* context = transport_get_context(transport);
|
|
|
|
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
WINPR_ASSERT(s);
|
|
|
|
|
|
|
|
client = context->peer;
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
peerCtx = (testPeerContext*)client->context;
|
|
|
|
WINPR_ASSERT(peerCtx);
|
|
|
|
WINPR_ASSERT(peerCtx->io.WritePdu);
|
|
|
|
|
|
|
|
info = client->ContextExtra;
|
|
|
|
WINPR_ASSERT(info);
|
|
|
|
|
|
|
|
/* Let the client authenticate.
|
|
|
|
* After that is done, we stop the normal operation and send
|
|
|
|
* a previously recorded session PDU by PDU to the client.
|
|
|
|
*
|
|
|
|
* This is fragile and the connecting client needs to use the same
|
|
|
|
* configuration as the one that recorded the session!
|
|
|
|
*/
|
|
|
|
WINPR_ASSERT(info);
|
|
|
|
state = freerdp_get_state(context);
|
|
|
|
if (state < CONNECTION_STATE_NEGO)
|
|
|
|
return peerCtx->io.WritePdu(transport, s);
|
|
|
|
|
|
|
|
ls = Stream_New(NULL, 4096);
|
|
|
|
if (!ls)
|
|
|
|
goto fail;
|
|
|
|
|
2022-10-06 17:03:31 +03:00
|
|
|
while (stream_dump_get(context, &flags, ls, &offset, &ts) > 0)
|
2021-09-23 15:52:03 +03:00
|
|
|
{
|
|
|
|
int rc;
|
2022-10-06 17:03:31 +03:00
|
|
|
/* Skip messages from client. */
|
|
|
|
if (flags & STREAM_MSG_SRV_TX)
|
2021-09-23 15:52:03 +03:00
|
|
|
{
|
2022-10-06 17:03:31 +03:00
|
|
|
if ((last_ts > 0) && (ts > last_ts))
|
|
|
|
{
|
|
|
|
UINT64 diff = ts - last_ts;
|
|
|
|
Sleep(diff);
|
|
|
|
}
|
|
|
|
last_ts = ts;
|
|
|
|
rc = peerCtx->io.WritePdu(transport, ls);
|
|
|
|
if (rc < 0)
|
|
|
|
goto fail;
|
2021-09-23 15:52:03 +03:00
|
|
|
}
|
|
|
|
Stream_SetPosition(ls, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
fail:
|
|
|
|
Stream_Free(ls, TRUE);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-07 14:03:10 +03:00
|
|
|
static DWORD WINAPI test_peer_mainloop(LPVOID arg)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2021-09-06 13:50:08 +03:00
|
|
|
BOOL rc;
|
2019-11-22 12:41:09 +03:00
|
|
|
DWORD error = CHANNEL_RC_OK;
|
2022-12-06 13:09:55 +03:00
|
|
|
HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
|
|
|
|
DWORD count = 0;
|
|
|
|
DWORD status = 0;
|
|
|
|
testPeerContext* context = NULL;
|
2021-09-06 13:50:08 +03:00
|
|
|
struct server_info* info;
|
2022-03-23 15:18:35 +03:00
|
|
|
rdpSettings* settings;
|
|
|
|
rdpInput* input;
|
|
|
|
rdpUpdate* update;
|
2019-11-06 17:24:51 +03:00
|
|
|
freerdp_peer* client = (freerdp_peer*)arg;
|
2021-09-08 16:37:45 +03:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
2021-09-06 13:50:08 +03:00
|
|
|
info = client->ContextExtra;
|
|
|
|
WINPR_ASSERT(info);
|
|
|
|
|
2015-04-28 18:00:41 +03:00
|
|
|
if (!test_peer_init(client))
|
|
|
|
{
|
|
|
|
freerdp_peer_free(client);
|
2018-03-07 14:03:10 +03:00
|
|
|
return 0;
|
2015-04-28 18:00:41 +03:00
|
|
|
}
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2011-08-23 07:50:41 +04:00
|
|
|
/* Initialize the real server settings here */
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(client->context);
|
|
|
|
settings = client->context->settings;
|
|
|
|
WINPR_ASSERT(settings);
|
2021-09-23 15:52:03 +03:00
|
|
|
if (info->replay_dump)
|
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE) ||
|
|
|
|
!freerdp_settings_set_string(settings, FreeRDP_TransportDumpFile, info->replay_dump))
|
2022-12-06 13:09:55 +03:00
|
|
|
goto fail;
|
2021-09-23 15:52:03 +03:00
|
|
|
}
|
2023-02-03 17:56:16 +03:00
|
|
|
|
|
|
|
rdpPrivateKey* key = freerdp_key_new_from_file(info->key);
|
|
|
|
if (!key)
|
|
|
|
goto fail;
|
|
|
|
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerRsaKey, key, 1))
|
|
|
|
goto fail;
|
|
|
|
rdpCertificate* cert = freerdp_certificate_new_from_file(info->cert);
|
|
|
|
if (!cert)
|
|
|
|
goto fail;
|
|
|
|
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, cert, 1))
|
2022-12-06 13:09:55 +03:00
|
|
|
goto fail;
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2023-02-06 11:51:50 +03:00
|
|
|
settings->RdpSecurity = TRUE;
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->TlsSecurity = TRUE;
|
|
|
|
settings->NlaSecurity = FALSE;
|
|
|
|
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
|
|
|
/* settings->EncryptionLevel = ENCRYPTION_LEVEL_HIGH; */
|
|
|
|
/* settings->EncryptionLevel = ENCRYPTION_LEVEL_LOW; */
|
|
|
|
/* settings->EncryptionLevel = ENCRYPTION_LEVEL_FIPS; */
|
|
|
|
settings->RemoteFxCodec = TRUE;
|
2022-06-22 13:42:48 +03:00
|
|
|
if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE) ||
|
|
|
|
!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32))
|
2022-12-06 13:09:55 +03:00
|
|
|
goto fail;
|
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
settings->SuppressOutput = TRUE;
|
|
|
|
settings->RefreshRect = TRUE;
|
|
|
|
|
2011-09-14 03:03:06 +04:00
|
|
|
client->PostConnect = tf_peer_post_connect;
|
|
|
|
client->Activate = tf_peer_activate;
|
2021-09-03 12:24:55 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(client->context);
|
2022-03-23 15:18:35 +03:00
|
|
|
input = client->context->input;
|
|
|
|
WINPR_ASSERT(input);
|
|
|
|
|
|
|
|
input->SynchronizeEvent = tf_peer_synchronize_event;
|
|
|
|
input->KeyboardEvent = tf_peer_keyboard_event;
|
|
|
|
input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event;
|
|
|
|
input->MouseEvent = tf_peer_mouse_event;
|
|
|
|
input->ExtendedMouseEvent = tf_peer_extended_mouse_event;
|
|
|
|
|
|
|
|
update = client->context->update;
|
|
|
|
WINPR_ASSERT(update);
|
|
|
|
|
|
|
|
update->RefreshRect = tf_peer_refresh_rect;
|
|
|
|
update->SuppressOutput = tf_peer_suppress_output;
|
|
|
|
settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */
|
2021-09-03 09:26:07 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(client->Initialize);
|
2021-09-06 13:50:08 +03:00
|
|
|
rc = client->Initialize(client);
|
2022-12-06 13:09:55 +03:00
|
|
|
if (!rc)
|
|
|
|
goto fail;
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
context = (testPeerContext*)client->context;
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
2021-09-23 15:52:03 +03:00
|
|
|
if (info->replay_dump)
|
|
|
|
{
|
|
|
|
const rdpTransportIo* cb = freerdp_get_io_callbacks(client->context);
|
|
|
|
rdpTransportIo replay;
|
|
|
|
|
|
|
|
WINPR_ASSERT(cb);
|
|
|
|
replay = *cb;
|
|
|
|
context->io = *cb;
|
|
|
|
replay.WritePdu = hook_peer_write_pdu;
|
|
|
|
freerdp_set_io_callbacks(client->context, &replay);
|
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname);
|
2011-10-18 11:10:12 +04:00
|
|
|
|
2019-11-22 12:41:09 +03:00
|
|
|
while (error == CHANNEL_RC_OK)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2015-04-19 11:31:28 +03:00
|
|
|
count = 0;
|
2016-10-27 18:43:09 +03:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
DWORD tmp;
|
|
|
|
|
|
|
|
WINPR_ASSERT(client->GetEventHandles);
|
|
|
|
tmp = client->GetEventHandles(client, &handles[count], 32 - count);
|
2016-10-27 18:43:09 +03:00
|
|
|
|
|
|
|
if (tmp == 0)
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "Failed to get FreeRDP transport event handles");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
count += tmp;
|
|
|
|
}
|
2015-04-19 11:31:28 +03:00
|
|
|
handles[count++] = WTSVirtualChannelManagerGetEventHandle(context->vcm);
|
|
|
|
status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2015-04-19 11:31:28 +03:00
|
|
|
if (status == WAIT_FAILED)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2015-04-19 11:31:28 +03:00
|
|
|
WLog_ERR(TAG, "WaitForMultipleObjects failed (errno: %d)", errno);
|
2011-08-18 12:06:32 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(client->CheckFileDescriptor);
|
2012-10-09 10:31:28 +04:00
|
|
|
if (client->CheckFileDescriptor(client) != TRUE)
|
2011-12-12 12:42:42 +04:00
|
|
|
break;
|
2013-03-22 01:49:10 +04:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
|
2011-08-18 12:06:32 +04:00
|
|
|
break;
|
2019-11-22 12:41:09 +03:00
|
|
|
|
|
|
|
/* Handle dynamic virtual channel intializations */
|
2021-08-25 11:02:46 +03:00
|
|
|
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, DRDYNVC_SVC_CHANNEL_NAME))
|
2019-11-22 12:41:09 +03:00
|
|
|
{
|
|
|
|
switch (WTSVirtualChannelManagerGetDrdynvcState(context->vcm))
|
|
|
|
{
|
|
|
|
case DRDYNVC_STATE_NONE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRDYNVC_STATE_INITIALIZED:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRDYNVC_STATE_READY:
|
|
|
|
|
|
|
|
/* Here is the correct state to start dynamic virtual channels */
|
|
|
|
if (sf_peer_audin_running(context) != context->audin_open)
|
|
|
|
{
|
|
|
|
if (!sf_peer_audin_running(context))
|
|
|
|
sf_peer_audin_start(context);
|
|
|
|
else
|
|
|
|
sf_peer_audin_stop(context);
|
|
|
|
}
|
|
|
|
|
2022-01-19 11:26:57 +03:00
|
|
|
#if defined(CHANNEL_AINPUT_SERVER)
|
|
|
|
if (sf_peer_ainput_running(context) != context->ainput_open)
|
|
|
|
{
|
|
|
|
if (!sf_peer_ainput_running(context))
|
|
|
|
sf_peer_ainput_start(context);
|
|
|
|
else
|
|
|
|
sf_peer_ainput_stop(context);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-11-22 12:41:09 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DRDYNVC_STATE_FAILED:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-08-18 12:06:32 +04:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_INFO(TAG, "Client %s disconnected.", client->local ? "(local)" : client->hostname);
|
2021-09-03 09:26:07 +03:00
|
|
|
|
|
|
|
WINPR_ASSERT(client->Disconnect);
|
2011-08-18 12:06:32 +04:00
|
|
|
client->Disconnect(client);
|
2022-12-06 13:09:55 +03:00
|
|
|
fail:
|
2011-10-18 11:10:12 +04:00
|
|
|
freerdp_peer_context_free(client);
|
2011-08-18 12:06:32 +04:00
|
|
|
freerdp_peer_free(client);
|
2019-11-22 12:41:09 +03:00
|
|
|
return error;
|
2011-08-18 12:06:32 +04:00
|
|
|
}
|
|
|
|
|
2015-04-28 18:00:41 +03:00
|
|
|
static BOOL test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2015-05-05 14:55:48 +03:00
|
|
|
HANDLE hThread;
|
2021-09-03 09:26:07 +03:00
|
|
|
struct server_info* info;
|
|
|
|
|
2019-02-07 19:41:34 +03:00
|
|
|
WINPR_UNUSED(instance);
|
2015-04-28 18:00:41 +03:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance);
|
|
|
|
WINPR_ASSERT(client);
|
|
|
|
|
|
|
|
info = instance->info;
|
|
|
|
client->ContextExtra = info;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(hThread = CreateThread(NULL, 0, test_peer_mainloop, (void*)client, 0, NULL)))
|
2015-05-05 14:55:48 +03:00
|
|
|
return FALSE;
|
2015-04-28 18:00:41 +03:00
|
|
|
|
2015-05-05 14:55:48 +03:00
|
|
|
CloseHandle(hThread);
|
|
|
|
return TRUE;
|
2011-08-18 12:06:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_server_mainloop(freerdp_listener* instance)
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
HANDLE handles[32] = { 0 };
|
2023-02-03 17:56:16 +03:00
|
|
|
DWORD count = 0;
|
|
|
|
DWORD status = 0;
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance);
|
2011-08-18 12:06:32 +04:00
|
|
|
while (1)
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance->GetEventHandles);
|
2015-04-21 16:57:25 +03:00
|
|
|
count = instance->GetEventHandles(instance, handles, 32);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-04-21 16:57:25 +03:00
|
|
|
if (0 == count)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2015-04-19 11:36:20 +03:00
|
|
|
WLog_ERR(TAG, "Failed to get FreeRDP event handles");
|
2011-08-18 12:06:32 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-04-19 11:36:20 +03:00
|
|
|
status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2015-04-19 11:36:20 +03:00
|
|
|
if (WAIT_FAILED == status)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2015-04-19 11:36:20 +03:00
|
|
|
WLog_ERR(TAG, "select failed");
|
2011-08-18 12:06:32 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance->CheckFileDescriptor);
|
2012-10-09 10:31:28 +04:00
|
|
|
if (instance->CheckFileDescriptor(instance) != TRUE)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2014-09-12 19:38:12 +04:00
|
|
|
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
|
2011-08-18 12:06:32 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance->Close);
|
2011-08-18 12:06:32 +04:00
|
|
|
instance->Close(instance);
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
const char spcap[7];
|
|
|
|
const char sfast[7];
|
|
|
|
const char sport[7];
|
|
|
|
const char slocal_only[13];
|
2021-09-06 13:50:08 +03:00
|
|
|
const char scert[7];
|
|
|
|
const char skey[6];
|
|
|
|
} options = { "--pcap=", "--fast", "--port=", "--local-only", "--cert=", "--key=" };
|
2021-09-03 09:26:07 +03:00
|
|
|
|
2021-09-08 16:37:45 +03:00
|
|
|
static void print_entry(FILE* fp, const char* fmt, const char* what, size_t size)
|
|
|
|
{
|
|
|
|
char buffer[32] = { 0 };
|
|
|
|
strncpy(buffer, what, MIN(size, sizeof(buffer)));
|
|
|
|
fprintf(fp, fmt, buffer);
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
static WINPR_NORETURN(void usage(const char* app, const char* invalid))
|
|
|
|
{
|
|
|
|
FILE* fp = stdout;
|
2021-09-08 16:37:45 +03:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
fprintf(fp, "Invalid argument '%s'\n", invalid);
|
|
|
|
fprintf(fp, "Usage: %s <arg>[ <arg> ...]\n", app);
|
|
|
|
fprintf(fp, "Arguments:\n");
|
2021-09-08 16:37:45 +03:00
|
|
|
print_entry(fp, "\t%s<pcap file>\n", options.spcap, sizeof(options.spcap));
|
|
|
|
print_entry(fp, "\t%s<cert file>\n", options.scert, sizeof(options.scert));
|
|
|
|
print_entry(fp, "\t%s<key file>\n", options.skey, sizeof(options.skey));
|
|
|
|
print_entry(fp, "\t%s\n", options.sfast, sizeof(options.sfast));
|
|
|
|
print_entry(fp, "\t%s<port>\n", options.sport, sizeof(options.sport));
|
|
|
|
print_entry(fp, "\t%s\n", options.slocal_only, sizeof(options.slocal_only));
|
2021-09-03 09:26:07 +03:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
2011-08-18 12:06:32 +04:00
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
int rc = -1;
|
|
|
|
BOOL started = FALSE;
|
2023-02-03 17:56:16 +03:00
|
|
|
WSADATA wsaData = { 0 };
|
|
|
|
freerdp_listener* instance = NULL;
|
2021-09-03 09:26:07 +03:00
|
|
|
char* file = NULL;
|
2023-02-03 17:56:16 +03:00
|
|
|
char name[MAX_PATH] = { 0 };
|
|
|
|
long port = 3389;
|
2016-07-06 19:30:12 +03:00
|
|
|
BOOL localOnly = FALSE;
|
2021-09-03 09:26:07 +03:00
|
|
|
struct server_info info = { 0 };
|
|
|
|
const char* app = argv[0];
|
|
|
|
|
|
|
|
info.test_dump_rfx_realtime = TRUE;
|
|
|
|
|
2017-11-14 18:10:52 +03:00
|
|
|
errno = 0;
|
2015-07-03 10:56:43 +03:00
|
|
|
|
2023-02-03 17:56:16 +03:00
|
|
|
for (int i = 1; i < argc; i++)
|
2015-07-03 10:56:43 +03:00
|
|
|
{
|
|
|
|
char* arg = argv[i];
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
if (strncmp(arg, options.sfast, sizeof(options.sfast)) == 0)
|
|
|
|
info.test_dump_rfx_realtime = FALSE;
|
|
|
|
else if (strncmp(arg, options.sport, sizeof(options.sport)) == 0)
|
2015-07-03 10:56:43 +03:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
const char* sport = &arg[sizeof(options.sport)];
|
|
|
|
port = strtol(sport, NULL, 10);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2021-06-16 13:59:25 +03:00
|
|
|
if ((port < 1) || (port > UINT16_MAX) || (errno != 0))
|
2021-09-03 09:26:07 +03:00
|
|
|
usage(app, arg);
|
2015-07-03 10:56:43 +03:00
|
|
|
}
|
2021-09-03 09:26:07 +03:00
|
|
|
else if (strncmp(arg, options.slocal_only, sizeof(options.slocal_only)) == 0)
|
2016-07-06 19:30:12 +03:00
|
|
|
localOnly = TRUE;
|
2021-09-03 09:26:07 +03:00
|
|
|
else if (strncmp(arg, options.spcap, sizeof(options.spcap)) == 0)
|
|
|
|
{
|
|
|
|
info.test_pcap_file = &arg[sizeof(options.spcap)];
|
|
|
|
if (!winpr_PathFileExists(info.test_pcap_file))
|
|
|
|
usage(app, arg);
|
|
|
|
}
|
2021-09-06 13:50:08 +03:00
|
|
|
else if (strncmp(arg, options.scert, sizeof(options.scert)) == 0)
|
|
|
|
{
|
|
|
|
info.cert = &arg[sizeof(options.scert)];
|
|
|
|
if (!winpr_PathFileExists(info.cert))
|
|
|
|
usage(app, arg);
|
|
|
|
}
|
|
|
|
else if (strncmp(arg, options.skey, sizeof(options.skey)) == 0)
|
|
|
|
{
|
|
|
|
info.key = &arg[sizeof(options.skey)];
|
|
|
|
if (!winpr_PathFileExists(info.key))
|
|
|
|
usage(app, arg);
|
|
|
|
}
|
2021-09-03 09:26:07 +03:00
|
|
|
else
|
|
|
|
usage(app, arg);
|
2015-07-03 10:56:43 +03:00
|
|
|
}
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2014-03-03 21:10:06 +04:00
|
|
|
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
|
2017-04-11 20:04:25 +03:00
|
|
|
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
2011-08-18 12:06:32 +04:00
|
|
|
instance = freerdp_listener_new();
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-07-03 10:56:43 +03:00
|
|
|
if (!instance)
|
2018-04-03 13:55:17 +03:00
|
|
|
return -1;
|
2011-08-18 12:06:32 +04:00
|
|
|
|
2023-02-03 17:56:16 +03:00
|
|
|
if (!info.cert)
|
|
|
|
info.cert = "server.crt";
|
|
|
|
if (!info.key)
|
|
|
|
info.key = "server.key";
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
instance->info = (void*)&info;
|
2011-08-18 12:06:32 +04:00
|
|
|
instance->PeerAccepted = test_peer_accepted;
|
|
|
|
|
2014-11-12 22:06:34 +03:00
|
|
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
2021-09-03 09:26:07 +03:00
|
|
|
goto fail;
|
2014-11-12 22:06:34 +03:00
|
|
|
|
2011-08-18 12:06:32 +04:00
|
|
|
/* Open the server socket and start listening. */
|
2017-11-15 11:11:12 +03:00
|
|
|
sprintf_s(name, sizeof(name), "tfreerdp-server.%ld", port);
|
2015-07-03 10:56:43 +03:00
|
|
|
file = GetKnownSubPath(KNOWN_PATH_TEMP, name);
|
2016-04-05 18:07:45 +03:00
|
|
|
|
2015-07-03 10:56:43 +03:00
|
|
|
if (!file)
|
2021-09-03 09:26:07 +03:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (localOnly)
|
2015-07-03 10:56:43 +03:00
|
|
|
{
|
2021-09-03 09:26:07 +03:00
|
|
|
WINPR_ASSERT(instance->OpenLocal);
|
|
|
|
started = instance->OpenLocal(instance, file);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WINPR_ASSERT(instance->Open);
|
|
|
|
started = instance->Open(instance, NULL, (UINT16)port);
|
2015-07-03 10:56:43 +03:00
|
|
|
}
|
2014-11-12 22:06:34 +03:00
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
if (started)
|
2011-08-18 12:06:32 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
/* Entering the server main loop. In a real server the listener can be run in its own
|
|
|
|
* thread. */
|
2011-08-18 12:06:32 +04:00
|
|
|
test_server_mainloop(instance);
|
|
|
|
}
|
|
|
|
|
2021-09-03 09:26:07 +03:00
|
|
|
rc = 0;
|
|
|
|
fail:
|
2016-04-05 18:07:45 +03:00
|
|
|
free(file);
|
2011-08-18 12:06:32 +04:00
|
|
|
freerdp_listener_free(instance);
|
2014-11-12 22:06:34 +03:00
|
|
|
WSACleanup();
|
2021-09-03 09:26:07 +03:00
|
|
|
return rc;
|
2011-08-18 12:06:32 +04:00
|
|
|
}
|