Merge pull request #10312 from akallabeth/http_timeout

[gateway,http] implement proper timeouts
This commit is contained in:
Martin Fleisz 2024-06-27 10:17:40 +02:00 committed by GitHub
commit c9aa349c52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 228 additions and 189 deletions

View File

@ -26,6 +26,7 @@
#include <winpr/stream.h> #include <winpr/stream.h>
#include <winpr/string.h> #include <winpr/string.h>
#include <winpr/rpc.h> #include <winpr/rpc.h>
#include <winpr/sysinfo.h>
#include <freerdp/log.h> #include <freerdp/log.h>
#include <freerdp/crypto/crypto.h> #include <freerdp/crypto/crypto.h>
@ -1107,9 +1108,11 @@ static BOOL http_use_content_length(const char* cur)
static int print_bio_error(const char* str, size_t len, void* bp) static int print_bio_error(const char* str, size_t len, void* bp)
{ {
wLog* log = bp;
WINPR_UNUSED(len); WINPR_UNUSED(len);
WINPR_UNUSED(bp); WINPR_UNUSED(bp);
WLog_ERR(TAG, "%s", str); WLog_Print(log, WLOG_ERROR, "%s", str);
return len; return len;
} }
@ -1219,56 +1222,65 @@ int http_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size,
} }
} }
HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength) #define sleep_or_timeout(tls, startMS, timeoutMS) \
sleep_or_timeout_((tls), (startMS), (timeoutMS), __FILE__, __func__, __LINE__)
static BOOL sleep_or_timeout_(rdpTls* tls, UINT64 startMS, UINT32 timeoutMS, const char* file,
const char* fkt, size_t line)
{ {
size_t position = 0; WINPR_ASSERT(tls);
size_t bodyLength = 0;
size_t payloadOffset = 0;
HttpResponse* response = http_response_new();
if (!response) USleep(100);
return NULL; const UINT64 nowMS = GetTickCount64();
if (nowMS - startMS > timeoutMS)
response->ContentLength = 0;
const UINT32 timeout = freerdp_settings_get_uint32(tls->settings, FreeRDP_TcpConnectTimeout);
while (payloadOffset == 0)
{ {
DWORD level = WLOG_ERROR;
wLog* log = WLog_Get(TAG);
if (WLog_IsLevelActive(log, level))
WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, level, line, file, fkt,
"timeout [%" PRIu32 "ms] exceeded", timeoutMS);
return TRUE;
}
if (!BIO_should_retry(tls->bio))
{
DWORD level = WLOG_ERROR;
wLog* log = WLog_Get(TAG);
if (WLog_IsLevelActive(log, level))
{
WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, level, line, file, fkt, "Retries exceeded");
ERR_print_errors_cb(print_bio_error, log);
}
return TRUE;
}
if (freerdp_shall_disconnect_context(tls->context))
return TRUE;
return FALSE;
}
static SSIZE_T http_response_recv_line(rdpTls* tls, HttpResponse* response)
{
WINPR_ASSERT(tls);
WINPR_ASSERT(response);
SSIZE_T payloadOffset = -1;
const UINT32 timeoutMS =
freerdp_settings_get_uint32(tls->context->settings, FreeRDP_TcpConnectTimeout);
const UINT64 startMS = GetTickCount64();
while (payloadOffset <= 0)
{
size_t bodyLength = 0;
size_t position = 0;
int status = -1; int status = -1;
size_t s = 0; size_t s = 0;
char* end = NULL; char* end = NULL;
/* Read until we encounter \r\n\r\n */ /* Read until we encounter \r\n\r\n */
ERR_clear_error(); ERR_clear_error();
const long wstatus = BIO_wait_read(tls->bio, timeout);
if (wstatus < 0)
{
if (!BIO_should_retry(tls->bio))
{
WLog_ERR(TAG, "[BIO_wait_read] Retries exceeded");
ERR_print_errors_cb(print_bio_error, NULL);
goto out_error;
}
USleep(100);
continue;
}
else if (wstatus == 0)
{
WLog_ERR(TAG, "[BIO_wait] timeout exceeded");
ERR_print_errors_cb(print_bio_error, NULL);
goto out_error;
}
status = BIO_read(tls->bio, Stream_Pointer(response->data), 1); status = BIO_read(tls->bio, Stream_Pointer(response->data), 1);
if (status <= 0) if (status <= 0)
{ {
if (!BIO_should_retry(tls->bio)) if (sleep_or_timeout(tls, startMS, timeoutMS))
{
WLog_ERR(TAG, "Retries exceeded");
ERR_print_errors_cb(print_bio_error, NULL);
goto out_error; goto out_error;
}
USleep(100);
continue; continue;
} }
@ -1299,6 +1311,119 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
payloadOffset = Stream_GetPosition(response->data); payloadOffset = Stream_GetPosition(response->data);
} }
out_error:
return payloadOffset;
}
static BOOL http_response_recv_body(rdpTls* tls, HttpResponse* response, BOOL readContentLength,
size_t payloadOffset, size_t bodyLength)
{
BOOL rc = FALSE;
WINPR_ASSERT(tls);
WINPR_ASSERT(response);
const UINT64 startMS = GetTickCount64();
const UINT32 timeoutMS =
freerdp_settings_get_uint32(tls->context->settings, FreeRDP_TcpConnectTimeout);
if ((response->TransferEncoding == TransferEncodingChunked) && readContentLength)
{
http_encoding_chunked_context ctx = { 0 };
ctx.state = ChunkStateLenghHeader;
ctx.nextOffset = 0;
ctx.headerFooterPos = 0;
int full_len = 0;
do
{
if (!Stream_EnsureRemainingCapacity(response->data, 2048))
goto out_error;
int status = http_chuncked_read(tls->bio, Stream_Pointer(response->data),
Stream_GetRemainingCapacity(response->data), &ctx);
if (status <= 0)
{
if (sleep_or_timeout(tls, startMS, timeoutMS))
goto out_error;
}
else
{
Stream_Seek(response->data, (size_t)status);
full_len += status;
}
} while (ctx.state != ChunkStateEnd);
response->BodyLength = full_len;
if (response->BodyLength > 0)
response->BodyContent = &(Stream_Buffer(response->data))[payloadOffset];
}
else
{
while (response->BodyLength < bodyLength)
{
int status = 0;
if (!Stream_EnsureRemainingCapacity(response->data, bodyLength - response->BodyLength))
goto out_error;
ERR_clear_error();
status = BIO_read(tls->bio, Stream_Pointer(response->data),
bodyLength - response->BodyLength);
if (status <= 0)
{
if (sleep_or_timeout(tls, startMS, timeoutMS))
goto out_error;
continue;
}
Stream_Seek(response->data, (size_t)status);
response->BodyLength += (unsigned long)status;
if (response->BodyLength > RESPONSE_SIZE_LIMIT)
{
WLog_ERR(TAG, "Request body too large! (%" PRIdz " bytes) Aborting!",
response->BodyLength);
goto out_error;
}
}
if (response->BodyLength > 0)
response->BodyContent = &(Stream_Buffer(response->data))[payloadOffset];
if (bodyLength != response->BodyLength)
{
WLog_WARN(TAG, "%s unexpected body length: actual: %" PRIuz ", expected: %" PRIuz,
response->ContentType, response->BodyLength, bodyLength);
if (bodyLength > 0)
response->BodyLength = MIN(bodyLength, response->BodyLength);
}
/* '\0' terminate the http body */
if (!Stream_EnsureRemainingCapacity(response->data, sizeof(UINT16)))
goto out_error;
Stream_Write_UINT16(response->data, 0);
}
rc = TRUE;
out_error:
return rc;
}
HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
{
size_t bodyLength = 0;
HttpResponse* response = http_response_new();
if (!response)
return NULL;
response->ContentLength = 0;
const SSIZE_T payloadOffset = http_response_recv_line(tls, response);
if (payloadOffset < 0)
goto out_error;
if (payloadOffset) if (payloadOffset)
{ {
size_t count = 0; size_t count = 0;
@ -1370,96 +1495,8 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
} }
/* Fetch remaining body! */ /* Fetch remaining body! */
if ((response->TransferEncoding == TransferEncodingChunked) && readContentLength) if (!http_response_recv_body(tls, response, readContentLength, payloadOffset, bodyLength))
{ goto out_error;
http_encoding_chunked_context ctx = { 0 };
ctx.state = ChunkStateLenghHeader;
ctx.nextOffset = 0;
ctx.headerFooterPos = 0;
int full_len = 0;
do
{
if (!Stream_EnsureRemainingCapacity(response->data, 2048))
goto out_error;
int status = http_chuncked_read(tls->bio, Stream_Pointer(response->data),
Stream_GetRemainingCapacity(response->data), &ctx);
if (status <= 0)
{
if (!BIO_should_retry(tls->bio))
{
WLog_ERR(TAG, "Retries exceeded");
ERR_print_errors_cb(print_bio_error, NULL);
goto out_error;
}
USleep(100);
}
else
{
Stream_Seek(response->data, (size_t)status);
full_len += status;
}
} while (ctx.state != ChunkStateEnd);
response->BodyLength = full_len;
if (response->BodyLength > 0)
response->BodyContent = &(Stream_Buffer(response->data))[payloadOffset];
}
else
{
while (response->BodyLength < bodyLength)
{
int status = 0;
if (!Stream_EnsureRemainingCapacity(response->data,
bodyLength - response->BodyLength))
goto out_error;
ERR_clear_error();
status = BIO_read(tls->bio, Stream_Pointer(response->data),
bodyLength - response->BodyLength);
if (status <= 0)
{
if (!BIO_should_retry(tls->bio))
{
WLog_ERR(TAG, "Retries exceeded");
ERR_print_errors_cb(print_bio_error, NULL);
goto out_error;
}
USleep(100);
continue;
}
Stream_Seek(response->data, (size_t)status);
response->BodyLength += (unsigned long)status;
if (response->BodyLength > RESPONSE_SIZE_LIMIT)
{
WLog_ERR(TAG, "Request body too large! (%" PRIdz " bytes) Aborting!",
response->BodyLength);
goto out_error;
}
}
if (response->BodyLength > 0)
response->BodyContent = &(Stream_Buffer(response->data))[payloadOffset];
if (bodyLength != response->BodyLength)
{
WLog_WARN(TAG, "%s unexpected body length: actual: %" PRIuz ", expected: %" PRIuz,
response->ContentType, response->BodyLength, bodyLength);
if (bodyLength > 0)
response->BodyLength = MIN(bodyLength, response->BodyLength);
}
/* '\0' terminate the http body */
if (!Stream_EnsureRemainingCapacity(response->data, sizeof(UINT16)))
goto out_error;
Stream_Write_UINT16(response->data, 0);
}
} }
Stream_SealLength(response->data); Stream_SealLength(response->data);

View File

@ -117,7 +117,6 @@ typedef struct
struct rdp_rdg struct rdp_rdg
{ {
rdpContext* context; rdpContext* context;
rdpSettings* settings;
BOOL attached; BOOL attached;
BIO* frontBio; BIO* frontBio;
rdpTls* tlsIn; rdpTls* tlsIn;
@ -500,7 +499,8 @@ static BOOL rdg_send_tunnel_request(rdpRdg* rdg)
if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA)
{ {
PAACookie = ConvertUtf8ToWCharAlloc(rdg->settings->GatewayAccessToken, &PAACookieLen); PAACookie =
ConvertUtf8ToWCharAlloc(rdg->context->settings->GatewayAccessToken, &PAACookieLen);
if (!PAACookie || (PAACookieLen > UINT16_MAX / sizeof(WCHAR))) if (!PAACookie || (PAACookieLen > UINT16_MAX / sizeof(WCHAR)))
{ {
@ -553,8 +553,8 @@ static BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
BOOL status = 0; BOOL status = 0;
WINPR_ASSERT(rdg); WINPR_ASSERT(rdg);
size_t clientNameLen = 0; size_t clientNameLen = 0;
WCHAR* clientName = WCHAR* clientName = freerdp_settings_get_string_as_utf16(
freerdp_settings_get_string_as_utf16(rdg->settings, FreeRDP_ClientHostname, &clientNameLen); rdg->context->settings, FreeRDP_ClientHostname, &clientNameLen);
if (!clientName || (clientNameLen >= UINT16_MAX / sizeof(WCHAR))) if (!clientName || (clientNameLen >= UINT16_MAX / sizeof(WCHAR)))
{ {
@ -600,8 +600,8 @@ static BOOL rdg_send_channel_create(rdpRdg* rdg)
size_t serverNameLen = 0; size_t serverNameLen = 0;
WINPR_ASSERT(rdg); WINPR_ASSERT(rdg);
serverName = serverName = freerdp_settings_get_string_as_utf16(rdg->context->settings,
freerdp_settings_get_string_as_utf16(rdg->settings, FreeRDP_ServerHostname, &serverNameLen); FreeRDP_ServerHostname, &serverNameLen);
if (!serverName || (serverNameLen >= UINT16_MAX / sizeof(WCHAR))) if (!serverName || (serverNameLen >= UINT16_MAX / sizeof(WCHAR)))
goto fail; goto fail;
@ -618,7 +618,8 @@ static BOOL rdg_send_channel_create(rdpRdg* rdg)
Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */ Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */
Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */ Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */
Stream_Write_UINT16(s, (UINT16)rdg->settings->ServerPort); /* Resource port (2 bytes) */ Stream_Write_UINT16(s,
(UINT16)rdg->context->settings->ServerPort); /* Resource port (2 bytes) */
Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */ Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */
Stream_Write_UINT16(s, (UINT16)serverNameLen * sizeof(WCHAR)); Stream_Write_UINT16(s, (UINT16)serverNameLen * sizeof(WCHAR));
Stream_Write_UTF16_String(s, serverName, (size_t)serverNameLen); Stream_Write_UTF16_String(s, serverName, (size_t)serverNameLen);
@ -688,7 +689,7 @@ static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method,
else if (rdg->extAuth == HTTP_EXTENDED_AUTH_BEARER) else if (rdg->extAuth == HTTP_EXTENDED_AUTH_BEARER)
{ {
http_request_set_auth_scheme(request, "Bearer"); http_request_set_auth_scheme(request, "Bearer");
http_request_set_auth_param(request, rdg->settings->GatewayHttpExtAuthBearer); http_request_set_auth_param(request, rdg->context->settings->GatewayHttpExtAuthBearer);
} }
http_request_set_transfer_encoding(request, transferEncoding); http_request_set_transfer_encoding(request, transferEncoding);
@ -1269,7 +1270,7 @@ static BOOL rdg_tls_connect(rdpRdg* rdg, rdpTls* tls, const char* peerAddress, i
long status = 0; long status = 0;
BIO* socketBio = NULL; BIO* socketBio = NULL;
BIO* bufferedBio = NULL; BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings; rdpSettings* settings = rdg->context->settings;
const char* peerHostname = settings->GatewayHostname; const char* peerHostname = settings->GatewayHostname;
UINT16 peerPort = (UINT16)settings->GatewayPort; UINT16 peerPort = (UINT16)settings->GatewayPort;
const char* proxyUsername = NULL; const char* proxyUsername = NULL;
@ -1355,7 +1356,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
return FALSE; return FALSE;
WINPR_ASSERT(rpcFallback); WINPR_ASSERT(rpcFallback);
if (rdg->settings->GatewayHttpExtAuthBearer && rdg->extAuth == HTTP_EXTENDED_AUTH_NONE) if (rdg->context->settings->GatewayHttpExtAuthBearer && rdg->extAuth == HTTP_EXTENDED_AUTH_NONE)
rdg->extAuth = HTTP_EXTENDED_AUTH_BEARER; rdg->extAuth = HTTP_EXTENDED_AUTH_BEARER;
if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE) if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE)
{ {
@ -2216,21 +2217,22 @@ rdpRdg* rdg_new(rdpContext* context)
rdg->log = WLog_Get(TAG); rdg->log = WLog_Get(TAG);
rdg->state = RDG_CLIENT_STATE_INITIAL; rdg->state = RDG_CLIENT_STATE_INITIAL;
rdg->context = context; rdg->context = context;
rdg->settings = rdg->context->settings; rdg->context->settings = rdg->context->settings;
rdg->extAuth = (rdg->settings->GatewayHttpExtAuthSspiNtlm ? HTTP_EXTENDED_AUTH_SSPI_NTLM rdg->extAuth =
: HTTP_EXTENDED_AUTH_NONE); (rdg->context->settings->GatewayHttpExtAuthSspiNtlm ? HTTP_EXTENDED_AUTH_SSPI_NTLM
: HTTP_EXTENDED_AUTH_NONE);
if (rdg->settings->GatewayAccessToken) if (rdg->context->settings->GatewayAccessToken)
rdg->extAuth = HTTP_EXTENDED_AUTH_PAA; rdg->extAuth = HTTP_EXTENDED_AUTH_PAA;
UuidCreate(&rdg->guid); UuidCreate(&rdg->guid);
rdg->tlsOut = freerdp_tls_new(rdg->settings); rdg->tlsOut = freerdp_tls_new(rdg->context);
if (!rdg->tlsOut) if (!rdg->tlsOut)
goto rdg_alloc_error; goto rdg_alloc_error;
rdg->tlsIn = freerdp_tls_new(rdg->settings); rdg->tlsIn = freerdp_tls_new(rdg->context);
if (!rdg->tlsIn) if (!rdg->tlsIn)
goto rdg_alloc_error; goto rdg_alloc_error;
@ -2246,12 +2248,12 @@ rdpRdg* rdg_new(rdpContext* context)
!http_context_set_pragma(rdg->http, "no-cache") || !http_context_set_pragma(rdg->http, "no-cache") ||
!http_context_set_connection(rdg->http, "Keep-Alive") || !http_context_set_connection(rdg->http, "Keep-Alive") ||
!http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0") || !http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0") ||
!http_context_set_host(rdg->http, rdg->settings->GatewayHostname) || !http_context_set_host(rdg->http, rdg->context->settings->GatewayHostname) ||
!http_context_set_rdg_connection_id(rdg->http, &rdg->guid) || !http_context_set_rdg_connection_id(rdg->http, &rdg->guid) ||
!http_context_set_rdg_correlation_id(rdg->http, &rdg->guid) || !http_context_set_rdg_correlation_id(rdg->http, &rdg->guid) ||
!http_context_enable_websocket_upgrade( !http_context_enable_websocket_upgrade(
rdg->http, rdg->http, freerdp_settings_get_bool(rdg->context->settings,
freerdp_settings_get_bool(rdg->settings, FreeRDP_GatewayHttpUseWebsockets))) FreeRDP_GatewayHttpUseWebsockets)))
{ {
goto rdg_alloc_error; goto rdg_alloc_error;
} }

View File

@ -762,7 +762,7 @@ static BOOL rpc_channel_tls_connect(RpcChannel* channel, UINT32 timeout)
} }
channel->bio = bufferedBio; channel->bio = bufferedBio;
tls = channel->tls = freerdp_tls_new(settings); tls = channel->tls = freerdp_tls_new(context);
if (!tls) if (!tls)
return FALSE; return FALSE;

View File

@ -53,7 +53,6 @@
struct rdp_wst struct rdp_wst
{ {
rdpContext* context; rdpContext* context;
rdpSettings* settings;
BOOL attached; BOOL attached;
BIO* frontBio; BIO* frontBio;
rdpTls* tls; rdpTls* tls;
@ -217,7 +216,7 @@ static BOOL wst_tls_connect(rdpWst* wst, rdpTls* tls, int timeout)
long status = 0; long status = 0;
BIO* socketBio = NULL; BIO* socketBio = NULL;
BIO* bufferedBio = NULL; BIO* bufferedBio = NULL;
rdpSettings* settings = wst->settings; rdpSettings* settings = wst->context->settings;
const char* peerHostname = wst->gwhostname; const char* peerHostname = wst->gwhostname;
UINT16 peerPort = wst->gwport; UINT16 peerPort = wst->gwport;
const char* proxyUsername = NULL; const char* proxyUsername = NULL;
@ -313,11 +312,12 @@ static wStream* wst_build_http_request(rdpWst* wst)
if (!wst_set_auth_header(wst->auth, request)) if (!wst_set_auth_header(wst->auth, request))
goto out; goto out;
} }
else if (freerdp_settings_get_string(wst->settings, FreeRDP_GatewayHttpExtAuthBearer)) else if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer))
{ {
http_request_set_auth_scheme(request, "Bearer"); http_request_set_auth_scheme(request, "Bearer");
http_request_set_auth_param( http_request_set_auth_param(
request, freerdp_settings_get_string(wst->settings, FreeRDP_GatewayHttpExtAuthBearer)); request,
freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer));
} }
s = http_request_write(wst->http, request); s = http_request_write(wst->http, request);
@ -362,7 +362,7 @@ static BOOL wst_handle_ok_or_forbidden(rdpWst* wst, HttpResponse** ppresponse, D
/* AVD returns a 403 response with a ARRAffinity cookie set. retry with that cookie */ /* AVD returns a 403 response with a ARRAffinity cookie set. retry with that cookie */
const char* affinity = http_response_get_setcookie(*ppresponse, "ARRAffinity"); const char* affinity = http_response_get_setcookie(*ppresponse, "ARRAffinity");
if (affinity && freerdp_settings_get_bool(wst->settings, FreeRDP_GatewayArmTransport)) if (affinity && freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
{ {
WLog_DBG(TAG, "Got Affinity cookie %s", affinity); WLog_DBG(TAG, "Got Affinity cookie %s", affinity);
http_context_set_cookie(wst->http, "ARRAffinity", affinity); http_context_set_cookie(wst->http, "ARRAffinity", affinity);
@ -374,19 +374,19 @@ static BOOL wst_handle_ok_or_forbidden(rdpWst* wst, HttpResponse** ppresponse, D
closesocket((SOCKET)fd); closesocket((SOCKET)fd);
freerdp_tls_free(wst->tls); freerdp_tls_free(wst->tls);
wst->tls = freerdp_tls_new(wst->settings); wst->tls = freerdp_tls_new(wst->context);
if (!wst_tls_connect(wst, wst->tls, timeout)) if (!wst_tls_connect(wst, wst->tls, timeout))
return FALSE; return FALSE;
if (freerdp_settings_get_string(wst->settings, FreeRDP_GatewayHttpExtAuthBearer) && if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer) &&
freerdp_settings_get_bool(wst->settings, FreeRDP_GatewayArmTransport)) freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
{ {
char* urlWithAuth = NULL; char* urlWithAuth = NULL;
size_t urlLen = 0; size_t urlLen = 0;
char firstParam = (strchr(wst->gwpath, '?') != NULL) ? '&' : '?'; char firstParam = (strchr(wst->gwpath, '?') != NULL) ? '&' : '?';
winpr_asprintf( winpr_asprintf(&urlWithAuth, &urlLen, arm_query_param, wst->gwpath, firstParam,
&urlWithAuth, &urlLen, arm_query_param, wst->gwpath, firstParam, freerdp_settings_get_string(wst->context->settings,
freerdp_settings_get_string(wst->settings, FreeRDP_GatewayHttpExtAuthBearer)); FreeRDP_GatewayHttpExtAuthBearer));
if (!urlWithAuth) if (!urlWithAuth)
return FALSE; return FALSE;
free(wst->gwpath); free(wst->gwpath);
@ -416,7 +416,7 @@ static BOOL wst_handle_denied(rdpWst* wst, HttpResponse** ppresponse, long* pSta
WINPR_ASSERT(*ppresponse); WINPR_ASSERT(*ppresponse);
WINPR_ASSERT(pStatusCode); WINPR_ASSERT(pStatusCode);
if (freerdp_settings_get_string(wst->settings, FreeRDP_GatewayHttpExtAuthBearer)) if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer))
return FALSE; return FALSE;
if (!wst_auth_init(wst, wst->tls, AUTH_PKG)) if (!wst_auth_init(wst, wst->tls, AUTH_PKG))
@ -457,7 +457,7 @@ BOOL wst_connect(rdpWst* wst, DWORD timeout)
WINPR_ASSERT(wst); WINPR_ASSERT(wst);
if (!wst_tls_connect(wst, wst->tls, timeout)) if (!wst_tls_connect(wst, wst->tls, timeout))
return FALSE; return FALSE;
if (freerdp_settings_get_bool(wst->settings, FreeRDP_GatewayArmTransport)) if (freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
{ {
/* /*
* If we are directed here from a ARM Gateway first * If we are directed here from a ARM Gateway first
@ -793,7 +793,6 @@ rdpWst* wst_new(rdpContext* context)
if (wst) if (wst)
{ {
wst->context = context; wst->context = context;
wst->settings = wst->context->settings;
wst->gwhostname = NULL; wst->gwhostname = NULL;
wst->gwport = 443; wst->gwport = 443;
@ -802,7 +801,7 @@ rdpWst* wst_new(rdpContext* context)
if (!wst_parse_url(wst, context->settings->GatewayUrl)) if (!wst_parse_url(wst, context->settings->GatewayUrl))
goto wst_alloc_error; goto wst_alloc_error;
wst->tls = freerdp_tls_new(wst->settings); wst->tls = freerdp_tls_new(wst->context);
if (!wst->tls) if (!wst->tls)
goto wst_alloc_error; goto wst_alloc_error;

View File

@ -291,7 +291,7 @@ static BOOL transport_default_connect_tls(rdpTransport* transport)
settings = context->settings; settings = context->settings;
WINPR_ASSERT(settings); WINPR_ASSERT(settings);
if (!(tls = freerdp_tls_new(settings))) if (!(tls = freerdp_tls_new(context)))
return FALSE; return FALSE;
transport->tls = tls; transport->tls = tls;
@ -629,7 +629,7 @@ static BOOL transport_default_accept_tls(rdpTransport* transport)
WINPR_ASSERT(settings); WINPR_ASSERT(settings);
if (!transport->tls) if (!transport->tls)
transport->tls = freerdp_tls_new(settings); transport->tls = freerdp_tls_new(context);
transport->layer = TRANSPORT_LAYER_TLS; transport->layer = TRANSPORT_LAYER_TLS;

View File

@ -750,7 +750,7 @@ static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int op
{ {
WINPR_ASSERT(tls); WINPR_ASSERT(tls);
rdpSettings* settings = tls->settings; rdpSettings* settings = tls->context->settings;
WINPR_ASSERT(settings); WINPR_ASSERT(settings);
tls_reset(tls); tls_reset(tls);
@ -1295,7 +1295,7 @@ static BOOL tls_match_hostname(const char* pattern, const size_t pattern_length,
static BOOL is_redirected(rdpTls* tls) static BOOL is_redirected(rdpTls* tls)
{ {
rdpSettings* settings = tls->settings; rdpSettings* settings = tls->context->settings;
if (LB_NOREDIRECT & settings->RedirectionFlags) if (LB_NOREDIRECT & settings->RedirectionFlags)
return FALSE; return FALSE;
@ -1305,7 +1305,7 @@ static BOOL is_redirected(rdpTls* tls)
static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length) static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
{ {
rdpSettings* settings = tls->settings; rdpSettings* settings = tls->context->settings;
char* AccpetedKey = NULL; char* AccpetedKey = NULL;
UINT32 AcceptedKeyLength = 0; UINT32 AcceptedKeyLength = 0;
@ -1431,7 +1431,7 @@ static BOOL accept_cert(rdpTls* tls, const BYTE* pem, UINT32 length)
FreeRDP_Settings_Keys_String id = FreeRDP_AcceptedCert; FreeRDP_Settings_Keys_String id = FreeRDP_AcceptedCert;
FreeRDP_Settings_Keys_UInt32 lid = FreeRDP_AcceptedCertLength; FreeRDP_Settings_Keys_UInt32 lid = FreeRDP_AcceptedCertLength;
rdpSettings* settings = tls->settings; rdpSettings* settings = tls->context->settings;
if (tls->isGatewayTransport) if (tls->isGatewayTransport)
{ {
@ -1477,9 +1477,9 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
freerdp* instance = NULL; freerdp* instance = NULL;
WINPR_ASSERT(tls); WINPR_ASSERT(tls);
WINPR_ASSERT(tls->settings); WINPR_ASSERT(tls->context->settings);
instance = (freerdp*)tls->settings->instance; instance = (freerdp*)tls->context->settings->instance;
WINPR_ASSERT(instance); WINPR_ASSERT(instance);
if (freerdp_shall_disconnect_context(instance->context)) if (freerdp_shall_disconnect_context(instance->context))
@ -1495,7 +1495,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
goto end; goto end;
} }
if (is_accepted_fingerprint(cert, tls->settings->CertificateAcceptedFingerprints)) if (is_accepted_fingerprint(cert, tls->context->settings->CertificateAcceptedFingerprints))
{ {
verification_status = 1; verification_status = 1;
goto end; goto end;
@ -1511,7 +1511,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
flags |= VERIFY_CERT_FLAG_REDIRECT; flags |= VERIFY_CERT_FLAG_REDIRECT;
/* Certificate management is done by the application */ /* Certificate management is done by the application */
if (tls->settings->ExternalCertificateManagement) if (tls->context->settings->ExternalCertificateManagement)
{ {
if (instance->VerifyX509Certificate) if (instance->VerifyX509Certificate)
verification_status = verification_status =
@ -1529,15 +1529,15 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
} }
} }
/* ignore certificate verification if user explicitly required it (discouraged) */ /* ignore certificate verification if user explicitly required it (discouraged) */
else if (tls->settings->IgnoreCertificate) else if (tls->context->settings->IgnoreCertificate)
verification_status = 1; /* success! */ verification_status = 1; /* success! */
else if (!tls->isGatewayTransport && (tls->settings->AuthenticationLevel == 0)) else if (!tls->isGatewayTransport && (tls->context->settings->AuthenticationLevel == 0))
verification_status = 1; /* success! */ verification_status = 1; /* success! */
else else
{ {
/* if user explicitly specified a certificate name, use it instead of the hostname */ /* if user explicitly specified a certificate name, use it instead of the hostname */
if (!tls->isGatewayTransport && tls->settings->CertificateName) if (!tls->isGatewayTransport && tls->context->settings->CertificateName)
hostname = tls->settings->CertificateName; hostname = tls->context->settings->CertificateName;
/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */ /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
certificate_status = freerdp_certificate_verify( certificate_status = freerdp_certificate_verify(
@ -1612,12 +1612,12 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
} }
/* Automatically accept certificate on first use */ /* Automatically accept certificate on first use */
if (tls->settings->AutoAcceptCertificate) if (tls->context->settings->AutoAcceptCertificate)
{ {
WLog_INFO(TAG, "No certificate stored, automatically accepting."); WLog_INFO(TAG, "No certificate stored, automatically accepting.");
accept_certificate = 1; accept_certificate = 1;
} }
else if (tls->settings->AutoDenyCertificate) else if (tls->context->settings->AutoDenyCertificate)
{ {
WLog_INFO(TAG, "No certificate stored, automatically denying."); WLog_INFO(TAG, "No certificate stored, automatically denying.");
accept_certificate = 0; accept_certificate = 0;
@ -1637,7 +1637,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
else if (instance->VerifyCertificateEx) else if (instance->VerifyCertificateEx)
{ {
const BOOL use_pem = freerdp_settings_get_bool( const BOOL use_pem = freerdp_settings_get_bool(
tls->settings, FreeRDP_CertificateCallbackPreferPEM); tls->context->settings, FreeRDP_CertificateCallbackPreferPEM);
char* fp = NULL; char* fp = NULL;
DWORD cflags = flags; DWORD cflags = flags;
if (use_pem) if (use_pem)
@ -1682,7 +1682,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
WLog_WARN(TAG, "Failed to get certificate entry for %s:%" PRIu16 "", hostname, WLog_WARN(TAG, "Failed to get certificate entry for %s:%" PRIu16 "", hostname,
port); port);
if (tls->settings->AutoDenyCertificate) if (tls->context->settings->AutoDenyCertificate)
{ {
WLog_INFO(TAG, "No certificate stored, automatically denying."); WLog_INFO(TAG, "No certificate stored, automatically denying.");
accept_certificate = 0; accept_certificate = 0;
@ -1708,8 +1708,9 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
const char* old_fp = freerdp_certificate_data_get_fingerprint(stored_data); const char* old_fp = freerdp_certificate_data_get_fingerprint(stored_data);
const char* old_pem = freerdp_certificate_data_get_pem(stored_data); const char* old_pem = freerdp_certificate_data_get_pem(stored_data);
const BOOL fpIsAllocated = const BOOL fpIsAllocated =
!old_pem || !freerdp_settings_get_bool( !old_pem ||
tls->settings, FreeRDP_CertificateCallbackPreferPEM); !freerdp_settings_get_bool(tls->context->settings,
FreeRDP_CertificateCallbackPreferPEM);
char* fp = NULL; char* fp = NULL;
if (!fpIsAllocated) if (!fpIsAllocated)
{ {
@ -1857,7 +1858,7 @@ void tls_print_certificate_name_mismatch_error(const char* hostname, UINT16 port
WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!"); WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!");
} }
rdpTls* freerdp_tls_new(rdpSettings* settings) rdpTls* freerdp_tls_new(rdpContext* context)
{ {
rdpTls* tls = NULL; rdpTls* tls = NULL;
tls = (rdpTls*)calloc(1, sizeof(rdpTls)); tls = (rdpTls*)calloc(1, sizeof(rdpTls));
@ -1865,11 +1866,11 @@ rdpTls* freerdp_tls_new(rdpSettings* settings)
if (!tls) if (!tls)
return NULL; return NULL;
tls->settings = settings; tls->context = context;
if (!settings->ServerMode) if (!freerdp_settings_get_bool(tls->context->settings, FreeRDP_ServerMode))
{ {
tls->certificate_store = freerdp_certificate_store_new(settings); tls->certificate_store = freerdp_certificate_store_new(tls->context->settings);
if (!tls->certificate_store) if (!tls->certificate_store)
goto out_free; goto out_free;

View File

@ -71,7 +71,7 @@ struct rdp_tls
SSL_CTX* ctx; SSL_CTX* ctx;
BYTE* PublicKey; BYTE* PublicKey;
DWORD PublicKeyLength; DWORD PublicKeyLength;
rdpSettings* settings; rdpContext* context;
SecPkgContext_Bindings* Bindings; SecPkgContext_Bindings* Bindings;
rdpCertificateStore* certificate_store; rdpCertificateStore* certificate_store;
BIO* underlying; BIO* underlying;
@ -122,7 +122,7 @@ extern "C"
FREERDP_LOCAL void freerdp_tls_free(rdpTls* tls); FREERDP_LOCAL void freerdp_tls_free(rdpTls* tls);
WINPR_ATTR_MALLOC(freerdp_tls_free, 1) WINPR_ATTR_MALLOC(freerdp_tls_free, 1)
FREERDP_LOCAL rdpTls* freerdp_tls_new(rdpSettings* settings); FREERDP_LOCAL rdpTls* freerdp_tls_new(rdpContext* context);
#ifdef __cplusplus #ifdef __cplusplus
} }