summaryrefslogtreecommitdiffstats
path: root/libfreerdp/core/gateway
diff options
context:
space:
mode:
Diffstat (limited to 'libfreerdp/core/gateway')
-rw-r--r--libfreerdp/core/gateway/arm.c9
-rw-r--r--libfreerdp/core/gateway/http.c20
-rw-r--r--libfreerdp/core/gateway/rdg.c221
-rw-r--r--libfreerdp/core/gateway/tsg.c120
-rw-r--r--libfreerdp/core/gateway/tsg.h2
-rw-r--r--libfreerdp/core/gateway/wst.c2
6 files changed, 248 insertions, 126 deletions
diff --git a/libfreerdp/core/gateway/arm.c b/libfreerdp/core/gateway/arm.c
index 9848c48..d506c75 100644
--- a/libfreerdp/core/gateway/arm.c
+++ b/libfreerdp/core/gateway/arm.c
@@ -549,6 +549,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output1 || !len1)
{
WLog_ERR(TAG, "error when first unbase64 for %s", name);
+ free(output1);
return FALSE;
}
@@ -558,6 +559,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output2 || !len2)
{
WLog_ERR(TAG, "error when decode('utf-16') for %s", name);
+ free(output2);
return FALSE;
}
@@ -567,6 +569,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output || !*plen)
{
WLog_ERR(TAG, "error when second unbase64 for %s", name);
+ free(output);
return FALSE;
}
@@ -842,7 +845,11 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO
0)
{
*retry = TRUE;
- WLog_DBG(TAG, "Starting your VM. It may take up to 5 minutes");
+ const cJSON* message = cJSON_GetObjectItemCaseSensitive(json, "Message");
+ if (!cJSON_IsString(message) || !message->valuestring)
+ WLog_WARN(TAG, "Starting your VM. It may take up to 5 minutes");
+ else
+ WLog_WARN(TAG, "%s", message->valuestring);
}
else
{
diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c
index cf70b3b..a7cdaab 100644
--- a/libfreerdp/core/gateway/http.c
+++ b/libfreerdp/core/gateway/http.c
@@ -322,8 +322,9 @@ static BOOL list_append(HttpContext* context, WINPR_FORMAT_ARG const char* str,
}
else
sstr = Pragma;
- free(context->Pragma);
+ Pragma = NULL;
+ free(context->Pragma);
context->Pragma = sstr;
rc = TRUE;
@@ -830,7 +831,10 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
const char* value)
{
BOOL status = TRUE;
- if (!response || !name)
+
+ WINPR_ASSERT(response);
+
+ if (!name)
return FALSE;
if (_stricmp(name, "Content-Length") == 0)
@@ -924,6 +928,10 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
*separator = '\0';
CookieName = value;
CookieValue = separator + 1;
+
+ if (!CookieName || !CookieValue)
+ return FALSE;
+
if (*CookieValue == '"')
{
char* p = CookieValue;
@@ -944,9 +952,6 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
}
*p = '\0';
}
-
- if (!CookieName || !CookieValue)
- return FALSE;
}
else
{
@@ -1053,12 +1058,13 @@ static void http_response_print(wLog* log, DWORD level, const HttpResponse* resp
freerdp_http_status_string_format(status, buffer, ARRAYSIZE(buffer)));
for (size_t i = 0; i < response->count; i++)
- WLog_Print(log, level, "[%" PRIuz "] %s", i, response->lines[i]);
+ WLog_Print(log, WLOG_DEBUG, "[%" PRIuz "] %s", i, response->lines[i]);
if (response->ReasonPhrase)
WLog_Print(log, level, "[reason] %s", response->ReasonPhrase);
- WLog_Print(log, level, "[body][%" PRIuz "] %s", response->BodyLength, response->BodyContent);
+ WLog_Print(log, WLOG_TRACE, "[body][%" PRIuz "] %s", response->BodyLength,
+ response->BodyContent);
}
static BOOL http_use_content_length(const char* cur)
diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c
index c6d952b..484b599 100644
--- a/libfreerdp/core/gateway/rdg.c
+++ b/libfreerdp/core/gateway/rdg.c
@@ -89,15 +89,6 @@
#define HTTP_TUNNEL_PACKET_FIELD_PAA_COOKIE 0x1
#define HTTP_TUNNEL_PACKET_FIELD_REAUTH 0x2
-/* HTTP tunnel redir flags. */
-#define HTTP_TUNNEL_REDIR_ENABLE_ALL 0x80000000
-#define HTTP_TUNNEL_REDIR_DISABLE_ALL 0x40000000
-#define HTTP_TUNNEL_REDIR_DISABLE_DRIVE 0x1
-#define HTTP_TUNNEL_REDIR_DISABLE_PRINTER 0x2
-#define HTTP_TUNNEL_REDIR_DISABLE_PORT 0x4
-#define HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD 0x8
-#define HTTP_TUNNEL_REDIR_DISABLE_PNP 0x10
-
/* HTTP tunnel response fields present flags. */
#define HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID 0x1
#define HTTP_TUNNEL_RESPONSE_FIELD_CAPS 0x2
@@ -146,6 +137,7 @@ struct rdp_rdg
rdg_http_encoding_context transferEncoding;
SmartcardCertInfo* smartcard;
+ wLog* log;
};
enum
@@ -261,15 +253,17 @@ static const char* capabilities_enum_to_string(UINT32 capabilities)
return flags_to_string(capabilities, capabilities_enum, ARRAYSIZE(capabilities_enum));
}
-static BOOL rdg_read_http_unicode_string(wStream* s, const WCHAR** string, UINT16* lengthInBytes)
+static BOOL rdg_read_http_unicode_string(wLog* log, wStream* s, const WCHAR** string,
+ UINT16* lengthInBytes)
{
UINT16 strLenBytes = 0;
size_t rem = Stream_GetRemainingLength(s);
/* Read length of the string */
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
{
- WLog_ERR(TAG, "Could not read stream length, only have %" PRIuz " bytes", rem);
+ WLog_Print(log, WLOG_ERROR, "Could not read stream length, only have %" PRIuz " bytes",
+ rem);
return FALSE;
}
Stream_Read_UINT16(s, strLenBytes);
@@ -280,8 +274,9 @@ static BOOL rdg_read_http_unicode_string(wStream* s, const WCHAR** string, UINT1
/* seek past the string - if this fails something is wrong */
if (!Stream_SafeSeek(s, strLenBytes))
{
- WLog_ERR(TAG, "Could not read stream data, only have %" PRIuz " bytes, expected %" PRIu16,
- rem - 4, strLenBytes);
+ WLog_Print(log, WLOG_ERROR,
+ "Could not read stream data, only have %" PRIuz " bytes, expected %" PRIu16,
+ rem - 4, strLenBytes);
return FALSE;
}
@@ -362,7 +357,13 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size,
}
}
-static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
+static BOOL rdg_shall_abort(rdpRdg* rdg)
+{
+ WINPR_ASSERT(rdg);
+ return freerdp_shall_disconnect_context(rdg->context);
+}
+
+static BOOL rdg_read_all(rdpContext* context, rdpTls* tls, BYTE* buffer, size_t size,
rdg_http_encoding_context* transferEncoding)
{
size_t readCount = 0;
@@ -370,6 +371,9 @@ static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
while (readCount < size)
{
+ if (freerdp_shall_disconnect_context(context))
+ return FALSE;
+
int status = rdg_socket_read(tls->bio, pBuffer, size - readCount, transferEncoding);
if (status <= 0)
{
@@ -396,7 +400,7 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
if (!s)
return NULL;
- if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), header, &rdg->transferEncoding))
+ if (!rdg_read_all(rdg->context, rdg->tlsOut, Stream_Buffer(s), header, &rdg->transferEncoding))
{
Stream_Free(s, TRUE);
return NULL;
@@ -412,8 +416,8 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
return NULL;
}
- if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + header, (int)packetLength - (int)header,
- &rdg->transferEncoding))
+ if (!rdg_read_all(rdg->context, rdg->tlsOut, Stream_Buffer(s) + header,
+ (int)packetLength - (int)header, &rdg->transferEncoding))
{
Stream_Free(s, TRUE);
return NULL;
@@ -699,7 +703,7 @@ out:
return s;
}
-static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
+static BOOL rdg_recv_auth_token(wLog* log, rdpCredsspAuth* auth, HttpResponse* response)
{
size_t len = 0;
const char* token64 = NULL;
@@ -719,7 +723,7 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
case HTTP_STATUS_OK:
break;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(log, WLOG_WARN, response);
return FALSE;
}
@@ -738,6 +742,8 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
authToken.cbBuffer = authTokenLength;
credssp_auth_take_input_buffer(auth, &authToken);
}
+ else
+ free(authTokenData);
rc = credssp_auth_authenticate(auth);
if (rc < 0)
@@ -746,7 +752,7 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
return TRUE;
}
-static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength,
+static BOOL rdg_skip_seed_payload(rdpContext* context, rdpTls* tls, size_t lastResponseLength,
rdg_http_encoding_context* transferEncoding)
{
BYTE seed_payload[10] = { 0 };
@@ -755,9 +761,9 @@ static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength,
/* Per [MS-TSGU] 3.3.5.1 step 4, after final OK response RDG server sends
* random "seed" payload of limited size. In practice it's 10 bytes.
*/
- if (lastResponseLength < (SSIZE_T)size)
+ if (lastResponseLength < size)
{
- if (!rdg_read_all(tls, seed_payload, size - lastResponseLength, transferEncoding))
+ if (!rdg_read_all(context, tls, seed_payload, size - lastResponseLength, transferEncoding))
{
return FALSE;
}
@@ -774,14 +780,14 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
BYTE verMajor = 0;
BYTE verMinor = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Handshake response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Handshake response received");
if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 10))
return FALSE;
Stream_Read_UINT32(s, errorCode);
@@ -790,14 +796,14 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
Stream_Read_UINT16(s, serverVersion);
Stream_Read_UINT16(s, extendedAuth);
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG,
- "errorCode=%s, verMajor=%" PRId8 ", verMinor=%" PRId8 ", serverVersion=%" PRId16
- ", extendedAuth=%s",
- error, verMajor, verMinor, serverVersion, extended_auth_to_string(extendedAuth));
+ WLog_Print(rdg->log, WLOG_DEBUG,
+ "errorCode=%s, verMajor=%" PRId8 ", verMinor=%" PRId8 ", serverVersion=%" PRId16
+ ", extendedAuth=%s",
+ error, verMajor, verMinor, serverVersion, extended_auth_to_string(extendedAuth));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "Handshake error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Handshake error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -815,8 +821,8 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
/* Seek over tunnelId (4 bytes) */
if (!Stream_SafeSeek(s, 4))
{
- WLog_ERR(TAG, "Short tunnelId, got %" PRIuz ", expected 4",
- Stream_GetRemainingLength(s));
+ WLog_Print(rdg->log, WLOG_ERROR, "Short tunnelId, got %" PRIuz ", expected 4",
+ Stream_GetRemainingLength(s));
return FALSE;
}
}
@@ -824,11 +830,11 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_CAPS)
{
UINT32 caps = 0;
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 4))
return FALSE;
Stream_Read_UINT32(s, caps);
- WLog_DBG(TAG, "capabilities=%s", capabilities_enum_to_string(caps));
+ WLog_Print(rdg->log, WLOG_DEBUG, "capabilities=%s", capabilities_enum_to_string(caps));
}
if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ)
@@ -836,14 +842,15 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
/* Seek over nonce (20 bytes) */
if (!Stream_SafeSeek(s, 20))
{
- WLog_ERR(TAG, "Short nonce, got %" PRIuz ", expected 20", Stream_GetRemainingLength(s));
+ WLog_Print(rdg->log, WLOG_ERROR, "Short nonce, got %" PRIuz ", expected 20",
+ Stream_GetRemainingLength(s));
return FALSE;
}
/* Read serverCert */
- if (!rdg_read_http_unicode_string(s, NULL, NULL))
+ if (!rdg_read_http_unicode_string(rdg->log, s, NULL, NULL))
{
- WLog_ERR(TAG, "Failed to read server certificate");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read server certificate");
return FALSE;
}
}
@@ -858,9 +865,9 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
WINPR_ASSERT(context->instance);
/* Read message string and invoke callback */
- if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes))
+ if (!rdg_read_http_unicode_string(rdg->log, s, &msg, &msgLenBytes))
{
- WLog_ERR(TAG, "Failed to read consent message");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read consent message");
return FALSE;
}
@@ -877,14 +884,14 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
UINT16 fieldsPresent = 0;
UINT32 errorCode = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Tunnel response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Tunnel response received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 10))
return FALSE;
Stream_Read_UINT16(s, serverVersion);
@@ -892,12 +899,12 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "serverVersion=%" PRId16 ", errorCode=%s, fieldsPresent=%s", serverVersion, error,
- tunnel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "serverVersion=%" PRId16 ", errorCode=%s, fieldsPresent=%s",
+ serverVersion, error, tunnel_response_fields_present_to_string(fieldsPresent));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "Tunnel creation error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Tunnel creation error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -913,31 +920,66 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
UINT32 errorCode = 0;
UINT16 fieldsPresent = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Tunnel authorization received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Tunnel authorization received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT32(s, errorCode);
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "errorCode=%s, fieldsPresent=%s", error,
- tunnel_authorization_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "errorCode=%s, fieldsPresent=%s", error,
+ tunnel_authorization_response_fields_present_to_string(fieldsPresent));
/* [MS-TSGU] 3.7.5.2.7 */
if (errorCode != S_OK && errorCode != E_PROXY_QUARANTINE_ACCESSDENIED)
{
- WLog_ERR(TAG, "Tunnel authorization error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Tunnel authorization error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS)
+ {
+ UINT32 redirFlags = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 4))
+ return FALSE;
+ Stream_Read_UINT32(s, redirFlags);
+
+ rdpContext* context = rdg->context;
+ if (!utils_apply_gateway_policy(rdg->log, context, redirFlags, "RDG"))
+ return FALSE;
+ }
+
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT)
+ {
+ UINT32 idleTimeout = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 4))
+ return FALSE;
+ Stream_Read_UINT32(s, idleTimeout);
+ WLog_Print(rdg->log, WLOG_DEBUG, "[IDLE_TIMEOUT] idleTimeout=%" PRIu32 ": TODO: unused",
+ idleTimeout);
+ }
+
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE)
+ {
+ UINT16 cbLen = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 2))
+ return FALSE;
+ Stream_Read_UINT16(s, cbLen);
+
+ WLog_Print(rdg->log, WLOG_DEBUG, "[SOH_RESPONSE] cbLen=%" PRIu16 ": TODO: unused", cbLen);
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, cbLen))
+ return FALSE;
+ Stream_Seek(s, cbLen);
+ }
+
return rdg_send_channel_create(rdg);
}
@@ -955,8 +997,8 @@ static BOOL rdg_process_extauth_sspi(rdpRdg* rdg, wStream* s)
if (errorCode != ERROR_SUCCESS)
{
- WLog_ERR(TAG, "EXTAUTH_SSPI_NTLM failed with error %s [0x%08X]",
- GetSecurityStatusString(errorCode), errorCode);
+ WLog_Print(rdg->log, WLOG_ERROR, "EXTAUTH_SSPI_NTLM failed with error %s [0x%08X]",
+ GetSecurityStatusString(errorCode), errorCode);
return FALSE;
}
@@ -972,6 +1014,8 @@ static BOOL rdg_process_extauth_sspi(rdpRdg* rdg, wStream* s)
}
authTokenData = malloc(authBlobLen);
+ if (authTokenData == NULL)
+ return FALSE;
Stream_Read(s, authTokenData, authBlobLen);
authToken.pvBuffer = authTokenData;
@@ -993,27 +1037,27 @@ static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
UINT16 fieldsPresent = 0;
UINT32 errorCode = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Channel response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Channel response received");
if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT32(s, errorCode);
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "channel response errorCode=%s, fieldsPresent=%s", error,
- channel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "channel response errorCode=%s, fieldsPresent=%s", error,
+ channel_response_fields_present_to_string(fieldsPresent));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "channel response errorCode=%s, fieldsPresent=%s", error,
- channel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_ERROR, "channel response errorCode=%s, fieldsPresent=%s", error,
+ channel_response_fields_present_to_string(fieldsPresent));
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -1029,7 +1073,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
UINT32 packetLength = 0;
Stream_SetPosition(s, 0);
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT16(s, type);
@@ -1038,7 +1082,8 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
if (Stream_Length(s) < packetLength)
{
- WLog_ERR(TAG, "Short packet %" PRIuz ", expected %" PRIuz, Stream_Length(s), packetLength);
+ WLog_Print(rdg->log, WLOG_ERROR, "Short packet %" PRIuz ", expected %" PRIuz,
+ Stream_Length(s), packetLength);
return FALSE;
}
@@ -1061,7 +1106,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
break;
case PKT_TYPE_DATA:
- WLog_ERR(TAG, "Unexpected packet type DATA");
+ WLog_Print(rdg->log, WLOG_ERROR, "Unexpected packet type DATA");
return FALSE;
case PKT_TYPE_EXTENDED_AUTH_MSG:
@@ -1069,7 +1114,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
break;
default:
- WLog_ERR(TAG, "PKG TYPE 0x%x not implemented", type);
+ WLog_Print(rdg->log, WLOG_ERROR, "PKG TYPE 0x%x not implemented", type);
return FALSE;
}
@@ -1325,7 +1370,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
* sending an answer if it is not happy with the http request */
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1336,7 +1381,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
{
case HTTP_STATUS_NOT_FOUND:
{
- WLog_INFO(TAG, "RD Gateway does not support HTTP transport.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway does not support HTTP transport.");
*rpcFallback = TRUE;
http_response_free(response);
@@ -1345,13 +1390,13 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
case HTTP_STATUS_OK:
break;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(rdg->log, WLOG_WARN, response);
break;
}
while (!credssp_auth_is_complete(rdg->auth))
{
- if (!rdg_recv_auth_token(rdg->auth, response))
+ if (!rdg_recv_auth_token(rdg->log, rdg->auth, response))
{
http_response_free(response);
return FALSE;
@@ -1367,7 +1412,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
response = http_response_recv(tls, TRUE);
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1388,7 +1433,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1398,9 +1443,9 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
const size_t bodyLength = http_response_get_body_length(response);
const TRANSFER_ENCODING encoding = http_response_get_transfer_encoding(response);
const BOOL isWebsocket = http_response_is_websocket(rdg->http, response);
- http_response_free(response);
- WLog_DBG(TAG, "%s authorization result: %s", method,
- freerdp_http_status_string_format(statusCode, buffer, ARRAYSIZE(buffer)));
+
+ WLog_Print(rdg->log, WLOG_DEBUG, "%s authorization result: %s", method,
+ freerdp_http_status_string_format(statusCode, buffer, ARRAYSIZE(buffer)));
switch (statusCode)
{
@@ -1408,11 +1453,14 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
/* old rdg endpoint without websocket support, don't request websocket for RDG_IN_DATA
*/
http_context_enable_websocket_upgrade(rdg->http, FALSE);
+ http_response_free(response);
break;
case HTTP_STATUS_DENIED:
freerdp_set_last_error_log(rdg->context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
+ http_response_free(response);
return FALSE;
case HTTP_STATUS_SWITCH_PROTOCOLS:
+ http_response_free(response);
if (!isWebsocket)
{
/*
@@ -1442,7 +1490,8 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
}
return TRUE;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(rdg->log, WLOG_WARN, response);
+ http_response_free(response);
return FALSE;
}
@@ -1455,7 +1504,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
rdg->transferEncoding.context.chunked.headerFooterPos = 0;
rdg->transferEncoding.context.chunked.state = ChunkStateLenghHeader;
}
- if (!rdg_skip_seed_payload(tls, bodyLength, &rdg->transferEncoding))
+ if (!rdg_skip_seed_payload(rdg->context, tls, bodyLength, &rdg->transferEncoding))
{
return FALSE;
}
@@ -1522,7 +1571,7 @@ BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback)
{
if (rdg->transferEncoding.isWebsocketTransport)
{
- WLog_DBG(TAG, "Upgraded to websocket. RDG_IN_DATA not required");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Upgraded to websocket. RDG_IN_DATA not required");
}
else
{
@@ -1717,7 +1766,7 @@ static BOOL rdg_process_close_packet(rdpRdg* rdg, wStream* s)
UINT32 packetSize = 12;
/* Read error code */
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 4))
return FALSE;
Stream_Read_UINT32(s, errorCode);
@@ -1769,9 +1818,9 @@ static BOOL rdg_process_service_message(rdpRdg* rdg, wStream* s)
WINPR_ASSERT(context->instance);
/* Read message string */
- if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes))
+ if (!rdg_read_http_unicode_string(rdg->log, s, &msg, &msgLenBytes))
{
- WLog_ERR(TAG, "Failed to read string");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read string");
return FALSE;
}
@@ -1783,7 +1832,7 @@ static BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
{
WINPR_UNUSED(rdg);
WINPR_UNUSED(type);
- WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
+ WLog_Print(rdg->log, WLOG_WARN, "Unknown Control Packet received: %X", type);
return TRUE;
}
@@ -1808,6 +1857,11 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
while (readCount < payloadSize)
{
+ if (rdg_shall_abort(rdg))
+ {
+ Stream_Free(s, TRUE);
+ return FALSE;
+ }
status = rdg_socket_read(rdg->tlsOut->bio, Stream_Pointer(s), payloadSize - readCount,
&rdg->transferEncoding);
@@ -1852,7 +1906,8 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
case PKT_TYPE_SERVICE_MESSAGE:
if (!s)
{
- WLog_ERR(TAG, "PKT_TYPE_SERVICE_MESSAGE requires payload but none was sent");
+ WLog_Print(rdg->log, WLOG_ERROR,
+ "PKT_TYPE_SERVICE_MESSAGE requires payload but none was sent");
return FALSE;
}
status = rdg_process_service_message(rdg, s);
@@ -1880,6 +1935,9 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
while (readCount < sizeof(RdgPacketHeader))
{
+ if (rdg_shall_abort(rdg))
+ return -1;
+
status = rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount,
(int)sizeof(RdgPacketHeader) - (int)readCount,
&rdg->transferEncoding);
@@ -1916,6 +1974,8 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
while (readCount < 2)
{
+ if (rdg_shall_abort(rdg))
+ return -1;
status =
rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount,
2 - (int)readCount, &rdg->transferEncoding);
@@ -2153,6 +2213,7 @@ rdpRdg* rdg_new(rdpContext* context)
if (rdg)
{
+ rdg->log = WLog_Get(TAG);
rdg->state = RDG_CLIENT_STATE_INITIAL;
rdg->context = context;
rdg->settings = rdg->context->settings;
@@ -2212,8 +2273,8 @@ rdpRdg* rdg_new(rdpContext* context)
break;
default:
- WLog_DBG(TAG, "RDG extended authentication method %d not supported",
- rdg->extAuth);
+ WLog_Print(rdg->log, WLOG_DEBUG,
+ "RDG extended authentication method %d not supported", rdg->extAuth);
}
}
diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
index 3ab833a..8101e53 100644
--- a/libfreerdp/core/gateway/tsg.c
+++ b/libfreerdp/core/gateway/tsg.c
@@ -35,6 +35,7 @@
#include "rpc_bind.h"
#include "rpc_client.h"
#include "tsg.h"
+#include "../utils.h"
#include "../../crypto/opensslcompat.h"
#define TAG FREERDP_TAG("core.gateway.tsg")
@@ -1590,7 +1591,7 @@ fail:
return FALSE;
}
-static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
+static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, const RPC_PDU* pdu,
CONTEXT_HANDLE* tunnelContext, UINT32* tunnelId)
{
BOOL rc = FALSE;
@@ -1728,7 +1729,41 @@ fail:
return FALSE;
}
-static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
+static UINT32 tsg_redir_to_flags(const TSG_REDIRECTION_FLAGS* redirect)
+{
+ UINT32 flags = 0;
+ if (redirect->enableAllRedirections)
+ flags |= HTTP_TUNNEL_REDIR_ENABLE_ALL;
+ if (redirect->disableAllRedirections)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_ALL;
+
+ if (redirect->driveRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_DRIVE;
+ if (redirect->printerRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PRINTER;
+ if (redirect->portRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PORT;
+ if (redirect->clipboardRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD;
+ if (redirect->pnpRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PNP;
+ return flags;
+}
+
+static BOOL tsg_redirect_apply(rdpTsg* tsg, const TSG_REDIRECTION_FLAGS* redirect)
+{
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(redirect);
+
+ rdpTransport* transport = tsg->transport;
+ WINPR_ASSERT(transport);
+
+ rdpContext* context = transport_get_context(transport);
+ UINT32 redirFlags = tsg_redir_to_flags(redirect);
+ return utils_apply_gateway_policy(tsg->log, context, redirFlags, "TSG");
+}
+
+static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
UINT32 SwitchValue = 0;
@@ -1736,8 +1771,12 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
TSG_PACKET packet = { 0 };
UINT32 PacketPtr = 0;
UINT32 PacketResponsePtr = 0;
- if (!pdu)
- return FALSE;
+
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(pdu);
+
+ wLog* log = tsg->log;
+ WINPR_ASSERT(log);
if (!tsg_ndr_pointer_read(log, pdu->s, &index, &PacketPtr, TRUE))
goto fail;
@@ -1773,6 +1812,9 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
goto fail;
rc = TRUE;
+
+ if (packet.tsgPacket.packetResponse.flags & TSG_PACKET_TYPE_QUARREQUEST)
+ rc = tsg_redirect_apply(tsg, &packet.tsgPacket.packetResponse.redirectionFlags);
fail:
return rc;
}
@@ -1846,7 +1888,7 @@ static BOOL TsProxyReadPacketSTringMessage(rdpTsg* tsg, wStream* s, TSG_PACKET_S
return tsg_ndr_read_string(tsg->log, s, &msg->msgBuffer, msg->msgBytes);
}
-static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
+static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
UINT32 index = 0;
@@ -1991,20 +2033,20 @@ fail:
static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext)
{
- size_t count = 0;
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(tunnelContext);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCreateChannelWriteRequest");
- if (!tsg || !tsg->rpc || !tunnelContext || !tsg->Hostname)
+ if (!tsg->rpc || !tsg->Hostname)
return FALSE;
- rpc = tsg->rpc;
- count = _wcslen(tsg->Hostname) + 1;
+ rdpRpc* rpc = tsg->rpc;
+ const size_t count = _wcslen(tsg->Hostname) + 1;
if (count > UINT32_MAX)
return FALSE;
- s = Stream_New(NULL, 60 + count * 2);
+ wStream* s = Stream_New(NULL, 60 + count * 2);
if (!s)
return FALSE;
@@ -2036,14 +2078,16 @@ fail:
return FALSE;
}
-static BOOL TsProxyCreateChannelReadResponse(wLog* log, RPC_PDU* pdu,
+static BOOL TsProxyCreateChannelReadResponse(wLog* log, const RPC_PDU* pdu,
CONTEXT_HANDLE* channelContext, UINT32* channelId)
{
BOOL rc = FALSE;
- WLog_Print(log, WLOG_DEBUG, "TsProxyCreateChannelReadResponse");
- if (!pdu)
- return FALSE;
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(pdu);
+ WINPR_ASSERT(channelId);
+
+ WLog_Print(log, WLOG_DEBUG, "TsProxyCreateChannelReadResponse");
if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 28))
goto fail;
@@ -2068,15 +2112,15 @@ fail:
static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context)
{
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(context);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCloseChannelWriteRequest");
- if (!tsg || !tsg->rpc || !context)
- return FALSE;
+ rdpRpc* rpc = tsg->rpc;
+ WINPR_ASSERT(rpc);
- rpc = tsg->rpc;
- s = Stream_New(NULL, 20);
+ wStream* s = Stream_New(NULL, 20);
if (!s)
return FALSE;
@@ -2090,7 +2134,7 @@ fail:
return FALSE;
}
-static BOOL TsProxyCloseChannelReadResponse(wLog* log, RPC_PDU* pdu, CONTEXT_HANDLE* context)
+static BOOL TsProxyCloseChannelReadResponse(wLog* log, const RPC_PDU* pdu, CONTEXT_HANDLE* context)
{
BOOL rc = FALSE;
WLog_Print(log, WLOG_DEBUG, "TsProxyCloseChannelReadResponse");
@@ -2124,15 +2168,15 @@ fail:
static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, const CONTEXT_HANDLE* context)
{
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(context);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCloseTunnelWriteRequest");
- if (!tsg || !tsg->rpc || !context)
- return FALSE;
+ rdpRpc* rpc = tsg->rpc;
+ WINPR_ASSERT(rpc);
- rpc = tsg->rpc;
- s = Stream_New(NULL, 20);
+ wStream* s = Stream_New(NULL, 20);
if (!s)
return FALSE;
@@ -2146,13 +2190,15 @@ fail:
return FALSE;
}
-static BOOL TsProxyCloseTunnelReadResponse(wLog* log, RPC_PDU* pdu, CONTEXT_HANDLE* context)
+static BOOL TsProxyCloseTunnelReadResponse(wLog* log, const RPC_PDU* pdu, CONTEXT_HANDLE* context)
{
BOOL rc = FALSE;
- WLog_Print(log, WLOG_DEBUG, "TsProxyCloseTunnelReadResponse");
- if (!pdu || !context)
- return FALSE;
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(pdu);
+ WINPR_ASSERT(context);
+
+ WLog_Print(log, WLOG_DEBUG, "TsProxyCloseTunnelReadResponse");
if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 24))
goto fail;
@@ -2294,7 +2340,7 @@ static BOOL tsg_proxy_reauth(rdpTsg* tsg)
return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
}
-BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
+BOOL tsg_recv_pdu(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
RpcClientCall* call = NULL;
@@ -2342,10 +2388,10 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
case TSG_STATE_CONNECTED:
{
- CONTEXT_HANDLE* TunnelContext = NULL;
- TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
+ CONTEXT_HANDLE* TunnelContext =
+ (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
- if (!TsProxyAuthorizeTunnelReadResponse(tsg->log, pdu))
+ if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu))
{
WLog_Print(tsg->log, WLOG_ERROR, "TsProxyAuthorizeTunnelReadResponse failure");
return FALSE;
diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h
index 626a7ac..81b50a7 100644
--- a/libfreerdp/core/gateway/tsg.h
+++ b/libfreerdp/core/gateway/tsg.h
@@ -109,7 +109,7 @@ FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg);
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout);
FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg);
-FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
+FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, const RPC_PDU* pdu);
FREERDP_LOCAL BOOL tsg_check_event_handles(rdpTsg* tsg);
FREERDP_LOCAL DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, DWORD count);
diff --git a/libfreerdp/core/gateway/wst.c b/libfreerdp/core/gateway/wst.c
index 00581d3..87194da 100644
--- a/libfreerdp/core/gateway/wst.c
+++ b/libfreerdp/core/gateway/wst.c
@@ -199,6 +199,8 @@ static BOOL wst_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
authToken.cbBuffer = authTokenLength;
credssp_auth_take_input_buffer(auth, &authToken);
}
+ else
+ free(authTokenData);
rc = credssp_auth_authenticate(auth);
if (rc < 0)