Merge pull request #2484 from dvincent-devolutions/gateway

RDP8 Gateway support
This commit is contained in:
Marc-André Moreau 2015-03-19 12:21:56 -04:00
commit 3a2a915221
21 changed files with 2116 additions and 51 deletions

View File

@ -78,6 +78,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
{ "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
{ "gt", COMMAND_LINE_VALUE_REQUIRED, "<rpc|http|auto>", NULL, NULL, -1, NULL, "Gateway transport type" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
{ "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
@ -1511,6 +1512,24 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->GatewayPassword = _strdup(arg->Value);
settings->GatewayUseSameCredentials = FALSE;
}
CommandLineSwitchCase(arg, "gt")
{
if (_stricmp(arg->Value, "rpc") == 0)
{
settings->GatewayRpcTransport = TRUE;
settings->GatewayHttpTransport = FALSE;
}
else if (_stricmp(arg->Value, "http") == 0)
{
settings->GatewayRpcTransport = FALSE;
settings->GatewayHttpTransport = TRUE;
}
else if (_stricmp(arg->Value, "auto") == 0)
{
settings->GatewayRpcTransport = TRUE;
settings->GatewayHttpTransport = TRUE;
}
}
CommandLineSwitchCase(arg, "gateway-usage-method")
{
int type;

View File

@ -692,6 +692,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_GatewayUseSameCredentials 1991
#define FreeRDP_GatewayEnabled 1992
#define FreeRDP_GatewayBypassLocal 1993
#define FreeRDP_GatewayRpcTransport 1994
#define FreeRDP_GatewayHttpTransport 1995
#define FreeRDP_GatewayUdpTransport 1996
#define FreeRDP_RemoteApplicationMode 2112
#define FreeRDP_RemoteApplicationName 2113
#define FreeRDP_RemoteApplicationIcon 2114
@ -1129,7 +1132,10 @@ struct rdp_settings
ALIGN64 BOOL GatewayUseSameCredentials; /* 1991 */
ALIGN64 BOOL GatewayEnabled; /* 1992 */
ALIGN64 BOOL GatewayBypassLocal; /* 1993 */
UINT64 padding2048[2048 - 1994]; /* 1994 */
ALIGN64 BOOL GatewayRpcTransport; /* 1994 */
ALIGN64 BOOL GatewayHttpTransport; /* 1995 */
ALIGN64 BOOL GatewayUdpTransport; /* 1996 */
UINT64 padding2048[2048 - 1997]; /* 1997 */
UINT64 padding2112[2112 - 2048]; /* 2048 */
/**

View File

@ -1629,6 +1629,168 @@ void freerdp_clrconv_free(HCLRCONV clrconv)
}
}
int freerdp_image1_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette)
{
int x, y;
int nSrcPad;
int nDstPad;
int nAlignedWidth;
int dstBitsPerPixel;
int dstBytesPerPixel;
BOOL vFlip = FALSE;
BOOL invert = FALSE;
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(DstFormat);
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(DstFormat) / 8);
nAlignedWidth = nWidth + nWidth % 8;
if (nSrcStep < 0)
nSrcStep = nAlignedWidth / 8;
if (nDstStep < 0)
nDstStep = dstBytesPerPixel * nWidth;
nSrcPad = (nSrcStep - (nAlignedWidth / 8));
nDstPad = (nDstStep - (nWidth * dstBytesPerPixel));
if (FREERDP_PIXEL_FORMAT_IS_ABGR(DstFormat))
invert = TRUE;
if (FREERDP_PIXEL_FORMAT_FLIP(DstFormat) == FREERDP_PIXEL_FLIP_VERTICAL)
vFlip = TRUE;
if (dstBytesPerPixel == 4)
{
BYTE SrcPixel;
BYTE* pSrcPixel;
UINT32* pDstPixel;
if (!invert)
{
if (!vFlip)
{
pSrcPixel = &pSrcData[nYSrc * nSrcStep];
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
for (x = 0; x < nWidth / 8; x++)
{
SrcPixel = *pSrcPixel;
pDstPixel[0] = (SrcPixel & 0x80) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[1] = (SrcPixel & 0x40) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[2] = (SrcPixel & 0x20) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[3] = (SrcPixel & 0x10) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[4] = (SrcPixel & 0x08) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[5] = (SrcPixel & 0x04) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[6] = (SrcPixel & 0x02) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel[7] = (SrcPixel & 0x01) ? 0xFFFFFFFF : 0xFF000000;
pDstPixel += 8;
pSrcPixel++;
}
if (nWidth % 8)
{
SrcPixel = *pSrcPixel;
for (x = 0; x < nWidth % 8; x++)
{
*pDstPixel = (SrcPixel & 0x80) ? 0xFFFFFFFF : 0xFF000000;
SrcPixel <<= 1;
pDstPixel++;
}
pSrcPixel++;
}
pSrcPixel += nSrcPad;
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
}
}
}
return 1;
}
return 1;
}
int freerdp_image4_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette)
{
int x, y;
int nSrcPad;
int nDstPad;
int nAlignedWidth;
int dstBitsPerPixel;
int dstBytesPerPixel;
BOOL vFlip = FALSE;
BOOL invert = FALSE;
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(DstFormat);
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(DstFormat) / 8);
nAlignedWidth = nWidth + (nWidth % 2);
if (nSrcStep < 0)
nSrcStep = nAlignedWidth / 2;
if (nDstStep < 0)
nDstStep = dstBytesPerPixel * nWidth;
nSrcPad = (nSrcStep - (nAlignedWidth / 2));
nDstPad = (nDstStep - (nWidth * dstBytesPerPixel));
if (FREERDP_PIXEL_FORMAT_IS_ABGR(DstFormat))
invert = TRUE;
if (FREERDP_PIXEL_FORMAT_FLIP(DstFormat) == FREERDP_PIXEL_FLIP_VERTICAL)
vFlip = TRUE;
if (dstBytesPerPixel == 4)
{
BYTE* pSrcPixel;
UINT32* pDstPixel;
UINT32* values = (UINT32*) palette;
if (!invert)
{
if (!vFlip)
{
pSrcPixel = &pSrcData[nYSrc * nSrcStep];
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
for (x = 0; x < nWidth / 2; x++)
{
pDstPixel[0] = values[*pSrcPixel >> 4];
pDstPixel[1] = values[*pSrcPixel & 0xF];
pDstPixel += 2;
pSrcPixel++;
}
if (nWidth % 2)
{
pDstPixel[0] = values[*pSrcPixel >> 4];
pDstPixel++;
pSrcPixel++;
}
pSrcPixel += nSrcPad;
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
}
}
}
return 1;
}
return 1;
}
int freerdp_image8_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette)
{
@ -3312,6 +3474,16 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
status = freerdp_image8_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette);
}
else if (srcBitsPerPixel == 1)
{
status = freerdp_image1_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette);
}
else if (srcBitsPerPixel == 4)
{
status = freerdp_image4_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette);
}
if (status < 0)
{

View File

@ -936,6 +936,15 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
case FreeRDP_GatewayBypassLocal:
return settings->GatewayBypassLocal;
case FreeRDP_GatewayRpcTransport:
return settings->GatewayRpcTransport;
case FreeRDP_GatewayHttpTransport:
return settings->GatewayHttpTransport;
case FreeRDP_GatewayUdpTransport:
return settings->GatewayUdpTransport;
case FreeRDP_RemoteApplicationMode:
return settings->RemoteApplicationMode;
@ -1396,6 +1405,18 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->GatewayBypassLocal = param;
break;
case FreeRDP_GatewayRpcTransport:
settings->GatewayRpcTransport = param;
break;
case FreeRDP_GatewayHttpTransport:
settings->GatewayHttpTransport = param;
break;
case FreeRDP_GatewayUdpTransport:
settings->GatewayUdpTransport = param;
break;
case FreeRDP_RemoteApplicationMode:
settings->RemoteApplicationMode = param;
break;

View File

@ -28,6 +28,8 @@ set(${MODULE_PREFIX}_GATEWAY_DIR "gateway")
set(${MODULE_PREFIX}_GATEWAY_SRCS
${${MODULE_PREFIX}_GATEWAY_DIR}/tsg.c
${${MODULE_PREFIX}_GATEWAY_DIR}/tsg.h
${${MODULE_PREFIX}_GATEWAY_DIR}/rdg.c
${${MODULE_PREFIX}_GATEWAY_DIR}/rdg.h
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc.c
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc.h
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_bind.c

View File

@ -174,6 +174,17 @@ BOOL http_context_set_pragma(HttpContext* context, const char* Pragma)
return TRUE;
}
BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgConnectionId)
{
free(context->RdgConnectionId);
context->RdgConnectionId = _strdup(RdgConnectionId);
if (!context->RdgConnectionId)
return FALSE;
return TRUE;
}
void http_context_free(HttpContext* context)
{
if (context)
@ -186,6 +197,7 @@ void http_context_free(HttpContext* context)
free(context->CacheControl);
free(context->Connection);
free(context->Pragma);
free(context->RdgConnectionId);
free(context);
}
}
@ -234,6 +246,17 @@ BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam)
return TRUE;
}
BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* TransferEncoding)
{
free(request->TransferEncoding);
request->TransferEncoding = _strdup(TransferEncoding);
if (!request->TransferEncoding)
return FALSE;
return TRUE;
}
char* http_encode_body_line(char* param, char* value)
{
char* line;
@ -325,6 +348,26 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request)
goto out_free;
}
if (context->RdgConnectionId)
{
lines[count] = http_encode_body_line("RDG-Connection-Id", context->RdgConnectionId);
if (!lines[count])
goto out_free;
count++;
}
if (request->TransferEncoding)
{
lines[count] = http_encode_body_line("Transfer-Encoding", request->TransferEncoding);
if (!lines[count])
goto out_free;
count++;
}
if (request->Authorization)
{
lines[count] = http_encode_body_line("Authorization", request->Authorization);
@ -403,6 +446,9 @@ void http_request_free(HttpRequest* request)
free(request->Content);
free(request->Method);
free(request->URI);
free(request->TransferEncoding);
free(request);
}
@ -589,7 +635,7 @@ HttpResponse* http_response_recv(rdpTls* tls)
int payloadOffset;
HttpResponse* response;
size = 1024;
size = 2048;
payload = NULL;
payloadOffset = 0;
@ -716,11 +762,17 @@ HttpResponse* http_response_recv(rdpTls* tls)
if (response->ContentType)
{
if (_stricmp(response->ContentType, "text/plain") == 0)
if (_stricmp(response->ContentType, "application/rpc") != 0)
bodyLength = response->ContentLength;
else if (_stricmp(response->ContentType, "text/plain") == 0)
bodyLength = response->ContentLength;
else if (_stricmp(response->ContentType, "text/html") == 0)
bodyLength = response->ContentLength;
}
else
{
bodyLength = response->BodyLength;
}
if (bodyLength != response->BodyLength)
{
@ -786,8 +838,11 @@ void http_response_free(HttpResponse* response)
ListDictionary_Free(response->Authenticates);
if (response->ContentLength > 0)
if (response->BodyContent)
{
free(response->BodyContent);
response->BodyContent = NULL;
}
free(response);
}

View File

@ -40,6 +40,7 @@ struct _http_context
char* CacheControl;
char* Connection;
char* Pragma;
char* RdgConnectionId;
};
BOOL http_context_set_method(HttpContext* context, const char* Method);
@ -50,6 +51,7 @@ BOOL http_context_set_accept(HttpContext* context, const char* Accept);
BOOL http_context_set_cache_control(HttpContext* context, const char* CacheControl);
BOOL http_context_set_connection(HttpContext* context, const char* Connection);
BOOL http_context_set_pragma(HttpContext* context, const char* Pragma);
BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgConnectionId);
HttpContext* http_context_new(void);
void http_context_free(HttpContext* context);
@ -63,12 +65,14 @@ struct _http_request
char* Authorization;
int ContentLength;
char* Content;
char* TransferEncoding;
};
BOOL http_request_set_method(HttpRequest* request, const char* Method);
BOOL http_request_set_uri(HttpRequest* request, const char* URI);
BOOL http_request_set_auth_scheme(HttpRequest* request, const char* AuthScheme);
BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam);
BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* TransferEncoding);
wStream* http_request_write(HttpContext* context, HttpRequest* request);

View File

@ -302,5 +302,7 @@ void ntlm_free(rdpNtlm* ntlm)
ntlm->outputBuffer[0].pvBuffer = NULL;
}
ntlm_client_uninit(ntlm);
free(ntlm);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Desktop Gateway (RDG)
*
* Copyright 2015 Denis Vincent <dvincent@devolutions.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CORE_RDG_H
#define FREERDP_CORE_RDG_H
#include <winpr/wtypes.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <winpr/interlocked.h>
#include <freerdp/log.h>
#include <freerdp/utils/ringbuffer.h>
#include <freerdp/freerdp.h>
#include <freerdp/crypto/tls.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
typedef struct rdp_rdg rdpRdg;
#include "http.h"
#include "ntlm.h"
#include "../transport.h"
/* HTTP channel response fields present flags. */
#define HTTP_CHANNEL_RESPONSE_FIELD_CHANNELID 0x1
#define HTTP_CHANNEL_RESPONSE_OPTIONAL 0x2
#define HTTP_CHANNEL_RESPONSE_FIELD_UDPPORT 0x4
/* HTTP extended auth. */
#define HTTP_EXTENDED_AUTH_NONE 0x0
#define HTTP_EXTENDED_AUTH_SC 0x1 /* Smart card authentication. */
#define HTTP_EXTENDED_AUTH_PAA 0x02 /* Pluggable authentication. */
/* HTTP packet types. */
#define PKT_TYPE_HANDSHAKE_REQUEST 0x1
#define PKT_TYPE_HANDSHAKE_RESPONSE 0x2
#define PKT_TYPE_EXTENDED_AUTH_MSG 0x3
#define PKT_TYPE_TUNNEL_CREATE 0x4
#define PKT_TYPE_TUNNEL_RESPONSE 0x5
#define PKT_TYPE_TUNNEL_AUTH 0x6
#define PKT_TYPE_TUNNEL_AUTH_RESPONSE 0x7
#define PKT_TYPE_CHANNEL_CREATE 0x8
#define PKT_TYPE_CHANNEL_RESPONSE 0x9
#define PKT_TYPE_DATA 0xA
#define PKT_TYPE_SERVICE_MESSAGE 0xB
#define PKT_TYPE_REAUTH_MESSAGE 0xC
#define PKT_TYPE_KEEPALIVE 0xD
#define PKT_TYPE_CLOSE_CHANNEL 0x10
#define PKT_TYPE_CLOSE_CHANNEL_RESPONSE 0x11
/* HTTP tunnel auth fields present flags. */
#define HTTP_TUNNEL_AUTH_FIELD_SOH 0x1
/* HTTP tunnel auth response fields present flags. */
#define HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS 0x1
#define HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT 0x2
#define HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE 0x4
/* HTTP tunnel packet fields present flags. */
#define HTTP_TUNNEL_PACKET_FIELD_PAA_COOKIE 0x1
#define HTTP_TUNNEL_PACKET_FIELD_REAUTH 0x2
/* HTTP tunnel redir flags. */
#define HTTP_TUNNEL_REDIR_ENABLE_ALL 0x80000000
#define HTTP_TUNNEL_REDIR_DISABLE_ALL 0x40000000
#define HTTP_TUNNEL_REDIR_DISABLE_DRIVE 0x1
#define HTTP_TUNNEL_REDIR_DISABLE_PRINTER 0x2
#define HTTP_TUNNEL_REDIR_DISABLE_PORT 0x4
#define HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD 0x8
#define HTTP_TUNNEL_REDIR_DISABLE_PNP 0x10
/* HTTP tunnel response fields present flags. */
#define HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID 0x1
#define HTTP_TUNNEL_RESPONSE_FIELD_CAPS 0x2
#define HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ 0x4
#define HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG 0x10
/* HTTP capability type enumeration. */
#define HTTP_CAPABILITY_TYPE_QUAR_SOH 0x1
#define HTTP_CAPABILITY_IDLE_TIMEOUT 0x2
#define HTTP_CAPABILITY_MESSAGING_CONSENT_SIGN 0x4
#define HTTP_CAPABILITY_MESSAGING_SERVICE_MSG 0x8
#define HTTP_CAPABILITY_REAUTH 0x10
#define HTTP_CAPABILITY_UDP_TRANSPORT 0x20
enum
{
RDG_CLIENT_STATE_INITIAL,
RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST,
RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE,
RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED,
RDG_CLIENT_STATE_IN_CHANNEL_REQUEST,
RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE,
RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED,
RDG_CLIENT_STATE_HANDSHAKE,
RDG_CLIENT_STATE_TUNNEL_CREATE,
RDG_CLIENT_STATE_TUNNEL_AUTHORIZE,
RDG_CLIENT_STATE_CHANNEL_CREATE,
RDG_CLIENT_STATE_OPENED,
RDG_CLIENT_STATE_CLOSE,
RDG_CLIENT_STATE_CLOSED,
RDG_CLIENT_STATE_NOT_FOUND,
};
struct rdp_rdg
{
rdpContext* context;
rdpSettings* settings;
BIO* frontBio;
rdpTls* tlsIn;
rdpTls* tlsOut;
rdpNtlm* ntlm;
HttpContext* http;
HANDLE readEvent;
UUID guid;
int state;
UINT16 packetRemainingCount;
int nonBlocking;
int timeout;
};
rdpRdg* rdg_new(rdpTransport* transport);
void rdg_free(rdpRdg* rdg);
BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout);
UINT32 rdg_get_event_handles(rdpRdg* rdg, HANDLE* events);
BOOL rdg_check_event_handles(rdpRdg* rdg);
#endif /* FREERDP_CORE_RDG_H */

View File

@ -554,6 +554,10 @@ int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CH
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
break;
case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
str = "CLIENT_OUT_CHANNEL_STATE_RECYCLED";
break;
case CLIENT_OUT_CHANNEL_STATE_FINAL:
str = "CLIENT_OUT_CHANNEL_STATE_FINAL";
break;
@ -866,8 +870,6 @@ int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout)
int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
{
int status = 0;
HttpResponse* response = NULL;
rdpRpc* rpc = outChannel->rpc;
/* Connect OUT Channel */

View File

@ -448,16 +448,23 @@ int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
int rpc_client_default_out_channel_recv(rdpRpc* rpc)
{
int status = -1;
UINT32 statusCode;
HttpResponse* response;
RpcInChannel* inChannel;
RpcOutChannel* outChannel;
HANDLE outChannelEvent = NULL;
RpcVirtualConnection* connection = rpc->VirtualConnection;
inChannel = connection->DefaultInChannel;
outChannel = connection->DefaultOutChannel;
BIO_get_event(outChannel->tls->bio, &outChannelEvent);
if (outChannel->State < CLIENT_OUT_CHANNEL_STATE_OPENED)
{
if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
return 1;
response = http_response_recv(outChannel->tls);
if (!response)
@ -512,18 +519,23 @@ int rpc_client_default_out_channel_recv(rdpRpc* rpc)
{
/* Receive OUT channel response */
if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
return 1;
response = http_response_recv(outChannel->tls);
if (!response)
return -1;
if (response->StatusCode != HTTP_STATUS_OK)
statusCode = response->StatusCode;
if (statusCode != HTTP_STATUS_OK)
{
WLog_ERR(TAG, "error! Status Code: %d", response->StatusCode);
WLog_ERR(TAG, "error! Status Code: %d", statusCode);
http_response_print(response);
http_response_free(response);
if (response->StatusCode == HTTP_STATUS_DENIED)
if (statusCode == HTTP_STATUS_DENIED)
{
if (!freerdp_get_last_error(rpc->context))
freerdp_set_last_error(rpc->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
@ -634,22 +646,33 @@ int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
int status = -1;
HttpResponse* response;
RpcOutChannel* nextOutChannel;
HANDLE nextOutChannelEvent = NULL;
nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
BIO_get_event(nextOutChannel->tls->bio, &nextOutChannelEvent);
if (WaitForSingleObject(nextOutChannelEvent, 0) != WAIT_OBJECT_0)
return 1;
response = http_response_recv(nextOutChannel->tls);
if (response)
{
if (nextOutChannel->State == CLIENT_OUT_CHANNEL_STATE_SECURITY)
{
status = rpc_ncacn_http_recv_out_channel_response(rpc, nextOutChannel, response);
if (status >= 0)
{
status = rpc_ncacn_http_send_out_channel_request(rpc, nextOutChannel, TRUE);
if (status >= 0)
{
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*)nextOutChannel);
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) nextOutChannel);
status = rts_send_OUT_R1_A3_pdu(rpc);
if (status >= 0)
{
rpc_out_channel_transition_to_state(nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
@ -678,37 +701,31 @@ int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
int rpc_client_out_channel_recv(rdpRpc* rpc)
{
RpcOutChannel* outChannel;
RpcOutChannel* nextOutChannel;
int status;
RpcVirtualConnection* connection = rpc->VirtualConnection;
HANDLE outChannelEvent = NULL;
HANDLE nextOutChannelEvent = NULL;
outChannel = connection->DefaultOutChannel;
BIO_get_event(outChannel->tls->bio, &outChannelEvent);
if (WaitForSingleObject(outChannelEvent, 0) == WAIT_OBJECT_0)
if (connection->DefaultOutChannel)
{
return rpc_client_default_out_channel_recv(rpc);
status = rpc_client_default_out_channel_recv(rpc);
if (status < 0)
return -1;
}
nextOutChannel = connection->NonDefaultOutChannel;
if (nextOutChannel)
if (connection->NonDefaultOutChannel)
{
BIO_get_event(nextOutChannel->tls->bio, &nextOutChannelEvent);
status = rpc_client_nondefault_out_channel_recv(rpc);
if (WaitForSingleObject(nextOutChannelEvent, 0) == WAIT_OBJECT_0)
{
return rpc_client_nondefault_out_channel_recv(rpc);
}
if (status < 0)
return -1;
}
return 0;
return 1;
}
int rpc_client_in_channel_recv(rdpRpc* rpc)
{
int status = -1;
int status = 1;
HttpResponse* response;
RpcInChannel* inChannel;
RpcOutChannel* outChannel;
@ -773,6 +790,17 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
http_response_free(response);
}
else
{
response = http_response_recv(inChannel->tls);
if (!response)
return -1;
/* We can receive an unauthorized HTTP response on the IN channel */
http_response_free(response);
}
return status;
}

View File

@ -678,7 +678,7 @@ int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UI
offset += rts_flow_control_ack_command_read(rpc, &buffer[offset], length - offset,
&BytesReceived, &AvailableWindow, (BYTE*) &ChannelCookie) + 4;
WLog_ERR(TAG, "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %d AvailableWindow: %d",
WLog_DBG(TAG, "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %d AvailableWindow: %d",
BytesReceived, AvailableWindow);
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow =

View File

@ -1720,7 +1720,7 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
while (tsg->state != TSG_STATE_PIPE_CREATED)
{
WaitForMultipleObjects(nCount, events, FALSE, 100);
WaitForMultipleObjects(nCount, events, FALSE, 250);
if (tsg_check_event_handles(tsg) < 0)
{
@ -1913,10 +1913,11 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
return -1;
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
BIO_set_flags(bio, BIO_FLAGS_WRITE);
WSASetLastError(WSAEWOULDBLOCK);
}
else
@ -1939,10 +1940,11 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
return -1;
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
BIO_set_flags(bio, BIO_FLAGS_READ);
WSASetLastError(WSAEWOULDBLOCK);
}
else

View File

@ -397,6 +397,9 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->GatewayUseSameCredentials = FALSE;
settings->GatewayBypassLocal = FALSE;
settings->GatewayRpcTransport = TRUE;
settings->GatewayHttpTransport = TRUE;
settings->GatewayUdpTransport = TRUE;
settings->FastPathInput = TRUE;
settings->FastPathOutput = TRUE;

View File

@ -207,18 +207,50 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
if (transport->GatewayEnabled)
{
transport->tsg = tsg_new(transport);
if (!status && settings->GatewayHttpTransport)
{
transport->rdg = rdg_new(transport);
if (!transport->tsg)
return FALSE;
if (!transport->rdg)
return FALSE;
if (!tsg_connect(transport->tsg, hostname, port, timeout))
return FALSE;
status = rdg_connect(transport->rdg, hostname, port, timeout);
transport->frontBio = transport->tsg->bio;
transport->layer = TRANSPORT_LAYER_TSG;
if (status)
{
transport->frontBio = transport->rdg->frontBio;
BIO_set_nonblock(transport->frontBio, 0);
transport->layer = TRANSPORT_LAYER_TSG;
status = TRUE;
}
else
{
rdg_free(transport->rdg);
transport->rdg = NULL;
}
}
status = TRUE;
if (!status && settings->GatewayRpcTransport)
{
transport->tsg = tsg_new(transport);
if (!transport->tsg)
return FALSE;
status = tsg_connect(transport->tsg, hostname, port, timeout);
if (status)
{
transport->frontBio = transport->tsg->bio;
transport->layer = TRANSPORT_LAYER_TSG;
status = TRUE;
}
else
{
tsg_free(transport->tsg);
transport->tsg = NULL;
}
}
}
else
{
@ -621,7 +653,14 @@ UINT32 transport_get_event_handles(rdpTransport* transport, HANDLE* events)
}
else
{
nCount += tsg_get_event_handles(transport->tsg, events);
if (transport->rdg)
{
nCount += rdg_get_event_handles(transport->rdg, events);
}
else if (transport->tsg)
{
nCount += tsg_get_event_handles(transport->tsg, events);
}
}
return nCount;
@ -780,6 +819,12 @@ BOOL transport_disconnect(rdpTransport* transport)
transport->tsg = NULL;
}
if (transport->rdg)
{
rdg_free(transport->rdg);
transport->rdg = NULL;
}
transport->frontBio = NULL;
transport->layer = TRANSPORT_LAYER_TCP;

View File

@ -35,6 +35,7 @@ typedef struct rdp_transport rdpTransport;
#include "nla.h"
#include "gateway/tsg.h"
#include "gateway/rdg.h"
#include <winpr/sspi.h>
#include <winpr/wlog.h>
@ -56,6 +57,7 @@ struct rdp_transport
{
TRANSPORT_LAYER layer;
BIO* frontBio;
rdpRdg* rdg;
rdpTsg* tsg;
rdpTls* tls;
rdpContext* context;

View File

@ -39,6 +39,10 @@
#include <poll.h>
#endif
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#define TAG FREERDP_TAG("crypto")
struct _BIO_RDP_TLS
@ -180,6 +184,13 @@ static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
}
}
#ifdef HAVE_VALGRIND_MEMCHECK_H
if (status > 0)
{
VALGRIND_MAKE_MEM_DEFINED(buf, status);
}
#endif
return status;
}

View File

@ -48,7 +48,7 @@ BOOL CloseHandle(HANDLE hObject)
ULONG Type;
WINPR_HANDLE *Object;
if (!winpr_Handle_GetInfo(hObject, &Type, (PVOID*)&Object))
if (!winpr_Handle_GetInfo(hObject, &Type, (PVOID*) &Object))
return FALSE;
if (!Object)
@ -57,7 +57,7 @@ BOOL CloseHandle(HANDLE hObject)
if (!Object->ops)
return FALSE;
if(Object->ops->CloseHandle)
if (Object->ops->CloseHandle)
return Object->ops->CloseHandle(hObject);
return FALSE;

View File

@ -54,13 +54,14 @@ static int MutexGetFd(HANDLE handle)
return -1;
}
BOOL MutexCloseHandle(HANDLE handle) {
WINPR_MUTEX *mutex = (WINPR_MUTEX *) handle;
BOOL MutexCloseHandle(HANDLE handle)
{
WINPR_MUTEX* mutex = (WINPR_MUTEX*) handle;
if (!MutexIsHandled(handle))
return FALSE;
if(pthread_mutex_destroy(&mutex->mutex))
if (!pthread_mutex_destroy(&mutex->mutex))
return FALSE;
free(handle);
@ -68,11 +69,12 @@ BOOL MutexCloseHandle(HANDLE handle) {
return TRUE;
}
static HANDLE_OPS ops = {
MutexIsHandled,
MutexCloseHandle,
MutexGetFd,
NULL /* CleanupHandle */
static HANDLE_OPS ops =
{
MutexIsHandled,
MutexCloseHandle,
MutexGetFd,
NULL /* CleanupHandle */
};
HANDLE CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName)

View File

@ -326,6 +326,9 @@ BYTE* BipBuffer_ReadReserve(wBipBuffer* bb, size_t size)
block = BipBuffer_ReadTryReserve(bb, size, &reserved);
if (reserved != size)
return NULL;
return block;
}