Merge branch 'master' of github.com:FreeRDP/FreeRDP into winpr
This commit is contained in:
commit
984a8c97a3
@ -4,4 +4,8 @@ To create your own virtual channel plugin, copy this directory
|
||||
then change all references of "skel" to your plugin name
|
||||
remember, plugin name are 7 chars or less, no spaces or funny chars
|
||||
|
||||
server_chan_test.cpp is an example of how to open a channel to the client
|
||||
this code needs to be compiled and run on the server in an rdp session
|
||||
when connect with a client that has the "skel" plugin loaded
|
||||
|
||||
Jay
|
||||
|
60
channels/skel/server_chan_test.cpp
Normal file
60
channels/skel/server_chan_test.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// xrdp_chan_test.cpp : Basic test for virtual channel use.
|
||||
|
||||
// These headers are required for the windows terminal service calls.
|
||||
#include "windows.h"
|
||||
#include "wtsapi32.h"
|
||||
#include <string>
|
||||
|
||||
#define DSIZE 1024
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize the data for send/receive
|
||||
char* data;
|
||||
char* data1;
|
||||
data = (char*)malloc(DSIZE);
|
||||
data1 = (char*)malloc(DSIZE);
|
||||
memset(data, 0xca, DSIZE);
|
||||
memset(data1, 0, DSIZE);
|
||||
|
||||
// Open the skel channel in current session
|
||||
void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0);
|
||||
|
||||
unsigned long written = 0;
|
||||
// Write the data to the channel
|
||||
bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written);
|
||||
if (!ret)
|
||||
{
|
||||
long err = GetLastError();
|
||||
printf("error 0x%8.8x\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written);
|
||||
if (!ret)
|
||||
{
|
||||
long err = GetLastError();
|
||||
printf("error 0x%8.8x\n", err);
|
||||
return 1;
|
||||
}
|
||||
if (written != DSIZE)
|
||||
{
|
||||
printf("error read %d\n", written);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = WTSVirtualChannelClose(channel);
|
||||
if (memcmp(data, data1, DSIZE) == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error data no match\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Success!\n");
|
||||
|
||||
Sleep(2000);
|
||||
return 0;
|
||||
}
|
@ -58,19 +58,25 @@ static void skel_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||
|
||||
if (skel == NULL)
|
||||
{
|
||||
printf("skel_process_receive: skel is nil\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* process data in(from server) here */
|
||||
/* here we just send the same data back */
|
||||
|
||||
bytes = stream_get_length(data_in);
|
||||
bytes = stream_get_size(data_in);
|
||||
printf("skel_process_receive: got bytes %d\n", bytes);
|
||||
if (bytes > 0)
|
||||
{
|
||||
data_out = stream_new(bytes);
|
||||
stream_copy(data_out, data_in, bytes);
|
||||
/* svc_plugin_send takes ownership of data_out, that is why
|
||||
we do not free it */
|
||||
|
||||
bytes = stream_get_length(data_in);
|
||||
printf("skel_process_receive: sending bytes %d\n", bytes);
|
||||
|
||||
svc_plugin_send(plugin, data_out);
|
||||
}
|
||||
|
||||
|
@ -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, 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, 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, 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);
|
||||
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, 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);
|
||||
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, 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);
|
||||
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, 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);
|
||||
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, 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, 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)
|
||||
{
|
||||
@ -711,7 +717,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 +774,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);
|
||||
|
@ -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, xfi->srcBpp, xfi->bpp, xfi->clrconv);
|
||||
bitmap->width, bitmap->height, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
|
||||
|
||||
if (bitmap->ephemeral != true)
|
||||
{
|
||||
@ -60,7 +61,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
if (data != bitmap->data)
|
||||
xfree(bitmap->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)
|
||||
{
|
||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||
xfContext* context_ = (xfContext*) context;
|
||||
xfInfo* xfi = 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, 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, xfi->srcBpp, xfi->bpp, xfi->clrconv):
|
||||
freerdp_color_convert_var_rgb(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, context_->settings->color_depth, xfi->bpp, xfi->clrconv);
|
||||
|
||||
XSetFunction(xfi->display, xfi->gc, GXcopy);
|
||||
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
|
||||
|
@ -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 */
|
||||
@ -295,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 */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "input.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "transport.h"
|
||||
|
||||
#include <freerdp/errorcodes.h>
|
||||
|
||||
@ -63,13 +64,16 @@
|
||||
|
||||
boolean rdp_client_connect(rdpRdp* rdp)
|
||||
{
|
||||
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_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);
|
||||
|
||||
if (!settings->ts_gateway)
|
||||
@ -78,36 +82,23 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
||||
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;
|
||||
}
|
||||
|
||||
selectedProtocol = rdp->nego->selected_protocol;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "tpdu.h"
|
||||
#include "nego.h"
|
||||
#include "mcs.h"
|
||||
#include "transport.h"
|
||||
#include "activation.h"
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
|
@ -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:
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "nego.h"
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
static const char* const NEGO_STATE_STRINGS[] =
|
||||
{
|
||||
"NEGO_STATE_INITIAL",
|
||||
@ -44,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
|
||||
@ -61,7 +65,31 @@ 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;
|
||||
}
|
||||
|
||||
if(!nego_send_preconnection_pdu(nego))
|
||||
{
|
||||
DEBUG_NEGO("Failed to send preconnection information");
|
||||
nego->state = NEGO_STATE_FINAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
@ -93,9 +121,35 @@ 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;
|
||||
}
|
||||
|
||||
/* 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 +158,25 @@ boolean nego_connect(rdpNego* nego)
|
||||
|
||||
boolean nego_tcp_connect(rdpNego* nego)
|
||||
{
|
||||
if (nego->tcp_connected == 0)
|
||||
{
|
||||
if (transport_connect(nego->transport, nego->hostname, nego->port) == false)
|
||||
{
|
||||
nego->tcp_connected = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nego->tcp_connected = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!nego->tcp_connected)
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
return nego->tcp_connected;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -147,7 +255,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 +276,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 +298,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 +318,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 +338,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;
|
||||
@ -261,7 +369,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -704,6 +812,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
|
||||
@ -761,3 +881,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;
|
||||
}
|
||||
|
@ -68,24 +68,40 @@ 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;
|
||||
NEGO_STATE state;
|
||||
int tcp_connected;
|
||||
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 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_send_preconnection_pdu(rdpNego* nego);
|
||||
|
||||
void nego_attempt_nla(rdpNego* nego);
|
||||
void nego_attempt_tls(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_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);
|
||||
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__)
|
||||
|
@ -135,6 +135,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;
|
||||
|
@ -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"
|
||||
" --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"
|
||||
@ -132,6 +133,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
" --tsg: Terminal Server Gateway (<username> <password> <hostname>)\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? */
|
||||
@ -579,6 +582,10 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
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)
|
||||
{
|
||||
settings->ts_gateway = true;
|
||||
@ -698,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);
|
||||
|
@ -360,6 +360,6 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
||||
NTLM_AV_PAIR* AvEOL;
|
||||
|
||||
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
|
||||
ZeroMemory((void*) AvEOL, 12);
|
||||
ZeroMemory((void*) AvEOL, 4);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user