[PATCH] RDP compositor: v2 fixes for multiple connections and mstsc

Hardening rdp.effort at gmail.com
Wed Feb 4 09:46:48 PST 2015


This patch fixes the problem reported on the mailing list
(http://lists.freedesktop.org/archives/wayland-devel/2015-January/019575.html).
All certificate and key paths were not copied when given to FreeRDP, so they
were freed when the peer was disconnecting. And so the next connection was failing.

All the initialization stuffs have been moved to the activate callback, as when it is
called the peer is ready for graphics.

We also differ the creation of the seat, so that a seat is initialized only the
peer really do the activation sequence. That helps when mstsc just connects to see
the certificate, ask if the certificate should be trusted, and then reconnects.

This patch also adds configuration settings for recent versions of FreeRDP that
comes with everything disabled. This makes remoteFx functionnal again.

The patch also handles the skipCompression flag for last FreeRDP versions, that
allows to skip bulk compression for surfaces that have been already compressed by
the remoteFx or NS codec.

This v2 fixes the detection of skipCompression support.
---
 src/compositor-rdp.c | 86 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 65 insertions(+), 21 deletions(-)

diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c
index 1c3f988..f443dce 100644
--- a/src/compositor-rdp.c
+++ b/src/compositor-rdp.c
@@ -33,6 +33,13 @@
 /* assume it's a early 1.1 version */
 #define FREERDP_VERSION_MAJOR 1
 #define FREERDP_VERSION_MINOR 1
+#define FREERDP_VERSION_RELEASE 0
+#endif
+
+#define FREERDP_FULL_VERSION (FREERDP_VERSION_MAJOR * 0x1000 + \
+		FREERDP_VERSION_MINOR * 0x100 + FREERDP_VERSION_RELEASE)
+#if FREERDP_FULL_VERSION >= 0x10201
+#define HAVE_SKIP_COMPRESSION
 #endif
 
 #include <freerdp/freerdp.h>
@@ -145,6 +152,11 @@ rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_p
 	width = (damage->extents.x2 - damage->extents.x1);
 	height = (damage->extents.y2 - damage->extents.y1);
 
+#ifdef HAVE_SKIP_COMPRESSION
+	cmd->skipCompression = TRUE;
+#else
+	memset(cmd, 0, sizeof(*cmd));
+#endif
 	cmd->destLeft = damage->extents.x1;
 	cmd->destTop = damage->extents.y1;
 	cmd->destRight = damage->extents.x2;
@@ -197,6 +209,11 @@ rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_p
 	width = (damage->extents.x2 - damage->extents.x1);
 	height = (damage->extents.y2 - damage->extents.y1);
 
+#ifdef HAVE_SKIP_COMPRESSION
+	cmd->skipCompression = TRUE;
+#else
+	memset(cmd, 0, sizeof(*cmd));
+#endif
 	cmd->destLeft = damage->extents.x1;
 	cmd->destTop = damage->extents.y1;
 	cmd->destRight = damage->extents.x2;
@@ -248,6 +265,11 @@ rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_p
 	marker->frameAction = SURFACECMD_FRAMEACTION_BEGIN;
 	update->SurfaceFrameMarker(peer->context, marker);
 
+#ifdef HAVE_SKIP_COMPRESSION
+	cmd->skipCompression = FALSE;
+#else
+	memset(cmd, 0, sizeof(*cmd));
+#endif
 	cmd->bpp = 32;
 	cmd->codecID = 0;
 
@@ -592,6 +614,7 @@ rdp_peer_context_free(freerdp_peer* client, RdpPeerContext* context)
 		weston_seat_release_pointer(&context->item.seat);
 		weston_seat_release(&context->item.seat);
 	}
+
 	Stream_Free(context->encode_stream, TRUE);
 	nsc_context_free(context->nsc_context);
 	rfx_context_free(context->rfx_context);
@@ -757,23 +780,26 @@ static char *rdp_keyboard_types[] = {
 };
 
 static BOOL
-xf_peer_post_connect(freerdp_peer* client)
+xf_peer_activate(freerdp_peer* client)
 {
 	RdpPeerContext *peerCtx;
 	struct rdp_compositor *c;
 	struct rdp_output *output;
 	rdpSettings *settings;
 	rdpPointerUpdate *pointer;
+	struct rdp_peers_item *peersItem;
 	struct xkb_context *xkbContext;
 	struct xkb_rule_names xkbRuleNames;
 	struct xkb_keymap *keymap;
 	int i;
 	pixman_box32_t box;
 	pixman_region32_t damage;
+	char seat_name[50];
 
 
 	peerCtx = (RdpPeerContext *)client->context;
 	c = peerCtx->rdpCompositor;
+	peersItem = &peerCtx->item;
 	output = c->output;
 	settings = client->settings;
 
@@ -813,7 +839,14 @@ xf_peer_post_connect(freerdp_peer* client)
 		}
 	}
 
-	weston_log("kbd_layout:%x kbd_type:%x kbd_subType:%x kbd_functionKeys:%x\n",
+	rfx_context_reset(peerCtx->rfx_context);
+	nsc_context_reset(peerCtx->nsc_context);
+
+	if (peersItem->flags & RDP_PEER_ACTIVATED)
+		return TRUE;
+
+	/* when here it's the first reactivation, we need to setup a little more */
+	weston_log("kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x kbd_functionKeys:0x%x\n",
 			settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType,
 			settings->KeyboardFunctionKey);
 
@@ -840,10 +873,17 @@ xf_peer_post_connect(freerdp_peer* client)
 
 		keymap = xkb_keymap_new_from_names(xkbContext, &xkbRuleNames, 0);
 	}
-	weston_seat_init_keyboard(&peerCtx->item.seat, keymap);
-	weston_seat_init_pointer(&peerCtx->item.seat);
 
-	peerCtx->item.flags |= RDP_PEER_ACTIVATED;
+	if (settings->ClientHostname)
+		snprintf(seat_name, sizeof(seat_name), "RDP %s", settings->ClientHostname);
+	else
+		snprintf(seat_name, sizeof(seat_name), "RDP peer @%s", settings->ClientAddress);
+
+	weston_seat_init(&peersItem->seat, &c->base, seat_name);
+	weston_seat_init_keyboard(&peersItem->seat, keymap);
+	weston_seat_init_pointer(&peersItem->seat);
+
+	peersItem->flags |= RDP_PEER_ACTIVATED;
 
 	/* disable pointer on the client side */
 	pointer = client->update->pointer;
@@ -864,11 +904,8 @@ xf_peer_post_connect(freerdp_peer* client)
 	return TRUE;
 }
 
-static BOOL
-xf_peer_activate(freerdp_peer *client)
+static BOOL xf_peer_post_connect(freerdp_peer *client)
 {
-	RdpPeerContext *context = (RdpPeerContext *)client->context;
-	rfx_context_reset(context->rfx_context);
 	return TRUE;
 }
 
@@ -965,6 +1002,9 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
 	RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
 	int notify = 0;
 
+	if (!(peerContext->item.flags & RDP_PEER_ACTIVATED))
+		return;
+
 	if (flags & KBD_FLAGS_DOWN) {
 		keyState = WL_KEYBOARD_KEY_STATE_PRESSED;
 		notify = 1;
@@ -1017,7 +1057,6 @@ rdp_peer_init(freerdp_peer *client, struct rdp_compositor *c)
 	rdpSettings	*settings;
 	rdpInput *input;
 	RdpPeerContext *peerCtx;
-	char seat_name[32];
 
 	client->ContextSize = sizeof(RdpPeerContext);
 	client->ContextNew = (psPeerContextNew)rdp_peer_context_new;
@@ -1027,17 +1066,29 @@ rdp_peer_init(freerdp_peer *client, struct rdp_compositor *c)
 	peerCtx = (RdpPeerContext *) client->context;
 	peerCtx->rdpCompositor = c;
 
+	client->Initialize(client);
+
 	settings = client->settings;
-	settings->RdpKeyFile = c->rdp_key;
+	/* configure security settings */
+	if (c->rdp_key)
+		settings->RdpKeyFile = strdup(c->rdp_key);
 	if (c->tls_enabled) {
-		settings->CertificateFile = c->server_cert;
-		settings->PrivateKeyFile = c->server_key;
+		settings->CertificateFile = strdup( c->server_cert);
+		settings->PrivateKeyFile = strdup(c->server_key);
 	} else {
 		settings->TlsSecurity = FALSE;
 	}
-
 	settings->NlaSecurity = FALSE;
 
+	settings->OsMajorType = OSMAJORTYPE_UNIX;
+	settings->OsMinorType = OSMINORTYPE_PSEUDO_XSERVER;
+	settings->ColorDepth = 32;
+	settings->RefreshRect = TRUE;
+	settings->RemoteFxCodec = TRUE;
+	settings->NSCodec = TRUE;
+	settings->FrameMarkerCommandEnabled = TRUE;
+	settings->SurfaceFrameMarkerEnabled = TRUE;
+
 	client->Capabilities = xf_peer_capabilities;
 	client->PostConnect = xf_peer_post_connect;
 	client->Activate = xf_peer_activate;
@@ -1051,13 +1102,6 @@ rdp_peer_init(freerdp_peer *client, struct rdp_compositor *c)
 	input->KeyboardEvent = xf_input_keyboard_event;
 	input->UnicodeKeyboardEvent = xf_input_unicode_keyboard_event;
 
-	if (snprintf(seat_name, 32, "rdp:%d:%s", client->sockfd, client->hostname) >= 32)
-		seat_name[31] = '\0';
-
-	weston_seat_init(&peerCtx->item.seat, &c->base, seat_name);
-
-	client->Initialize(client);
-
 	if (!client->GetFileDescriptor(client, rfds, &rcount)) {
 		weston_log("unable to retrieve client fds\n");
 		return -1;
-- 
1.9.1



More information about the wayland-devel mailing list