From 0c944b07c451212bd287e79985a99333b8d4c368 Mon Sep 17 00:00:00 2001 From: Hardening Date: Mon, 11 May 2015 22:19:02 +0100 Subject: [PATCH] RDP compositor: fixes for multiple connections, mstsc and FreeRDP master compilation 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 also fixes the compilation against FreeRDP master with callback that now return BOOL. Signed-off-by: Hardening Acked-by: Pekka Paalanen --- src/compositor-rdp.c | 127 +++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 30 deletions(-) diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index 0d649286..3185141f 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -33,6 +33,23 @@ /* assume it's a early 1.1 version */ #define FREERDP_VERSION_MAJOR 1 #define FREERDP_VERSION_MINOR 1 +#define FREERDP_VERSION_REVISION 0 +#endif + +#define FREERDP_VERSION_NUMBER ((FREERDP_VERSION_MAJOR * 0x10000) + \ + (FREERDP_VERSION_MINOR * 0x100) + FREERDP_VERSION_REVISION) + +#if FREERDP_VERSION_NUMBER >= 0x10201 +#define HAVE_SKIP_COMPRESSION +#endif + +#if FREERDP_VERSION_NUMBER < 0x10202 +#define FREERDP_CB_RET_TYPE void +#define FREERDP_CB_RETURN(V) return +#else +#define HAVE_NSC_RESET +#define FREERDP_CB_RET_TYPE BOOL +#define FREERDP_CB_RETURN(V) return TRUE #endif #include @@ -145,6 +162,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 +219,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 +275,7 @@ rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_p marker->frameAction = SURFACECMD_FRAMEACTION_BEGIN; update->SurfaceFrameMarker(peer->context, marker); + memset(cmd, 0, sizeof(*cmd)); cmd->bpp = 32; cmd->codecID = 0; @@ -592,6 +620,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 +786,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 +845,16 @@ 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); +#ifdef HAVE_NSC_RESET + nsc_context_reset(peerCtx->nsc_context); +#endif + + 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 +881,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,15 +912,12 @@ 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; } -static void +static FREERDP_CB_RET_TYPE xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { wl_fixed_t wl_x, wl_y, axis; RdpPeerContext *peerContext = (RdpPeerContext *)input->context; @@ -917,9 +962,11 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { WL_POINTER_AXIS_VERTICAL_SCROLL, axis); } + + FREERDP_CB_RETURN(TRUE); } -static void +static FREERDP_CB_RET_TYPE xf_extendedMouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { wl_fixed_t wl_x, wl_y; RdpPeerContext *peerContext = (RdpPeerContext *)input->context; @@ -932,10 +979,12 @@ xf_extendedMouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { notify_motion_absolute(&peerContext->item.seat, weston_compositor_get_time(), wl_x, wl_y); } + + FREERDP_CB_RETURN(TRUE); } -static void +static FREERDP_CB_RET_TYPE xf_input_synchronize_event(rdpInput *input, UINT32 flags) { freerdp_peer *client = input->context->peer; @@ -954,10 +1003,11 @@ xf_input_synchronize_event(rdpInput *input, UINT32 flags) rdp_peer_refresh_region(&damage, client); pixman_region32_fini(&damage); + FREERDP_CB_RETURN(TRUE); } -static void +static FREERDP_CB_RET_TYPE xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) { uint32_t scan_code, vk_code, full_code; @@ -965,6 +1015,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)) + FREERDP_CB_RETURN(TRUE); + if (flags & KBD_FLAGS_DOWN) { keyState = WL_KEYBOARD_KEY_STATE_PRESSED; notify = 1; @@ -989,22 +1042,28 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) notify_key(&peerContext->item.seat, weston_compositor_get_time(), scan_code - 8, keyState, STATE_UPDATE_AUTOMATIC); } + + FREERDP_CB_RETURN(TRUE); } -static void +static FREERDP_CB_RET_TYPE xf_input_unicode_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) { weston_log("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code); + FREERDP_CB_RETURN(TRUE); } -static void +static FREERDP_CB_RET_TYPE xf_suppress_output(rdpContext *context, BYTE allow, RECTANGLE_16 *area) { RdpPeerContext *peerContext = (RdpPeerContext *)context; + if (allow) peerContext->item.flags |= RDP_PEER_OUTPUT_ENABLED; else peerContext->item.flags &= (~RDP_PEER_OUTPUT_ENABLED); + + FREERDP_CB_RETURN(TRUE); } static int @@ -1017,7 +1076,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 +1085,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 +1121,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; @@ -1078,12 +1141,16 @@ rdp_peer_init(freerdp_peer *client, struct rdp_compositor *c) } -static void +static FREERDP_CB_RET_TYPE rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client) { struct rdp_compositor *c = (struct rdp_compositor *)instance->param4; - if (rdp_peer_init(client, c) < 0) - return; + if (rdp_peer_init(client, c) < 0) { + weston_log("error when treating incoming peer"); + FREERDP_CB_RETURN(FALSE); + } + + FREERDP_CB_RETURN(TRUE); } static struct weston_compositor *