From 8afdf99e6165e9531a23a5dc6a6805ff8799c89b Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Thu, 31 May 2012 16:34:38 +0200 Subject: [PATCH 01/13] first spooky attempts to implement Hyper-V VM connection support: sending a PCB and disabling security negotiation --- libfreerdp-core/connection.c | 40 +++++++++++++++++++++++++++++++++--- libfreerdp-core/nego.h | 1 + 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 46fc2c470..9b2d7b927 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -54,6 +54,24 @@ * */ +// XXX: Send a PCB (preconnection BLOB) as specified in MS-RDPEPS (RDP_PRECONNECTION_PDU_V2) +boolean rdp_send_pcb(rdpNego* nego) { + STREAM* s; + // XXX: this is a fixed RDP_PRECONNECTION_PDU_V2, with Id=0 and a Hyper-V instance id as string + // must be customizable in the final version. + uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x32, 0x00, 0x37, 0x00, 0x41, 0x00, 0x41, 0x00, 0x39, 0x00, 0x30, 0x00, 0x46, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x43, 0x00, 0x30, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x42, 0x00, 0x34, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x36, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x41, 0x00, 0x37, 0x00, 0x37, 0x00, 0x45, 0x00, 0x34, 0x00, 0x38, 0x00, 0x45, 0x00, 0x46, 0x00, 0x44, 0x00, 0x36, 0x00, 0x46, 0x00, 0x00, 0x00}; + + if(!nego_tcp_connect(nego)) return false; + + s = transport_send_stream_init(nego->transport, 93); + stream_write(s, buf, 92); + + if (transport_write(nego->transport, s) < 0) + return false; + + return true; +} + /** * Establish RDP Connection based on the settings given in the 'rdp' paremeter. * @msdn{cc240452} @@ -63,6 +81,8 @@ boolean rdp_client_connect(rdpRdp* rdp) { + boolean negotiateSecurityLayer = false; // XXX: should be an option in the final version, with default value=true + boolean status; uint32 selectedProtocol; rdpSettings* settings = rdp->settings; @@ -78,10 +98,24 @@ boolean rdp_client_connect(rdpRdp* rdp) nego_enable_tls(rdp->nego, settings->tls_security); } - if (nego_connect(rdp->nego) != true) + rdp_send_pcb(rdp->nego); // XXX: different name?! + + if(negotiateSecurityLayer) { - printf("Error: protocol security negotiation failure\n"); - return false; + if (nego_connect(rdp->nego) != true) + { + printf("Error: protocol security negotiation failure\n"); + return false; + } + } + else + { + // set some predefined protocols if negotiateSecurityLayer is false + // XXX: should take settings->rdp_security into account. Right now we pretend NLA has been selected. + rdp->nego->state = NEGO_STATE_FINAL; + rdp->nego->transport->settings->requested_protocols = rdp->nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS; + rdp->nego->transport->settings->selected_protocol = rdp->nego->selected_protocol = PROTOCOL_NLA; + rdp->nego->transport->settings->negotiationFlags = rdp->nego->flags; } selectedProtocol = rdp->nego->selected_protocol; diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index 800b3b48c..5bd7b6302 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -85,6 +85,7 @@ struct rdp_nego typedef struct rdp_nego rdpNego; boolean nego_connect(rdpNego* nego); +boolean nego_tcp_connect(rdpNego* nego); // XXX: this is here for rdp_send_pcb. maybe there is a way around exporting it... void nego_attempt_nla(rdpNego* nego); void nego_attempt_tls(rdpNego* nego); From ee9b0b93a19ea6a82ec6e80fc0a21f585663dae7 Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Sat, 2 Jun 2012 21:34:06 +0200 Subject: [PATCH 02/13] choosing another VM instance in PCB --- libfreerdp-core/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 9b2d7b927..6eb384492 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -59,7 +59,7 @@ boolean rdp_send_pcb(rdpNego* nego) { STREAM* s; // XXX: this is a fixed RDP_PRECONNECTION_PDU_V2, with Id=0 and a Hyper-V instance id as string // must be customizable in the final version. - uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x32, 0x00, 0x37, 0x00, 0x41, 0x00, 0x41, 0x00, 0x39, 0x00, 0x30, 0x00, 0x46, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x43, 0x00, 0x30, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x42, 0x00, 0x34, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x36, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x41, 0x00, 0x37, 0x00, 0x37, 0x00, 0x45, 0x00, 0x34, 0x00, 0x38, 0x00, 0x45, 0x00, 0x46, 0x00, 0x44, 0x00, 0x36, 0x00, 0x46, 0x00, 0x00, 0x00}; + uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x32, 0x00, 0x39, 0x00, 0x46, 0x00, 0x46, 0x00, 0x43, 0x00, 0x46, 0x00, 0x35, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x43, 0x00, 0x33, 0x00, 0x36, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x34, 0x00, 0x35, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x39, 0x00, 0x34, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x33, 0x00, 0x30, 0x00, 0x32, 0x00, 0x37, 0x00, 0x30, 0x00, 0x39, 0x00, 0x31, 0x00, 0x35, 0x00, 0x31, 0x00, 0x42, 0x00, 0x00, 0x00}; if(!nego_tcp_connect(nego)) return false; From b119af583a2dad98f51ab854c6db089f4b0d8b5f Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Sat, 2 Jun 2012 21:35:34 +0200 Subject: [PATCH 03/13] introducing a bad hack to send the connection request after establishing a secure connection, and without a negotiation request --- libfreerdp-core/connection.c | 14 ++++++++++++++ libfreerdp-core/nego.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 6eb384492..bc9550de0 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -137,6 +137,20 @@ boolean rdp_client_connect(rdpRdp* rdp) if (status != true) return false; + if(!negotiateSecurityLayer) + { + // XXX: the whole negotioation thing should be called differently. + // this is more like a hack in order to allow connection requests after establishing a secure connection. + rdp->nego->state = NEGO_STATE_INITIAL; + rdp->nego->transport = rdp->transport; + rdp->nego->transport->settings->requested_protocols = PROTOCOL_RDP; // removes requested_protocols section + if (nego_connect(rdp->nego) != true) + { + printf("Error: X.224 connection request failure\n"); + return false; + } + } + rdp_set_blocking_mode(rdp, false); rdp->state = CONNECTION_STATE_NEGO; rdp->finalize_sc_pdus = 0; diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index b7ddbf0c3..ba4dbdb16 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -261,7 +261,7 @@ boolean nego_recv_response(rdpNego* nego) if (transport_read(nego->transport, s) < 0) return false; - return nego_recv(nego->transport, s, nego->transport->recv_extra); + return nego_recv(nego->transport, s, nego); } /** From 1d753aa5d7a66a74be91b12048c4c12144da59c0 Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Mon, 11 Jun 2012 17:52:46 +0200 Subject: [PATCH 04/13] yet another vm identifier. time to make this configurable... --- libfreerdp-core/connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index bc9550de0..f4154defc 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -59,7 +59,8 @@ boolean rdp_send_pcb(rdpNego* nego) { STREAM* s; // XXX: this is a fixed RDP_PRECONNECTION_PDU_V2, with Id=0 and a Hyper-V instance id as string // must be customizable in the final version. - uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x32, 0x00, 0x39, 0x00, 0x46, 0x00, 0x46, 0x00, 0x43, 0x00, 0x46, 0x00, 0x35, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x43, 0x00, 0x33, 0x00, 0x36, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x34, 0x00, 0x35, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x39, 0x00, 0x34, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x33, 0x00, 0x30, 0x00, 0x32, 0x00, 0x37, 0x00, 0x30, 0x00, 0x39, 0x00, 0x31, 0x00, 0x35, 0x00, 0x31, 0x00, 0x42, 0x00, 0x00, 0x00}; + // 49ECFD99-8A50-43DC-B2EF-39965652C371 + uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 52, 0, 57, 0, 69, 0, 67, 0, 70, 0, 68, 0, 57, 0, 57, 0, 45, 0, 56, 0, 65, 0, 53, 0, 48, 0, 45, 0, 52, 0, 51, 0, 68, 0, 67, 0, 45, 0, 66, 0, 50, 0, 69, 0, 70, 0, 45, 0, 51, 0, 57, 0, 57, 0, 54, 0, 53, 0, 54, 0, 53, 0, 50, 0, 67, 0, 51, 0, 55, 0, 49, 0, 0x00, 0x00}; if(!nego_tcp_connect(nego)) return false; From ac4b32b9cccc8658845a8782f9270dad498c3bff Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Mon, 23 Jul 2012 23:01:23 +0200 Subject: [PATCH 05/13] print fastpath debug information if WITH_DEBUG_RDP is set --- libfreerdp-core/fastpath.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index a54330fcf..c77789894 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -42,6 +42,24 @@ #define FASTPATH_MAX_PACKET_SIZE 0x3FFF +#ifdef WITH_DEBUG_RDP +static const char* const FASTPATH_UPDATETYPE_STRINGS[] = +{ + "Orders", /* 0x0 */ + "Bitmap", /* 0x1 */ + "Palette", /* 0x2 */ + "Synchronize", /* 0x3 */ + "Surface Commands", /* 0x4 */ + "System Pointer Hidden", /* 0x5 */ + "System Pointer Default", /* 0x6 */ + "???", /* 0x7 */ + "Pointer Position", /* 0x8 */ + "Color Pointer", /* 0x9 */ + "Cached Pointer", /* 0xA */ + "New Pointer", /* 0xB */ +}; +#endif + /* * The fastpath header may be two or three bytes long. * This function assumes that at least two bytes are available in the stream @@ -170,6 +188,11 @@ static boolean fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uin rdpContext* context = fastpath->rdp->update->context; rdpPointerUpdate* pointer = update->pointer; +#ifdef WITH_DEBUG_RDP + DEBUG_RDP("recv Fast-Path %s Update (0x%X), length:%d", + updateCode < ARRAY_SIZE(FASTPATH_UPDATETYPE_STRINGS) ? FASTPATH_UPDATETYPE_STRINGS[updateCode] : "???", updateCode, size); +#endif + switch (updateCode) { case FASTPATH_UPDATETYPE_ORDERS: From e43e14e2e74aff75dcbf8933176537954d667aab Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Tue, 24 Jul 2012 18:05:34 +0200 Subject: [PATCH 06/13] fix an issue with bitmap creation in X11 client where xfi->srcBpp differs from the connection's color depth --- client/X11/xf_graphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index b25dc99d1..dfcedbca3 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -43,7 +43,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) if (bitmap->data != NULL) { data = freerdp_image_convert(bitmap->data, NULL, - bitmap->width, bitmap->height, xfi->srcBpp, xfi->bpp, xfi->clrconv); + bitmap->width, bitmap->height, bitmap->bpp, xfi->bpp, xfi->clrconv); if (bitmap->ephemeral != true) { From 083711fd0992e7d544cc22001b4587b5641dedb7 Mon Sep 17 00:00:00 2001 From: Lysann Kessler Date: Wed, 25 Jul 2012 00:08:02 +0200 Subject: [PATCH 07/13] use xfContext->settings->color_depth instead of xfi->srcBpp --- client/X11/xf_gdi.c | 22 +++++++++++----------- client/X11/xf_graphics.c | 10 +++++----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 421306c50..6977513c7 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -334,8 +334,8 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) brush = &patblt->brush; xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop)); - foreColor = freerdp_color_convert_rgb(patblt->foreColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); - backColor = freerdp_color_convert_rgb(patblt->backColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + foreColor = freerdp_color_convert_rgb(patblt->foreColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + backColor = freerdp_color_convert_rgb(patblt->backColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); if (brush->style == GDI_BS_SOLID) { @@ -438,7 +438,7 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) uint32 color; xfInfo* xfi = ((xfContext*) context)->xfi; - color = freerdp_color_convert_var(opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(opaque_rect->color, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -468,7 +468,7 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult DELTA_RECT* rectangle; xfInfo* xfi = ((xfContext*) context)->xfi; - color = freerdp_color_convert_var(multi_opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(multi_opaque_rect->color, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -506,7 +506,7 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop2(xfi, line_to->bRop2); - color = freerdp_color_convert_rgb(line_to->penColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_rgb(line_to->penColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); @@ -553,7 +553,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop2(xfi, polyline->bRop2); - color = freerdp_color_convert_var(polyline->penColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(polyline->penColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); @@ -641,8 +641,8 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) brush = &mem3blt->brush; bitmap = (xfBitmap*) mem3blt->bitmap; xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop)); - foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); - backColor = freerdp_color_convert_rgb(mem3blt->backColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + backColor = freerdp_color_convert_rgb(mem3blt->backColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); if (brush->style == GDI_BS_PATTERN) { @@ -711,7 +711,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) xfInfo* xfi = ((xfContext*) context)->xfi; xf_set_rop2(xfi, polygon_sc->bRop2); - brush_color = freerdp_color_convert_var(polygon_sc->brushColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + brush_color = freerdp_color_convert_var(polygon_sc->brushColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); npoints = polygon_sc->numPoints + 1; points = xmalloc(sizeof(XPoint) * npoints); @@ -768,8 +768,8 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) brush = &(polygon_cb->brush); xf_set_rop2(xfi, polygon_cb->bRop2); - foreColor = freerdp_color_convert_rgb(polygon_cb->foreColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); - backColor = freerdp_color_convert_rgb(polygon_cb->backColor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + foreColor = freerdp_color_convert_rgb(polygon_cb->foreColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + backColor = freerdp_color_convert_rgb(polygon_cb->backColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); npoints = polygon_cb->numPoints + 1; points = xmalloc(sizeof(XPoint) * npoints); diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index b25dc99d1..7cb248773 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -43,7 +43,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) if (bitmap->data != NULL) { data = freerdp_image_convert(bitmap->data, NULL, - bitmap->width, bitmap->height, xfi->srcBpp, xfi->bpp, xfi->clrconv); + bitmap->width, bitmap->height, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); if (bitmap->ephemeral != true) { @@ -273,12 +273,12 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height xfInfo* xfi = ((xfContext*) context)->xfi; bgcolor = (xfi->clrconv->invert)? - freerdp_color_convert_var_bgr(bgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv): - freerdp_color_convert_var_rgb(bgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + freerdp_color_convert_var_bgr(bgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv): + freerdp_color_convert_var_rgb(bgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); fgcolor = (xfi->clrconv->invert)? - freerdp_color_convert_var_bgr(fgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv): - freerdp_color_convert_var_rgb(fgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv); + freerdp_color_convert_var_bgr(fgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv): + freerdp_color_convert_var_rgb(fgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); From 664c870de8dc13561e85d716df8d9292ea578bd6 Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Wed, 25 Jul 2012 10:38:47 +0200 Subject: [PATCH 08/13] move transport.h include from header into c file --- libfreerdp-core/connection.c | 1 + libfreerdp-core/connection.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 181c7a89d..1bed2cb40 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -21,6 +21,7 @@ #include "input.h" #include "connection.h" +#include "transport.h" #include diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index eb5c0460f..8d05bedb9 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -25,7 +25,6 @@ #include "tpdu.h" #include "nego.h" #include "mcs.h" -#include "transport.h" #include "activation.h" #include From 3c6df9597811c32dfd4555e69b18f5498f030dcc Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Wed, 25 Jul 2012 12:29:49 +0200 Subject: [PATCH 09/13] added a setting and a command line flag to disable security layer negotiation --- include/freerdp/settings.h | 3 +- libfreerdp-core/connection.c | 55 +++------------------ libfreerdp-core/nego.c | 96 +++++++++++++++++++++++++++++------- libfreerdp-core/nego.h | 8 ++- libfreerdp-core/settings.c | 1 + libfreerdp-utils/args.c | 5 ++ 6 files changed, 100 insertions(+), 68 deletions(-) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 7d0a24be8..6255cf202 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -269,7 +269,8 @@ struct rdp_settings ALIGN64 uint32 encryption_level; /* 28 */ ALIGN64 boolean authentication; /* 29 */ ALIGN64 uint32 negotiationFlags; /* 30 */ - ALIGN64 uint64 paddingB[48 - 31]; /* 31 */ + ALIGN64 boolean security_layer_negotiation; /* 31 */ + ALIGN64 uint64 paddingB[48 - 32]; /* 32 */ /* Connection Settings */ ALIGN64 uint32 port; /* 48 */ diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 1bed2cb40..346dd1317 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -83,15 +83,12 @@ boolean rdp_send_pcb(rdpNego* nego) { boolean rdp_client_connect(rdpRdp* rdp) { - boolean negotiateSecurityLayer = false; // XXX: should be an option in the final version, with default value=true - - boolean status; - uint32 selectedProtocol; rdpSettings* settings = rdp->settings; nego_init(rdp->nego); nego_set_target(rdp->nego, settings->hostname, settings->port); nego_set_cookie(rdp->nego, settings->username); + nego_set_negotiation_enabled(rdp->nego, settings->security_layer_negotiation); nego_enable_rdp(rdp->nego, settings->rdp_security); if (!settings->ts_gateway) @@ -102,62 +99,26 @@ boolean rdp_client_connect(rdpRdp* rdp) rdp_send_pcb(rdp->nego); // XXX: different name?! - if(negotiateSecurityLayer) + if (!nego_connect(rdp->nego)) { - if (nego_connect(rdp->nego) != true) - { - printf("Error: protocol security negotiation failure\n"); - return false; - } - } - else - { - // set some predefined protocols if negotiateSecurityLayer is false - // XXX: should take settings->rdp_security into account. Right now we pretend NLA has been selected. - rdp->nego->state = NEGO_STATE_FINAL; - rdp->nego->transport->settings->requested_protocols = rdp->nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS; - rdp->nego->transport->settings->selected_protocol = rdp->nego->selected_protocol = PROTOCOL_NLA; - rdp->nego->transport->settings->negotiationFlags = rdp->nego->flags; + printf("Error: protocol security negotiation failure\n"); + return false; } - selectedProtocol = rdp->nego->selected_protocol; + if (!nego_security_connect(rdp->nego)) + return false; - if ((selectedProtocol & PROTOCOL_TLS) || (selectedProtocol == PROTOCOL_RDP)) + if ((rdp->nego->selected_protocol & PROTOCOL_TLS) || (rdp->nego->selected_protocol == PROTOCOL_RDP)) { if ((settings->username != NULL) && ((settings->password != NULL) || (settings->password_cookie != NULL && settings->password_cookie->length > 0))) settings->autologon = true; } - status = false; - if (selectedProtocol & PROTOCOL_NLA) - status = transport_connect_nla(rdp->transport); - else if (selectedProtocol & PROTOCOL_TLS) - status = transport_connect_tls(rdp->transport); - else if (selectedProtocol == PROTOCOL_RDP) /* 0 */ - status = transport_connect_rdp(rdp->transport); - - if (status != true) - return false; - - if(!negotiateSecurityLayer) - { - // XXX: the whole negotioation thing should be called differently. - // this is more like a hack in order to allow connection requests after establishing a secure connection. - rdp->nego->state = NEGO_STATE_INITIAL; - rdp->nego->transport = rdp->transport; - rdp->nego->transport->settings->requested_protocols = PROTOCOL_RDP; // removes requested_protocols section - if (nego_connect(rdp->nego) != true) - { - printf("Error: X.224 connection request failure\n"); - return false; - } - } - rdp_set_blocking_mode(rdp, false); rdp->state = CONNECTION_STATE_NEGO; rdp->finalize_sc_pdus = 0; - if (mcs_send_connect_initial(rdp->mcs) != true) + if (!mcs_send_connect_initial(rdp->mcs)) { if (!connectErrorCode) { diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index 9f9f6b6b4..d6cb9121b 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -27,6 +27,8 @@ #include "nego.h" +#include "transport.h" + static const char* const NEGO_STATE_STRINGS[] = { "NEGO_STATE_INITIAL", @@ -61,7 +63,24 @@ boolean nego_connect(rdpNego* nego) else if (nego->enabled_protocols[PROTOCOL_RDP] > 0) nego->state = NEGO_STATE_RDP; else + { + DEBUG_NEGO("No security protocol is enabled"); nego->state = NEGO_STATE_FAIL; + } + + if (!nego->security_layer_negotiation_enabled) + { + DEBUG_NEGO("Security Layer Negotiation is disabled"); + nego->enabled_protocols[PROTOCOL_NLA] = 0; + nego->enabled_protocols[PROTOCOL_TLS] = 0; + nego->enabled_protocols[PROTOCOL_RDP] = 0; + if(nego->state == NEGO_STATE_NLA) + nego->enabled_protocols[PROTOCOL_NLA] = 1; + else if (nego->state == NEGO_STATE_TLS) + nego->enabled_protocols[PROTOCOL_TLS] = 1; + else if (nego->state == NEGO_STATE_RDP) + nego->enabled_protocols[PROTOCOL_RDP] = 1; + } } do @@ -96,6 +115,25 @@ boolean nego_connect(rdpNego* nego) return true; } +/* connect to selected security layer */ +boolean nego_security_connect(rdpNego* nego) +{ + if(!nego->tcp_connected) + { + nego->security_connected = false; + } + else if (!nego->security_connected) + { + if (nego->enabled_protocols[PROTOCOL_NLA] > 0) + nego->security_connected = transport_connect_nla(nego->transport); + else if (nego->enabled_protocols[PROTOCOL_TLS] > 0) + nego->security_connected = transport_connect_tls(nego->transport); + else if (nego->enabled_protocols[PROTOCOL_RDP] > 0) + nego->security_connected = transport_connect_rdp(nego->transport); + } + return nego->security_connected; +} + /** * Connect TCP layer. * @param nego @@ -104,21 +142,30 @@ boolean nego_connect(rdpNego* nego) boolean nego_tcp_connect(rdpNego* nego) { - if (nego->tcp_connected == 0) + if (!nego->tcp_connected) { - if (transport_connect(nego->transport, nego->hostname, nego->port) == false) - { - nego->tcp_connected = 0; - return false; - } - else - { - nego->tcp_connected = 1; - return true; - } + nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port); + } + return nego->tcp_connected; +} + +/** + * Connect TCP layer. For direct approach, connect security layer as well. + * @param nego + * @return + */ + +boolean nego_transport_connect(rdpNego* nego) +{ + nego_tcp_connect(nego); + + if (nego->tcp_connected && !nego->security_layer_negotiation_enabled) + { + nego_security_connect(nego); + return nego->security_connected; } - return true; + return nego->tcp_connected; } /** @@ -127,12 +174,13 @@ boolean nego_tcp_connect(rdpNego* nego) * @return */ -int nego_tcp_disconnect(rdpNego* nego) +int nego_transport_disconnect(rdpNego* nego) { if (nego->tcp_connected) transport_disconnect(nego->transport); nego->tcp_connected = 0; + nego->security_connected = 0; return 1; } @@ -147,7 +195,7 @@ void nego_attempt_nla(rdpNego* nego) DEBUG_NEGO("Attempting NLA security"); - if (!nego_tcp_connect(nego)) + if (!nego_transport_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; @@ -168,7 +216,7 @@ void nego_attempt_nla(rdpNego* nego) DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]); if (nego->state != NEGO_STATE_FINAL) { - nego_tcp_disconnect(nego); + nego_transport_disconnect(nego); if (nego->enabled_protocols[PROTOCOL_TLS] > 0) nego->state = NEGO_STATE_TLS; @@ -190,7 +238,7 @@ void nego_attempt_tls(rdpNego* nego) DEBUG_NEGO("Attempting TLS security"); - if (!nego_tcp_connect(nego)) + if (!nego_transport_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; @@ -210,7 +258,7 @@ void nego_attempt_tls(rdpNego* nego) if (nego->state != NEGO_STATE_FINAL) { - nego_tcp_disconnect(nego); + nego_transport_disconnect(nego); if (nego->enabled_protocols[PROTOCOL_RDP] > 0) nego->state = NEGO_STATE_RDP; @@ -230,7 +278,7 @@ void nego_attempt_rdp(rdpNego* nego) DEBUG_NEGO("Attempting RDP security"); - if (!nego_tcp_connect(nego)) + if (!nego_transport_connect(nego)) { nego->state = NEGO_STATE_FAIL; return; @@ -704,6 +752,18 @@ void nego_set_target(rdpNego* nego, char* hostname, int port) nego->port = port; } +/** + * Enable security layer negotiation. + * @param nego pointer to the negotiation structure + * @param enable_rdp whether to enable security layer negotiation (true for enabled, false for disabled) + */ + +void nego_set_negotiation_enabled(rdpNego* nego, boolean security_layer_negotiation_enabled) +{ + DEBUG_NEGO("Enabling security layer negotiation: %s", security_layer_negotiation_enabled ? "true" : "false"); + nego->security_layer_negotiation_enabled = security_layer_negotiation_enabled; +} + /** * Enable RDP security protocol. * @param nego pointer to the negotiation structure diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index 5bd7b6302..e71e505f8 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -75,17 +75,20 @@ struct rdp_nego char* hostname; char* cookie; NEGO_STATE state; - int tcp_connected; + boolean tcp_connected; + boolean security_connected; rdpBlob* routing_token; uint32 selected_protocol; uint32 requested_protocols; + boolean security_layer_negotiation_enabled; uint8 enabled_protocols[3]; rdpTransport* transport; }; typedef struct rdp_nego rdpNego; boolean nego_connect(rdpNego* nego); -boolean nego_tcp_connect(rdpNego* nego); // XXX: this is here for rdp_send_pcb. maybe there is a way around exporting it... +boolean nego_tcp_connect(rdpNego* nego); +boolean nego_security_connect(rdpNego* nego); void nego_attempt_nla(rdpNego* nego); void nego_attempt_tls(rdpNego* nego); @@ -106,6 +109,7 @@ rdpNego* nego_new(struct rdp_transport * transport); void nego_free(rdpNego* nego); void nego_init(rdpNego* nego); void nego_set_target(rdpNego* nego, char* hostname, int port); +void nego_set_negotiation_enabled(rdpNego* nego, boolean security_layer_negotiation_enabled); void nego_enable_rdp(rdpNego* nego, boolean enable_rdp); void nego_enable_nla(rdpNego* nego, boolean enable_nla); void nego_enable_tls(rdpNego* nego, boolean enable_tls); diff --git a/libfreerdp-core/settings.c b/libfreerdp-core/settings.c index 4540ed91c..277ea5e19 100644 --- a/libfreerdp-core/settings.c +++ b/libfreerdp-core/settings.c @@ -97,6 +97,7 @@ rdpSettings* settings_new(void* instance) settings->nla_security = true; settings->tls_security = true; settings->rdp_security = true; + settings->security_layer_negotiation = true; settings->client_build = 2600; settings->kbd_type = 4; /* @msdn{cc240510} 'IBM enhanced (101- or 102-key) keyboard' */ settings->kbd_subtype = 0; diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index 1a5b39125..6853d00a3 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -122,6 +122,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, " --disable-full-window-drag: disables full window drag\n" " --disable-menu-animations: disables menu animations\n" " --disable-theming: disables theming\n" + " --disable-security-layer-negotiation: disable negotiation of security layer and force highest enabled layer\n" " --no-rdp: disable Standard RDP encryption\n" " --no-tls: disable TLS encryption\n" " --no-nla: disable network level authentication\n" @@ -579,6 +580,10 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, return FREERDP_ARGS_PARSE_FAILURE; } } + else if (strcmp("--disable-security-layer-negotiation", argv[index]) == 0) + { + settings->security_layer_negotiation = false; + } else if (strcmp("--tsg", argv[index]) == 0) { settings->ts_gateway = true; From d9c260f2216a7917e1a885194ff778bdffa1a22b Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Wed, 25 Jul 2012 18:46:43 +0200 Subject: [PATCH 10/13] added command line options to specify preconnection PDU information --- include/freerdp/settings.h | 5 +- libfreerdp-core/connection.c | 25 ++-------- libfreerdp-core/nego.c | 96 +++++++++++++++++++++++++++++++++--- libfreerdp-core/nego.h | 20 +++++++- libfreerdp-utils/args.c | 24 +++++++++ 5 files changed, 140 insertions(+), 30 deletions(-) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 6255cf202..362037ff0 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -296,7 +296,10 @@ struct rdp_settings ALIGN64 boolean local; /* 68 */ ALIGN64 boolean authentication_only; /* 69 */ ALIGN64 boolean from_stdin; /* 70 */ - ALIGN64 uint64 paddingC[80 - 71]; /* 71 */ + ALIGN64 boolean send_preconnection_pdu; /* 71 */ + ALIGN64 uint32 preconnection_id; /* 72 */ + ALIGN64 char* preconnection_blob; /* 73 */ + ALIGN64 uint64 paddingC[80 - 74]; /* 74 */ /* User Interface Parameters */ ALIGN64 boolean sw_gdi; /* 80 */ diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 346dd1317..57e687752 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -55,25 +55,6 @@ * */ -// XXX: Send a PCB (preconnection BLOB) as specified in MS-RDPEPS (RDP_PRECONNECTION_PDU_V2) -boolean rdp_send_pcb(rdpNego* nego) { - STREAM* s; - // XXX: this is a fixed RDP_PRECONNECTION_PDU_V2, with Id=0 and a Hyper-V instance id as string - // must be customizable in the final version. - // 49ECFD99-8A50-43DC-B2EF-39965652C371 - uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 52, 0, 57, 0, 69, 0, 67, 0, 70, 0, 68, 0, 57, 0, 57, 0, 45, 0, 56, 0, 65, 0, 53, 0, 48, 0, 45, 0, 52, 0, 51, 0, 68, 0, 67, 0, 45, 0, 66, 0, 50, 0, 69, 0, 70, 0, 45, 0, 51, 0, 57, 0, 57, 0, 54, 0, 53, 0, 54, 0, 53, 0, 50, 0, 67, 0, 51, 0, 55, 0, 49, 0, 0x00, 0x00}; - - if(!nego_tcp_connect(nego)) return false; - - s = transport_send_stream_init(nego->transport, 93); - stream_write(s, buf, 92); - - if (transport_write(nego->transport, s) < 0) - return false; - - return true; -} - /** * Establish RDP Connection based on the settings given in the 'rdp' paremeter. * @msdn{cc240452} @@ -88,6 +69,10 @@ boolean rdp_client_connect(rdpRdp* rdp) nego_init(rdp->nego); nego_set_target(rdp->nego, settings->hostname, settings->port); nego_set_cookie(rdp->nego, settings->username); + nego_set_send_preconnection_pdu(rdp->nego, settings->send_preconnection_pdu); + nego_set_preconnection_id(rdp->nego, settings->preconnection_id); + nego_set_preconnection_blob(rdp->nego, settings->preconnection_blob); + nego_set_negotiation_enabled(rdp->nego, settings->security_layer_negotiation); nego_enable_rdp(rdp->nego, settings->rdp_security); @@ -97,8 +82,6 @@ boolean rdp_client_connect(rdpRdp* rdp) nego_enable_tls(rdp->nego, settings->tls_security); } - rdp_send_pcb(rdp->nego); // XXX: different name?! - if (!nego_connect(rdp->nego)) { printf("Error: protocol security negotiation failure\n"); diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index d6cb9121b..388b257fc 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -81,6 +81,13 @@ boolean nego_connect(rdpNego* nego) else if (nego->state == NEGO_STATE_RDP) nego->enabled_protocols[PROTOCOL_RDP] = 1; } + + if(!nego_send_preconnection_pdu(nego)) + { + DEBUG_NEGO("Failed to send preconnection information"); + nego->state = NEGO_STATE_FINAL; + return false; + } } do @@ -143,9 +150,7 @@ boolean nego_security_connect(rdpNego* nego) boolean nego_tcp_connect(rdpNego* nego) { if (!nego->tcp_connected) - { nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port); - } return nego->tcp_connected; } @@ -160,10 +165,7 @@ boolean nego_transport_connect(rdpNego* nego) nego_tcp_connect(nego); if (nego->tcp_connected && !nego->security_layer_negotiation_enabled) - { - nego_security_connect(nego); - return nego->security_connected; - } + return nego_security_connect(nego); return nego->tcp_connected; } @@ -184,6 +186,55 @@ int nego_transport_disconnect(rdpNego* nego) return 1; } +/** + * Send preconnection information if enabled. + * @param nego + * @return + */ + +boolean nego_send_preconnection_pdu(rdpNego* nego) +{ + STREAM* s; + uint32 cbSize; + UNICONV* uniconv; + uint16 cchPCB_times2 = 0; + char* wszPCB = NULL; + + if(!nego->send_preconnection_pdu) + return true; + + DEBUG_NEGO("Sending preconnection PDU"); + if(!nego_tcp_connect(nego)) + return false; + + /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */ + cbSize = PRECONNECTION_PDU_V2_MIN_SIZE; + if(nego->preconnection_blob) { + uniconv = freerdp_uniconv_new(); + wszPCB = freerdp_uniconv_out(uniconv, nego->preconnection_blob, &cchPCB_times2); + freerdp_uniconv_free(uniconv); + cchPCB_times2 += 2; /* zero-termination */ + cbSize += cchPCB_times2; + } + + s = transport_send_stream_init(nego->transport, cbSize); + stream_write_uint32(s, cbSize); /* cbSize */ + stream_write_uint32(s, 0); /* Flags */ + stream_write_uint32(s, PRECONNECTION_PDU_V2); /* Version */ + stream_write_uint32(s, nego->preconnection_id); /* Id */ + stream_write_uint16(s, cchPCB_times2 / 2); /* cchPCB */ + if(wszPCB) + { + stream_write(s, wszPCB, cchPCB_times2); /* wszPCB */ + xfree(wszPCB); + } + + if (transport_write(nego->transport, s) < 0) + return false; + + return true; +} + /** * Attempt negotiating NLA + TLS security. * @param nego @@ -821,3 +872,36 @@ void nego_set_cookie(rdpNego* nego, char* cookie) { nego->cookie = cookie; } + +/** + * Enable / disable preconnection PDU. + * @param nego + * @param send_pcpdu + */ + +void nego_set_send_preconnection_pdu(rdpNego* nego, boolean send_pcpdu) +{ + nego->send_preconnection_pdu = send_pcpdu; +} + +/** + * Set preconnection id. + * @param nego + * @param id + */ + +void nego_set_preconnection_id(rdpNego* nego, uint32 id) +{ + nego->preconnection_id = id; +} + +/** + * Set preconnection blob. + * @param nego + * @param blob + */ + +void nego_set_preconnection_blob(rdpNego* nego, char* blob) +{ + nego->preconnection_blob = blob; +} diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index e71e505f8..68a8d6504 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -68,28 +68,41 @@ enum RDP_NEG_MSG #define EXTENDED_CLIENT_DATA_SUPPORTED 0x01 +#define PRECONNECTION_PDU_V1_SIZE 16 +#define PRECONNECTION_PDU_V2_MIN_SIZE (PRECONNECTION_PDU_V1_SIZE+2) + +#define PRECONNECTION_PDU_V1 1 +#define PRECONNECTION_PDU_V2 2 + struct rdp_nego { int port; uint32 flags; char* hostname; char* cookie; + rdpBlob* routing_token; + boolean send_preconnection_pdu; + uint32 preconnection_id; + char* preconnection_blob; + NEGO_STATE state; boolean tcp_connected; boolean security_connected; - rdpBlob* routing_token; + uint32 selected_protocol; uint32 requested_protocols; boolean security_layer_negotiation_enabled; uint8 enabled_protocols[3]; + rdpTransport* transport; }; typedef struct rdp_nego rdpNego; boolean nego_connect(rdpNego* nego); -boolean nego_tcp_connect(rdpNego* nego); boolean nego_security_connect(rdpNego* nego); +boolean nego_send_preconnection_pdu(rdpNego* nego); + void nego_attempt_nla(rdpNego* nego); void nego_attempt_tls(rdpNego* nego); void nego_attempt_rdp(rdpNego* nego); @@ -115,6 +128,9 @@ void nego_enable_nla(rdpNego* nego, boolean enable_nla); void nego_enable_tls(rdpNego* nego, boolean enable_tls); void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token); void nego_set_cookie(rdpNego* nego, char* cookie); +void nego_set_send_preconnection_pdu(rdpNego* nego, boolean send_pcpdu); +void nego_set_preconnection_id(rdpNego* nego, uint32 id); +void nego_set_preconnection_blob(rdpNego* nego, char* blob); #ifdef WITH_DEBUG_NEGO #define DEBUG_NEGO(fmt, ...) DEBUG_CLASS(NEGO, fmt, ## __VA_ARGS__) diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index 6853d00a3..cba318520 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -133,6 +133,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, " --tsg: Terminal Server Gateway ( )\n" " --kbd-list: list all keyboard layout ids used by -k\n" " --no-salted-checksum: disable salted checksums with Standard RDP encryption\n" + " --pcid: preconnection id\n" + " --pcb: preconnection blob\n" " --version: print version information\n" "\n", argv[0]); return FREERDP_ARGS_PARSE_HELP; /* TODO: What is the correct return? */ @@ -703,6 +705,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, { settings->salted_checksum = false; } + else if (strcmp("--pcid", argv[index]) == 0) + { + index++; + if (index == argc) + { + printf("missing preconnection id value\n"); + return -1; + } + settings->send_preconnection_pdu = true; + settings->preconnection_id = atoi(argv[index]); + } + else if (strcmp("--pcb", argv[index]) == 0) + { + index++; + if (index == argc) + { + printf("missing preconnection blob value\n"); + return -1; + } + settings->send_preconnection_pdu = true; + settings->preconnection_blob = xstrdup(argv[index]); + } else if (strcmp("--version", argv[index]) == 0) { printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL); From f8430e246cab1cc2d180e29a8e995ebc60ca7860 Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Wed, 25 Jul 2012 18:50:19 +0200 Subject: [PATCH 11/13] moved final security connection step into nego_connect for consistency --- libfreerdp-core/connection.c | 5 +---- libfreerdp-core/nego.c | 9 +++++++++ libfreerdp-core/nego.h | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 57e687752..b408992a0 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -84,13 +84,10 @@ boolean rdp_client_connect(rdpRdp* rdp) if (!nego_connect(rdp->nego)) { - printf("Error: protocol security negotiation failure\n"); + printf("Error: protocol security negotiation or connection failure\n"); return false; } - if (!nego_security_connect(rdp->nego)) - return false; - if ((rdp->nego->selected_protocol & PROTOCOL_TLS) || (rdp->nego->selected_protocol == PROTOCOL_RDP)) { if ((settings->username != NULL) && ((settings->password != NULL) || (settings->password_cookie != NULL && settings->password_cookie->length > 0))) diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index 388b257fc..0558fca6a 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -46,6 +46,8 @@ static const char PROTOCOL_SECURITY_STRINGS[3][4] = "NLA" }; +boolean nego_security_connect(rdpNego* nego); + /** * Negotiate protocol security and connect. * @param nego @@ -119,6 +121,13 @@ boolean nego_connect(rdpNego* nego) nego->transport->settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } + /* finally connect security layer (if not already done) */ + if(!nego_security_connect(nego)) + { + DEBUG_NEGO("Failed to connect with %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]); + return false; + } + return true; } diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index 68a8d6504..cf30c94e9 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -99,7 +99,6 @@ struct rdp_nego typedef struct rdp_nego rdpNego; boolean nego_connect(rdpNego* nego); -boolean nego_security_connect(rdpNego* nego); boolean nego_send_preconnection_pdu(rdpNego* nego); From 6b754ab8368b4f17b5b20ff92c5841e9c7b8158f Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Wed, 25 Jul 2012 19:05:03 +0200 Subject: [PATCH 12/13] casting context to xfContext in more lines and more code clarity --- client/X11/xf_gdi.c | 34 ++++++++++++++++++++-------------- client/X11/xf_graphics.c | 16 +++++++++------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 6977513c7..539f5ffa2 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -329,13 +329,14 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) rdpBrush* brush; uint32 foreColor; uint32 backColor; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; brush = &patblt->brush; xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop)); - foreColor = freerdp_color_convert_rgb(patblt->foreColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); - backColor = freerdp_color_convert_rgb(patblt->backColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + foreColor = freerdp_color_convert_rgb(patblt->foreColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); + backColor = freerdp_color_convert_rgb(patblt->backColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); if (brush->style == GDI_BS_SOLID) { @@ -436,9 +437,10 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { uint32 color; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; - color = freerdp_color_convert_var(opaque_rect->color, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(opaque_rect->color, context_->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -466,9 +468,10 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult int i; uint32 color; DELTA_RECT* rectangle; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; - color = freerdp_color_convert_var(multi_opaque_rect->color, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(multi_opaque_rect->color, context_->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -503,10 +506,11 @@ void xf_gdi_draw_nine_grid(rdpContext* context, DRAW_NINE_GRID_ORDER* draw_nine_ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) { uint32 color; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; xf_set_rop2(xfi, line_to->bRop2); - color = freerdp_color_convert_rgb(line_to->penColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_rgb(line_to->penColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); @@ -550,10 +554,11 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) uint32 color; XPoint* points; int width, height; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; xf_set_rop2(xfi, polyline->bRop2); - color = freerdp_color_convert_var(polyline->penColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + color = freerdp_color_convert_var(polyline->penColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetForeground(xfi->display, xfi->gc, color); @@ -636,13 +641,14 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) uint32 foreColor; uint32 backColor; Pixmap pattern = 0; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; brush = &mem3blt->brush; bitmap = (xfBitmap*) mem3blt->bitmap; xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop)); - foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); - backColor = freerdp_color_convert_rgb(mem3blt->backColor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); + backColor = freerdp_color_convert_rgb(mem3blt->backColor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); if (brush->style == GDI_BS_PATTERN) { diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 7cb248773..ef4d1c3f8 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -35,7 +35,8 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) uint8* data; Pixmap pixmap; XImage* image; - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; XSetFunction(xfi->display, xfi->gc, GXcopy); pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth); @@ -43,7 +44,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) if (bitmap->data != NULL) { data = freerdp_image_convert(bitmap->data, NULL, - bitmap->width, bitmap->height, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + bitmap->width, bitmap->height, context_->settings->color_depth, xfi->bpp, xfi->clrconv); if (bitmap->ephemeral != true) { @@ -270,15 +271,16 @@ void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y) void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor) { - xfInfo* xfi = ((xfContext*) context)->xfi; + xfContext* context_ = (xfContext*) context; + xfInfo* xfi = context_->xfi; bgcolor = (xfi->clrconv->invert)? - freerdp_color_convert_var_bgr(bgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv): - freerdp_color_convert_var_rgb(bgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + freerdp_color_convert_var_bgr(bgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv): + freerdp_color_convert_var_rgb(bgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); fgcolor = (xfi->clrconv->invert)? - freerdp_color_convert_var_bgr(fgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv): - freerdp_color_convert_var_rgb(fgcolor, ((xfContext*)context)->settings->color_depth, xfi->bpp, xfi->clrconv); + freerdp_color_convert_var_bgr(fgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv): + freerdp_color_convert_var_rgb(fgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); From ecc0209bc394400126c84766db7400a4e9b36631 Mon Sep 17 00:00:00 2001 From: lysannkessler Date: Thu, 26 Jul 2012 12:55:35 +0200 Subject: [PATCH 13/13] rename command line option --disable-security-layer-negotiation to --no-nego --- libfreerdp-utils/args.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index cba318520..89a1aa1ba 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -122,7 +122,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, " --disable-full-window-drag: disables full window drag\n" " --disable-menu-animations: disables menu animations\n" " --disable-theming: disables theming\n" - " --disable-security-layer-negotiation: disable negotiation of security layer and force highest enabled layer\n" + " --no-nego: disable negotiation of security layer and enforce highest enabled security protocol\n" " --no-rdp: disable Standard RDP encryption\n" " --no-tls: disable TLS encryption\n" " --no-nla: disable network level authentication\n" @@ -582,7 +582,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, return FREERDP_ARGS_PARSE_FAILURE; } } - else if (strcmp("--disable-security-layer-negotiation", argv[index]) == 0) + else if (strcmp("--no-nego", argv[index]) == 0) { settings->security_layer_negotiation = false; }