mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #4964 from akallabeth/rdg_fixes
Rdg/RPC and gateway fixes
This commit is contained in:
commit
b8cf70b13a
|
@ -726,7 +726,7 @@ static BOOL http_use_content_length(const char* cur)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
HttpResponse* http_response_recv(rdpTls* tls)
|
||||
HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
|
||||
{
|
||||
size_t size;
|
||||
size_t position;
|
||||
|
@ -827,16 +827,19 @@ HttpResponse* http_response_recv(rdpTls* tls)
|
|||
goto out_error;
|
||||
|
||||
response->BodyLength = Stream_GetPosition(response->data) - payloadOffset;
|
||||
bodyLength = 0; /* expected body length */
|
||||
bodyLength = response->BodyLength; /* expected body length */
|
||||
|
||||
if (readContentLength)
|
||||
{
|
||||
const char* cur = response->ContentType;
|
||||
bodyLength = response->BodyLength;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (http_use_content_length(cur))
|
||||
{
|
||||
bodyLength = response->ContentLength;
|
||||
if (response->ContentLength < RESPONSE_SIZE_LIMIT)
|
||||
bodyLength = response->ContentLength;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ FREERDP_LOCAL HttpResponse* http_response_new(void);
|
|||
FREERDP_LOCAL void http_response_free(HttpResponse* response);
|
||||
|
||||
FREERDP_LOCAL BOOL http_response_print(HttpResponse* response);
|
||||
FREERDP_LOCAL HttpResponse* http_response_recv(rdpTls* tls);
|
||||
FREERDP_LOCAL HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength);
|
||||
|
||||
FREERDP_LOCAL long http_response_get_status_code(HttpResponse* response);
|
||||
FREERDP_LOCAL SSIZE_T http_response_get_body_length(HttpResponse* response);
|
||||
|
|
|
@ -76,7 +76,7 @@ BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
|
|||
wStream* s;
|
||||
int status;
|
||||
int contentLength;
|
||||
BOOL continueNeeded;
|
||||
BOOL continueNeeded = FALSE;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
const SecBuffer* buffer;
|
||||
|
@ -86,7 +86,10 @@ BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
|
|||
|
||||
ntlm = inChannel->ntlm;
|
||||
http = inChannel->http;
|
||||
continueNeeded = ntlm_authenticate(ntlm);
|
||||
|
||||
if (!ntlm_authenticate(ntlm, &continueNeeded))
|
||||
return FALSE;
|
||||
|
||||
contentLength = (continueNeeded) ? 0 : 0x40000000;
|
||||
buffer = ntlm_client_get_output_buffer(ntlm);
|
||||
s = rpc_ntlm_http_request(http, "RPC_IN_DATA", contentLength, buffer);
|
||||
|
@ -212,7 +215,7 @@ BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel,
|
|||
BOOL rc = TRUE;
|
||||
wStream* s;
|
||||
int contentLength;
|
||||
BOOL continueNeeded;
|
||||
BOOL continueNeeded = FALSE;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
const SecBuffer* buffer;
|
||||
|
@ -222,7 +225,9 @@ BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel,
|
|||
|
||||
ntlm = outChannel->ntlm;
|
||||
http = outChannel->http;
|
||||
continueNeeded = ntlm_authenticate(ntlm);
|
||||
|
||||
if (!ntlm_authenticate(ntlm, &continueNeeded))
|
||||
return FALSE;
|
||||
|
||||
if (!replacement)
|
||||
contentLength = (continueNeeded) ? 0 : 76;
|
||||
|
|
|
@ -216,7 +216,7 @@ error:
|
|||
* --------------
|
||||
*/
|
||||
|
||||
BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
BOOL ntlm_authenticate(rdpNtlm* ntlm, BOOL* pbContinueNeeded)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
|
||||
|
@ -308,7 +308,11 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
|||
|
||||
ntlm->haveInputBuffer = TRUE;
|
||||
ntlm->haveContext = TRUE;
|
||||
return (status == SEC_I_CONTINUE_NEEDED) ? TRUE : FALSE;
|
||||
|
||||
if (pbContinueNeeded)
|
||||
*pbContinueNeeded = (status == SEC_I_CONTINUE_NEEDED) ? TRUE : FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ntlm_client_uninit(rdpNtlm* ntlm)
|
||||
|
|
|
@ -31,7 +31,7 @@ typedef struct rdp_ntlm rdpNtlm;
|
|||
FREERDP_LOCAL rdpNtlm* ntlm_new(void);
|
||||
FREERDP_LOCAL void ntlm_free(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_authenticate(rdpNtlm* ntlm);
|
||||
FREERDP_LOCAL BOOL ntlm_authenticate(rdpNtlm* ntlm, BOOL* pbContinueNeeded);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality,
|
||||
LPCTSTR user, LPCTSTR domain,
|
||||
|
|
|
@ -40,6 +40,102 @@
|
|||
|
||||
#define TAG FREERDP_TAG("core.gateway.rdg")
|
||||
|
||||
|
||||
/* 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. */
|
||||
#define HTTP_EXTENDED_AUTH_SSPI_NTLM 0x04 /* NTLM extended 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
|
||||
|
||||
struct rdp_rdg
|
||||
{
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
BOOL attached;
|
||||
BIO* frontBio;
|
||||
rdpTls* tlsIn;
|
||||
rdpTls* tlsOut;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
CRITICAL_SECTION writeSection;
|
||||
|
||||
UUID guid;
|
||||
|
||||
int state;
|
||||
UINT16 packetRemainingCount;
|
||||
UINT16 reserved1;
|
||||
int timeout;
|
||||
UINT16 extAuth;
|
||||
UINT16 reserved2;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RDG_CLIENT_STATE_INITIAL,
|
||||
RDG_CLIENT_STATE_HANDSHAKE,
|
||||
RDG_CLIENT_STATE_TUNNEL_CREATE,
|
||||
RDG_CLIENT_STATE_TUNNEL_AUTHORIZE,
|
||||
RDG_CLIENT_STATE_CHANNEL_CREATE,
|
||||
RDG_CLIENT_STATE_OPENED,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct rdg_packet_header
|
||||
|
@ -53,6 +149,7 @@ typedef struct rdg_packet_header
|
|||
|
||||
static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket)
|
||||
{
|
||||
size_t s;
|
||||
int status;
|
||||
wStream* sChunk;
|
||||
char chunkSize[11];
|
||||
|
@ -66,7 +163,12 @@ static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket)
|
|||
Stream_Write(sChunk, Stream_Buffer(sPacket), Stream_Length(sPacket));
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
s = Stream_Length(sChunk);
|
||||
|
||||
if (s > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s);
|
||||
Stream_Free(sChunk, TRUE);
|
||||
|
||||
if (status < 0)
|
||||
|
@ -103,13 +205,15 @@ static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, int size)
|
|||
static wStream* rdg_receive_packet(rdpRdg* rdg)
|
||||
{
|
||||
wStream* s;
|
||||
const size_t header = sizeof(RdgPacketHeader);
|
||||
size_t packetLength;
|
||||
assert(header <= INT_MAX);
|
||||
s = Stream_New(NULL, 1024);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), sizeof(RdgPacketHeader)))
|
||||
if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), header))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return NULL;
|
||||
|
@ -118,14 +222,14 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
|
|||
Stream_Seek(s, 4);
|
||||
Stream_Read_UINT32(s, packetLength);
|
||||
|
||||
if (!Stream_EnsureCapacity(s, packetLength))
|
||||
if ((packetLength > INT_MAX) || !Stream_EnsureCapacity(s, packetLength))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + sizeof(RdgPacketHeader),
|
||||
packetLength - sizeof(RdgPacketHeader)))
|
||||
if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + header,
|
||||
(int)packetLength - (int)header))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return NULL;
|
||||
|
@ -170,16 +274,19 @@ static BOOL rdg_send_tunnel_request(rdpRdg* rdg)
|
|||
UINT32 packetSize = 16;
|
||||
UINT16 fieldsPresent = 0;
|
||||
WCHAR* PAACookie = NULL;
|
||||
UINT16 PAACookieLen = 0;
|
||||
int PAACookieLen = 0;
|
||||
|
||||
if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA)
|
||||
{
|
||||
PAACookieLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->GatewayAccessToken, -1, &PAACookie, 0);
|
||||
|
||||
if (!PAACookie)
|
||||
if (!PAACookie || (PAACookieLen < 0) || (PAACookieLen > UINT16_MAX / 2))
|
||||
{
|
||||
free(PAACookie);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
packetSize += 2 + PAACookieLen * sizeof(WCHAR);
|
||||
packetSize += 2 + (UINT32)PAACookieLen * sizeof(WCHAR);
|
||||
fieldsPresent = HTTP_TUNNEL_PACKET_FIELD_PAA_COOKIE;
|
||||
}
|
||||
|
||||
|
@ -200,8 +307,8 @@ static BOOL rdg_send_tunnel_request(rdpRdg* rdg)
|
|||
|
||||
if (PAACookie)
|
||||
{
|
||||
Stream_Write_UINT16(s, PAACookieLen * 2); /* PAA cookie string length */
|
||||
Stream_Write_UTF16_String(s, PAACookie, PAACookieLen);
|
||||
Stream_Write_UINT16(s, (UINT16)PAACookieLen * 2); /* PAA cookie string length */
|
||||
Stream_Write_UTF16_String(s, PAACookie, (size_t)PAACookieLen);
|
||||
}
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
@ -219,18 +326,19 @@ static BOOL rdg_send_tunnel_request(rdpRdg* rdg)
|
|||
|
||||
static BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
|
||||
{
|
||||
int i;
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
WCHAR* clientName = NULL;
|
||||
UINT16 clientNameLen;
|
||||
UINT32 packetSize;
|
||||
clientNameLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->ClientHostname, -1, &clientName, 0);
|
||||
int clientNameLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->ClientHostname, -1, &clientName, 0);
|
||||
|
||||
if (!clientName)
|
||||
if (!clientName || (clientNameLen < 0) || (clientNameLen > UINT16_MAX / 2))
|
||||
{
|
||||
free(clientName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
packetSize = 12 + clientNameLen * sizeof(WCHAR);
|
||||
packetSize = 12 + (UINT32)clientNameLen * sizeof(WCHAR);
|
||||
s = Stream_New(NULL, packetSize);
|
||||
|
||||
if (!s)
|
||||
|
@ -243,11 +351,8 @@ static BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
|
|||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */
|
||||
Stream_Write_UINT16(s, clientNameLen * 2); /* Client name string length */
|
||||
|
||||
for (i = 0; i < clientNameLen; i++)
|
||||
Stream_Write_UINT16(s, clientName[i]);
|
||||
|
||||
Stream_Write_UINT16(s, (UINT16)clientNameLen * 2); /* Client name string length */
|
||||
Stream_Write_UTF16_String(s, clientName, (size_t)clientNameLen);
|
||||
Stream_SealLength(s);
|
||||
status = rdg_write_packet(rdg, s);
|
||||
Stream_Free(s, TRUE);
|
||||
|
@ -263,39 +368,37 @@ static BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
|
|||
|
||||
static BOOL rdg_send_channel_create(rdpRdg* rdg)
|
||||
{
|
||||
int i;
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
char* serverName = rdg->settings->ServerHostname;
|
||||
UINT16 serverNameLen = strlen(serverName) + 1;
|
||||
UINT32 packetSize = 16 + serverNameLen * 2;
|
||||
wStream* s = NULL;
|
||||
BOOL status = FALSE;
|
||||
WCHAR* serverName = NULL;
|
||||
int serverNameLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->ServerHostname, -1, &serverName, 0);
|
||||
UINT32 packetSize = 16 + ((UINT32)serverNameLen) * 2;
|
||||
|
||||
if ((serverNameLen < 0) || (serverNameLen > UINT16_MAX / 2))
|
||||
goto fail;
|
||||
|
||||
s = Stream_New(NULL, packetSize);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
Stream_Write_UINT16(s, PKT_TYPE_CHANNEL_CREATE); /* Type (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
|
||||
Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */
|
||||
Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */
|
||||
Stream_Write_UINT16(s, rdg->settings->ServerPort); /* Resource port (2 bytes) */
|
||||
Stream_Write_UINT16(s, (UINT16)rdg->settings->ServerPort); /* Resource port (2 bytes) */
|
||||
Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */
|
||||
Stream_Write_UINT16(s, serverNameLen * 2);
|
||||
|
||||
for (i = 0; i < serverNameLen; i++)
|
||||
{
|
||||
Stream_Write_UINT16(s, serverName[i]);
|
||||
}
|
||||
|
||||
Stream_Write_UINT16(s, (UINT16)serverNameLen * 2);
|
||||
Stream_Write_UTF16_String(s, serverName, (size_t)serverNameLen);
|
||||
Stream_SealLength(s);
|
||||
status = rdg_write_packet(rdg, s);
|
||||
fail:
|
||||
free(serverName);
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
if (status)
|
||||
{
|
||||
rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -306,7 +409,12 @@ static BOOL rdg_set_ntlm_auth_header(rdpNtlm* ntlm, HttpRequest* request)
|
|||
char* base64NtlmToken = NULL;
|
||||
|
||||
if (ntlmToken)
|
||||
base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);
|
||||
{
|
||||
if (ntlmToken->cbBuffer > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, (int)ntlmToken->cbBuffer);
|
||||
}
|
||||
|
||||
if (base64NtlmToken)
|
||||
{
|
||||
|
@ -364,6 +472,8 @@ out:
|
|||
|
||||
static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
|
||||
{
|
||||
BOOL continueNeeded = FALSE;
|
||||
size_t len;
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
|
@ -386,19 +496,35 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
|
|||
if (!token64)
|
||||
return FALSE;
|
||||
|
||||
crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
|
||||
len = strlen(token64);
|
||||
|
||||
if (len > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
crypto_base64_decode(token64, (int)len, &ntlmTokenData, &ntlmTokenLength);
|
||||
|
||||
if (ntlmTokenLength < 0)
|
||||
{
|
||||
free(ntlmTokenData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
{
|
||||
if (!ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength))
|
||||
if (!ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, (size_t)ntlmTokenLength))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ntlm_authenticate(ntlm);
|
||||
if (!ntlm_authenticate(ntlm, &continueNeeded))
|
||||
return FALSE;
|
||||
|
||||
if (continueNeeded)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdg_skip_seed_payload(rdpTls* tls, int lastResponseLength)
|
||||
static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength)
|
||||
{
|
||||
BYTE seed_payload[10];
|
||||
|
||||
|
@ -419,7 +545,7 @@ static BOOL rdg_skip_seed_payload(rdpTls* tls, int lastResponseLength)
|
|||
|
||||
static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
HRESULT errorCode;
|
||||
UINT32 errorCode;
|
||||
WLog_DBG(TAG, "Handshake response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
|
||||
|
@ -435,7 +561,7 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Handshake error %x", errorCode);
|
||||
WLog_DBG(TAG, "Handshake error %"PRIx32, (HRESULT)errorCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -444,7 +570,7 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
HRESULT errorCode;
|
||||
UINT32 errorCode;
|
||||
WLog_DBG(TAG, "Tunnel response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
|
||||
|
@ -460,7 +586,7 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Tunnel creation error %x", errorCode);
|
||||
WLog_DBG(TAG, "Tunnel creation error %"PRIx32, (HRESULT)errorCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -469,7 +595,7 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
HRESULT errorCode;
|
||||
UINT32 errorCode;
|
||||
WLog_DBG(TAG, "Tunnel authorization received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
|
||||
|
@ -485,7 +611,7 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Tunnel authorization error %x", errorCode);
|
||||
WLog_DBG(TAG, "Tunnel authorization error %"PRIx32, (HRESULT)errorCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -494,7 +620,7 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
HRESULT errorCode;
|
||||
UINT32 errorCode;
|
||||
WLog_DBG(TAG, "Channel response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
|
||||
|
@ -510,7 +636,7 @@ static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
|
|||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Channel error %x", errorCode);
|
||||
WLog_DBG(TAG, "Channel error %"PRIx32, (HRESULT)errorCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -638,6 +764,7 @@ static BOOL rdg_get_gateway_credentials(rdpContext* context)
|
|||
|
||||
static BOOL rdg_ntlm_init(rdpRdg* rdg, rdpTls* tls)
|
||||
{
|
||||
BOOL continueNeeded = FALSE;
|
||||
rdpContext* context = rdg->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
rdg->ntlm = ntlm_new();
|
||||
|
@ -655,23 +782,28 @@ static BOOL rdg_ntlm_init(rdpRdg* rdg, rdpTls* tls)
|
|||
if (!ntlm_client_make_spn(rdg->ntlm, _T("HTTP"), settings->GatewayHostname))
|
||||
return FALSE;
|
||||
|
||||
if (!ntlm_authenticate(rdg->ntlm))
|
||||
if (!ntlm_authenticate(rdg->ntlm, &continueNeeded))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return continueNeeded;
|
||||
}
|
||||
|
||||
static BOOL rdg_send_http_request(rdpRdg* rdg, rdpTls* tls, const char* method,
|
||||
const char* transferEncoding)
|
||||
{
|
||||
size_t sz;
|
||||
wStream* s = NULL;
|
||||
int status;
|
||||
int status = -1;
|
||||
s = rdg_build_http_request(rdg, method, transferEncoding);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
status = tls_write_all(tls, Stream_Buffer(s), Stream_Length(s));
|
||||
sz = Stream_Length(s);
|
||||
|
||||
if (sz <= INT_MAX)
|
||||
status = tls_write_all(tls, Stream_Buffer(s), (int)sz);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return (status >= 0);
|
||||
}
|
||||
|
@ -679,27 +811,33 @@ static BOOL rdg_send_http_request(rdpRdg* rdg, rdpTls* tls, const char* method,
|
|||
static BOOL rdg_tls_connect(rdpRdg* rdg, rdpTls* tls, const char* peerAddress, int timeout)
|
||||
{
|
||||
int sockfd = 0;
|
||||
int status = 0;
|
||||
long status = 0;
|
||||
BIO* socketBio = NULL;
|
||||
BIO* bufferedBio = NULL;
|
||||
rdpSettings* settings = rdg->settings;
|
||||
const char* peerHostname = settings->GatewayHostname;
|
||||
UINT16 peerPort = settings->GatewayPort;
|
||||
UINT16 peerPort = (UINT16)settings->GatewayPort;
|
||||
const char* proxyUsername, *proxyPassword;
|
||||
BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, &proxyUsername,
|
||||
&proxyPassword);
|
||||
|
||||
if (settings->GatewayPort > UINT16_MAX)
|
||||
return FALSE;
|
||||
|
||||
sockfd = freerdp_tcp_connect(rdg->context, settings,
|
||||
peerAddress ? peerAddress : peerHostname,
|
||||
peerPort, timeout);
|
||||
|
||||
if (sockfd < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!socketBio)
|
||||
{
|
||||
closesocket(sockfd);
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -718,7 +856,7 @@ static BOOL rdg_tls_connect(rdpRdg* rdg, rdpTls* tls, const char* peerAddress, i
|
|||
if (isProxyConnection)
|
||||
{
|
||||
if (!proxy_connect(settings, bufferedBio, proxyUsername, proxyPassword, settings->GatewayHostname,
|
||||
settings->GatewayPort))
|
||||
(UINT16)settings->GatewayPort))
|
||||
{
|
||||
BIO_free_all(bufferedBio);
|
||||
return FALSE;
|
||||
|
@ -732,7 +870,7 @@ static BOOL rdg_tls_connect(rdpRdg* rdg, rdpTls* tls, const char* peerAddress, i
|
|||
}
|
||||
|
||||
tls->hostname = settings->GatewayHostname;
|
||||
tls->port = settings->GatewayPort;
|
||||
tls->port = (int)settings->GatewayPort;
|
||||
tls->isGatewayTransport = TRUE;
|
||||
status = tls_connect(tls, bufferedBio);
|
||||
return (status >= 1);
|
||||
|
@ -742,8 +880,8 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
|||
const char* method, const char* peerAddress, int timeout, BOOL* rpcFallback)
|
||||
{
|
||||
HttpResponse* response = NULL;
|
||||
int statusCode;
|
||||
int bodyLength;
|
||||
long statusCode;
|
||||
SSIZE_T bodyLength;
|
||||
long StatusCode;
|
||||
|
||||
if (!rdg_tls_connect(rdg, tls, peerAddress, timeout))
|
||||
|
@ -757,7 +895,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
|||
if (!rdg_send_http_request(rdg, tls, method, NULL))
|
||||
return FALSE;
|
||||
|
||||
response = http_response_recv(tls);
|
||||
response = http_response_recv(tls, TRUE);
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
@ -788,7 +926,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
|||
|
||||
ntlm_free(rdg->ntlm);
|
||||
rdg->ntlm = NULL;
|
||||
response = http_response_recv(tls);
|
||||
response = http_response_recv(tls, TRUE);
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
@ -877,17 +1015,22 @@ BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
|
||||
static int rdg_write_data_packet(rdpRdg* rdg, const BYTE* buf, int isize)
|
||||
{
|
||||
int status;
|
||||
size_t s;
|
||||
wStream* sChunk;
|
||||
int packetSize = size + 10;
|
||||
size_t size = (size_t)isize;
|
||||
size_t packetSize = size + 10;
|
||||
char chunkSize[11];
|
||||
|
||||
if ((isize < 0) || (isize > UINT16_MAX))
|
||||
return -1;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%"PRIxz"\r\n", packetSize);
|
||||
sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
|
||||
|
||||
if (!sChunk)
|
||||
|
@ -896,69 +1039,94 @@ static int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
|
|||
Stream_Write(sChunk, chunkSize, strlen(chunkSize));
|
||||
Stream_Write_UINT16(sChunk, PKT_TYPE_DATA); /* Type */
|
||||
Stream_Write_UINT16(sChunk, 0); /* Reserved */
|
||||
Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
|
||||
Stream_Write_UINT16(sChunk, size); /* Data size */
|
||||
Stream_Write_UINT32(sChunk, (UINT32)packetSize); /* Packet length */
|
||||
Stream_Write_UINT16(sChunk, (UINT16)size); /* Data size */
|
||||
Stream_Write(sChunk, buf, size); /* Data */
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
s = Stream_Length(sChunk);
|
||||
|
||||
if (s > INT_MAX)
|
||||
return -1;
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s);
|
||||
Stream_Free(sChunk, TRUE);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
return size;
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
static BOOL rdg_process_close_packet(rdpRdg* rdg)
|
||||
{
|
||||
int status;
|
||||
int status = -1;
|
||||
size_t s;
|
||||
wStream* sChunk;
|
||||
int packetSize = 12;
|
||||
UINT32 packetSize = 12;
|
||||
char chunkSize[11];
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
|
||||
sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
|
||||
int chunkLen = sprintf_s(chunkSize, sizeof(chunkSize), "%"PRIx32"\r\n", packetSize);
|
||||
|
||||
if (chunkLen < 0)
|
||||
return FALSE;
|
||||
|
||||
sChunk = Stream_New(NULL, (size_t)chunkLen + packetSize + 2);
|
||||
|
||||
if (!sChunk)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write(sChunk, chunkSize, strlen(chunkSize));
|
||||
Stream_Write(sChunk, chunkSize, (size_t)chunkLen);
|
||||
Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE); /* Type */
|
||||
Stream_Write_UINT16(sChunk, 0); /* Reserved */
|
||||
Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
|
||||
Stream_Write_UINT32(sChunk, 0); /* Status code */
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
s = Stream_Length(sChunk);
|
||||
|
||||
if (s <= INT_MAX)
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s);
|
||||
|
||||
Stream_Free(sChunk, TRUE);
|
||||
return (status < 0 ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
static BOOL rdg_process_keep_alive_packet(rdpRdg* rdg)
|
||||
{
|
||||
int status;
|
||||
int status = -1;
|
||||
size_t s;
|
||||
wStream* sChunk;
|
||||
int packetSize = 8;
|
||||
size_t packetSize = 8;
|
||||
char chunkSize[11];
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
|
||||
sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
|
||||
int chunkLen = sprintf_s(chunkSize, sizeof(chunkSize), "%"PRIxz"\r\n", packetSize);
|
||||
|
||||
if ((chunkLen < 0) || (packetSize > UINT32_MAX))
|
||||
return FALSE;
|
||||
|
||||
sChunk = Stream_New(NULL, (size_t)chunkLen + packetSize + 2);
|
||||
|
||||
if (!sChunk)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write(sChunk, chunkSize, strlen(chunkSize));
|
||||
Stream_Write(sChunk, chunkSize, (size_t)chunkLen);
|
||||
Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE); /* Type */
|
||||
Stream_Write_UINT16(sChunk, 0); /* Reserved */
|
||||
Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
|
||||
Stream_Write_UINT32(sChunk, (UINT32)packetSize); /* Packet length */
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
s = Stream_Length(sChunk);
|
||||
|
||||
if (s <= INT_MAX)
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s);
|
||||
|
||||
Stream_Free(sChunk, TRUE);
|
||||
return (status < 0 ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
static BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
|
||||
{
|
||||
WINPR_UNUSED(rdg);
|
||||
WINPR_UNUSED(type);
|
||||
WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -970,6 +1138,11 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
|
|||
int status;
|
||||
size_t payloadSize = packetLength - sizeof(RdgPacketHeader);
|
||||
|
||||
if (packetLength < sizeof(RdgPacketHeader))
|
||||
return FALSE;
|
||||
|
||||
assert(sizeof(RdgPacketHeader) < INT_MAX);
|
||||
|
||||
if (payloadSize)
|
||||
{
|
||||
s = Stream_New(NULL, payloadSize);
|
||||
|
@ -979,7 +1152,8 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
|
|||
|
||||
while (readCount < payloadSize)
|
||||
{
|
||||
status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
|
||||
status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s),
|
||||
(int)payloadSize - (int)readCount);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
|
@ -992,8 +1166,14 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
|
|||
continue;
|
||||
}
|
||||
|
||||
Stream_Seek(s, status);
|
||||
readCount += status;
|
||||
Stream_Seek(s, (size_t)status);
|
||||
readCount += (size_t)status;
|
||||
|
||||
if (readCount > INT_MAX)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1029,10 +1209,12 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
|||
|
||||
if (!rdg->packetRemainingCount)
|
||||
{
|
||||
assert(sizeof(RdgPacketHeader) < INT_MAX);
|
||||
|
||||
while (readCount < sizeof(RdgPacketHeader))
|
||||
{
|
||||
status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount,
|
||||
sizeof(RdgPacketHeader) - readCount);
|
||||
(int)sizeof(RdgPacketHeader) - (int)readCount);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
|
@ -1046,7 +1228,10 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
|||
continue;
|
||||
}
|
||||
|
||||
readCount += status;
|
||||
readCount += (size_t)status;
|
||||
|
||||
if (readCount > INT_MAX)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header.type != PKT_TYPE_DATA)
|
||||
|
@ -1063,7 +1248,8 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
|||
|
||||
while (readCount < 2)
|
||||
{
|
||||
status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, 2 - readCount);
|
||||
status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount,
|
||||
2 - (int)readCount);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
|
@ -1074,7 +1260,7 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
|||
continue;
|
||||
}
|
||||
|
||||
readCount += status;
|
||||
readCount += (size_t)status;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1101,7 +1287,7 @@ static int rdg_bio_write(BIO* bio, const char* buf, int num)
|
|||
rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio);
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
EnterCriticalSection(&rdg->writeSection);
|
||||
status = rdg_write_data_packet(rdg, (BYTE*) buf, num);
|
||||
status = rdg_write_data_packet(rdg, (const BYTE*) buf, num);
|
||||
LeaveCriticalSection(&rdg->writeSection);
|
||||
|
||||
if (status < 0)
|
||||
|
@ -1149,17 +1335,22 @@ static int rdg_bio_read(BIO* bio, char* buf, int size)
|
|||
|
||||
static int rdg_bio_puts(BIO* bio, const char* str)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int rdg_bio_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
WINPR_UNUSED(size);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
int status = -1;
|
||||
long status = -1;
|
||||
rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio);
|
||||
rdpTls* tlsOut = rdg->tlsOut;
|
||||
rdpTls* tlsIn = rdg->tlsIn;
|
||||
|
@ -1233,6 +1424,7 @@ static int rdg_bio_new(BIO* bio)
|
|||
|
||||
static int rdg_bio_free(BIO* bio)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1257,19 +1449,22 @@ static BIO_METHOD* BIO_s_rdg(void)
|
|||
return bio_methods;
|
||||
}
|
||||
|
||||
rdpRdg* rdg_new(rdpTransport* transport)
|
||||
rdpRdg* rdg_new(rdpContext* context)
|
||||
{
|
||||
rdpRdg* rdg;
|
||||
RPC_CSTR stringUuid;
|
||||
char bracedUuid[40];
|
||||
RPC_STATUS rpcStatus;
|
||||
assert(transport != NULL);
|
||||
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
rdg = (rdpRdg*) calloc(1, sizeof(rdpRdg));
|
||||
|
||||
if (rdg)
|
||||
{
|
||||
rdg->state = RDG_CLIENT_STATE_INITIAL;
|
||||
rdg->context = transport->context;
|
||||
rdg->context = context;
|
||||
rdg->settings = rdg->context->settings;
|
||||
rdg->extAuth = HTTP_EXTENDED_AUTH_NONE;
|
||||
|
||||
|
@ -1350,7 +1545,19 @@ void rdg_free(rdpRdg* rdg)
|
|||
tls_free(rdg->tlsIn);
|
||||
http_context_free(rdg->http);
|
||||
ntlm_free(rdg->ntlm);
|
||||
BIO_free_all(rdg->frontBio);
|
||||
|
||||
if (!rdg->attached)
|
||||
BIO_free_all(rdg->frontBio);
|
||||
|
||||
DeleteCriticalSection(&rdg->writeSection);
|
||||
free(rdg);
|
||||
}
|
||||
|
||||
BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg)
|
||||
{
|
||||
if (!rdg)
|
||||
return NULL;
|
||||
|
||||
rdg->attached = TRUE;
|
||||
return rdg->frontBio;
|
||||
}
|
||||
|
|
|
@ -39,105 +39,12 @@ 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. */
|
||||
#define HTTP_EXTENDED_AUTH_SSPI_NTLM 0x04 /* NTLM extended 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_HANDSHAKE,
|
||||
RDG_CLIENT_STATE_TUNNEL_CREATE,
|
||||
RDG_CLIENT_STATE_TUNNEL_AUTHORIZE,
|
||||
RDG_CLIENT_STATE_CHANNEL_CREATE,
|
||||
RDG_CLIENT_STATE_OPENED,
|
||||
};
|
||||
|
||||
struct rdp_rdg
|
||||
{
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
BIO* frontBio;
|
||||
rdpTls* tlsIn;
|
||||
rdpTls* tlsOut;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
CRITICAL_SECTION writeSection;
|
||||
|
||||
UUID guid;
|
||||
|
||||
int state;
|
||||
UINT16 packetRemainingCount;
|
||||
int timeout;
|
||||
UINT16 extAuth;
|
||||
};
|
||||
|
||||
|
||||
FREERDP_LOCAL rdpRdg* rdg_new(rdpTransport* transport);
|
||||
FREERDP_LOCAL rdpRdg* rdg_new(rdpContext* context);
|
||||
FREERDP_LOCAL void rdg_free(rdpRdg* rdg);
|
||||
|
||||
FREERDP_LOCAL BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg);
|
||||
|
||||
FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback);
|
||||
FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events,
|
||||
DWORD count);
|
||||
|
|
|
@ -107,6 +107,7 @@ const p_uuid_t BTFN_UUID =
|
|||
|
||||
int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
{
|
||||
BOOL continueNeeded = FALSE;
|
||||
int status = -1;
|
||||
BYTE* buffer = NULL;
|
||||
UINT32 offset;
|
||||
|
@ -165,7 +166,10 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
|||
if (!ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname))
|
||||
goto fail;
|
||||
|
||||
if (!ntlm_authenticate(rpc->ntlm))
|
||||
if (!ntlm_authenticate(rpc->ntlm, &continueNeeded))
|
||||
goto fail;
|
||||
|
||||
if (!continueNeeded)
|
||||
goto fail;
|
||||
|
||||
bind_pdu = (rpcconn_bind_hdr_t*) calloc(1, sizeof(rpcconn_bind_hdr_t));
|
||||
|
@ -302,6 +306,7 @@ fail:
|
|||
|
||||
int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
BOOL continueNeeded = FALSE;
|
||||
BYTE* auth_data;
|
||||
rpcconn_hdr_t* header;
|
||||
header = (rpcconn_hdr_t*) buffer;
|
||||
|
@ -317,7 +322,12 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
|||
if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header->common.auth_length))
|
||||
return -1;
|
||||
|
||||
ntlm_authenticate(rpc->ntlm);
|
||||
if (!ntlm_authenticate(rpc->ntlm, &continueNeeded))
|
||||
return -1;
|
||||
|
||||
if (continueNeeded)
|
||||
return -1;
|
||||
|
||||
return (int) length;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL const p_uuid_t TSGU_UUID;
|
||||
FREERDP_LOCAL extern const p_uuid_t TSGU_UUID;
|
||||
#define TSGU_SYNTAX_IF_VERSION 0x00030001
|
||||
|
||||
FREERDP_LOCAL const p_uuid_t NDR_UUID;
|
||||
FREERDP_LOCAL extern const p_uuid_t NDR_UUID;
|
||||
#define NDR_SYNTAX_IF_VERSION 0x00000002
|
||||
|
||||
FREERDP_LOCAL const p_uuid_t BTFN_UUID;
|
||||
FREERDP_LOCAL extern const p_uuid_t BTFN_UUID;
|
||||
#define BTFN_SYNTAX_IF_VERSION 0x00000001
|
||||
|
||||
FREERDP_LOCAL int rpc_send_bind_pdu(rdpRpc* rpc);
|
||||
|
|
|
@ -476,7 +476,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
|||
if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
response = http_response_recv(outChannel->common.tls);
|
||||
response = http_response_recv(outChannel->common.tls, TRUE);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
@ -533,7 +533,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
|||
if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
response = http_response_recv(outChannel->common.tls);
|
||||
response = http_response_recv(outChannel->common.tls, FALSE);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
@ -646,7 +646,7 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
|
|||
if (WaitForSingleObject(nextOutChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
response = http_response_recv(nextOutChannel->common.tls);
|
||||
response = http_response_recv(nextOutChannel->common.tls, TRUE);
|
||||
|
||||
if (response)
|
||||
{
|
||||
|
@ -726,7 +726,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
|||
|
||||
if (inChannel->State < CLIENT_IN_CHANNEL_STATE_OPENED)
|
||||
{
|
||||
response = http_response_recv(inChannel->common.tls);
|
||||
response = http_response_recv(inChannel->common.tls, TRUE);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
@ -778,7 +778,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
|||
}
|
||||
else
|
||||
{
|
||||
response = http_response_recv(inChannel->common.tls);
|
||||
response = http_response_recv(inChannel->common.tls, TRUE);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
|
|
@ -369,7 +369,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname,
|
|||
{
|
||||
if (!status && settings->GatewayHttpTransport)
|
||||
{
|
||||
transport->rdg = rdg_new(transport);
|
||||
transport->rdg = rdg_new(context);
|
||||
|
||||
if (!transport->rdg)
|
||||
return FALSE;
|
||||
|
@ -378,7 +378,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname,
|
|||
|
||||
if (status)
|
||||
{
|
||||
transport->frontBio = transport->rdg->frontBio;
|
||||
transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
|
||||
BIO_set_nonblock(transport->frontBio, 0);
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
status = TRUE;
|
||||
|
@ -1093,9 +1093,6 @@ BOOL transport_disconnect(rdpTransport* transport)
|
|||
if (!transport)
|
||||
return FALSE;
|
||||
|
||||
if (transport->rdg && (transport->rdg->frontBio == transport->frontBio))
|
||||
transport->frontBio = NULL;
|
||||
|
||||
if (transport->tls)
|
||||
{
|
||||
tls_free(transport->tls);
|
||||
|
|
Loading…
Reference in New Issue