Merge pull request #4902 from akallabeth/gw_refactor_3
Gateway refactoring
This commit is contained in:
commit
8fe3ac5d26
@ -409,21 +409,13 @@ static BOOL rdp_client_reconnect_channels(rdpRdp* rdp, BOOL redirect)
|
||||
|
||||
static BOOL rdp_client_redirect_resolvable(const char* host)
|
||||
{
|
||||
int status;
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* result = NULL;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
status = getaddrinfo(host, NULL, &hints, &result);
|
||||
errno = 0;
|
||||
struct addrinfo* result = freerdp_tcp_resolve_host(host, -1, 0);
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
return TRUE;
|
||||
}
|
||||
if (!result)
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
freeaddrinfo(result);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdp_client_redirect_try_fqdn(rdpSettings* settings)
|
||||
|
@ -40,6 +40,50 @@
|
||||
|
||||
#define RESPONSE_SIZE_LIMIT 64 * 1024 * 1024
|
||||
|
||||
struct _http_context
|
||||
{
|
||||
char* Method;
|
||||
char* URI;
|
||||
char* UserAgent;
|
||||
char* Host;
|
||||
char* Accept;
|
||||
char* CacheControl;
|
||||
char* Connection;
|
||||
char* Pragma;
|
||||
char* RdgConnectionId;
|
||||
char* RdgAuthScheme;
|
||||
};
|
||||
|
||||
struct _http_request
|
||||
{
|
||||
char* Method;
|
||||
char* URI;
|
||||
char* AuthScheme;
|
||||
char* AuthParam;
|
||||
char* Authorization;
|
||||
size_t ContentLength;
|
||||
char* Content;
|
||||
char* TransferEncoding;
|
||||
};
|
||||
|
||||
struct _http_response
|
||||
{
|
||||
size_t count;
|
||||
char** lines;
|
||||
|
||||
long StatusCode;
|
||||
const char* ReasonPhrase;
|
||||
|
||||
size_t ContentLength;
|
||||
const char* ContentType;
|
||||
|
||||
size_t BodyLength;
|
||||
BYTE* BodyContent;
|
||||
|
||||
wListDictionary* Authenticates;
|
||||
wStream* data;
|
||||
};
|
||||
|
||||
static char* string_strnstr(const char* str1, const char* str2, size_t slen)
|
||||
{
|
||||
char c, sc;
|
||||
@ -84,6 +128,9 @@ HttpContext* http_context_new(void)
|
||||
|
||||
BOOL http_context_set_method(HttpContext* context, const char* Method)
|
||||
{
|
||||
if (!context || !Method)
|
||||
return FALSE;
|
||||
|
||||
free(context->Method);
|
||||
context->Method = _strdup(Method);
|
||||
|
||||
@ -93,8 +140,19 @@ BOOL http_context_set_method(HttpContext* context, const char* Method)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char* http_context_get_uri(HttpContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
return context->URI;
|
||||
}
|
||||
|
||||
BOOL http_context_set_uri(HttpContext* context, const char* URI)
|
||||
{
|
||||
if (!context || !URI)
|
||||
return FALSE;
|
||||
|
||||
free(context->URI);
|
||||
context->URI = _strdup(URI);
|
||||
|
||||
@ -106,6 +164,9 @@ BOOL http_context_set_uri(HttpContext* context, const char* URI)
|
||||
|
||||
BOOL http_context_set_user_agent(HttpContext* context, const char* UserAgent)
|
||||
{
|
||||
if (!context || !UserAgent)
|
||||
return FALSE;
|
||||
|
||||
free(context->UserAgent);
|
||||
context->UserAgent = _strdup(UserAgent);
|
||||
|
||||
@ -117,6 +178,9 @@ BOOL http_context_set_user_agent(HttpContext* context, const char* UserAgent)
|
||||
|
||||
BOOL http_context_set_host(HttpContext* context, const char* Host)
|
||||
{
|
||||
if (!context || !Host)
|
||||
return FALSE;
|
||||
|
||||
free(context->Host);
|
||||
context->Host = _strdup(Host);
|
||||
|
||||
@ -128,6 +192,9 @@ BOOL http_context_set_host(HttpContext* context, const char* Host)
|
||||
|
||||
BOOL http_context_set_accept(HttpContext* context, const char* Accept)
|
||||
{
|
||||
if (!context || !Accept)
|
||||
return FALSE;
|
||||
|
||||
free(context->Accept);
|
||||
context->Accept = _strdup(Accept);
|
||||
|
||||
@ -139,6 +206,9 @@ BOOL http_context_set_accept(HttpContext* context, const char* Accept)
|
||||
|
||||
BOOL http_context_set_cache_control(HttpContext* context, const char* CacheControl)
|
||||
{
|
||||
if (!context || !CacheControl)
|
||||
return FALSE;
|
||||
|
||||
free(context->CacheControl);
|
||||
context->CacheControl = _strdup(CacheControl);
|
||||
|
||||
@ -150,6 +220,9 @@ BOOL http_context_set_cache_control(HttpContext* context, const char* CacheContr
|
||||
|
||||
BOOL http_context_set_connection(HttpContext* context, const char* Connection)
|
||||
{
|
||||
if (!context || !Connection)
|
||||
return FALSE;
|
||||
|
||||
free(context->Connection);
|
||||
context->Connection = _strdup(Connection);
|
||||
|
||||
@ -161,6 +234,9 @@ BOOL http_context_set_connection(HttpContext* context, const char* Connection)
|
||||
|
||||
BOOL http_context_set_pragma(HttpContext* context, const char* Pragma)
|
||||
{
|
||||
if (!context || !Pragma)
|
||||
return FALSE;
|
||||
|
||||
free(context->Pragma);
|
||||
context->Pragma = _strdup(Pragma);
|
||||
|
||||
@ -172,6 +248,9 @@ BOOL http_context_set_pragma(HttpContext* context, const char* Pragma)
|
||||
|
||||
BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgConnectionId)
|
||||
{
|
||||
if (!context || !RdgConnectionId)
|
||||
return FALSE;
|
||||
|
||||
free(context->RdgConnectionId);
|
||||
context->RdgConnectionId = _strdup(RdgConnectionId);
|
||||
|
||||
@ -183,6 +262,9 @@ BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgCon
|
||||
|
||||
BOOL http_context_set_rdg_auth_scheme(HttpContext* context, const char* RdgAuthScheme)
|
||||
{
|
||||
if (!context || !RdgAuthScheme)
|
||||
return FALSE;
|
||||
|
||||
free(context->RdgAuthScheme);
|
||||
context->RdgAuthScheme = _strdup(RdgAuthScheme);
|
||||
return context->RdgAuthScheme != NULL;
|
||||
@ -208,6 +290,9 @@ void http_context_free(HttpContext* context)
|
||||
|
||||
BOOL http_request_set_method(HttpRequest* request, const char* Method)
|
||||
{
|
||||
if (!request || !Method)
|
||||
return FALSE;
|
||||
|
||||
free(request->Method);
|
||||
request->Method = _strdup(Method);
|
||||
|
||||
@ -219,6 +304,9 @@ BOOL http_request_set_method(HttpRequest* request, const char* Method)
|
||||
|
||||
BOOL http_request_set_uri(HttpRequest* request, const char* URI)
|
||||
{
|
||||
if (!request || !URI)
|
||||
return FALSE;
|
||||
|
||||
free(request->URI);
|
||||
request->URI = _strdup(URI);
|
||||
|
||||
@ -230,6 +318,9 @@ BOOL http_request_set_uri(HttpRequest* request, const char* URI)
|
||||
|
||||
BOOL http_request_set_auth_scheme(HttpRequest* request, const char* AuthScheme)
|
||||
{
|
||||
if (!request || !AuthScheme)
|
||||
return FALSE;
|
||||
|
||||
free(request->AuthScheme);
|
||||
request->AuthScheme = _strdup(AuthScheme);
|
||||
|
||||
@ -241,6 +332,9 @@ BOOL http_request_set_auth_scheme(HttpRequest* request, const char* AuthScheme)
|
||||
|
||||
BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam)
|
||||
{
|
||||
if (!request || !AuthParam)
|
||||
return FALSE;
|
||||
|
||||
free(request->AuthParam);
|
||||
request->AuthParam = _strdup(AuthParam);
|
||||
|
||||
@ -252,6 +346,9 @@ BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam)
|
||||
|
||||
BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* TransferEncoding)
|
||||
{
|
||||
if (!request || !TransferEncoding)
|
||||
return FALSE;
|
||||
|
||||
free(request->TransferEncoding);
|
||||
request->TransferEncoding = _strdup(TransferEncoding);
|
||||
|
||||
@ -261,149 +358,125 @@ BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* Transf
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char* http_encode_body_line(const char* param, const char* value)
|
||||
static BOOL http_encode_print(wStream* s, const char* fmt, ...)
|
||||
{
|
||||
char* line;
|
||||
int length;
|
||||
length = strlen(param) + strlen(value) + 2;
|
||||
line = (char*) malloc(length + 1);
|
||||
char* str;
|
||||
va_list ap;
|
||||
size_t length, used;
|
||||
|
||||
if (!line)
|
||||
return NULL;
|
||||
if (!s || !fmt)
|
||||
return FALSE;
|
||||
|
||||
sprintf_s(line, length + 1, "%s: %s", param, value);
|
||||
return line;
|
||||
va_start(ap, fmt);
|
||||
length = vsnprintf(NULL, 0, fmt, ap) + 1;
|
||||
va_end(ap);
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, length))
|
||||
return FALSE;
|
||||
|
||||
str = (char*)Stream_Pointer(s);
|
||||
va_start(ap, fmt);
|
||||
used = vsnprintf(str, length, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Strip the trailing '\0' from the string. */
|
||||
if ((used + 1) != length)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(s, used);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char* http_encode_content_length_line(int ContentLength)
|
||||
static BOOL http_encode_body_line(wStream* s, const char* param, const char* value)
|
||||
{
|
||||
const char* key = "Content-Length:";
|
||||
char* line;
|
||||
int length;
|
||||
char str[32];
|
||||
_itoa_s(ContentLength, str, sizeof(str), 10);
|
||||
length = strlen(key) + strlen(str) + 2;
|
||||
line = (char*) malloc(length + 1);
|
||||
if (!s || !param || !value)
|
||||
return FALSE;
|
||||
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
sprintf_s(line, length + 1, "%s %s", key, str);
|
||||
return line;
|
||||
return http_encode_print(s, "%s: %s\r\n", param, value);
|
||||
}
|
||||
|
||||
static char* http_encode_header_line(const char* Method, const char* URI)
|
||||
static BOOL http_encode_content_length_line(wStream* s, size_t ContentLength)
|
||||
{
|
||||
const char* key = "HTTP/1.1";
|
||||
char* line;
|
||||
int length;
|
||||
length = strlen(key) + strlen(Method) + strlen(URI) + 2;
|
||||
line = (char*)malloc(length + 1);
|
||||
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
sprintf_s(line, length + 1, "%s %s %s", Method, URI, key);
|
||||
return line;
|
||||
return http_encode_print(s, "Content-Length: %"PRIdz"\r\n", ContentLength);
|
||||
}
|
||||
|
||||
static char* http_encode_authorization_line(const char* AuthScheme, const char* AuthParam)
|
||||
static BOOL http_encode_header_line(wStream* s, const char* Method, const char* URI)
|
||||
{
|
||||
const char* key = "Authorization:";
|
||||
char* line;
|
||||
int length;
|
||||
length = strlen(key) + strlen(AuthScheme) + strlen(AuthParam) + 3;
|
||||
line = (char*) malloc(length + 1);
|
||||
if (!s || !Method || !URI)
|
||||
return FALSE;
|
||||
|
||||
if (!line)
|
||||
return NULL;
|
||||
return http_encode_print(s, "%s %s HTTP/1.1\r\n", Method, URI);
|
||||
}
|
||||
|
||||
sprintf_s(line, length + 1, "%s %s %s", key, AuthScheme, AuthParam);
|
||||
return line;
|
||||
static BOOL http_encode_authorization_line(wStream* s, const char* AuthScheme,
|
||||
const char* AuthParam)
|
||||
{
|
||||
if (!s || !AuthScheme || !AuthParam)
|
||||
return FALSE;
|
||||
|
||||
return http_encode_print(s, "Authorization: %s %s\r\n", AuthScheme, AuthParam);
|
||||
}
|
||||
|
||||
wStream* http_request_write(HttpContext* context, HttpRequest* request)
|
||||
{
|
||||
wStream* s;
|
||||
int i, count;
|
||||
char** lines;
|
||||
int length = 0;
|
||||
count = 0;
|
||||
lines = (char**) calloc(32, sizeof(char*));
|
||||
|
||||
if (!lines)
|
||||
if (!context || !request)
|
||||
return NULL;
|
||||
|
||||
lines[count++] = http_encode_header_line(request->Method, request->URI);
|
||||
lines[count++] = http_encode_body_line("Cache-Control", context->CacheControl);
|
||||
lines[count++] = http_encode_body_line("Connection", context->Connection);
|
||||
lines[count++] = http_encode_body_line("Pragma", context->Pragma);
|
||||
lines[count++] = http_encode_body_line("Accept", context->Accept);
|
||||
lines[count++] = http_encode_body_line("User-Agent", context->UserAgent);
|
||||
lines[count++] = http_encode_body_line("Host", context->Host);
|
||||
s = Stream_New(NULL, 1024);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!http_encode_header_line(s, request->Method, request->URI) ||
|
||||
!http_encode_body_line(s, "Cache-Control", context->CacheControl) ||
|
||||
!http_encode_body_line(s, "Connection", context->Connection) ||
|
||||
!http_encode_body_line(s, "Pragma", context->Pragma) ||
|
||||
!http_encode_body_line(s, "Accept", context->Accept) ||
|
||||
!http_encode_body_line(s, "User-Agent", context->UserAgent) ||
|
||||
!http_encode_body_line(s, "Host", context->Host))
|
||||
goto fail;
|
||||
|
||||
if (context->RdgConnectionId)
|
||||
lines[count++] = http_encode_body_line("RDG-Connection-Id", context->RdgConnectionId);
|
||||
{
|
||||
if (!http_encode_body_line(s, "RDG-Connection-Id", context->RdgConnectionId))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (context->RdgAuthScheme)
|
||||
lines[count++] = http_encode_body_line("RDG-Auth-Scheme", context->RdgAuthScheme);
|
||||
{
|
||||
if (!http_encode_body_line(s, "RDG-Auth-Scheme", context->RdgAuthScheme))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (request->TransferEncoding)
|
||||
{
|
||||
lines[count++] = http_encode_body_line("Transfer-Encoding", request->TransferEncoding);
|
||||
if (!http_encode_body_line(s, "Transfer-Encoding", request->TransferEncoding))
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[count++] = http_encode_content_length_line(request->ContentLength);
|
||||
if (!http_encode_content_length_line(s, request->ContentLength))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (request->Authorization)
|
||||
{
|
||||
lines[count++] = http_encode_body_line("Authorization", request->Authorization);
|
||||
if (!http_encode_body_line(s, "Authorization", request->Authorization))
|
||||
goto fail;
|
||||
}
|
||||
else if (request->AuthScheme && request->AuthParam)
|
||||
{
|
||||
lines[count++] = http_encode_authorization_line(request->AuthScheme, request->AuthParam);
|
||||
}
|
||||
|
||||
/* check that everything went well */
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (!lines[i])
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
length += (strlen(lines[i]) + 2); /* add +2 for each '\r\n' character */
|
||||
}
|
||||
|
||||
length += 2; /* empty line "\r\n" at end of header */
|
||||
length += 1; /* null terminator */
|
||||
s = Stream_New(NULL, length);
|
||||
|
||||
if (!s)
|
||||
goto out_free;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Stream_Write(s, lines[i], strlen(lines[i]));
|
||||
Stream_Write(s, "\r\n", 2);
|
||||
free(lines[i]);
|
||||
if (!http_encode_authorization_line(s, request->AuthScheme, request->AuthParam))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
Stream_Write(s, "\r\n", 2);
|
||||
free(lines);
|
||||
Stream_Write(s, "\0", 1); /* append null terminator */
|
||||
Stream_Rewind(s, 1); /* don't include null terminator in length */
|
||||
Stream_SetLength(s, Stream_GetPosition(s));
|
||||
Stream_SealLength(s);
|
||||
return s;
|
||||
out_free:
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
free(lines[i]);
|
||||
|
||||
free(lines);
|
||||
fail:
|
||||
Stream_Free(s, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -433,6 +506,9 @@ static BOOL http_response_parse_header_status_line(HttpResponse* response, char*
|
||||
char* status_code;
|
||||
char* reason_phrase;
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
if (status_line)
|
||||
separator = strchr(status_line, ' ');
|
||||
|
||||
@ -470,6 +546,9 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (!response || !name)
|
||||
return FALSE;
|
||||
|
||||
if (_stricmp(name, "Content-Length") == 0)
|
||||
{
|
||||
unsigned long long val;
|
||||
@ -520,7 +599,7 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
|
||||
authValue = NULL;
|
||||
}
|
||||
|
||||
status = ListDictionary_Add(response->Authenticates, (void*)authScheme, (void*)authValue);
|
||||
status = ListDictionary_Add(response->Authenticates, authScheme, authValue);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -599,14 +678,17 @@ static BOOL http_response_parse_header(HttpResponse* response)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void http_response_print(HttpResponse* response)
|
||||
BOOL http_response_print(HttpResponse* response)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < response->count; i++)
|
||||
{
|
||||
WLog_ERR(TAG, "%s", response->lines[i]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HttpResponse* http_response_recv(rdpTls* tls)
|
||||
@ -642,7 +724,7 @@ HttpResponse* http_response_recv(rdpTls* tls)
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(Stream_Pointer(response->data), status);
|
||||
#endif
|
||||
Stream_Seek(response->data, status);
|
||||
Stream_Seek(response->data, (size_t)status);
|
||||
|
||||
if (Stream_GetRemainingLength(response->data) < 1024)
|
||||
{
|
||||
@ -749,7 +831,7 @@ HttpResponse* http_response_recv(rdpTls* tls)
|
||||
continue;
|
||||
}
|
||||
|
||||
Stream_Seek(response->data, status);
|
||||
Stream_Seek(response->data, (size_t)status);
|
||||
response->BodyLength += status;
|
||||
|
||||
if (response->BodyLength > RESPONSE_SIZE_LIMIT)
|
||||
@ -813,3 +895,55 @@ void http_response_free(HttpResponse* response)
|
||||
Stream_Free(response->data, TRUE);
|
||||
free(response);
|
||||
}
|
||||
|
||||
const char* http_request_get_uri(HttpRequest* request)
|
||||
{
|
||||
if (!request)
|
||||
return NULL;
|
||||
|
||||
return request->URI;
|
||||
}
|
||||
|
||||
SSIZE_T http_request_get_content_length(HttpRequest* request)
|
||||
{
|
||||
if (!request)
|
||||
return -1;
|
||||
|
||||
return (SSIZE_T)request->ContentLength;
|
||||
}
|
||||
|
||||
BOOL http_request_set_content_length(HttpRequest* request, size_t length)
|
||||
{
|
||||
if (!request)
|
||||
return FALSE;
|
||||
|
||||
request->ContentLength = length;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
long http_response_get_status_code(HttpResponse* response)
|
||||
{
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
return response->StatusCode;
|
||||
}
|
||||
|
||||
SSIZE_T http_response_get_body_length(HttpResponse* response)
|
||||
{
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
return (SSIZE_T)response->BodyLength;
|
||||
}
|
||||
|
||||
const char* http_response_get_auth_token(HttpResponse* respone, const char* method)
|
||||
{
|
||||
if (!respone || !method)
|
||||
return NULL;
|
||||
|
||||
if (!ListDictionary_Contains(respone->Authenticates, method))
|
||||
return NULL;
|
||||
|
||||
return ListDictionary_GetItemValue(respone->Authenticates, method);
|
||||
}
|
||||
|
@ -20,33 +20,21 @@
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_HTTP_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_HTTP_H
|
||||
|
||||
typedef struct _http_context HttpContext;
|
||||
typedef struct _http_request HttpRequest;
|
||||
typedef struct _http_response HttpResponse;
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/crypto/tls.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winhttp.h>
|
||||
|
||||
struct _http_context
|
||||
{
|
||||
char* Method;
|
||||
char* URI;
|
||||
char* UserAgent;
|
||||
char* Host;
|
||||
char* Accept;
|
||||
char* CacheControl;
|
||||
char* Connection;
|
||||
char* Pragma;
|
||||
char* RdgConnectionId;
|
||||
char* RdgAuthScheme;
|
||||
};
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/crypto/tls.h>
|
||||
|
||||
/* HTTP context */
|
||||
typedef struct _http_context HttpContext;
|
||||
|
||||
FREERDP_LOCAL HttpContext* http_context_new(void);
|
||||
FREERDP_LOCAL void http_context_free(HttpContext* context);
|
||||
|
||||
FREERDP_LOCAL BOOL http_context_set_method(HttpContext* context,
|
||||
const char* Method);
|
||||
FREERDP_LOCAL const char* http_context_get_uri(HttpContext* context);
|
||||
FREERDP_LOCAL BOOL http_context_set_uri(HttpContext* context, const char* URI);
|
||||
FREERDP_LOCAL BOOL http_context_set_user_agent(HttpContext* context,
|
||||
const char* UserAgent);
|
||||
@ -65,23 +53,18 @@ FREERDP_LOCAL BOOL http_context_set_rdg_connection_id(HttpContext* context,
|
||||
FREERDP_LOCAL BOOL http_context_set_rdg_auth_scheme(HttpContext* context,
|
||||
const char* RdgAuthScheme);
|
||||
|
||||
HttpContext* http_context_new(void);
|
||||
void http_context_free(HttpContext* context);
|
||||
/* HTTP request */
|
||||
typedef struct _http_request HttpRequest;
|
||||
|
||||
struct _http_request
|
||||
{
|
||||
char* Method;
|
||||
char* URI;
|
||||
char* AuthScheme;
|
||||
char* AuthParam;
|
||||
char* Authorization;
|
||||
int ContentLength;
|
||||
char* Content;
|
||||
char* TransferEncoding;
|
||||
};
|
||||
FREERDP_LOCAL HttpRequest* http_request_new(void);
|
||||
FREERDP_LOCAL void http_request_free(HttpRequest* request);
|
||||
|
||||
FREERDP_LOCAL BOOL http_request_set_method(HttpRequest* request,
|
||||
const char* Method);
|
||||
FREERDP_LOCAL SSIZE_T http_request_get_content_length(HttpRequest* request);
|
||||
FREERDP_LOCAL BOOL http_request_set_content_length(HttpRequest* request, size_t length);
|
||||
|
||||
FREERDP_LOCAL const char* http_request_get_uri(HttpRequest* request);
|
||||
FREERDP_LOCAL BOOL http_request_set_uri(HttpRequest* request, const char* URI);
|
||||
FREERDP_LOCAL BOOL http_request_set_auth_scheme(HttpRequest* request,
|
||||
const char* AuthScheme);
|
||||
@ -93,32 +76,17 @@ FREERDP_LOCAL BOOL http_request_set_transfer_encoding(HttpRequest* request,
|
||||
FREERDP_LOCAL wStream* http_request_write(HttpContext* context,
|
||||
HttpRequest* request);
|
||||
|
||||
FREERDP_LOCAL HttpRequest* http_request_new(void);
|
||||
FREERDP_LOCAL void http_request_free(HttpRequest* request);
|
||||
|
||||
struct _http_response
|
||||
{
|
||||
size_t count;
|
||||
char** lines;
|
||||
|
||||
long StatusCode;
|
||||
const char* ReasonPhrase;
|
||||
|
||||
size_t ContentLength;
|
||||
const char* ContentType;
|
||||
|
||||
size_t BodyLength;
|
||||
BYTE* BodyContent;
|
||||
|
||||
wListDictionary* Authenticates;
|
||||
wStream* data;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL void http_response_print(HttpResponse* response);
|
||||
|
||||
FREERDP_LOCAL HttpResponse* http_response_recv(rdpTls* tls);
|
||||
/* HTTP response */
|
||||
typedef struct _http_response HttpResponse;
|
||||
|
||||
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 long http_response_get_status_code(HttpResponse* response);
|
||||
FREERDP_LOCAL SSIZE_T http_response_get_body_length(HttpResponse* response);
|
||||
FREERDP_LOCAL const char* http_response_get_auth_token(HttpResponse* respone, const char* method);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_HTTP_H */
|
||||
|
@ -31,87 +31,111 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.ntlm")
|
||||
|
||||
static wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method,
|
||||
static wStream* rpc_ntlm_http_request(HttpContext* http, const char* method,
|
||||
int contentLength, SecBuffer* ntlmToken)
|
||||
{
|
||||
wStream* s;
|
||||
HttpRequest* request;
|
||||
wStream* s = NULL;
|
||||
HttpRequest* request = NULL;
|
||||
char* base64NtlmToken = NULL;
|
||||
const char* uri;
|
||||
|
||||
if (!http || !method || !ntlmToken)
|
||||
goto fail;
|
||||
|
||||
request = http_request_new();
|
||||
|
||||
if (ntlmToken)
|
||||
base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);
|
||||
|
||||
http_request_set_method(request, method);
|
||||
request->ContentLength = contentLength;
|
||||
http_request_set_uri(request, http->URI);
|
||||
uri = http_context_get_uri(http);
|
||||
|
||||
if (!http_request_set_method(request, method) ||
|
||||
!http_request_set_content_length(request, contentLength) ||
|
||||
!http_request_set_uri(request, uri))
|
||||
return NULL;
|
||||
|
||||
if (base64NtlmToken)
|
||||
{
|
||||
http_request_set_auth_scheme(request, "NTLM");
|
||||
http_request_set_auth_param(request, base64NtlmToken);
|
||||
if (!http_request_set_auth_scheme(request, "NTLM") ||
|
||||
!http_request_set_auth_param(request, base64NtlmToken))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s = http_request_write(http, request);
|
||||
fail:
|
||||
http_request_free(request);
|
||||
free(base64NtlmToken);
|
||||
return s;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel)
|
||||
BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
|
||||
{
|
||||
wStream* s;
|
||||
int status;
|
||||
int contentLength;
|
||||
BOOL continueNeeded;
|
||||
rdpNtlm* ntlm = inChannel->ntlm;
|
||||
HttpContext* http = inChannel->http;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
const SecBuffer* buffer;
|
||||
|
||||
if (!inChannel || !inChannel->ntlm || !inChannel->http)
|
||||
return FALSE;
|
||||
|
||||
ntlm = inChannel->ntlm;
|
||||
http = inChannel->http;
|
||||
continueNeeded = ntlm_authenticate(ntlm);
|
||||
contentLength = (continueNeeded) ? 0 : 0x40000000;
|
||||
s = rpc_ntlm_http_request(rpc, http, "RPC_IN_DATA", contentLength, &ntlm->outputBuffer[0]);
|
||||
buffer = ntlm_client_get_output_buffer(ntlm);
|
||||
s = rpc_ntlm_http_request(http, "RPC_IN_DATA", contentLength, buffer);
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
status = rpc_in_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
|
||||
status = rpc_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
|
||||
Stream_Free(s, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel,
|
||||
BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel,
|
||||
HttpResponse* response)
|
||||
{
|
||||
char* token64 = NULL;
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm = inChannel->ntlm;
|
||||
rdpNtlm* ntlm;
|
||||
|
||||
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
|
||||
{
|
||||
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
|
||||
if (!inChannel || !response || !inChannel->ntlm)
|
||||
return FALSE;
|
||||
|
||||
if (!token64)
|
||||
return -1;
|
||||
ntlm = inChannel->ntlm;
|
||||
token64 = http_response_get_auth_token(response, "NTLM");
|
||||
|
||||
if (token64)
|
||||
crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
|
||||
}
|
||||
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
{
|
||||
ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
|
||||
ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
|
||||
}
|
||||
return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength);
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
BOOL rpc_ncacn_http_ntlm_init(rdpContext* context, RpcChannel* channel)
|
||||
{
|
||||
rdpTls* tls = channel->tls;
|
||||
rdpNtlm* ntlm = channel->ntlm;
|
||||
rdpContext* context = rpc->context;
|
||||
rdpSettings* settings = rpc->settings;
|
||||
freerdp* instance = context->instance;
|
||||
rdpTls* tls;
|
||||
rdpNtlm* ntlm;
|
||||
rdpSettings* settings;
|
||||
freerdp* instance;
|
||||
|
||||
if (!context || !channel)
|
||||
return FALSE;
|
||||
|
||||
tls = channel->tls;
|
||||
ntlm = channel->ntlm;
|
||||
settings = context->settings;
|
||||
instance = context->instance;
|
||||
|
||||
if (!tls || !ntlm || !instance || !settings)
|
||||
return FALSE;
|
||||
|
||||
if (!settings->GatewayPassword || !settings->GatewayUsername ||
|
||||
!strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername))
|
||||
@ -124,7 +148,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
if (!proceed)
|
||||
{
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (settings->GatewayUseSameCredentials)
|
||||
@ -134,7 +158,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
free(settings->Username);
|
||||
|
||||
if (!(settings->Username = _strdup(settings->GatewayUsername)))
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (settings->GatewayDomain)
|
||||
@ -142,7 +166,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
free(settings->Domain);
|
||||
|
||||
if (!(settings->Domain = _strdup(settings->GatewayDomain)))
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (settings->GatewayPassword)
|
||||
@ -150,7 +174,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
free(settings->Password);
|
||||
|
||||
if (!(settings->Password = _strdup(settings->GatewayPassword)))
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,33 +183,42 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername,
|
||||
settings->GatewayDomain, settings->GatewayPassword, tls->Bindings))
|
||||
{
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname))
|
||||
{
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, RpcChannel* channel)
|
||||
void rpc_ncacn_http_ntlm_uninit(RpcChannel* channel)
|
||||
{
|
||||
ntlm_client_uninit(channel->ntlm);
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
ntlm_free(channel->ntlm);
|
||||
channel->ntlm = NULL;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel,
|
||||
BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel,
|
||||
BOOL replacement)
|
||||
{
|
||||
BOOL rc = TRUE;
|
||||
wStream* s;
|
||||
int status;
|
||||
int contentLength;
|
||||
BOOL continueNeeded;
|
||||
rdpNtlm* ntlm = outChannel->ntlm;
|
||||
HttpContext* http = outChannel->http;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
const SecBuffer* buffer;
|
||||
|
||||
if (!outChannel || !outChannel->ntlm || !outChannel->http)
|
||||
return FALSE;
|
||||
|
||||
ntlm = outChannel->ntlm;
|
||||
http = outChannel->http;
|
||||
continueNeeded = ntlm_authenticate(ntlm);
|
||||
|
||||
if (!replacement)
|
||||
@ -193,39 +226,38 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChann
|
||||
else
|
||||
contentLength = (continueNeeded) ? 0 : 120;
|
||||
|
||||
s = rpc_ntlm_http_request(rpc, http, "RPC_OUT_DATA", contentLength, &ntlm->outputBuffer[0]);
|
||||
buffer = ntlm_client_get_output_buffer(ntlm);
|
||||
s = rpc_ntlm_http_request(http, "RPC_OUT_DATA", contentLength, buffer);
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
status = rpc_out_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s));
|
||||
if (rpc_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s)) < 0)
|
||||
rc = FALSE;
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel,
|
||||
BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel,
|
||||
HttpResponse* response)
|
||||
{
|
||||
char* token64 = NULL;
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm = outChannel->ntlm;
|
||||
rdpNtlm* ntlm;
|
||||
|
||||
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
|
||||
{
|
||||
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
|
||||
if (!outChannel || !response || !outChannel->ntlm)
|
||||
return FALSE;
|
||||
|
||||
if (!token64)
|
||||
return -1;
|
||||
ntlm = outChannel->ntlm;
|
||||
token64 = http_response_get_auth_token(response, "NTLM");
|
||||
|
||||
if (token64)
|
||||
crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
|
||||
}
|
||||
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
{
|
||||
ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
|
||||
ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
|
||||
}
|
||||
return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength);
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -20,29 +20,21 @@
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
#include <freerdp/crypto/tls.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "rpc.h"
|
||||
#include "http.h"
|
||||
|
||||
FREERDP_LOCAL int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel);
|
||||
FREERDP_LOCAL void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, RpcChannel* channel);
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_ntlm_init(rdpContext* context, RpcChannel* channel);
|
||||
FREERDP_LOCAL void rpc_ncacn_http_ntlm_uninit(RpcChannel* channel);
|
||||
|
||||
FREERDP_LOCAL int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc,
|
||||
RpcInChannel* inChannel);
|
||||
FREERDP_LOCAL int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc,
|
||||
RpcInChannel* inChannel, HttpResponse* response);
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel);
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel,
|
||||
HttpResponse* response);
|
||||
|
||||
FREERDP_LOCAL int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc,
|
||||
RpcOutChannel* outChannel, BOOL replacement);
|
||||
FREERDP_LOCAL int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc,
|
||||
RpcOutChannel* outChannel, HttpResponse* response);
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel,
|
||||
BOOL replacement);
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel,
|
||||
HttpResponse* response);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H */
|
||||
|
@ -35,7 +35,46 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.ntlm")
|
||||
|
||||
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password,
|
||||
struct rdp_ntlm
|
||||
{
|
||||
BOOL http;
|
||||
CtxtHandle context;
|
||||
ULONG cbMaxToken;
|
||||
ULONG fContextReq;
|
||||
ULONG pfContextAttr;
|
||||
TimeStamp expiration;
|
||||
PSecBuffer pBuffer;
|
||||
SecBuffer inputBuffer[2];
|
||||
SecBuffer outputBuffer[2];
|
||||
BOOL haveContext;
|
||||
BOOL haveInputBuffer;
|
||||
LPTSTR ServicePrincipalName;
|
||||
SecBufferDesc inputBufferDesc;
|
||||
SecBufferDesc outputBufferDesc;
|
||||
CredHandle credentials;
|
||||
BOOL confidentiality;
|
||||
SecPkgInfo* pPackageInfo;
|
||||
SecurityFunctionTable* table;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SecPkgContext_Sizes ContextSizes;
|
||||
SecPkgContext_Bindings* Bindings;
|
||||
};
|
||||
|
||||
static ULONG cast_from_size_(size_t size, const char* fkt, const char* file, int line)
|
||||
{
|
||||
if (size > ULONG_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s %s:%d] Size %"PRIdz" is larger than INT_MAX %lu", fkt, file, line, size,
|
||||
ULONG_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (ULONG) size;
|
||||
}
|
||||
|
||||
#define cast_from_size(size) cast_from_size_(size, __FUNCTION__, __FILE__, __LINE__)
|
||||
|
||||
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, LPCTSTR user, LPCTSTR domain, LPCTSTR password,
|
||||
SecPkgContext_Bindings* Bindings)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
@ -96,7 +135,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname)
|
||||
BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, LPCTSTR hostname)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
DWORD SpnLength = 0;
|
||||
@ -272,7 +311,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
return (status == SEC_I_CONTINUE_NEEDED) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void ntlm_client_uninit(rdpNtlm* ntlm)
|
||||
static void ntlm_client_uninit(rdpNtlm* ntlm)
|
||||
{
|
||||
free(ntlm->identity.User);
|
||||
ntlm->identity.User = NULL;
|
||||
@ -335,3 +374,87 @@ void ntlm_free(rdpNtlm* ntlm)
|
||||
ntlm_client_uninit(ntlm);
|
||||
free(ntlm);
|
||||
}
|
||||
|
||||
SSIZE_T ntlm_client_get_context_max_size(rdpNtlm* ntlm)
|
||||
{
|
||||
if (!ntlm)
|
||||
return -1;
|
||||
|
||||
if (ntlm->ContextSizes.cbMaxSignature > UINT16_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES ContextSizes.cbMaxSignature > 0xFFFF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ntlm->ContextSizes.cbMaxSignature;
|
||||
}
|
||||
|
||||
SSIZE_T ntlm_client_query_auth_size(rdpNtlm* ntlm)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
|
||||
if (!ntlm || !ntlm->table || !ntlm->table->QueryContextAttributes)
|
||||
return -1;
|
||||
|
||||
status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES,
|
||||
&ntlm->ContextSizes);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [0x%08"PRIX32"]",
|
||||
GetSecurityStatusString(status), status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ntlm_client_get_context_max_size(ntlm);
|
||||
}
|
||||
|
||||
BOOL ntlm_client_encrypt(rdpNtlm* ntlm, ULONG fQOP, SecBufferDesc* Message, size_t sequence)
|
||||
{
|
||||
SECURITY_STATUS encrypt_status;
|
||||
const ULONG s = cast_from_size(sequence);
|
||||
|
||||
if (!ntlm || !Message)
|
||||
return FALSE;
|
||||
|
||||
encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, fQOP, Message, s);
|
||||
|
||||
if (encrypt_status != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]",
|
||||
GetSecurityStatusString(encrypt_status), encrypt_status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL ntlm_client_set_input_buffer(rdpNtlm* ntlm, BOOL copy, const void* data, size_t size)
|
||||
{
|
||||
if (!ntlm || !data || (size == 0))
|
||||
return FALSE;
|
||||
|
||||
ntlm->inputBuffer[0].cbBuffer = cast_from_size(size);
|
||||
|
||||
if (copy)
|
||||
{
|
||||
ntlm->inputBuffer[0].pvBuffer = malloc(size);
|
||||
|
||||
if (!ntlm->inputBuffer[0].pvBuffer)
|
||||
return FALSE;
|
||||
|
||||
memcpy(ntlm->inputBuffer[0].pvBuffer, data, size);
|
||||
}
|
||||
else
|
||||
ntlm->inputBuffer[0].pvBuffer = (void*)data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const SecBuffer* ntlm_client_get_output_buffer(rdpNtlm* ntlm)
|
||||
{
|
||||
if (!ntlm)
|
||||
return NULL;
|
||||
|
||||
return &ntlm->outputBuffer[0];
|
||||
}
|
||||
|
@ -24,58 +24,30 @@
|
||||
|
||||
typedef struct rdp_ntlm rdpNtlm;
|
||||
|
||||
#include "../tcp.h"
|
||||
#include "../transport.h"
|
||||
|
||||
#include "rts.h"
|
||||
#include "http.h"
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/crypto/tls.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
struct rdp_ntlm
|
||||
{
|
||||
BOOL http;
|
||||
CtxtHandle context;
|
||||
ULONG cbMaxToken;
|
||||
ULONG fContextReq;
|
||||
ULONG pfContextAttr;
|
||||
TimeStamp expiration;
|
||||
PSecBuffer pBuffer;
|
||||
SecBuffer inputBuffer[2];
|
||||
SecBuffer outputBuffer[2];
|
||||
BOOL haveContext;
|
||||
BOOL haveInputBuffer;
|
||||
LPTSTR ServicePrincipalName;
|
||||
SecBufferDesc inputBufferDesc;
|
||||
SecBufferDesc outputBufferDesc;
|
||||
CredHandle credentials;
|
||||
BOOL confidentiality;
|
||||
SecPkgInfo* pPackageInfo;
|
||||
SecurityFunctionTable* table;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SecPkgContext_Sizes ContextSizes;
|
||||
SecPkgContext_Bindings* Bindings;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_authenticate(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality,
|
||||
char* user,
|
||||
char* domain, char* password, SecPkgContext_Bindings* Bindings);
|
||||
FREERDP_LOCAL void ntlm_client_uninit(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass,
|
||||
char* hostname);
|
||||
|
||||
FREERDP_LOCAL rdpNtlm* ntlm_new(void);
|
||||
FREERDP_LOCAL void ntlm_free(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_authenticate(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality,
|
||||
LPCTSTR user, LPCTSTR domain,
|
||||
LPCTSTR password, SecPkgContext_Bindings* Bindings);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass,
|
||||
LPCTSTR hostname);
|
||||
|
||||
FREERDP_LOCAL SSIZE_T ntlm_client_query_auth_size(rdpNtlm* ntlm);
|
||||
FREERDP_LOCAL SSIZE_T ntlm_client_get_context_max_size(rdpNtlm* ntlm);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_encrypt(rdpNtlm* ntlm, ULONG fQOP, SecBufferDesc* Message,
|
||||
size_t sequence);
|
||||
|
||||
FREERDP_LOCAL BOOL ntlm_client_set_input_buffer(rdpNtlm* ntlm, BOOL copy, const void* data,
|
||||
size_t size);
|
||||
FREERDP_LOCAL const SecBuffer* ntlm_client_get_output_buffer(rdpNtlm* ntlm);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_NTLM_H */
|
||||
|
@ -300,7 +300,7 @@ static BOOL rdg_send_channel_create(rdpRdg* rdg)
|
||||
|
||||
static BOOL rdg_set_ntlm_auth_header(rdpNtlm* ntlm, HttpRequest* request)
|
||||
{
|
||||
SecBuffer* ntlmToken = ntlm->outputBuffer;
|
||||
const SecBuffer* ntlmToken = ntlm_client_get_output_buffer(ntlm);
|
||||
char* base64NtlmToken = NULL;
|
||||
|
||||
if (ntlmToken)
|
||||
@ -308,11 +308,11 @@ static BOOL rdg_set_ntlm_auth_header(rdpNtlm* ntlm, HttpRequest* request)
|
||||
|
||||
if (base64NtlmToken)
|
||||
{
|
||||
http_request_set_auth_scheme(request, "NTLM");
|
||||
http_request_set_auth_param(request, base64NtlmToken);
|
||||
BOOL rc = http_request_set_auth_scheme(request, "NTLM") &&
|
||||
http_request_set_auth_param(request, base64NtlmToken);
|
||||
free(base64NtlmToken);
|
||||
|
||||
if (!request->AuthScheme || !request->AuthParam)
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -324,16 +324,19 @@ static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method,
|
||||
{
|
||||
wStream* s = NULL;
|
||||
HttpRequest* request = NULL;
|
||||
assert(method != NULL);
|
||||
const char* uri;
|
||||
|
||||
if (!rdg || !method || !transferEncoding)
|
||||
return NULL;
|
||||
|
||||
uri = http_context_get_uri(rdg->http);
|
||||
request = http_request_new();
|
||||
|
||||
if (!request)
|
||||
return NULL;
|
||||
|
||||
http_request_set_method(request, method);
|
||||
http_request_set_uri(request, rdg->http->URI);
|
||||
|
||||
if (!request->Method || !request->URI)
|
||||
if (!http_request_set_method(request, method) ||
|
||||
!http_request_set_uri(request, uri))
|
||||
goto out;
|
||||
|
||||
if (rdg->ntlm)
|
||||
@ -359,18 +362,24 @@ out:
|
||||
|
||||
static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
|
||||
{
|
||||
char* token64 = NULL;
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
long StatusCode;
|
||||
|
||||
if (response->StatusCode != HTTP_STATUS_DENIED)
|
||||
if (!ntlm || !response)
|
||||
return FALSE;
|
||||
|
||||
StatusCode = http_response_get_status_code(response);
|
||||
|
||||
if (StatusCode != HTTP_STATUS_DENIED)
|
||||
{
|
||||
WLog_DBG(TAG, "Unexpected NTLM challenge HTTP status: %d",
|
||||
response->StatusCode);
|
||||
WLog_DBG(TAG, "Unexpected NTLM challenge HTTP status: %ld",
|
||||
StatusCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
|
||||
token64 = http_response_get_auth_token(response, "NTLM");
|
||||
|
||||
if (!token64)
|
||||
return FALSE;
|
||||
@ -379,8 +388,8 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
|
||||
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
{
|
||||
ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
|
||||
ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
|
||||
if (!ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ntlm_authenticate(ntlm);
|
||||
@ -733,6 +742,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
||||
HttpResponse* response = NULL;
|
||||
int statusCode;
|
||||
int bodyLength;
|
||||
long StatusCode;
|
||||
|
||||
if (!rdg_tls_connect(rdg, tls, peerAddress, timeout))
|
||||
return FALSE;
|
||||
@ -750,7 +760,9 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
if (response->StatusCode == HTTP_STATUS_NOT_FOUND)
|
||||
StatusCode = http_response_get_status_code(response);
|
||||
|
||||
if (StatusCode == HTTP_STATUS_NOT_FOUND)
|
||||
{
|
||||
WLog_INFO(TAG, "RD Gateway does not support HTTP transport.");
|
||||
|
||||
@ -779,8 +791,8 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
statusCode = response->StatusCode;
|
||||
bodyLength = response->BodyLength;
|
||||
statusCode = http_response_get_status_code(response);
|
||||
bodyLength = http_response_get_body_length(response);
|
||||
http_response_free(response);
|
||||
WLog_DBG(TAG, "%s authorization result: %d", method, statusCode);
|
||||
|
||||
@ -1285,18 +1297,14 @@ rdpRdg* rdg_new(rdpTransport* transport)
|
||||
if (!rdg->http)
|
||||
goto rdg_alloc_error;
|
||||
|
||||
http_context_set_uri(rdg->http, "/remoteDesktopGateway/");
|
||||
http_context_set_accept(rdg->http, "*/*");
|
||||
http_context_set_cache_control(rdg->http, "no-cache");
|
||||
http_context_set_pragma(rdg->http, "no-cache");
|
||||
http_context_set_connection(rdg->http, "Keep-Alive");
|
||||
http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0");
|
||||
http_context_set_host(rdg->http, rdg->settings->GatewayHostname);
|
||||
http_context_set_rdg_connection_id(rdg->http, bracedUuid);
|
||||
|
||||
if (!rdg->http->URI || !rdg->http->Accept || !rdg->http->CacheControl ||
|
||||
!rdg->http->Pragma || !rdg->http->Connection || !rdg->http->UserAgent
|
||||
|| !rdg->http->Host || !rdg->http->RdgConnectionId)
|
||||
if (!http_context_set_uri(rdg->http, "/remoteDesktopGateway/") ||
|
||||
!http_context_set_accept(rdg->http, "*/*") ||
|
||||
!http_context_set_cache_control(rdg->http, "no-cache") ||
|
||||
!http_context_set_pragma(rdg->http, "no-cache") ||
|
||||
!http_context_set_connection(rdg->http, "Keep-Alive") ||
|
||||
!http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0") ||
|
||||
!http_context_set_host(rdg->http, rdg->settings->GatewayHostname) ||
|
||||
!http_context_set_rdg_connection_id(rdg->http, bracedUuid))
|
||||
{
|
||||
goto rdg_alloc_error;
|
||||
}
|
||||
@ -1306,9 +1314,7 @@ rdpRdg* rdg_new(rdpTransport* transport)
|
||||
switch (rdg->extAuth)
|
||||
{
|
||||
case HTTP_EXTENDED_AUTH_PAA:
|
||||
http_context_set_rdg_auth_scheme(rdg->http, "PAA");
|
||||
|
||||
if (!rdg->http->RdgAuthScheme)
|
||||
if (!http_context_set_rdg_auth_scheme(rdg->http, "PAA"))
|
||||
goto rdg_alloc_error;
|
||||
|
||||
break;
|
||||
|
@ -327,42 +327,43 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length)
|
||||
SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length)
|
||||
{
|
||||
int status;
|
||||
status = BIO_read(outChannel->tls->bio, data, length);
|
||||
|
||||
if (!channel)
|
||||
return -1;
|
||||
|
||||
status = BIO_read(channel->tls->bio, Stream_Pointer(s), length);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(data, status);
|
||||
#endif
|
||||
Stream_Seek(s, (size_t)status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (BIO_should_retry(outChannel->tls->bio))
|
||||
if (BIO_should_retry(channel->tls->bio))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpc_in_channel_write(RpcInChannel* inChannel, const BYTE* data, int length)
|
||||
SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length)
|
||||
{
|
||||
int status;
|
||||
status = tls_write_all(inChannel->tls, data, length);
|
||||
|
||||
if (!channel)
|
||||
return -1;
|
||||
|
||||
status = tls_write_all(channel->tls, data, length);
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length)
|
||||
BOOL rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
|
||||
{
|
||||
int status;
|
||||
status = tls_write_all(outChannel->tls, data, length);
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
|
||||
{
|
||||
int status = 1;
|
||||
const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
@ -396,67 +397,65 @@ int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNE
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inChannel)
|
||||
return FALSE;
|
||||
|
||||
inChannel->State = state;
|
||||
WLog_DBG(TAG, "%s", str);
|
||||
return status;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel)
|
||||
static int rpc_channel_rpch_init(RpcClient* client, RpcChannel* channel, const char* inout)
|
||||
{
|
||||
HttpContext* http;
|
||||
inChannel->ntlm = ntlm_new();
|
||||
rdpSettings* settings;
|
||||
|
||||
if (!inChannel->ntlm)
|
||||
if (!client || !channel || !inout || !client->context || !client->context->settings)
|
||||
return -1;
|
||||
|
||||
inChannel->http = http_context_new();
|
||||
settings = client->context->settings;
|
||||
channel->ntlm = ntlm_new();
|
||||
rts_generate_cookie((BYTE*) &channel->Cookie);
|
||||
channel->client = client;
|
||||
|
||||
if (!inChannel->http)
|
||||
if (!channel->ntlm)
|
||||
return -1;
|
||||
|
||||
channel->http = http_context_new();
|
||||
|
||||
if (!channel->http)
|
||||
return -1;
|
||||
|
||||
http = channel->http;
|
||||
|
||||
if (!http_context_set_method(http, inout) ||
|
||||
!http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388") ||
|
||||
!http_context_set_accept(http, "application/rpc") ||
|
||||
!http_context_set_cache_control(http, "no-cache") ||
|
||||
!http_context_set_connection(http, "Keep-Alive") || !http_context_set_user_agent(http, "MSRPC") ||
|
||||
!http_context_set_host(http, settings->GatewayHostname) ||
|
||||
!http_context_set_pragma(http,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
"SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"))
|
||||
return -1;
|
||||
|
||||
http = inChannel->http;
|
||||
http_context_set_method(http, "RPC_IN_DATA");
|
||||
http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388");
|
||||
http_context_set_accept(http, "application/rpc");
|
||||
http_context_set_cache_control(http, "no-cache");
|
||||
http_context_set_connection(http, "Keep-Alive");
|
||||
http_context_set_user_agent(http, "MSRPC");
|
||||
http_context_set_host(http, rpc->settings->GatewayHostname);
|
||||
http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel)
|
||||
{
|
||||
rts_generate_cookie((BYTE*) &inChannel->Cookie);
|
||||
inChannel->rpc = rpc;
|
||||
inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
|
||||
inChannel->BytesSent = 0;
|
||||
inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
|
||||
inChannel->PingOriginator.ConnectionTimeout = 30;
|
||||
inChannel->PingOriginator.KeepAliveInterval = 0;
|
||||
|
||||
if (rpc_in_channel_rpch_init(rpc, inChannel) < 0)
|
||||
if (rpc_channel_rpch_init(rpc->client, &inChannel->common, "RPC_IN_DATA") < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel)
|
||||
{
|
||||
if (inChannel->ntlm)
|
||||
{
|
||||
ntlm_free(inChannel->ntlm);
|
||||
inChannel->ntlm = NULL;
|
||||
}
|
||||
|
||||
if (inChannel->http)
|
||||
{
|
||||
http_context_free(inChannel->http);
|
||||
inChannel->http = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc)
|
||||
{
|
||||
RpcInChannel* inChannel = NULL;
|
||||
@ -470,25 +469,19 @@ static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc)
|
||||
return inChannel;
|
||||
}
|
||||
|
||||
static void rpc_in_channel_free(RpcInChannel* inChannel)
|
||||
void rpc_channel_free(RpcChannel* channel)
|
||||
{
|
||||
if (!inChannel)
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
rpc_in_channel_rpch_uninit(inChannel);
|
||||
|
||||
if (inChannel->tls)
|
||||
{
|
||||
tls_free(inChannel->tls);
|
||||
inChannel->tls = NULL;
|
||||
}
|
||||
|
||||
free(inChannel);
|
||||
ntlm_free(channel->ntlm);
|
||||
http_context_free(channel->http);
|
||||
tls_free(channel->tls);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
|
||||
BOOL rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
|
||||
{
|
||||
int status = 1;
|
||||
const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
@ -534,42 +527,16 @@ int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CH
|
||||
break;
|
||||
}
|
||||
|
||||
if (!outChannel)
|
||||
return FALSE;
|
||||
|
||||
outChannel->State = state;
|
||||
WLog_DBG(TAG, "%s", str);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel)
|
||||
{
|
||||
HttpContext* http;
|
||||
outChannel->ntlm = ntlm_new();
|
||||
|
||||
if (!outChannel->ntlm)
|
||||
return -1;
|
||||
|
||||
outChannel->http = http_context_new();
|
||||
|
||||
if (!outChannel->http)
|
||||
return -1;
|
||||
|
||||
http = outChannel->http;
|
||||
http_context_set_method(http, "RPC_OUT_DATA");
|
||||
http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388");
|
||||
http_context_set_accept(http, "application/rpc");
|
||||
http_context_set_cache_control(http, "no-cache");
|
||||
http_context_set_connection(http, "Keep-Alive");
|
||||
http_context_set_user_agent(http, "MSRPC");
|
||||
http_context_set_host(http, rpc->settings->GatewayHostname);
|
||||
http_context_set_pragma(http,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
"SessionId=fbd9c34f-397d-471d-a109-1b08cc554624");
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
|
||||
{
|
||||
rts_generate_cookie((BYTE*) &outChannel->Cookie);
|
||||
outChannel->rpc = rpc;
|
||||
outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
|
||||
outChannel->BytesReceived = 0;
|
||||
outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
|
||||
@ -577,27 +544,12 @@ static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
|
||||
outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
|
||||
outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
|
||||
|
||||
if (rpc_out_channel_rpch_init(rpc, outChannel) < 0)
|
||||
if (rpc_channel_rpch_init(rpc->client, &outChannel->common, "RPC_OUT_DATA") < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel)
|
||||
{
|
||||
if (outChannel->ntlm)
|
||||
{
|
||||
ntlm_free(outChannel->ntlm);
|
||||
outChannel->ntlm = NULL;
|
||||
}
|
||||
|
||||
if (outChannel->http)
|
||||
{
|
||||
http_context_free(outChannel->http);
|
||||
outChannel->http = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc)
|
||||
{
|
||||
RpcOutChannel* outChannel = NULL;
|
||||
@ -611,26 +563,9 @@ RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc)
|
||||
return outChannel;
|
||||
}
|
||||
|
||||
void rpc_out_channel_free(RpcOutChannel* outChannel)
|
||||
{
|
||||
if (!outChannel)
|
||||
return;
|
||||
|
||||
rpc_out_channel_rpch_uninit(outChannel);
|
||||
|
||||
if (outChannel->tls)
|
||||
{
|
||||
tls_free(outChannel->tls);
|
||||
outChannel->tls = NULL;
|
||||
}
|
||||
|
||||
free(outChannel);
|
||||
}
|
||||
|
||||
int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state)
|
||||
{
|
||||
int status = 1;
|
||||
const char* str = "VIRTUAL_CONNECTION_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
@ -660,9 +595,12 @@ int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!connection)
|
||||
return FALSE;
|
||||
|
||||
connection->State = state;
|
||||
WLog_DBG(TAG, "%s", str);
|
||||
return status;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc)
|
||||
@ -699,34 +637,40 @@ static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
rpc_in_channel_free(connection->DefaultInChannel);
|
||||
rpc_in_channel_free(connection->NonDefaultInChannel);
|
||||
rpc_out_channel_free(connection->DefaultOutChannel);
|
||||
rpc_out_channel_free(connection->NonDefaultOutChannel);
|
||||
rpc_channel_free(&connection->DefaultInChannel->common);
|
||||
rpc_channel_free(&connection->NonDefaultInChannel->common);
|
||||
rpc_channel_free(&connection->DefaultOutChannel->common);
|
||||
rpc_channel_free(&connection->NonDefaultOutChannel->common);
|
||||
free(connection);
|
||||
}
|
||||
|
||||
static int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
{
|
||||
int sockfd;
|
||||
rdpTls* tls;
|
||||
int tlsStatus;
|
||||
BIO* socketBio;
|
||||
BIO* bufferedBio;
|
||||
rdpRpc* rpc = channel->rpc;
|
||||
rdpContext* context = rpc->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
const char* peerHostname = settings->GatewayHostname;
|
||||
UINT16 peerPort = settings->GatewayPort;
|
||||
const char* proxyUsername = settings->ProxyUsername, *proxyPassword = settings->ProxyPassword;
|
||||
BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, &proxyUsername,
|
||||
&proxyPassword);
|
||||
sockfd = freerdp_tcp_connect(context, settings, peerHostname,
|
||||
peerPort, timeout);
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
const char* proxyUsername;
|
||||
const char* proxyPassword;
|
||||
|
||||
if (sockfd < 0)
|
||||
return -1;
|
||||
if (!channel || !channel->client || !channel->client->context ||
|
||||
!channel->client->context->settings)
|
||||
return FALSE;
|
||||
|
||||
context = channel->client->context;
|
||||
settings = context->settings;
|
||||
proxyUsername = settings->ProxyUsername;
|
||||
proxyPassword = settings->ProxyPassword;
|
||||
{
|
||||
sockfd = freerdp_tcp_connect(context, settings, channel->client->host,
|
||||
channel->client->port, timeout);
|
||||
|
||||
if (sockfd < 0)
|
||||
return FALSE;
|
||||
}
|
||||
socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!socketBio)
|
||||
@ -741,20 +685,20 @@ static int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
bufferedBio = BIO_push(bufferedBio, socketBio);
|
||||
|
||||
if (!BIO_set_nonblock(bufferedBio, TRUE))
|
||||
return -1;
|
||||
return FALSE;
|
||||
|
||||
if (isProxyConnection)
|
||||
if (channel->client->isProxy)
|
||||
{
|
||||
if (!proxy_connect(settings, bufferedBio, proxyUsername, proxyPassword, settings->GatewayHostname,
|
||||
settings->GatewayPort))
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
channel->bio = bufferedBio;
|
||||
tls = channel->tls = tls_new(settings);
|
||||
|
||||
if (!tls)
|
||||
return -1;
|
||||
return FALSE;
|
||||
|
||||
tls->hostname = settings->GatewayHostname;
|
||||
tls->port = settings->GatewayPort;
|
||||
@ -774,55 +718,67 @@ static int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout)
|
||||
{
|
||||
rdpRpc* rpc = inChannel->rpc;
|
||||
rdpContext* context;
|
||||
|
||||
if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = inChannel->common.client->context;
|
||||
|
||||
/* Connect IN Channel */
|
||||
|
||||
if (rpc_channel_tls_connect((RpcChannel*) inChannel, timeout) < 0)
|
||||
if (!rpc_channel_tls_connect(&inChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) inChannel) < 0)
|
||||
if (!rpc_ncacn_http_ntlm_init(context, &inChannel->common))
|
||||
return -1;
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0)
|
||||
if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY);
|
||||
if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout)
|
||||
{
|
||||
rdpRpc* rpc = outChannel->rpc;
|
||||
rdpContext* context;
|
||||
|
||||
if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = outChannel->common.client->context;
|
||||
|
||||
/* Connect OUT Channel */
|
||||
|
||||
if (rpc_channel_tls_connect((RpcChannel*) outChannel, timeout) < 0)
|
||||
if (!rpc_channel_tls_connect(&outChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0)
|
||||
if (!rpc_ncacn_http_ntlm_init(context, &outChannel->common))
|
||||
return FALSE;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, FALSE) < 0)
|
||||
if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
@ -834,21 +790,26 @@ static int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout)
|
||||
|
||||
int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
|
||||
{
|
||||
rdpRpc* rpc = outChannel->rpc;
|
||||
rdpContext* context;
|
||||
|
||||
if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = outChannel->common.client->context;
|
||||
|
||||
/* Connect OUT Channel */
|
||||
|
||||
if (rpc_channel_tls_connect((RpcChannel*) outChannel, timeout) < 0)
|
||||
if (!rpc_channel_tls_connect(&outChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, (RpcChannel*) outChannel) < 0)
|
||||
if (!rpc_ncacn_http_ntlm_init(context, (RpcChannel*) outChannel))
|
||||
return FALSE;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, TRUE) < 0)
|
||||
if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
@ -917,15 +878,14 @@ rdpRpc* rpc_new(rdpTransport* transport)
|
||||
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
|
||||
rpc->CurrentKeepAliveTime = 0;
|
||||
rpc->CallId = 2;
|
||||
rpc->client = rpc_client_new(rpc->context, rpc->max_recv_frag);
|
||||
|
||||
if (rpc_client_new(rpc) < 0)
|
||||
goto out_free_rpc_client;
|
||||
if (!rpc->client)
|
||||
goto out_free;
|
||||
|
||||
return rpc;
|
||||
out_free_rpc_client:
|
||||
rpc_client_free(rpc);
|
||||
out_free:
|
||||
free(rpc);
|
||||
rpc_free(rpc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -933,21 +893,9 @@ void rpc_free(rdpRpc* rpc)
|
||||
{
|
||||
if (rpc)
|
||||
{
|
||||
rpc_client_free(rpc);
|
||||
|
||||
if (rpc->ntlm)
|
||||
{
|
||||
ntlm_client_uninit(rpc->ntlm);
|
||||
ntlm_free(rpc->ntlm);
|
||||
rpc->ntlm = NULL;
|
||||
}
|
||||
|
||||
if (rpc->VirtualConnection)
|
||||
{
|
||||
rpc_virtual_connection_free(rpc->VirtualConnection);
|
||||
rpc->VirtualConnection = NULL;
|
||||
}
|
||||
|
||||
rpc_client_free(rpc->client);
|
||||
ntlm_free(rpc->ntlm);
|
||||
rpc_virtual_connection_free(rpc->VirtualConnection);
|
||||
free(rpc);
|
||||
}
|
||||
}
|
||||
|
@ -585,17 +585,29 @@ struct rpc_client_call
|
||||
};
|
||||
typedef struct rpc_client_call RpcClientCall;
|
||||
|
||||
#define RPC_CHANNEL_COMMON() \
|
||||
rdpRpc* rpc; \
|
||||
BIO* bio; \
|
||||
rdpTls* tls; \
|
||||
rdpNtlm* ntlm; \
|
||||
HttpContext* http; \
|
||||
BYTE Cookie[16]
|
||||
struct rpc_client
|
||||
{
|
||||
rdpContext* context;
|
||||
RPC_PDU* pdu;
|
||||
HANDLE PipeEvent;
|
||||
RingBuffer ReceivePipe;
|
||||
wStream* ReceiveFragment;
|
||||
CRITICAL_SECTION PipeLock;
|
||||
wArrayList* ClientCallList;
|
||||
char* host;
|
||||
UINT16 port;
|
||||
BOOL isProxy;
|
||||
};
|
||||
typedef struct rpc_client RpcClient;
|
||||
|
||||
struct rpc_channel
|
||||
{
|
||||
RPC_CHANNEL_COMMON();
|
||||
RpcClient* client;
|
||||
BIO* bio;
|
||||
rdpTls* tls;
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
BYTE Cookie[16];
|
||||
};
|
||||
typedef struct rpc_channel RpcChannel;
|
||||
|
||||
@ -627,7 +639,7 @@ struct rpc_in_channel
|
||||
{
|
||||
/* Sending Channel */
|
||||
|
||||
RPC_CHANNEL_COMMON();
|
||||
RpcChannel common;
|
||||
|
||||
CLIENT_IN_CHANNEL_STATE State;
|
||||
|
||||
@ -664,7 +676,7 @@ struct rpc_out_channel
|
||||
{
|
||||
/* Receiving Channel */
|
||||
|
||||
RPC_CHANNEL_COMMON();
|
||||
RpcChannel common;
|
||||
|
||||
CLIENT_OUT_CHANNEL_STATE State;
|
||||
|
||||
@ -717,17 +729,6 @@ struct rpc_virtual_connection_cookie_entry
|
||||
typedef struct rpc_virtual_connection_cookie_entry
|
||||
RpcVirtualConnectionCookieEntry;
|
||||
|
||||
struct rpc_client
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
HANDLE PipeEvent;
|
||||
RingBuffer ReceivePipe;
|
||||
wStream* ReceiveFragment;
|
||||
CRITICAL_SECTION PipeLock;
|
||||
wArrayList* ClientCallList;
|
||||
};
|
||||
typedef struct rpc_client RpcClient;
|
||||
|
||||
struct rdp_rpc
|
||||
{
|
||||
RPC_CLIENT_STATE State;
|
||||
@ -774,25 +775,24 @@ FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad);
|
||||
FREERDP_LOCAL BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header,
|
||||
UINT32* offset, UINT32* length);
|
||||
|
||||
FREERDP_LOCAL int rpc_in_channel_write(RpcInChannel* inChannel,
|
||||
const BYTE* data, int length);
|
||||
FREERDP_LOCAL SSIZE_T rpc_channel_write(RpcChannel* channel,
|
||||
const BYTE* data, size_t length);
|
||||
|
||||
FREERDP_LOCAL int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data,
|
||||
int length);
|
||||
FREERDP_LOCAL int rpc_out_channel_write(RpcOutChannel* outChannel,
|
||||
const BYTE* data, int length);
|
||||
FREERDP_LOCAL SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s,
|
||||
size_t length);
|
||||
|
||||
FREERDP_LOCAL void rpc_channel_free(RpcChannel* channel);
|
||||
|
||||
FREERDP_LOCAL RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel,
|
||||
int timeout);
|
||||
FREERDP_LOCAL void rpc_out_channel_free(RpcOutChannel* outChannel);
|
||||
|
||||
FREERDP_LOCAL int rpc_in_channel_transition_to_state(RpcInChannel* inChannel,
|
||||
FREERDP_LOCAL BOOL rpc_in_channel_transition_to_state(RpcInChannel* inChannel,
|
||||
CLIENT_IN_CHANNEL_STATE state);
|
||||
FREERDP_LOCAL int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel,
|
||||
FREERDP_LOCAL BOOL rpc_out_channel_transition_to_state(RpcOutChannel* outChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE state);
|
||||
|
||||
FREERDP_LOCAL int rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
FREERDP_LOCAL BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, int timeout);
|
||||
|
@ -119,6 +119,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
freerdp* instance = (freerdp*) settings->instance;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
RpcInChannel* inChannel = connection->DefaultInChannel;
|
||||
const SecBuffer* sbuffer;
|
||||
WLog_DBG(TAG, "Sending Bind PDU");
|
||||
ntlm_free(rpc->ntlm);
|
||||
rpc->ntlm = ntlm_new();
|
||||
@ -172,9 +173,14 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
if (!bind_pdu)
|
||||
return -1;
|
||||
|
||||
sbuffer = ntlm_client_get_output_buffer(rpc->ntlm);
|
||||
|
||||
if (!sbuffer)
|
||||
return -1;
|
||||
|
||||
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) bind_pdu);
|
||||
bind_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer;
|
||||
bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer;
|
||||
bind_pdu->auth_length = (UINT16) sbuffer->cbBuffer;
|
||||
bind_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
bind_pdu->ptype = PTYPE_BIND;
|
||||
bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
|
||||
bind_pdu->call_id = 2;
|
||||
@ -293,16 +299,17 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
rpcconn_hdr_t* header;
|
||||
header = (rpcconn_hdr_t*) buffer;
|
||||
WLog_DBG(TAG, "Receiving BindAck PDU");
|
||||
rpc->max_recv_frag = header->bind_ack.max_xmit_frag;
|
||||
rpc->max_xmit_frag = header->bind_ack.max_recv_frag;
|
||||
rpc->ntlm->inputBuffer[0].cbBuffer = header->common.auth_length;
|
||||
rpc->ntlm->inputBuffer[0].pvBuffer = malloc(header->common.auth_length);
|
||||
|
||||
if (!rpc->ntlm->inputBuffer[0].pvBuffer)
|
||||
if (!rpc || !rpc->ntlm)
|
||||
return -1;
|
||||
|
||||
rpc->max_recv_frag = header->bind_ack.max_xmit_frag;
|
||||
rpc->max_xmit_frag = header->bind_ack.max_recv_frag;
|
||||
auth_data = buffer + (header->common.frag_length - header->common.auth_length);
|
||||
CopyMemory(rpc->ntlm->inputBuffer[0].pvBuffer, auth_data, header->common.auth_length);
|
||||
|
||||
if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header->common.auth_length))
|
||||
return -1;
|
||||
|
||||
ntlm_authenticate(rpc->ntlm);
|
||||
return (int) length;
|
||||
}
|
||||
@ -320,6 +327,7 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
BYTE* buffer;
|
||||
UINT32 offset;
|
||||
UINT32 length;
|
||||
const SecBuffer* sbuffer;
|
||||
RpcClientCall* clientCall;
|
||||
rpcconn_rpc_auth_3_hdr_t* auth_3_pdu;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
@ -330,9 +338,14 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
if (!auth_3_pdu)
|
||||
return -1;
|
||||
|
||||
sbuffer = ntlm_client_get_output_buffer(rpc->ntlm);
|
||||
|
||||
if (!sbuffer)
|
||||
return -1;
|
||||
|
||||
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu);
|
||||
auth_3_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer;
|
||||
auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer;
|
||||
auth_3_pdu->auth_length = (UINT16) sbuffer->cbBuffer;
|
||||
auth_3_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
auth_3_pdu->ptype = PTYPE_RPC_AUTH_3;
|
||||
auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
|
||||
auth_3_pdu->call_id = 2;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "rpc_fault.h"
|
||||
#include "rpc_client.h"
|
||||
#include "../rdp.h"
|
||||
#include "../proxy.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
@ -76,11 +77,14 @@ static void rpc_pdu_free(RPC_PDU* pdu)
|
||||
free(pdu);
|
||||
}
|
||||
|
||||
static int rpc_client_receive_pipe_write(rdpRpc* rpc, const BYTE* buffer, size_t length)
|
||||
static int rpc_client_receive_pipe_write(RpcClient* client, const BYTE* buffer, size_t length)
|
||||
{
|
||||
int status = 0;
|
||||
RpcClient* client = rpc->client;
|
||||
EnterCriticalSection(&(rpc->client->PipeLock));
|
||||
|
||||
if (!client || !buffer)
|
||||
return -1;
|
||||
|
||||
EnterCriticalSection(&(client->PipeLock));
|
||||
|
||||
if (ringbuffer_write(&(client->ReceivePipe), buffer, length))
|
||||
status += (int) length;
|
||||
@ -88,17 +92,20 @@ static int rpc_client_receive_pipe_write(rdpRpc* rpc, const BYTE* buffer, size_t
|
||||
if (ringbuffer_used(&(client->ReceivePipe)) > 0)
|
||||
SetEvent(client->PipeEvent);
|
||||
|
||||
LeaveCriticalSection(&(rpc->client->PipeLock));
|
||||
LeaveCriticalSection(&(client->PipeLock));
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_client_receive_pipe_read(rdpRpc* rpc, BYTE* buffer, size_t length)
|
||||
int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length)
|
||||
{
|
||||
int index = 0;
|
||||
int status = 0;
|
||||
int nchunks = 0;
|
||||
DataChunk chunks[2];
|
||||
RpcClient* client = rpc->client;
|
||||
|
||||
if (!client || !buffer)
|
||||
return -1;
|
||||
|
||||
EnterCriticalSection(&(client->PipeLock));
|
||||
nchunks = ringbuffer_peek(&(client->ReceivePipe), chunks, length);
|
||||
|
||||
@ -182,7 +189,7 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
|
||||
rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s);
|
||||
|
||||
if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_A3_SIGNATURE, rts))
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_A3_SIGNATURE, rts))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3");
|
||||
return -1;
|
||||
@ -204,7 +211,7 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_C2:
|
||||
rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s);
|
||||
|
||||
if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_C2_SIGNATURE, rts))
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_C2_SIGNATURE, rts))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2");
|
||||
return -1;
|
||||
@ -266,7 +273,7 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
|
||||
rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_CONTEXT_NEGOTIATED);
|
||||
|
||||
if (tsg_proxy_begin(tsg) < 0)
|
||||
if (!tsg_proxy_begin(tsg))
|
||||
{
|
||||
WLog_ERR(TAG, "tsg_proxy_begin failure");
|
||||
return -1;
|
||||
@ -281,7 +288,10 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
}
|
||||
else if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
|
||||
{
|
||||
status = tsg_recv_pdu(tsg, pdu);
|
||||
if (!tsg_recv_pdu(tsg, pdu))
|
||||
status = -1;
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -324,7 +334,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
TerminateEventArgs e;
|
||||
rpc->result = *((UINT32*) &buffer[StubOffset]);
|
||||
freerdp_abort_connect(rpc->context->instance);
|
||||
rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;
|
||||
tsg_set_state(rpc->transport->tsg, TSG_STATE_TUNNEL_CLOSE_PENDING);
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = 0;
|
||||
PubSub_OnTerminate(rpc->context->pubSub, rpc->context, &e);
|
||||
@ -347,7 +357,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
rpc->StubCallId, header->common.call_id, rpc->StubFragCount);
|
||||
}
|
||||
|
||||
call = rpc_client_call_find_by_id(rpc, rpc->StubCallId);
|
||||
call = rpc_client_call_find_by_id(rpc->client, rpc->StubCallId);
|
||||
|
||||
if (!call)
|
||||
return -1;
|
||||
@ -374,7 +384,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
}
|
||||
else
|
||||
{
|
||||
rpc_client_receive_pipe_write(rpc, &buffer[StubOffset], (size_t) StubLength);
|
||||
rpc_client_receive_pipe_write(rpc->client, &buffer[StubOffset], (size_t) StubLength);
|
||||
rpc->StubFragCount++;
|
||||
|
||||
if (header->response.alloc_hint == StubLength)
|
||||
@ -459,14 +469,14 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
inChannel = connection->DefaultInChannel;
|
||||
outChannel = connection->DefaultOutChannel;
|
||||
BIO_get_event(outChannel->tls->bio, &outChannelEvent);
|
||||
BIO_get_event(outChannel->common.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);
|
||||
response = http_response_recv(outChannel->common.tls);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
@ -474,7 +484,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_SECURITY)
|
||||
{
|
||||
/* Receive OUT Channel Response */
|
||||
if (rpc_ncacn_http_recv_out_channel_response(rpc, outChannel, response) < 0)
|
||||
if (!rpc_ncacn_http_recv_out_channel_response(&outChannel->common, response))
|
||||
{
|
||||
http_response_free(response);
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
|
||||
@ -483,14 +493,14 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, FALSE) < 0)
|
||||
if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
|
||||
{
|
||||
http_response_free(response);
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*)outChannel);
|
||||
rpc_ncacn_http_ntlm_uninit(&outChannel->common);
|
||||
rpc_out_channel_transition_to_state(outChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE_NEGOTIATED);
|
||||
|
||||
@ -523,12 +533,12 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
if (WaitForSingleObject(outChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
response = http_response_recv(outChannel->tls);
|
||||
response = http_response_recv(outChannel->common.tls);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
statusCode = response->StatusCode;
|
||||
statusCode = http_response_get_status_code(response);
|
||||
|
||||
if (statusCode != HTTP_STATUS_OK)
|
||||
{
|
||||
@ -560,21 +570,16 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
{
|
||||
while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
|
||||
{
|
||||
status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment),
|
||||
RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
|
||||
status = rpc_channel_read(&outChannel->common, fragment,
|
||||
RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment));
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
if (!status)
|
||||
if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
|
||||
return 0;
|
||||
|
||||
Stream_Seek(fragment, status);
|
||||
}
|
||||
|
||||
if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
|
||||
return status;
|
||||
|
||||
header = (rpcconn_common_hdr_t*)Stream_Buffer(fragment);
|
||||
|
||||
if (header->frag_length > rpc->max_recv_frag)
|
||||
@ -587,8 +592,8 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
while (Stream_GetPosition(fragment) < header->frag_length)
|
||||
{
|
||||
status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment),
|
||||
header->frag_length - Stream_GetPosition(fragment));
|
||||
status = rpc_channel_read(&outChannel->common, fragment,
|
||||
header->frag_length - Stream_GetPosition(fragment));
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -596,16 +601,10 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
if (Stream_GetPosition(fragment) < header->frag_length)
|
||||
return 0;
|
||||
|
||||
Stream_Seek(fragment, status);
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
if (Stream_GetPosition(fragment) >= header->frag_length)
|
||||
{
|
||||
/* complete fragment received */
|
||||
Stream_SealLength(fragment);
|
||||
@ -618,7 +617,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
/* channel recycling may update channel pointers */
|
||||
if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_RECYCLED && connection->NonDefaultOutChannel)
|
||||
{
|
||||
rpc_out_channel_free(connection->DefaultOutChannel);
|
||||
rpc_channel_free(&connection->DefaultOutChannel->common);
|
||||
connection->DefaultOutChannel = connection->NonDefaultOutChannel;
|
||||
connection->NonDefaultOutChannel = NULL;
|
||||
rpc_out_channel_transition_to_state(connection->DefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED);
|
||||
@ -642,26 +641,22 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
|
||||
RpcOutChannel* nextOutChannel;
|
||||
HANDLE nextOutChannelEvent = NULL;
|
||||
nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
|
||||
BIO_get_event(nextOutChannel->tls->bio, &nextOutChannelEvent);
|
||||
BIO_get_event(nextOutChannel->common.tls->bio, &nextOutChannelEvent);
|
||||
|
||||
if (WaitForSingleObject(nextOutChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
response = http_response_recv(nextOutChannel->tls);
|
||||
response = http_response_recv(nextOutChannel->common.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)
|
||||
if (rpc_ncacn_http_recv_out_channel_response(&nextOutChannel->common, response))
|
||||
{
|
||||
status = rpc_ncacn_http_send_out_channel_request(rpc, nextOutChannel, TRUE);
|
||||
|
||||
if (status >= 0)
|
||||
if (rpc_ncacn_http_send_out_channel_request(&nextOutChannel->common, TRUE))
|
||||
{
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) nextOutChannel);
|
||||
rpc_ncacn_http_ntlm_uninit(&nextOutChannel->common);
|
||||
status = rts_send_OUT_R1_A3_pdu(rpc);
|
||||
|
||||
if (status >= 0)
|
||||
@ -724,21 +719,21 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
inChannel = connection->DefaultInChannel;
|
||||
outChannel = connection->DefaultOutChannel;
|
||||
BIO_get_event(inChannel->tls->bio, &InChannelEvent);
|
||||
BIO_get_event(inChannel->common.tls->bio, &InChannelEvent);
|
||||
|
||||
if (WaitForSingleObject(InChannelEvent, 0) != WAIT_OBJECT_0)
|
||||
return 1;
|
||||
|
||||
if (inChannel->State < CLIENT_IN_CHANNEL_STATE_OPENED)
|
||||
{
|
||||
response = http_response_recv(inChannel->tls);
|
||||
response = http_response_recv(inChannel->common.tls);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
if (inChannel->State == CLIENT_IN_CHANNEL_STATE_SECURITY)
|
||||
{
|
||||
if (rpc_ncacn_http_recv_in_channel_response(rpc, inChannel, response) < 0)
|
||||
if (!rpc_ncacn_http_recv_in_channel_response(&inChannel->common, response))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_recv_in_channel_response failure");
|
||||
http_response_free(response);
|
||||
@ -747,14 +742,14 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0)
|
||||
if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
|
||||
http_response_free(response);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) inChannel);
|
||||
rpc_ncacn_http_ntlm_uninit(&inChannel->common);
|
||||
rpc_in_channel_transition_to_state(inChannel,
|
||||
CLIENT_IN_CHANNEL_STATE_NEGOTIATED);
|
||||
|
||||
@ -783,7 +778,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
}
|
||||
else
|
||||
{
|
||||
response = http_response_recv(inChannel->tls);
|
||||
response = http_response_recv(inChannel->common.tls);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
@ -800,23 +795,27 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
* http://msdn.microsoft.com/en-us/library/gg593159/
|
||||
*/
|
||||
|
||||
RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
|
||||
RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT32 CallId)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
RpcClientCall* clientCall = NULL;
|
||||
ArrayList_Lock(rpc->client->ClientCallList);
|
||||
count = ArrayList_Count(rpc->client->ClientCallList);
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
|
||||
ArrayList_Lock(client->ClientCallList);
|
||||
count = ArrayList_Count(client->ClientCallList);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
clientCall = (RpcClientCall*) ArrayList_GetItem(rpc->client->ClientCallList, index);
|
||||
clientCall = (RpcClientCall*) ArrayList_GetItem(client->ClientCallList, index);
|
||||
|
||||
if (clientCall->CallId == CallId)
|
||||
break;
|
||||
}
|
||||
|
||||
ArrayList_Unlock(rpc->client->ClientCallList);
|
||||
ArrayList_Unlock(client->ClientCallList);
|
||||
return clientCall;
|
||||
}
|
||||
|
||||
@ -844,14 +843,13 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length
|
||||
int status;
|
||||
RpcClientCall* clientCall;
|
||||
rpcconn_common_hdr_t* header;
|
||||
rdpRpc* rpc = inChannel->rpc;
|
||||
status = rpc_in_channel_write(inChannel, buffer, length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
|
||||
if (status <= 0)
|
||||
return -1;
|
||||
|
||||
header = (rpcconn_common_hdr_t*) buffer;
|
||||
clientCall = rpc_client_call_find_by_id(rpc, header->call_id);
|
||||
clientCall = rpc_client_call_find_by_id(inChannel->common.client, header->call_id);
|
||||
clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
|
||||
|
||||
/*
|
||||
@ -870,47 +868,69 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
||||
BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
UINT32 offset;
|
||||
BYTE* buffer = NULL;
|
||||
UINT32 stub_data_pad;
|
||||
SecBuffer Buffers[2];
|
||||
SecBuffer Buffers[2] = { 0 };
|
||||
SecBufferDesc Message;
|
||||
RpcClientCall* clientCall;
|
||||
rdpNtlm* ntlm = rpc->ntlm;
|
||||
SECURITY_STATUS encrypt_status;
|
||||
RpcClientCall* clientCall = NULL;
|
||||
rdpNtlm* ntlm;
|
||||
rpcconn_request_hdr_t* request_pdu = NULL;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
RpcInChannel* inChannel = connection->DefaultInChannel;
|
||||
RpcVirtualConnection* connection;
|
||||
RpcInChannel* inChannel;
|
||||
size_t length;
|
||||
SSIZE_T size;
|
||||
|
||||
if (!ntlm || !ntlm->table)
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!rpc)
|
||||
goto fail;
|
||||
|
||||
ntlm = rpc->ntlm;
|
||||
connection = rpc->VirtualConnection;
|
||||
|
||||
if (!ntlm)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid ntlm context");
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES,
|
||||
&ntlm->ContextSizes);
|
||||
if (!connection)
|
||||
goto fail;
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
inChannel = connection->DefaultInChannel;
|
||||
|
||||
if (!inChannel)
|
||||
goto fail;
|
||||
|
||||
Stream_SealLength(s);
|
||||
length = Stream_Length(s);
|
||||
|
||||
if (ntlm_client_query_auth_size(ntlm) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [0x%08"PRIX32"]",
|
||||
GetSecurityStatusString(status), status);
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ZeroMemory(&Buffers, sizeof(Buffers));
|
||||
request_pdu = (rpcconn_request_hdr_t*) calloc(1, sizeof(rpcconn_request_hdr_t));
|
||||
|
||||
if (!request_pdu)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
size = ntlm_client_get_context_max_size(ntlm);
|
||||
|
||||
if (size < 0)
|
||||
goto fail;
|
||||
|
||||
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) request_pdu);
|
||||
request_pdu->ptype = PTYPE_REQUEST;
|
||||
request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
|
||||
request_pdu->auth_length = (UINT16) ntlm->ContextSizes.cbMaxSignature;
|
||||
request_pdu->auth_length = (UINT16) size;
|
||||
request_pdu->call_id = rpc->CallId++;
|
||||
request_pdu->alloc_hint = length;
|
||||
request_pdu->p_cont_id = 0x0000;
|
||||
@ -918,15 +938,15 @@ int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
||||
clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum);
|
||||
|
||||
if (!clientCall)
|
||||
goto out_free_pdu;
|
||||
goto fail;
|
||||
|
||||
if (ArrayList_Add(rpc->client->ClientCallList, clientCall) < 0)
|
||||
goto out_free_clientCall;
|
||||
goto fail;
|
||||
|
||||
if (request_pdu->opnum == TsProxySetupReceivePipeOpnum)
|
||||
rpc->PipeCallId = request_pdu->call_id;
|
||||
|
||||
request_pdu->stub_data = data;
|
||||
request_pdu->stub_data = Stream_Buffer(s);
|
||||
offset = 24;
|
||||
stub_data_pad = rpc_offset_align(&offset, 8);
|
||||
offset += length;
|
||||
@ -940,7 +960,7 @@ int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
||||
buffer = (BYTE*) calloc(1, request_pdu->frag_length);
|
||||
|
||||
if (!buffer)
|
||||
goto out_free_pdu;
|
||||
goto fail;
|
||||
|
||||
CopyMemory(buffer, request_pdu, 24);
|
||||
offset = 24;
|
||||
@ -954,89 +974,119 @@ int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
||||
Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */
|
||||
Buffers[0].pvBuffer = buffer;
|
||||
Buffers[0].cbBuffer = offset;
|
||||
Buffers[1].cbBuffer = ntlm->ContextSizes.cbMaxSignature;
|
||||
Buffers[1].cbBuffer = size;
|
||||
Buffers[1].pvBuffer = calloc(1, Buffers[1].cbBuffer);
|
||||
|
||||
if (!Buffers[1].pvBuffer)
|
||||
goto out_free_pdu;
|
||||
goto fail;
|
||||
|
||||
Message.cBuffers = 2;
|
||||
Message.ulVersion = SECBUFFER_VERSION;
|
||||
Message.pBuffers = (PSecBuffer) &Buffers;
|
||||
encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, 0, &Message, rpc->SendSeqNum++);
|
||||
|
||||
if (encrypt_status != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]",
|
||||
GetSecurityStatusString(encrypt_status), encrypt_status);
|
||||
goto out_free_pdu;
|
||||
}
|
||||
if (!ntlm_client_encrypt(ntlm, 0, &Message, rpc->SendSeqNum++))
|
||||
goto fail;
|
||||
|
||||
CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer);
|
||||
offset += Buffers[1].cbBuffer;
|
||||
free(Buffers[1].pvBuffer);
|
||||
|
||||
if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu->frag_length) < 0)
|
||||
length = -1;
|
||||
goto fail;
|
||||
|
||||
free(request_pdu);
|
||||
free(buffer);
|
||||
return length;
|
||||
out_free_clientCall:
|
||||
Stream_Free(s, TRUE);
|
||||
return TRUE;
|
||||
fail:
|
||||
rpc_client_call_free(clientCall);
|
||||
out_free_pdu:
|
||||
free(buffer);
|
||||
free(Buffers[1].pvBuffer);
|
||||
free(request_pdu);
|
||||
return -1;
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int rpc_client_new(rdpRpc* rpc)
|
||||
static BOOL rpc_client_resolve_gateway(rdpSettings* settings, char** host, UINT16* port,
|
||||
BOOL* isProxy)
|
||||
{
|
||||
RpcClient* client;
|
||||
client = (RpcClient*) calloc(1, sizeof(RpcClient));
|
||||
rpc->client = client;
|
||||
struct addrinfo* result;
|
||||
|
||||
if (!settings || !host || !port || !isProxy)
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
const char* peerHostname = settings->GatewayHostname;
|
||||
const char* proxyUsername = settings->ProxyUsername;
|
||||
const char* proxyPassword = settings->ProxyPassword;
|
||||
*port = settings->GatewayPort;
|
||||
*isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword);
|
||||
result = freerdp_tcp_resolve_host(peerHostname, *port, 0);
|
||||
|
||||
if (!result)
|
||||
return FALSE;
|
||||
|
||||
*host = freerdp_tcp_address_to_string(result->ai_addr, NULL);
|
||||
freeaddrinfo(result);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
|
||||
{
|
||||
RpcClient* client = (RpcClient*) calloc(1, sizeof(RpcClient));
|
||||
|
||||
if (!client)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
if (!rpc_client_resolve_gateway(context->settings, &client->host, &client->port, &client->isProxy))
|
||||
goto fail;
|
||||
|
||||
client->context = context;
|
||||
|
||||
if (!client->context)
|
||||
goto fail;
|
||||
|
||||
client->pdu = rpc_pdu_new();
|
||||
|
||||
if (!client->pdu)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
client->ReceiveFragment = Stream_New(NULL, rpc->max_recv_frag);
|
||||
client->ReceiveFragment = Stream_New(NULL, max_recv_frag);
|
||||
|
||||
if (!client->ReceiveFragment)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
client->PipeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (!client->PipeEvent)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!ringbuffer_init(&(client->ReceivePipe), 4096))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&(client->PipeLock), 4000))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
client->ClientCallList = ArrayList_New(TRUE);
|
||||
|
||||
if (!client->ClientCallList)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
ArrayList_Object(client->ClientCallList)->fnObjectFree = (OBJECT_FREE_FN) rpc_client_call_free;
|
||||
return 1;
|
||||
ArrayList_Object(client->ClientCallList)->fnObjectFree = rpc_client_call_free;
|
||||
return client;
|
||||
fail:
|
||||
rpc_client_free(client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rpc_client_free(rdpRpc* rpc)
|
||||
void rpc_client_free(RpcClient* client)
|
||||
{
|
||||
RpcClient* client = rpc->client;
|
||||
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
free(client->host);
|
||||
|
||||
if (client->ReceiveFragment)
|
||||
Stream_Free(client->ReceiveFragment, TRUE);
|
||||
|
||||
@ -1053,5 +1103,4 @@ void rpc_client_free(rdpRpc* rpc)
|
||||
ArrayList_Free(client->ClientCallList);
|
||||
|
||||
free(client);
|
||||
rpc->client = NULL;
|
||||
}
|
||||
|
@ -20,11 +20,13 @@
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc,
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_find_by_id(RpcClient* client,
|
||||
UINT32 CallId);
|
||||
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum);
|
||||
@ -36,13 +38,12 @@ FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer,
|
||||
FREERDP_LOCAL int rpc_client_in_channel_recv(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rpc_client_out_channel_recv(rdpRpc* rpc);
|
||||
|
||||
FREERDP_LOCAL int rpc_client_receive_pipe_read(rdpRpc* rpc, BYTE* buffer,
|
||||
FREERDP_LOCAL int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer,
|
||||
size_t length);
|
||||
|
||||
FREERDP_LOCAL int rpc_client_write_call(rdpRpc* rpc, BYTE* data, int length,
|
||||
UINT16 opnum);
|
||||
FREERDP_LOCAL BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum);
|
||||
|
||||
FREERDP_LOCAL int rpc_client_new(rdpRpc* rpc);
|
||||
FREERDP_LOCAL void rpc_client_free(rdpRpc* rpc);
|
||||
FREERDP_LOCAL RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag);
|
||||
FREERDP_LOCAL void rpc_client_free(RpcClient* client);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H */
|
||||
|
@ -240,7 +240,7 @@ static int rts_empty_command_write(BYTE* buffer)
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int rts_padding_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
static SSIZE_T rts_padding_command_read(const BYTE* buffer, size_t length)
|
||||
{
|
||||
UINT32 ConformanceCount;
|
||||
ConformanceCount = *((UINT32*) &buffer[0]); /* ConformanceCount (4 bytes) */
|
||||
@ -290,7 +290,7 @@ static int rts_ance_command_write(BYTE* buffer)
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int rts_client_address_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
static SSIZE_T rts_client_address_command_read(const BYTE* buffer, size_t length)
|
||||
{
|
||||
UINT32 AddressType;
|
||||
AddressType = *((UINT32*) &buffer[0]); /* AddressType (4 bytes) */
|
||||
@ -416,7 +416,7 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc)
|
||||
header.NumberOfCommands = 4;
|
||||
WLog_DBG(TAG, "Sending CONN/A1 RTS PDU");
|
||||
VirtualConnectionCookie = (BYTE*) & (connection->Cookie);
|
||||
OUTChannelCookie = (BYTE*) & (outChannel->Cookie);
|
||||
OUTChannelCookie = (BYTE*) & (outChannel->common.Cookie);
|
||||
ReceiveWindowSize = outChannel->ReceiveWindow;
|
||||
buffer = (BYTE*) malloc(header.frag_length);
|
||||
|
||||
@ -430,7 +430,7 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc)
|
||||
rts_cookie_command_write(&buffer[48], OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
|
||||
rts_receive_window_size_command_write(&buffer[68],
|
||||
ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
|
||||
status = rpc_out_channel_write(outChannel, buffer, header.frag_length);
|
||||
status = rpc_channel_write(&outChannel->common, buffer, header.frag_length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -463,7 +463,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
|
||||
header.NumberOfCommands = 6;
|
||||
WLog_DBG(TAG, "Sending CONN/B1 RTS PDU");
|
||||
VirtualConnectionCookie = (BYTE*) & (connection->Cookie);
|
||||
INChannelCookie = (BYTE*) & (inChannel->Cookie);
|
||||
INChannelCookie = (BYTE*) & (inChannel->common.Cookie);
|
||||
AssociationGroupId = (BYTE*) & (connection->AssociationGroupId);
|
||||
buffer = (BYTE*) malloc(header.frag_length);
|
||||
|
||||
@ -482,7 +482,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
|
||||
rts_association_group_id_command_write(&buffer[84],
|
||||
AssociationGroupId); /* AssociationGroupId (20 bytes) */
|
||||
length = header.frag_length;
|
||||
status = rpc_in_channel_write(inChannel, buffer, length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -531,7 +531,7 @@ static int rts_send_keep_alive_pdu(rdpRpc* rpc)
|
||||
rts_client_keepalive_command_write(&buffer[20],
|
||||
rpc->CurrentKeepAliveInterval); /* ClientKeepAlive (8 bytes) */
|
||||
length = header.frag_length;
|
||||
status = rpc_in_channel_write(inChannel, buffer, length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -555,7 +555,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
|
||||
WLog_DBG(TAG, "Sending FlowControlAck RTS PDU");
|
||||
BytesReceived = outChannel->BytesReceived;
|
||||
AvailableWindow = outChannel->AvailableWindowAdvertised;
|
||||
ChannelCookie = (BYTE*) & (outChannel->Cookie);
|
||||
ChannelCookie = (BYTE*) & (outChannel->common.Cookie);
|
||||
outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
|
||||
buffer = (BYTE*) malloc(header.frag_length);
|
||||
|
||||
@ -567,7 +567,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
|
||||
/* FlowControlAck Command (28 bytes) */
|
||||
rts_flow_control_ack_command_write(&buffer[28], BytesReceived, AvailableWindow, ChannelCookie);
|
||||
length = header.frag_length;
|
||||
status = rpc_in_channel_write(inChannel, buffer, length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -642,12 +642,12 @@ static int rts_send_ping_pdu(rdpRpc* rpc)
|
||||
|
||||
CopyMemory(buffer, ((BYTE*) &header), 20); /* RTS Header (20 bytes) */
|
||||
length = header.frag_length;
|
||||
status = rpc_in_channel_write(inChannel, buffer, length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 length)
|
||||
SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length)
|
||||
{
|
||||
int CommandLength = 0;
|
||||
|
||||
@ -686,7 +686,7 @@ int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 len
|
||||
break;
|
||||
|
||||
case RTS_CMD_PADDING: /* variable-size */
|
||||
CommandLength = rts_padding_command_read(rpc, buffer, length);
|
||||
CommandLength = rts_padding_command_read(buffer, length);
|
||||
break;
|
||||
|
||||
case RTS_CMD_NEGATIVE_ANCE:
|
||||
@ -698,7 +698,7 @@ int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 len
|
||||
break;
|
||||
|
||||
case RTS_CMD_CLIENT_ADDRESS: /* variable-size */
|
||||
CommandLength = rts_client_address_command_read(rpc, buffer, length);
|
||||
CommandLength = rts_client_address_command_read(buffer, length);
|
||||
break;
|
||||
|
||||
case RTS_CMD_ASSOCIATION_GROUP_ID:
|
||||
@ -716,7 +716,6 @@ int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 len
|
||||
default:
|
||||
WLog_ERR(TAG, "Error: Unknown RTS Command Type: 0x%"PRIx32"", CommandType);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return CommandLength;
|
||||
@ -735,7 +734,7 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
|
||||
header.Flags = RTS_FLAG_OUT_CHANNEL;
|
||||
header.NumberOfCommands = 3;
|
||||
WLog_DBG(TAG, "Sending OUT_R2/A7 RTS PDU");
|
||||
SuccessorChannelCookie = (BYTE*) & (nextOutChannel->Cookie);
|
||||
SuccessorChannelCookie = (BYTE*) & (nextOutChannel->common.Cookie);
|
||||
buffer = (BYTE*) malloc(header.frag_length);
|
||||
|
||||
if (!buffer)
|
||||
@ -746,7 +745,7 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
|
||||
rts_cookie_command_write(&buffer[28],
|
||||
SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
|
||||
rts_version_command_write(&buffer[48]); /* Version (8 bytes) */
|
||||
status = rpc_in_channel_write(inChannel, buffer, header.frag_length);
|
||||
status = rpc_channel_write(&inChannel->common, buffer, header.frag_length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -769,7 +768,7 @@ static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
|
||||
|
||||
CopyMemory(buffer, ((BYTE*) &header), 20); /* RTS Header (20 bytes) */
|
||||
rts_empty_command_write(&buffer[20]); /* Empty command (4 bytes) */
|
||||
status = rpc_out_channel_write(nextOutChannel, buffer, header.frag_length);
|
||||
status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -792,8 +791,8 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
|
||||
header.NumberOfCommands = 5;
|
||||
WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU");
|
||||
VirtualConnectionCookie = (BYTE*) & (connection->Cookie);
|
||||
PredecessorChannelCookie = (BYTE*) & (outChannel->Cookie);
|
||||
SuccessorChannelCookie = (BYTE*) & (nextOutChannel->Cookie);
|
||||
PredecessorChannelCookie = (BYTE*) & (outChannel->common.Cookie);
|
||||
SuccessorChannelCookie = (BYTE*) & (nextOutChannel->common.Cookie);
|
||||
ReceiveWindowSize = outChannel->ReceiveWindow;
|
||||
buffer = (BYTE*) malloc(header.frag_length);
|
||||
|
||||
@ -810,7 +809,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
|
||||
SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
|
||||
rts_receive_window_size_command_write(&buffer[88],
|
||||
ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
|
||||
status = rpc_out_channel_write(nextOutChannel, buffer, header.frag_length);
|
||||
status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length);
|
||||
free(buffer);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
@ -889,20 +888,32 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
UINT32 SignatureId;
|
||||
rpcconn_rts_hdr_t* rts;
|
||||
RtsPduSignature signature;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
rts = (rpcconn_rts_hdr_t*) buffer;
|
||||
rts_extract_pdu_signature(rpc, &signature, rts);
|
||||
SignatureId = rts_identify_pdu_signature(rpc, &signature, NULL);
|
||||
RpcVirtualConnection* connection;
|
||||
|
||||
if (rts_match_pdu_signature(rpc, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, rts))
|
||||
if (!rpc || !buffer)
|
||||
return -1;
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
|
||||
if (!connection)
|
||||
return -1;
|
||||
|
||||
rts = (rpcconn_rts_hdr_t*) buffer;
|
||||
|
||||
if (!rts_extract_pdu_signature(&signature, rts))
|
||||
return -1;
|
||||
|
||||
SignatureId = rts_identify_pdu_signature(&signature, NULL);
|
||||
|
||||
if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_recv_flow_control_ack_pdu(rpc, buffer, length);
|
||||
}
|
||||
else if (rts_match_pdu_signature(rpc, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, rts))
|
||||
else if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer, length);
|
||||
}
|
||||
else if (rts_match_pdu_signature(rpc, &RTS_PDU_PING_SIGNATURE, rts))
|
||||
else if (rts_match_pdu_signature(&RTS_PDU_PING_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_send_ping_pdu(rpc);
|
||||
}
|
||||
@ -910,21 +921,21 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED)
|
||||
{
|
||||
if (rts_match_pdu_signature(rpc, &RTS_PDU_OUT_R1_A2_SIGNATURE, rts))
|
||||
if (rts_match_pdu_signature(&RTS_PDU_OUT_R1_A2_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_recv_OUT_R1_A2_pdu(rpc, buffer, length);
|
||||
}
|
||||
}
|
||||
else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W)
|
||||
{
|
||||
if (rts_match_pdu_signature(rpc, &RTS_PDU_OUT_R2_A6_SIGNATURE, rts))
|
||||
if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_A6_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_recv_OUT_R2_A6_pdu(rpc, buffer, length);
|
||||
}
|
||||
}
|
||||
else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W)
|
||||
{
|
||||
if (rts_match_pdu_signature(rpc, &RTS_PDU_OUT_R2_B3_SIGNATURE, rts))
|
||||
if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_B3_SIGNATURE, rts))
|
||||
{
|
||||
status = rts_recv_OUT_R2_B3_pdu(rpc, buffer, length);
|
||||
}
|
||||
@ -934,7 +945,7 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error parsing RTS PDU with signature id: 0x%08"PRIX32"", SignatureId);
|
||||
rts_print_pdu_signature(rpc, &signature);
|
||||
rts_print_pdu_signature(&signature);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -79,8 +79,7 @@
|
||||
|
||||
FREERDP_LOCAL void rts_generate_cookie(BYTE* cookie);
|
||||
|
||||
FREERDP_LOCAL int rts_command_length(rdpRpc* rpc, UINT32 CommandType,
|
||||
BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length);
|
||||
|
||||
FREERDP_LOCAL int rts_send_CONN_A1_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer,
|
||||
|
@ -23,191 +23,191 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rts")
|
||||
|
||||
RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
const RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 5,
|
||||
const RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 5,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE = { RTS_FLAG_NONE, 6,
|
||||
const RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE = { RTS_FLAG_NONE, 6,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_CLIENT_KEEPALIVE, RTS_CMD_ASSOCIATION_GROUP_ID, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE = { RTS_FLAG_IN_CHANNEL, 7,
|
||||
const RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE = { RTS_FLAG_IN_CHANNEL, 7,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, RTS_CMD_ASSOCIATION_GROUP_ID, RTS_CMD_CLIENT_ADDRESS, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
const RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
{ RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_VERSION, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
const RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
const RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
{
|
||||
RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE = { RTS_FLAG_NONE, 4,
|
||||
{
|
||||
RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_EMPTY, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4,
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL, 7,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL, 7,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5,
|
||||
{
|
||||
RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0
|
||||
}
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE = { RTS_FLAG_NONE, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE = { RTS_FLAG_NONE, 3,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_COOKIE, RTS_CMD_VERSION, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE = { RTS_FLAG_NONE, 1,
|
||||
{ RTS_CMD_NEGATIVE_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE = { RTS_FLAG_EOF, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE = { RTS_FLAG_EOF, 1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE = { RTS_FLAG_PING, 1,
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE = { RTS_FLAG_PING, 1,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
const RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
{ RTS_CMD_CLIENT_KEEPALIVE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
const RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
{ RTS_CMD_PING_TRAFFIC_SENT_NOTIFY, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_ECHO_SIGNATURE = { RTS_FLAG_ECHO, 0,
|
||||
const RtsPduSignature RTS_PDU_ECHO_SIGNATURE = { RTS_FLAG_ECHO, 0,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_PING_SIGNATURE = { RTS_FLAG_PING, 0,
|
||||
const RtsPduSignature RTS_PDU_PING_SIGNATURE = { RTS_FLAG_PING, 0,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1,
|
||||
{ RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE = { RTS_FLAG_OTHER_CMD, 2,
|
||||
const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE = { RTS_FLAG_OTHER_CMD, 2,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -274,26 +274,30 @@ static const RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] =
|
||||
{ RTS_PDU_FLOW_CONTROL_ACK, TRUE, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, "FlowControlAck" },
|
||||
{ RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION, TRUE, &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, "FlowControlAckWithDestination" },
|
||||
|
||||
{ 0, 0, NULL }
|
||||
{ 0, FALSE, NULL, NULL }
|
||||
};
|
||||
|
||||
BOOL rts_match_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rts_hdr_t* rts)
|
||||
BOOL rts_match_pdu_signature(const RtsPduSignature* signature,
|
||||
const rpcconn_rts_hdr_t* rts)
|
||||
{
|
||||
int i;
|
||||
UINT16 i;
|
||||
int status;
|
||||
BYTE* buffer;
|
||||
const BYTE* buffer;
|
||||
UINT32 length;
|
||||
UINT32 offset;
|
||||
UINT32 CommandType;
|
||||
UINT32 CommandLength;
|
||||
|
||||
if (!signature || !rts)
|
||||
return FALSE;
|
||||
|
||||
if (rts->Flags != signature->Flags)
|
||||
return FALSE;
|
||||
|
||||
if (rts->NumberOfCommands != signature->NumberOfCommands)
|
||||
return FALSE;
|
||||
|
||||
buffer = (BYTE*) rts;
|
||||
buffer = (const BYTE*) rts;
|
||||
offset = RTS_PDU_HEADER_LENGTH;
|
||||
length = rts->frag_length - offset;
|
||||
|
||||
@ -305,7 +309,7 @@ BOOL rts_match_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rt
|
||||
if (CommandType != signature->CommandTypes[i])
|
||||
return FALSE;
|
||||
|
||||
status = rts_command_length(rpc, CommandType, &buffer[offset], length);
|
||||
status = rts_command_length(CommandType, &buffer[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
@ -318,7 +322,7 @@ BOOL rts_match_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rt
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rts_hdr_t* rts)
|
||||
BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr_t* rts)
|
||||
{
|
||||
int i;
|
||||
int status;
|
||||
@ -327,6 +331,10 @@ int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_r
|
||||
UINT32 offset;
|
||||
UINT32 CommandType;
|
||||
UINT32 CommandLength;
|
||||
|
||||
if (!signature || !rts)
|
||||
return FALSE;
|
||||
|
||||
signature->Flags = rts->Flags;
|
||||
signature->NumberOfCommands = rts->NumberOfCommands;
|
||||
buffer = (BYTE*) rts;
|
||||
@ -338,7 +346,7 @@ int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_r
|
||||
CommandType = *((UINT32*) &buffer[offset]); /* CommandType (4 bytes) */
|
||||
offset += 4;
|
||||
signature->CommandTypes[i] = CommandType;
|
||||
status = rts_command_length(rpc, CommandType, &buffer[offset], length);
|
||||
status = rts_command_length(CommandType, &buffer[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
@ -348,18 +356,17 @@ int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_r
|
||||
length = rts->frag_length - offset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT32 rts_identify_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature,
|
||||
UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
const RTS_PDU_SIGNATURE_ENTRY** entry)
|
||||
{
|
||||
int i, j;
|
||||
RtsPduSignature* pSignature;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; RTS_PDU_SIGNATURE_TABLE[i].SignatureId != 0; i++)
|
||||
{
|
||||
pSignature = RTS_PDU_SIGNATURE_TABLE[i].Signature;
|
||||
const RtsPduSignature* pSignature = RTS_PDU_SIGNATURE_TABLE[i].Signature;
|
||||
|
||||
if (!RTS_PDU_SIGNATURE_TABLE[i].SignatureClient)
|
||||
continue;
|
||||
@ -385,16 +392,20 @@ UINT32 rts_identify_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rts_print_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature)
|
||||
BOOL rts_print_pdu_signature(const RtsPduSignature* signature)
|
||||
{
|
||||
UINT32 SignatureId;
|
||||
const RTS_PDU_SIGNATURE_ENTRY* entry;
|
||||
|
||||
if (!signature)
|
||||
return FALSE;
|
||||
|
||||
WLog_INFO(TAG, "RTS PDU Signature: Flags: 0x%04"PRIX16" NumberOfCommands: %"PRIu16"",
|
||||
signature->Flags, signature->NumberOfCommands);
|
||||
SignatureId = rts_identify_pdu_signature(rpc, signature, &entry);
|
||||
SignatureId = rts_identify_pdu_signature(signature, &entry);
|
||||
|
||||
if (SignatureId)
|
||||
WLog_ERR(TAG, "Identified %s RTS PDU", entry->PduName);
|
||||
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ struct _RTS_PDU_SIGNATURE_ENTRY
|
||||
{
|
||||
UINT32 SignatureId;
|
||||
BOOL SignatureClient;
|
||||
RtsPduSignature* Signature;
|
||||
const RtsPduSignature* Signature;
|
||||
const char* PduName;
|
||||
};
|
||||
|
||||
@ -117,75 +117,74 @@ struct _RTS_PDU_SIGNATURE_ENTRY
|
||||
#define RTS_PDU_FLOW_CONTROL_ACK (RTS_PDU_OUT_OF_SEQUENCE | 0x00000005)
|
||||
#define RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION (RTS_PDU_OUT_OF_SEQUENCE | 0x00000006)
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_ECHO_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_PING_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE;
|
||||
FREERDP_LOCAL extern RtsPduSignature
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_ECHO_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_PING_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature
|
||||
RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature(rdpRpc* rpc,
|
||||
RtsPduSignature* signature, rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL int rts_extract_pdu_signature(rdpRpc* rpc,
|
||||
RtsPduSignature* signature, rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL UINT32 rts_identify_pdu_signature(rdpRpc* rpc,
|
||||
RtsPduSignature* signature, const RTS_PDU_SIGNATURE_ENTRY** entry);
|
||||
FREERDP_LOCAL int rts_print_pdu_signature(rdpRpc* rpc,
|
||||
RtsPduSignature* signature);
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature,
|
||||
const rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature,
|
||||
const rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
const RTS_PDU_SIGNATURE_ENTRY** entry);
|
||||
FREERDP_LOCAL BOOL rts_print_pdu_signature(const RtsPduSignature* signature);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RTS_SIGNATURE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,16 +31,10 @@ typedef struct rdp_tsg rdpTsg;
|
||||
#include <winpr/rpc.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/error.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
enum _TSG_STATE
|
||||
{
|
||||
TSG_STATE_INITIAL,
|
||||
@ -54,8 +48,6 @@ enum _TSG_STATE
|
||||
};
|
||||
typedef enum _TSG_STATE TSG_STATE;
|
||||
|
||||
typedef WCHAR* RESOURCENAME;
|
||||
|
||||
#define TsProxyCreateTunnelOpnum 1
|
||||
#define TsProxyAuthorizeTunnelOpnum 2
|
||||
#define TsProxyMakeTunnelCallOpnum 3
|
||||
@ -68,15 +60,6 @@ typedef WCHAR* RESOURCENAME;
|
||||
|
||||
#define MAX_RESOURCE_NAMES 50
|
||||
|
||||
typedef struct _tsendpointinfo
|
||||
{
|
||||
RESOURCENAME* resourceName;
|
||||
UINT32 numResourceNames;
|
||||
RESOURCENAME* alternateResourceNames;
|
||||
UINT16 numAlternateResourceNames;
|
||||
UINT32 Port;
|
||||
} TSENDPOINTINFO, *PTSENDPOINTINFO;
|
||||
|
||||
#define TS_GATEWAY_TRANSPORT 0x5452
|
||||
|
||||
#define TSG_PACKET_TYPE_HEADER 0x00004844
|
||||
@ -130,198 +113,24 @@ typedef struct _tsendpointinfo
|
||||
#define E_PROXY_REAUTH_NAP_FAILED 0x00005A00
|
||||
#define E_PROXY_CONNECTIONABORTED 0x000004D4
|
||||
|
||||
typedef struct _TSG_PACKET_HEADER
|
||||
{
|
||||
UINT16 ComponentId;
|
||||
UINT16 PacketId;
|
||||
} TSG_PACKET_HEADER, *PTSG_PACKET_HEADER;
|
||||
FREERDP_LOCAL rdpTsg* tsg_new(rdpTransport* transport);
|
||||
FREERDP_LOCAL void tsg_free(rdpTsg* tsg);
|
||||
|
||||
typedef struct _TSG_CAPABILITY_NAP
|
||||
{
|
||||
UINT32 capabilities;
|
||||
} TSG_CAPABILITY_NAP, *PTSG_CAPABILITY_NAP;
|
||||
|
||||
typedef union
|
||||
{
|
||||
TSG_CAPABILITY_NAP tsgCapNap;
|
||||
} TSG_CAPABILITIES_UNION, *PTSG_CAPABILITIES_UNION;
|
||||
|
||||
typedef struct _TSG_PACKET_CAPABILITIES
|
||||
{
|
||||
UINT32 capabilityType;
|
||||
TSG_CAPABILITIES_UNION tsgPacket;
|
||||
} TSG_PACKET_CAPABILITIES, *PTSG_PACKET_CAPABILITIES;
|
||||
|
||||
typedef struct _TSG_PACKET_VERSIONCAPS
|
||||
{
|
||||
TSG_PACKET_HEADER tsgHeader;
|
||||
PTSG_PACKET_CAPABILITIES tsgCaps;
|
||||
UINT32 numCapabilities;
|
||||
UINT16 majorVersion;
|
||||
UINT16 minorVersion;
|
||||
UINT16 quarantineCapabilities;
|
||||
} TSG_PACKET_VERSIONCAPS, *PTSG_PACKET_VERSIONCAPS;
|
||||
|
||||
typedef struct _TSG_PACKET_QUARCONFIGREQUEST
|
||||
{
|
||||
UINT32 flags;
|
||||
} TSG_PACKET_QUARCONFIGREQUEST, *PTSG_PACKET_QUARCONFIGREQUEST;
|
||||
|
||||
typedef struct _TSG_PACKET_QUARREQUEST
|
||||
{
|
||||
UINT32 flags;
|
||||
WCHAR* machineName;
|
||||
UINT32 nameLength;
|
||||
BYTE* data;
|
||||
UINT32 dataLen;
|
||||
} TSG_PACKET_QUARREQUEST, *PTSG_PACKET_QUARREQUEST;
|
||||
|
||||
typedef struct _TSG_REDIRECTION_FLAGS
|
||||
{
|
||||
BOOL enableAllRedirections;
|
||||
BOOL disableAllRedirections;
|
||||
BOOL driveRedirectionDisabled;
|
||||
BOOL printerRedirectionDisabled;
|
||||
BOOL portRedirectionDisabled;
|
||||
BOOL reserved;
|
||||
BOOL clipboardRedirectionDisabled;
|
||||
BOOL pnpRedirectionDisabled;
|
||||
} TSG_REDIRECTION_FLAGS, *PTSG_REDIRECTION_FLAGS;
|
||||
|
||||
typedef struct _TSG_PACKET_RESPONSE
|
||||
{
|
||||
UINT32 flags;
|
||||
UINT32 reserved;
|
||||
BYTE* responseData;
|
||||
UINT32 responseDataLen;
|
||||
TSG_REDIRECTION_FLAGS redirectionFlags;
|
||||
} TSG_PACKET_RESPONSE, *PTSG_PACKET_RESPONSE;
|
||||
|
||||
typedef struct _TSG_PACKET_QUARENC_RESPONSE
|
||||
{
|
||||
UINT32 flags;
|
||||
UINT32 certChainLen;
|
||||
WCHAR* certChainData;
|
||||
GUID nonce;
|
||||
PTSG_PACKET_VERSIONCAPS versionCaps;
|
||||
} TSG_PACKET_QUARENC_RESPONSE, *PTSG_PACKET_QUARENC_RESPONSE;
|
||||
|
||||
typedef struct TSG_PACKET_STRING_MESSAGE
|
||||
{
|
||||
INT32 isDisplayMandatory;
|
||||
INT32 isConsentMandatory;
|
||||
UINT32 msgBytes;
|
||||
WCHAR* msgBuffer;
|
||||
} TSG_PACKET_STRING_MESSAGE, *PTSG_PACKET_STRING_MESSAGE;
|
||||
|
||||
typedef struct TSG_PACKET_REAUTH_MESSAGE
|
||||
{
|
||||
UINT64 tunnelContext;
|
||||
} TSG_PACKET_REAUTH_MESSAGE, *PTSG_PACKET_REAUTH_MESSAGE;
|
||||
|
||||
typedef union
|
||||
{
|
||||
PTSG_PACKET_STRING_MESSAGE consentMessage;
|
||||
PTSG_PACKET_STRING_MESSAGE serviceMessage;
|
||||
PTSG_PACKET_REAUTH_MESSAGE reauthMessage;
|
||||
} TSG_PACKET_TYPE_MESSAGE_UNION, *PTSG_PACKET_TYPE_MESSAGE_UNION;
|
||||
|
||||
typedef struct _TSG_PACKET_MSG_RESPONSE
|
||||
{
|
||||
UINT32 msgID;
|
||||
UINT32 msgType;
|
||||
INT32 isMsgPresent;
|
||||
TSG_PACKET_TYPE_MESSAGE_UNION messagePacket;
|
||||
} TSG_PACKET_MSG_RESPONSE, *PTSG_PACKET_MSG_RESPONSE;
|
||||
|
||||
typedef struct TSG_PACKET_CAPS_RESPONSE
|
||||
{
|
||||
TSG_PACKET_QUARENC_RESPONSE pktQuarEncResponse;
|
||||
TSG_PACKET_MSG_RESPONSE pktConsentMessage;
|
||||
} TSG_PACKET_CAPS_RESPONSE, *PTSG_PACKET_CAPS_RESPONSE;
|
||||
|
||||
typedef struct TSG_PACKET_MSG_REQUEST
|
||||
{
|
||||
UINT32 maxMessagesPerBatch;
|
||||
} TSG_PACKET_MSG_REQUEST, *PTSG_PACKET_MSG_REQUEST;
|
||||
|
||||
typedef struct _TSG_PACKET_AUTH
|
||||
{
|
||||
TSG_PACKET_VERSIONCAPS tsgVersionCaps;
|
||||
UINT32 cookieLen;
|
||||
BYTE* cookie;
|
||||
} TSG_PACKET_AUTH, *PTSG_PACKET_AUTH;
|
||||
|
||||
typedef union
|
||||
{
|
||||
PTSG_PACKET_VERSIONCAPS packetVersionCaps;
|
||||
PTSG_PACKET_AUTH packetAuth;
|
||||
} TSG_INITIAL_PACKET_TYPE_UNION, *PTSG_INITIAL_PACKET_TYPE_UNION;
|
||||
|
||||
typedef struct TSG_PACKET_REAUTH
|
||||
{
|
||||
UINT64 tunnelContext;
|
||||
UINT32 packetId;
|
||||
TSG_INITIAL_PACKET_TYPE_UNION tsgInitialPacket;
|
||||
} TSG_PACKET_REAUTH, *PTSG_PACKET_REAUTH;
|
||||
|
||||
typedef union
|
||||
{
|
||||
PTSG_PACKET_HEADER packetHeader;
|
||||
PTSG_PACKET_VERSIONCAPS packetVersionCaps;
|
||||
PTSG_PACKET_QUARCONFIGREQUEST packetQuarConfigRequest;
|
||||
PTSG_PACKET_QUARREQUEST packetQuarRequest;
|
||||
PTSG_PACKET_RESPONSE packetResponse;
|
||||
PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse;
|
||||
PTSG_PACKET_CAPS_RESPONSE packetCapsResponse;
|
||||
PTSG_PACKET_MSG_REQUEST packetMsgRequest;
|
||||
PTSG_PACKET_MSG_RESPONSE packetMsgResponse;
|
||||
PTSG_PACKET_AUTH packetAuth;
|
||||
PTSG_PACKET_REAUTH packetReauth;
|
||||
} TSG_PACKET_TYPE_UNION;
|
||||
|
||||
typedef struct _TSG_PACKET
|
||||
{
|
||||
UINT32 packetId;
|
||||
TSG_PACKET_TYPE_UNION tsgPacket;
|
||||
} TSG_PACKET, *PTSG_PACKET;
|
||||
|
||||
struct rdp_tsg
|
||||
{
|
||||
BIO* bio;
|
||||
rdpRpc* rpc;
|
||||
UINT16 Port;
|
||||
LPWSTR Hostname;
|
||||
LPWSTR MachineName;
|
||||
TSG_STATE state;
|
||||
UINT32 TunnelId;
|
||||
UINT32 ChannelId;
|
||||
BOOL reauthSequence;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
UINT64 ReauthTunnelContext;
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
CONTEXT_HANDLE NewTunnelContext;
|
||||
CONTEXT_HANDLE NewChannelContext;
|
||||
TSG_PACKET_REAUTH packetReauth;
|
||||
TSG_PACKET_CAPABILITIES tsgCaps;
|
||||
TSG_PACKET_VERSIONCAPS packetVersionCaps;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL int tsg_proxy_begin(rdpTsg* tsg);
|
||||
FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg);
|
||||
|
||||
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port,
|
||||
int timeout);
|
||||
FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg);
|
||||
|
||||
FREERDP_LOCAL int tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
|
||||
FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
|
||||
|
||||
FREERDP_LOCAL int tsg_check_event_handles(rdpTsg* tsg);
|
||||
FREERDP_LOCAL BOOL tsg_check_event_handles(rdpTsg* tsg);
|
||||
FREERDP_LOCAL DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events,
|
||||
DWORD count);
|
||||
|
||||
FREERDP_LOCAL rdpTsg* tsg_new(rdpTransport* transport);
|
||||
FREERDP_LOCAL void tsg_free(rdpTsg* tsg);
|
||||
FREERDP_LOCAL TSG_STATE tsg_get_state(rdpTsg* tsg);
|
||||
FREERDP_LOCAL BOOL tsg_set_state(rdpTsg* tsg, TSG_STATE state);
|
||||
|
||||
FREERDP_LOCAL BIO* tsg_get_bio(rdpTsg* tsg);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_TSG_H */
|
||||
|
@ -51,37 +51,26 @@
|
||||
|
||||
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
|
||||
{
|
||||
int ai_flags = 0;
|
||||
int status;
|
||||
int sockfd;
|
||||
char addr[64];
|
||||
void* sin_addr;
|
||||
int option_value;
|
||||
char servname[16];
|
||||
struct addrinfo* ai;
|
||||
struct addrinfo* res;
|
||||
struct addrinfo hints = { 0 };
|
||||
rdpListener* listener = (rdpListener*) instance->listener;
|
||||
#ifdef _WIN32
|
||||
u_long arg;
|
||||
#endif
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (!bind_address)
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
ai_flags = AI_PASSIVE;
|
||||
|
||||
sprintf_s(servname, sizeof(servname), "%"PRIu16"", port);
|
||||
status = getaddrinfo(bind_address, servname, &hints, &res);
|
||||
res = freerdp_tcp_resolve_host(bind_address, port, ai_flags);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WLog_ERR("getaddrinfo error: %s", gai_strerrorA(status));
|
||||
#else
|
||||
WLog_ERR(TAG, "getaddrinfo");
|
||||
#endif
|
||||
if (!res)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
|
||||
{
|
||||
@ -148,7 +137,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
||||
|
||||
WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
|
||||
listener->num_sockfds++;
|
||||
WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
|
||||
WLog_INFO(TAG, "Listening on %s:%d", addr, port);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
@ -1513,16 +1513,15 @@ int rdp_check_fds(rdpRdp* rdp)
|
||||
if (transport->tsg)
|
||||
{
|
||||
rdpTsg* tsg = transport->tsg;
|
||||
status = tsg_check_event_handles(tsg);
|
||||
|
||||
if (status < 0)
|
||||
if (!tsg_check_event_handles(tsg))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_check_fds: tsg_check_event_handles() - %i", status);
|
||||
WLog_ERR(TAG, "rdp_check_fds: tsg_check_event_handles()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tsg->state != TSG_STATE_PIPE_CREATED)
|
||||
return status;
|
||||
if (tsg_get_state(tsg) != TSG_STATE_PIPE_CREATED)
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = transport_check_fds(transport);
|
||||
|
@ -664,7 +664,7 @@ BIO_METHOD* BIO_s_buffered_socket(void)
|
||||
return bio_methods;
|
||||
}
|
||||
|
||||
static char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
|
||||
char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
|
||||
{
|
||||
char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
|
||||
struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)addr;
|
||||
@ -762,16 +762,39 @@ static int freerdp_uds_connect(const char* path)
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL freerdp_tcp_resolve_hostname(rdpContext* context, const char* hostname)
|
||||
struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port, int ai_flags)
|
||||
{
|
||||
char* service = NULL;
|
||||
char port_str[16];
|
||||
int status;
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* result = NULL;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
status = getaddrinfo(hostname, NULL, &hints, &result);
|
||||
hints.ai_flags = ai_flags;
|
||||
|
||||
if (port >= 0)
|
||||
{
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
|
||||
service = port_str;
|
||||
}
|
||||
|
||||
status = getaddrinfo(hostname, service, &hints, &result);
|
||||
|
||||
if (status)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char* hostname)
|
||||
{
|
||||
struct addrinfo* result = freerdp_tcp_resolve_host(hostname, -1, 0);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
|
||||
@ -870,13 +893,10 @@ static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames,
|
||||
SOCKET* sockfds;
|
||||
HANDLE* events;
|
||||
DWORD waitStatus;
|
||||
char port_str[16];
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* addr;
|
||||
struct addrinfo* result;
|
||||
struct addrinfo** addrs;
|
||||
struct addrinfo** results;
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
|
||||
sockfds = (SOCKET*) calloc(count, sizeof(SOCKET));
|
||||
events = (HANDLE*) calloc(count + 1, sizeof(HANDLE));
|
||||
addrs = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
|
||||
@ -893,19 +913,15 @@ static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames,
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int port = -1;
|
||||
|
||||
if (ports)
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%"PRIu32"", ports[index]);
|
||||
port = ports[index];
|
||||
|
||||
status = getaddrinfo(hostnames[index], port_str, &hints, &result);
|
||||
result = freerdp_tcp_resolve_host(hostnames[index], port, 0);
|
||||
|
||||
if (status)
|
||||
{
|
||||
if (!result)
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = result;
|
||||
|
||||
@ -1089,7 +1105,6 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
|
||||
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
|
||||
const char* hostname, int port, int timeout)
|
||||
{
|
||||
int status;
|
||||
int sockfd;
|
||||
UINT32 optval;
|
||||
socklen_t optlen;
|
||||
@ -1130,7 +1145,7 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
|
||||
|
||||
if (!settings->GatewayEnabled)
|
||||
{
|
||||
if (!freerdp_tcp_resolve_hostname(context, hostname) || settings->RemoteAssistanceMode)
|
||||
if (!freerdp_tcp_is_hostname_resolvable(context, hostname) || settings->RemoteAssistanceMode)
|
||||
{
|
||||
if (settings->TargetNetAddressCount > 0)
|
||||
{
|
||||
@ -1146,23 +1161,16 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
|
||||
|
||||
if (sockfd <= 0)
|
||||
{
|
||||
char port_str[16];
|
||||
char* peerAddress;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* addr;
|
||||
struct addrinfo* result;
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
|
||||
status = getaddrinfo(hostname, port_str, &hints, &result);
|
||||
result = freerdp_tcp_resolve_host(hostname, port, 0);
|
||||
|
||||
if (status)
|
||||
if (!result)
|
||||
{
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
|
||||
|
||||
WLog_ERR(TAG, "getaddrinfo: %s", gai_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -69,4 +69,8 @@ FREERDP_LOCAL int freerdp_tcp_connect(rdpContext* context,
|
||||
|
||||
FREERDP_LOCAL char* freerdp_tcp_get_peer_address(SOCKET sockfd);
|
||||
|
||||
FREERDP_LOCAL struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port,
|
||||
int ai_flags);
|
||||
FREERDP_LOCAL char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_TCP_H */
|
||||
|
@ -393,7 +393,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname,
|
||||
|
||||
if (status)
|
||||
{
|
||||
transport->frontBio = transport->tsg->bio;
|
||||
transport->frontBio = tsg_get_bio(transport->tsg);
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
status = TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user