Merge pull request #668 from lysannkessler/spikes/hyperv

Allow connections to Hyper-V VMMS
This commit is contained in:
Marc-André Moreau 2012-07-26 07:34:57 -07:00
commit 32390d7807
10 changed files with 298 additions and 70 deletions

View File

@ -329,13 +329,14 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
rdpBrush* brush; rdpBrush* brush;
uint32 foreColor; uint32 foreColor;
uint32 backColor; uint32 backColor;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
brush = &patblt->brush; brush = &patblt->brush;
xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop)); xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop));
foreColor = freerdp_color_convert_rgb(patblt->foreColor, xfi->srcBpp, 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, xfi->srcBpp, 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) 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) void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
{ {
uint32 color; uint32 color;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
color = freerdp_color_convert_var(opaque_rect->color, xfi->srcBpp, 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); XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid); 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; int i;
uint32 color; uint32 color;
DELTA_RECT* rectangle; 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, xfi->srcBpp, 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); XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid); 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) void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
{ {
uint32 color; uint32 color;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
xf_set_rop2(xfi, line_to->bRop2); 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, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XSetForeground(xfi->display, xfi->gc, color); XSetForeground(xfi->display, xfi->gc, color);
@ -550,10 +554,11 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
uint32 color; uint32 color;
XPoint* points; XPoint* points;
int width, height; int width, height;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
xf_set_rop2(xfi, polyline->bRop2); 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, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XSetForeground(xfi->display, xfi->gc, color); XSetForeground(xfi->display, xfi->gc, color);
@ -636,13 +641,14 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
uint32 foreColor; uint32 foreColor;
uint32 backColor; uint32 backColor;
Pixmap pattern = 0; Pixmap pattern = 0;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
brush = &mem3blt->brush; brush = &mem3blt->brush;
bitmap = (xfBitmap*) mem3blt->bitmap; bitmap = (xfBitmap*) mem3blt->bitmap;
xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop)); xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop));
foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, xfi->srcBpp, 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, xfi->srcBpp, 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) if (brush->style == GDI_BS_PATTERN)
{ {
@ -711,7 +717,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
xfInfo* xfi = ((xfContext*) context)->xfi; xfInfo* xfi = ((xfContext*) context)->xfi;
xf_set_rop2(xfi, polygon_sc->bRop2); 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; npoints = polygon_sc->numPoints + 1;
points = xmalloc(sizeof(XPoint) * npoints); points = xmalloc(sizeof(XPoint) * npoints);
@ -768,8 +774,8 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
brush = &(polygon_cb->brush); brush = &(polygon_cb->brush);
xf_set_rop2(xfi, polygon_cb->bRop2); xf_set_rop2(xfi, polygon_cb->bRop2);
foreColor = freerdp_color_convert_rgb(polygon_cb->foreColor, 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, xfi->srcBpp, 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; npoints = polygon_cb->numPoints + 1;
points = xmalloc(sizeof(XPoint) * npoints); points = xmalloc(sizeof(XPoint) * npoints);

View File

@ -35,7 +35,8 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
uint8* data; uint8* data;
Pixmap pixmap; Pixmap pixmap;
XImage* image; XImage* image;
xfInfo* xfi = ((xfContext*) context)->xfi; xfContext* context_ = (xfContext*) context;
xfInfo* xfi = context_->xfi;
XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFunction(xfi->display, xfi->gc, GXcopy);
pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth); 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) if (bitmap->data != NULL)
{ {
data = freerdp_image_convert(bitmap->data, NULL, data = freerdp_image_convert(bitmap->data, NULL,
bitmap->width, bitmap->height, xfi->srcBpp, xfi->bpp, xfi->clrconv); bitmap->width, bitmap->height, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
if (bitmap->ephemeral != true) if (bitmap->ephemeral != true)
{ {
@ -60,7 +61,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
{ {
if (data != bitmap->data) if (data != bitmap->data)
xfree(bitmap->data); xfree(bitmap->data);
bitmap->data = data; bitmap->data = data;
} }
} }
@ -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) 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)? bgcolor = (xfi->clrconv->invert)?
freerdp_color_convert_var_bgr(bgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv): freerdp_color_convert_var_bgr(bgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv):
freerdp_color_convert_var_rgb(bgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv); freerdp_color_convert_var_rgb(bgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
fgcolor = (xfi->clrconv->invert)? fgcolor = (xfi->clrconv->invert)?
freerdp_color_convert_var_bgr(fgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv): freerdp_color_convert_var_bgr(fgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv):
freerdp_color_convert_var_rgb(fgcolor, xfi->srcBpp, xfi->bpp, xfi->clrconv); freerdp_color_convert_var_rgb(fgcolor, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid); XSetFillStyle(xfi->display, xfi->gc, FillSolid);

View File

@ -269,7 +269,8 @@ struct rdp_settings
ALIGN64 uint32 encryption_level; /* 28 */ ALIGN64 uint32 encryption_level; /* 28 */
ALIGN64 boolean authentication; /* 29 */ ALIGN64 boolean authentication; /* 29 */
ALIGN64 uint32 negotiationFlags; /* 30 */ ALIGN64 uint32 negotiationFlags; /* 30 */
ALIGN64 uint64 paddingB[48 - 31]; /* 31 */ ALIGN64 boolean security_layer_negotiation; /* 31 */
ALIGN64 uint64 paddingB[48 - 32]; /* 32 */
/* Connection Settings */ /* Connection Settings */
ALIGN64 uint32 port; /* 48 */ ALIGN64 uint32 port; /* 48 */
@ -295,7 +296,10 @@ struct rdp_settings
ALIGN64 boolean local; /* 68 */ ALIGN64 boolean local; /* 68 */
ALIGN64 boolean authentication_only; /* 69 */ ALIGN64 boolean authentication_only; /* 69 */
ALIGN64 boolean from_stdin; /* 70 */ 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 */ /* User Interface Parameters */
ALIGN64 boolean sw_gdi; /* 80 */ ALIGN64 boolean sw_gdi; /* 80 */

View File

@ -21,6 +21,7 @@
#include "input.h" #include "input.h"
#include "connection.h" #include "connection.h"
#include "transport.h"
#include <freerdp/errorcodes.h> #include <freerdp/errorcodes.h>
@ -63,13 +64,16 @@
boolean rdp_client_connect(rdpRdp* rdp) boolean rdp_client_connect(rdpRdp* rdp)
{ {
boolean status;
uint32 selectedProtocol;
rdpSettings* settings = rdp->settings; rdpSettings* settings = rdp->settings;
nego_init(rdp->nego); nego_init(rdp->nego);
nego_set_target(rdp->nego, settings->hostname, settings->port); nego_set_target(rdp->nego, settings->hostname, settings->port);
nego_set_cookie(rdp->nego, settings->username); 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); nego_enable_rdp(rdp->nego, settings->rdp_security);
if (!settings->ts_gateway) if (!settings->ts_gateway)
@ -78,36 +82,23 @@ boolean rdp_client_connect(rdpRdp* rdp)
nego_enable_tls(rdp->nego, settings->tls_security); nego_enable_tls(rdp->nego, settings->tls_security);
} }
if (nego_connect(rdp->nego) != true) if (!nego_connect(rdp->nego))
{ {
printf("Error: protocol security negotiation failure\n"); printf("Error: protocol security negotiation or connection failure\n");
return false; return false;
} }
selectedProtocol = rdp->nego->selected_protocol; if ((rdp->nego->selected_protocol & PROTOCOL_TLS) || (rdp->nego->selected_protocol == PROTOCOL_RDP))
if ((selectedProtocol & PROTOCOL_TLS) || (selectedProtocol == PROTOCOL_RDP))
{ {
if ((settings->username != NULL) && ((settings->password != NULL) || (settings->password_cookie != NULL && settings->password_cookie->length > 0))) if ((settings->username != NULL) && ((settings->password != NULL) || (settings->password_cookie != NULL && settings->password_cookie->length > 0)))
settings->autologon = true; 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;
rdp_set_blocking_mode(rdp, false); rdp_set_blocking_mode(rdp, false);
rdp->state = CONNECTION_STATE_NEGO; rdp->state = CONNECTION_STATE_NEGO;
rdp->finalize_sc_pdus = 0; rdp->finalize_sc_pdus = 0;
if (mcs_send_connect_initial(rdp->mcs) != true) if (!mcs_send_connect_initial(rdp->mcs))
{ {
if (!connectErrorCode) if (!connectErrorCode)
{ {

View File

@ -25,7 +25,6 @@
#include "tpdu.h" #include "tpdu.h"
#include "nego.h" #include "nego.h"
#include "mcs.h" #include "mcs.h"
#include "transport.h"
#include "activation.h" #include "activation.h"
#include <freerdp/settings.h> #include <freerdp/settings.h>

View File

@ -42,6 +42,24 @@
#define FASTPATH_MAX_PACKET_SIZE 0x3FFF #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. * The fastpath header may be two or three bytes long.
* This function assumes that at least two bytes are available in the stream * 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; rdpContext* context = fastpath->rdp->update->context;
rdpPointerUpdate* pointer = update->pointer; 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) switch (updateCode)
{ {
case FASTPATH_UPDATETYPE_ORDERS: case FASTPATH_UPDATETYPE_ORDERS:

View File

@ -27,6 +27,8 @@
#include "nego.h" #include "nego.h"
#include "transport.h"
static const char* const NEGO_STATE_STRINGS[] = static const char* const NEGO_STATE_STRINGS[] =
{ {
"NEGO_STATE_INITIAL", "NEGO_STATE_INITIAL",
@ -44,6 +46,8 @@ static const char PROTOCOL_SECURITY_STRINGS[3][4] =
"NLA" "NLA"
}; };
boolean nego_security_connect(rdpNego* nego);
/** /**
* Negotiate protocol security and connect. * Negotiate protocol security and connect.
* @param nego * @param nego
@ -61,7 +65,31 @@ boolean nego_connect(rdpNego* nego)
else if (nego->enabled_protocols[PROTOCOL_RDP] > 0) else if (nego->enabled_protocols[PROTOCOL_RDP] > 0)
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
else else
{
DEBUG_NEGO("No security protocol is enabled");
nego->state = NEGO_STATE_FAIL; 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;
}
if(!nego_send_preconnection_pdu(nego))
{
DEBUG_NEGO("Failed to send preconnection information");
nego->state = NEGO_STATE_FINAL;
return false;
}
} }
do do
@ -93,9 +121,35 @@ boolean nego_connect(rdpNego* nego)
nego->transport->settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; 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; 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. * Connect TCP layer.
* @param nego * @param nego
@ -104,21 +158,25 @@ boolean nego_connect(rdpNego* nego)
boolean nego_tcp_connect(rdpNego* nego) boolean nego_tcp_connect(rdpNego* nego)
{ {
if (nego->tcp_connected == 0) if (!nego->tcp_connected)
{ nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
if (transport_connect(nego->transport, nego->hostname, nego->port) == false) return nego->tcp_connected;
{ }
nego->tcp_connected = 0;
return false;
}
else
{
nego->tcp_connected = 1;
return true;
}
}
return true; /**
* 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)
return nego_security_connect(nego);
return nego->tcp_connected;
} }
/** /**
@ -127,15 +185,65 @@ boolean nego_tcp_connect(rdpNego* nego)
* @return * @return
*/ */
int nego_tcp_disconnect(rdpNego* nego) int nego_transport_disconnect(rdpNego* nego)
{ {
if (nego->tcp_connected) if (nego->tcp_connected)
transport_disconnect(nego->transport); transport_disconnect(nego->transport);
nego->tcp_connected = 0; nego->tcp_connected = 0;
nego->security_connected = 0;
return 1; 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. * Attempt negotiating NLA + TLS security.
* @param nego * @param nego
@ -147,7 +255,7 @@ void nego_attempt_nla(rdpNego* nego)
DEBUG_NEGO("Attempting NLA security"); DEBUG_NEGO("Attempting NLA security");
if (!nego_tcp_connect(nego)) if (!nego_transport_connect(nego))
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
return; return;
@ -168,7 +276,7 @@ void nego_attempt_nla(rdpNego* nego)
DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]); DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]);
if (nego->state != NEGO_STATE_FINAL) if (nego->state != NEGO_STATE_FINAL)
{ {
nego_tcp_disconnect(nego); nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_TLS] > 0) if (nego->enabled_protocols[PROTOCOL_TLS] > 0)
nego->state = NEGO_STATE_TLS; nego->state = NEGO_STATE_TLS;
@ -190,7 +298,7 @@ void nego_attempt_tls(rdpNego* nego)
DEBUG_NEGO("Attempting TLS security"); DEBUG_NEGO("Attempting TLS security");
if (!nego_tcp_connect(nego)) if (!nego_transport_connect(nego))
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
return; return;
@ -210,7 +318,7 @@ void nego_attempt_tls(rdpNego* nego)
if (nego->state != NEGO_STATE_FINAL) if (nego->state != NEGO_STATE_FINAL)
{ {
nego_tcp_disconnect(nego); nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_RDP] > 0) if (nego->enabled_protocols[PROTOCOL_RDP] > 0)
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
@ -230,7 +338,7 @@ void nego_attempt_rdp(rdpNego* nego)
DEBUG_NEGO("Attempting RDP security"); DEBUG_NEGO("Attempting RDP security");
if (!nego_tcp_connect(nego)) if (!nego_transport_connect(nego))
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
return; return;
@ -261,7 +369,7 @@ boolean nego_recv_response(rdpNego* nego)
if (transport_read(nego->transport, s) < 0) if (transport_read(nego->transport, s) < 0)
return false; return false;
return nego_recv(nego->transport, s, nego->transport->recv_extra); return nego_recv(nego->transport, s, nego);
} }
/** /**
@ -704,6 +812,18 @@ void nego_set_target(rdpNego* nego, char* hostname, int port)
nego->port = 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. * Enable RDP security protocol.
* @param nego pointer to the negotiation structure * @param nego pointer to the negotiation structure
@ -761,3 +881,36 @@ void nego_set_cookie(rdpNego* nego, char* cookie)
{ {
nego->cookie = 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;
}

View File

@ -68,24 +68,40 @@ enum RDP_NEG_MSG
#define EXTENDED_CLIENT_DATA_SUPPORTED 0x01 #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 struct rdp_nego
{ {
int port; int port;
uint32 flags; uint32 flags;
char* hostname; char* hostname;
char* cookie; char* cookie;
NEGO_STATE state;
int tcp_connected;
rdpBlob* routing_token; rdpBlob* routing_token;
boolean send_preconnection_pdu;
uint32 preconnection_id;
char* preconnection_blob;
NEGO_STATE state;
boolean tcp_connected;
boolean security_connected;
uint32 selected_protocol; uint32 selected_protocol;
uint32 requested_protocols; uint32 requested_protocols;
boolean security_layer_negotiation_enabled;
uint8 enabled_protocols[3]; uint8 enabled_protocols[3];
rdpTransport* transport; rdpTransport* transport;
}; };
typedef struct rdp_nego rdpNego; typedef struct rdp_nego rdpNego;
boolean nego_connect(rdpNego* nego); boolean nego_connect(rdpNego* nego);
boolean nego_send_preconnection_pdu(rdpNego* nego);
void nego_attempt_nla(rdpNego* nego); void nego_attempt_nla(rdpNego* nego);
void nego_attempt_tls(rdpNego* nego); void nego_attempt_tls(rdpNego* nego);
void nego_attempt_rdp(rdpNego* nego); void nego_attempt_rdp(rdpNego* nego);
@ -105,11 +121,15 @@ rdpNego* nego_new(struct rdp_transport * transport);
void nego_free(rdpNego* nego); void nego_free(rdpNego* nego);
void nego_init(rdpNego* nego); void nego_init(rdpNego* nego);
void nego_set_target(rdpNego* nego, char* hostname, int port); 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_rdp(rdpNego* nego, boolean enable_rdp);
void nego_enable_nla(rdpNego* nego, boolean enable_nla); void nego_enable_nla(rdpNego* nego, boolean enable_nla);
void nego_enable_tls(rdpNego* nego, boolean enable_tls); void nego_enable_tls(rdpNego* nego, boolean enable_tls);
void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token); void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token);
void nego_set_cookie(rdpNego* nego, char* cookie); 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 #ifdef WITH_DEBUG_NEGO
#define DEBUG_NEGO(fmt, ...) DEBUG_CLASS(NEGO, fmt, ## __VA_ARGS__) #define DEBUG_NEGO(fmt, ...) DEBUG_CLASS(NEGO, fmt, ## __VA_ARGS__)

View File

@ -97,6 +97,7 @@ rdpSettings* settings_new(void* instance)
settings->nla_security = true; settings->nla_security = true;
settings->tls_security = true; settings->tls_security = true;
settings->rdp_security = true; settings->rdp_security = true;
settings->security_layer_negotiation = true;
settings->client_build = 2600; settings->client_build = 2600;
settings->kbd_type = 4; /* @msdn{cc240510} 'IBM enhanced (101- or 102-key) keyboard' */ settings->kbd_type = 4; /* @msdn{cc240510} 'IBM enhanced (101- or 102-key) keyboard' */
settings->kbd_subtype = 0; settings->kbd_subtype = 0;

View File

@ -122,6 +122,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
" --disable-full-window-drag: disables full window drag\n" " --disable-full-window-drag: disables full window drag\n"
" --disable-menu-animations: disables menu animations\n" " --disable-menu-animations: disables menu animations\n"
" --disable-theming: disables theming\n" " --disable-theming: disables theming\n"
" --no-nego: disable negotiation of security layer and enforce highest enabled security protocol\n"
" --no-rdp: disable Standard RDP encryption\n" " --no-rdp: disable Standard RDP encryption\n"
" --no-tls: disable TLS encryption\n" " --no-tls: disable TLS encryption\n"
" --no-nla: disable network level authentication\n" " --no-nla: disable network level authentication\n"
@ -132,6 +133,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
" --tsg: Terminal Server Gateway (<username> <password> <hostname>)\n" " --tsg: Terminal Server Gateway (<username> <password> <hostname>)\n"
" --kbd-list: list all keyboard layout ids used by -k\n" " --kbd-list: list all keyboard layout ids used by -k\n"
" --no-salted-checksum: disable salted checksums with Standard RDP encryption\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" " --version: print version information\n"
"\n", argv[0]); "\n", argv[0]);
return FREERDP_ARGS_PARSE_HELP; /* TODO: What is the correct return? */ return FREERDP_ARGS_PARSE_HELP; /* TODO: What is the correct return? */
@ -579,6 +582,10 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
return FREERDP_ARGS_PARSE_FAILURE; return FREERDP_ARGS_PARSE_FAILURE;
} }
} }
else if (strcmp("--no-nego", argv[index]) == 0)
{
settings->security_layer_negotiation = false;
}
else if (strcmp("--tsg", argv[index]) == 0) else if (strcmp("--tsg", argv[index]) == 0)
{ {
settings->ts_gateway = true; settings->ts_gateway = true;
@ -698,6 +705,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
{ {
settings->salted_checksum = false; 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) else if (strcmp("--version", argv[index]) == 0)
{ {
printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL); printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL);