From 0dd6d838bb794545353db5c9d88774416f8f1d01 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 12:15:47 +0100 Subject: [PATCH 1/7] [winpr,json] add WINPR_JSON_AddIntegerToObject This function adds a integer value (in contrast to real values with WINPR_JSON_AddNumberToObject) to a JSON object. --- winpr/include/winpr/json.h | 10 ++++++++++ winpr/libwinpr/utils/json/c-json.c | 7 +++++++ winpr/libwinpr/utils/json/jansson.c | 6 ++++++ winpr/libwinpr/utils/json/json-c.c | 11 +++++++++++ 4 files changed, 34 insertions(+) diff --git a/winpr/include/winpr/json.h b/winpr/include/winpr/json.h index c06296ba6..d4b2f0eb6 100644 --- a/winpr/include/winpr/json.h +++ b/winpr/include/winpr/json.h @@ -346,6 +346,16 @@ extern "C" WINPR_API WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number); + /** + * @brief WINPR_JSON_AddIntegerToObject + * @param object The JSON object the new item is added to + * @param name The name of the object + * @return the new JSON item added + * @since version 3.6.0 + */ + WINPR_API WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, + int64_t number); + /** * @brief WINPR_JSON_AddStringToObject * @param object The JSON object the new item is added to diff --git a/winpr/libwinpr/utils/json/c-json.c b/winpr/libwinpr/utils/json/c-json.c index bd95d77e7..7686b51d4 100644 --- a/winpr/libwinpr/utils/json/c-json.c +++ b/winpr/libwinpr/utils/json/c-json.c @@ -259,6 +259,13 @@ WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, d return cJSON_AddNumberToObject((cJSON*)object, name, number); } +WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number) +{ + char str[64] = { 0 }; + (void)_snprintf(str, sizeof(str), "%" PRId64, number); + return cJSON_AddRawToObject((cJSON*)object, name, str); +} + WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) { return cJSON_AddStringToObject((cJSON*)object, name, string); diff --git a/winpr/libwinpr/utils/json/jansson.c b/winpr/libwinpr/utils/json/jansson.c index a1f68cba8..ce3c23ce0 100644 --- a/winpr/libwinpr/utils/json/jansson.c +++ b/winpr/libwinpr/utils/json/jansson.c @@ -298,6 +298,12 @@ WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, d return add_to_object(object, name, obj); } +WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number) +{ + json_t* obj = json_integer(number); + return add_to_object(object, name, obj); +} + WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) { json_t* obj = json_string(string); diff --git a/winpr/libwinpr/utils/json/json-c.c b/winpr/libwinpr/utils/json/json-c.c index 1fde41331..df1d2a590 100644 --- a/winpr/libwinpr/utils/json/json-c.c +++ b/winpr/libwinpr/utils/json/json-c.c @@ -274,6 +274,17 @@ WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, d return obj; } +WINPR_JSON* WINPR_JSON_AddIntegerToObject(WINPR_JSON* object, const char* name, int64_t number) +{ + struct json_object* obj = json_object_new_int64(number); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) { struct json_object* obj = json_object_new_string(string); From c8698a1b9c5b1bc5bf6e5a9b8a35620604017a09 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 12:17:02 +0100 Subject: [PATCH 2/7] [core,settings] add new keys for gateway Add missing settings: * FreeRDP_GatewayHttpReferer * FreeRDP_GatewayHttpUserAgent * FreeRDP_GatewayHttpMsUserAgent --- include/freerdp/settings_types_private.h | 11 ++++- libfreerdp/common/settings_getters.c | 42 ++++++++++++++++++- libfreerdp/common/settings_str.h | 4 ++ libfreerdp/core/settings.c | 13 +++++- .../core/test/settings_property_lists.h | 3 ++ 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/include/freerdp/settings_types_private.h b/include/freerdp/settings_types_private.h index 6acfaa1c2..10f6dcb66 100644 --- a/include/freerdp/settings_types_private.h +++ b/include/freerdp/settings_types_private.h @@ -512,7 +512,16 @@ struct rdp_settings SETTINGS_DEPRECATED(ALIGN64 char* GatewayAvdAccessAadFormat); /** 2023 * @since version 3.16.0 */ - UINT64 padding2112[2112 - 2024]; /* 2024 */ + SETTINGS_DEPRECATED(ALIGN64 char* GatewayHttpReferer); /** 2024 + * @since version 3.18.0 + */ + SETTINGS_DEPRECATED(ALIGN64 char* GatewayHttpUserAgent); /** 2025 + * @since version 3.18.0 + */ + SETTINGS_DEPRECATED(ALIGN64 char* GatewayHttpMsUserAgent); /** 2026 + * @since version 3.18.0 + */ + UINT64 padding2112[2112 - 2027]; /* 2027 */ /** * RemoteApp diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index 6256f259c..5a5ba0969 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -2373,7 +2373,8 @@ BOOL freerdp_settings_set_uint32(WINPR_ATTR_UNUSED rdpSettings* settings, break; case FreeRDP_ReceivedCapabilitiesSize: - return freerdp_capability_buffer_resize(settings, cnv.c, FALSE); + settings->ReceivedCapabilitiesSize = cnv.c; + break; case FreeRDP_RedirectedSessionId: settings->RedirectedSessionId = cnv.c; @@ -2500,7 +2501,8 @@ BOOL freerdp_settings_set_uint32(WINPR_ATTR_UNUSED rdpSettings* settings, break; case FreeRDP_TargetNetAddressCount: - return freerdp_target_net_addresses_resize(settings, cnv.c); + settings->TargetNetAddressCount = cnv.c; + break; case FreeRDP_TcpAckTimeout: settings->TcpAckTimeout = cnv.c; @@ -2863,6 +2865,15 @@ const char* freerdp_settings_get_string(WINPR_ATTR_UNUSED const rdpSettings* set case FreeRDP_GatewayHttpExtAuthBearer: return settings->GatewayHttpExtAuthBearer; + case FreeRDP_GatewayHttpMsUserAgent: + return settings->GatewayHttpMsUserAgent; + + case FreeRDP_GatewayHttpReferer: + return settings->GatewayHttpReferer; + + case FreeRDP_GatewayHttpUserAgent: + return settings->GatewayHttpUserAgent; + case FreeRDP_GatewayPassword: return settings->GatewayPassword; @@ -3187,6 +3198,15 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, FreeRDP_Settin case FreeRDP_GatewayHttpExtAuthBearer: return settings->GatewayHttpExtAuthBearer; + case FreeRDP_GatewayHttpMsUserAgent: + return settings->GatewayHttpMsUserAgent; + + case FreeRDP_GatewayHttpReferer: + return settings->GatewayHttpReferer; + + case FreeRDP_GatewayHttpUserAgent: + return settings->GatewayHttpUserAgent; + case FreeRDP_GatewayPassword: return settings->GatewayPassword; @@ -3522,6 +3542,15 @@ BOOL freerdp_settings_set_string_(WINPR_ATTR_UNUSED rdpSettings* settings, case FreeRDP_GatewayHttpExtAuthBearer: return update_string_(&settings->GatewayHttpExtAuthBearer, cnv.c, len); + case FreeRDP_GatewayHttpMsUserAgent: + return update_string_(&settings->GatewayHttpMsUserAgent, cnv.c, len); + + case FreeRDP_GatewayHttpReferer: + return update_string_(&settings->GatewayHttpReferer, cnv.c, len); + + case FreeRDP_GatewayHttpUserAgent: + return update_string_(&settings->GatewayHttpUserAgent, cnv.c, len); + case FreeRDP_GatewayPassword: return update_string_(&settings->GatewayPassword, cnv.c, len); @@ -3877,6 +3906,15 @@ BOOL freerdp_settings_set_string_copy_(WINPR_ATTR_UNUSED rdpSettings* settings, case FreeRDP_GatewayHttpExtAuthBearer: return update_string_copy_(&settings->GatewayHttpExtAuthBearer, cnv.cc, len, cleanup); + case FreeRDP_GatewayHttpMsUserAgent: + return update_string_copy_(&settings->GatewayHttpMsUserAgent, cnv.cc, len, cleanup); + + case FreeRDP_GatewayHttpReferer: + return update_string_copy_(&settings->GatewayHttpReferer, cnv.cc, len, cleanup); + + case FreeRDP_GatewayHttpUserAgent: + return update_string_copy_(&settings->GatewayHttpUserAgent, cnv.cc, len, cleanup); + case FreeRDP_GatewayPassword: return update_string_copy_(&settings->GatewayPassword, cnv.cc, len, cleanup); diff --git a/libfreerdp/common/settings_str.h b/libfreerdp/common/settings_str.h index 8d6b70a0a..cd6a32516 100644 --- a/libfreerdp/common/settings_str.h +++ b/libfreerdp/common/settings_str.h @@ -513,6 +513,10 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_GatewayHostname, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayHostname" }, { FreeRDP_GatewayHttpExtAuthBearer, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayHttpExtAuthBearer" }, + { FreeRDP_GatewayHttpMsUserAgent, FREERDP_SETTINGS_TYPE_STRING, + "FreeRDP_GatewayHttpMsUserAgent" }, + { FreeRDP_GatewayHttpReferer, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayHttpReferer" }, + { FreeRDP_GatewayHttpUserAgent, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayHttpUserAgent" }, { FreeRDP_GatewayPassword, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayPassword" }, { FreeRDP_GatewayUrl, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayUrl" }, { FreeRDP_GatewayUsername, FREERDP_SETTINGS_TYPE_STRING, "FreeRDP_GatewayUsername" }, diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 3dbcb5e13..3074dc6ac 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -770,6 +771,15 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!server && !remote) { + if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpUserAgent, + FREERDP_USER_AGENT)) + goto out_fail; + if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpMsUserAgent, + FREERDP_USER_AGENT)) + goto out_fail; + + if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpReferer, "")) + goto out_fail; if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAccessTokenFormat, "ms-appx-web%%3a%%2f%%2fMicrosoft.AAD.BrokerPlugin%%2f%s")) goto out_fail; @@ -777,7 +787,8 @@ rdpSettings* freerdp_settings_new(DWORD flags) "https%%3A%%2F%%2F%s%%2F%s%%2Foauth2%%2Fnativeclient")) goto out_fail; if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdScope, - "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default")) + "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default%20openid%" + "20profile%20offline_access")) goto out_fail; if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdClientID, diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index b2a9a2bc0..b47490443 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -405,6 +405,9 @@ static const size_t string_list_indices[] = { FreeRDP_GatewayDomain, FreeRDP_GatewayHostname, FreeRDP_GatewayHttpExtAuthBearer, + FreeRDP_GatewayHttpMsUserAgent, + FreeRDP_GatewayHttpReferer, + FreeRDP_GatewayHttpUserAgent, FreeRDP_GatewayPassword, FreeRDP_GatewayUrl, FreeRDP_GatewayUsername, From e9890c3960d19b0018114b981a320f3df48a43fb Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 12:19:10 +0100 Subject: [PATCH 3/7] [core,gateway] add http_request_append_header --- libfreerdp/core/gateway/http.c | 17 ++++++++++++++++- libfreerdp/core/gateway/http.h | 4 ++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index da89f02e0..be53d8a40 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -1486,7 +1486,7 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength) WINPR_ASSERT(response->BodyLength == 0); bodyLength = response->BodyLength; /* expected body length */ - if (readContentLength) + if (readContentLength && (response->BodyLength > 0)) { const char* cur = response->ContentType; @@ -1737,3 +1737,18 @@ void http_response_log_error_status_(wLog* log, DWORD level, const HttpResponse* freerdp_http_status_string_format(status, buffer, ARRAYSIZE(buffer))); http_response_print(log, level, response, file, line, fkt); } + +WINPR_ATTR_FORMAT_ARG(3, 4) +BOOL http_request_append_header(wStream* stream, const char* param, + WINPR_FORMAT_ARG const char* value, ...) +{ + va_list ap; + va_start(ap, value); + char* str = NULL; + size_t slen = 0; + winpr_vasprintf(&str, &slen, value, ap); + va_end(ap); + const BOOL rc = http_encode_body_line(stream, param, str); + free(str); + return rc; +} diff --git a/libfreerdp/core/gateway/http.h b/libfreerdp/core/gateway/http.h index 835863739..954e669f7 100644 --- a/libfreerdp/core/gateway/http.h +++ b/libfreerdp/core/gateway/http.h @@ -104,6 +104,10 @@ FREERDP_LOCAL BOOL http_request_set_transfer_encoding(HttpRequest* request, FREERDP_LOCAL wStream* http_request_write(HttpContext* context, HttpRequest* request); +WINPR_ATTR_FORMAT_ARG(3, 4) +FREERDP_LOCAL BOOL http_request_append_header(wStream* stream, const char* param, + WINPR_FORMAT_ARG const char* value, ...); + /* HTTP response */ typedef struct s_http_response HttpResponse; From 08b00be4122656b319fe94aa8c9f36fd7d638702 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 12:27:05 +0100 Subject: [PATCH 4/7] [core,gateway] set user agent for websocket --- libfreerdp/core/gateway/wst.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/libfreerdp/core/gateway/wst.c b/libfreerdp/core/gateway/wst.c index bd212c0d8..6019cb7a5 100644 --- a/libfreerdp/core/gateway/wst.c +++ b/libfreerdp/core/gateway/wst.c @@ -68,7 +68,7 @@ struct rdp_wst websocket_context* wscontext; }; -static const char arm_query_param[] = "%s%cClmTk=Bearer%%20%s&X-MS-User-Agent=FreeRDP%%2F3.0"; +static const char arm_query_param[] = "%s%cClmTk=Bearer%%20%s&X-MS-User-Agent=%s"; static BOOL wst_get_gateway_credentials(rdpContext* context, rdp_auth_reason reason) { @@ -356,10 +356,16 @@ 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 */ const char* affinity = http_response_get_setcookie(*ppresponse, "ARRAffinity"); - if (affinity && freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport)) + const char* samesite = http_response_get_setcookie(*ppresponse, "ARRAffinitySameSite"); + if ((affinity || samesite) && + freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport)) { - WLog_DBG(TAG, "Got Affinity cookie %s", affinity); - http_context_set_cookie(wst->http, "ARRAffinity", affinity); + WLog_INFO(TAG, "Got ARRAffinity cookie %s", affinity); + WLog_INFO(TAG, "Got ARRAffinitySameSite cookie %s", samesite); + if (affinity) + http_context_set_cookie(wst->http, "ARRAffinity", affinity); + if (samesite) + http_context_set_cookie(wst->http, "ARRAffinitySameSite", samesite); http_response_free(*ppresponse); *ppresponse = NULL; /* Terminate this connection and make a new one with the Loadbalancing Cookie */ @@ -378,9 +384,12 @@ static BOOL wst_handle_ok_or_forbidden(rdpWst* wst, HttpResponse** ppresponse, D char* urlWithAuth = NULL; size_t urlLen = 0; char firstParam = (strchr(wst->gwpath, '?') != NULL) ? '&' : '?'; - winpr_asprintf(&urlWithAuth, &urlLen, arm_query_param, wst->gwpath, firstParam, - freerdp_settings_get_string(wst->context->settings, - FreeRDP_GatewayHttpExtAuthBearer)); + const char* bearer = freerdp_settings_get_string(wst->context->settings, + FreeRDP_GatewayHttpExtAuthBearer); + const char* ua = + freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpMsUserAgent); + winpr_asprintf(&urlWithAuth, &urlLen, arm_query_param, wst->gwpath, firstParam, bearer, + ua); if (!urlWithAuth) return FALSE; free(wst->gwpath); @@ -838,13 +847,17 @@ rdpWst* wst_new(rdpContext* context) if (!wst->http) goto wst_alloc_error; + const char* useragent = + freerdp_settings_get_string(context->settings, FreeRDP_GatewayHttpUserAgent); + const char* msuseragent = + freerdp_settings_get_string(context->settings, FreeRDP_GatewayHttpMsUserAgent); if (!http_context_set_uri(wst->http, wst->gwpath) || !http_context_set_accept(wst->http, "*/*") || !http_context_set_cache_control(wst->http, "no-cache") || !http_context_set_pragma(wst->http, "no-cache") || !http_context_set_connection(wst->http, "Keep-Alive") || - !http_context_set_user_agent(wst->http, FREERDP_USER_AGENT) || - !http_context_set_x_ms_user_agent(wst->http, FREERDP_USER_AGENT) || + !http_context_set_user_agent(wst->http, useragent) || + !http_context_set_x_ms_user_agent(wst->http, msuseragent) || !http_context_set_host(wst->http, wst->gwhostname) || !http_context_enable_websocket_upgrade(wst->http, TRUE)) { From 3db117283a3e8898e999210ed37808e0abaad5de Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 14:05:24 +0100 Subject: [PATCH 5/7] [winpr,print] mark function WINPR_ATTR_MALLOC --- winpr/include/winpr/print.h | 1 + 1 file changed, 1 insertion(+) diff --git a/winpr/include/winpr/print.h b/winpr/include/winpr/print.h index 7710378b8..ebe70d3cb 100644 --- a/winpr/include/winpr/print.h +++ b/winpr/include/winpr/print.h @@ -40,6 +40,7 @@ extern "C" WINPR_API void winpr_CArrayDump(const char* tag, UINT32 level, const void* data, size_t length, size_t width); + WINPR_ATTR_MALLOC(free, 1) WINPR_API char* winpr_BinToHexString(const BYTE* data, size_t length, BOOL space); WINPR_API size_t winpr_BinToHexStringBuffer(const BYTE* data, size_t length, char* dstStr, size_t dstSize, BOOL space); From 50662536853d9b6b1edd8be1f9ca2b9bf5bfb462 Mon Sep 17 00:00:00 2001 From: Richard Markiewicz Date: Mon, 27 Oct 2025 12:32:40 -0400 Subject: [PATCH 6/7] [crypto,x509] set comparison function for sk_ASN1_OBJECT_find in EKU check --- libfreerdp/crypto/x509_utils.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libfreerdp/crypto/x509_utils.c b/libfreerdp/crypto/x509_utils.c index 0adb828d5..f36d5b02b 100644 --- a/libfreerdp/crypto/x509_utils.c +++ b/libfreerdp/crypto/x509_utils.c @@ -569,6 +569,17 @@ char* x509_utils_get_issuer(const X509* xcert) return issuer; } +static int asn1_object_cmp(const ASN1_OBJECT* const* a, const ASN1_OBJECT* const* b) +{ + if (!a || !b) + return (a == b) ? 0 : (a ? 1 : -1); + + if (!*a || !*b) + return (*a == *b) ? 0 : (*a ? 1 : -1); + + return OBJ_cmp(*a, *b); +} + BOOL x509_utils_check_eku(const X509* xcert, int nid) { BOOL ret = FALSE; @@ -586,6 +597,7 @@ BOOL x509_utils_check_eku(const X509* xcert, int nid) if (!oid_stack) return FALSE; + sk_ASN1_OBJECT_set_cmp_func(oid_stack, asn1_object_cmp); if (sk_ASN1_OBJECT_find(oid_stack, oid) >= 0) ret = TRUE; From 6c0a302083eb9b9caf75d641792538c9f4cff146 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 27 Oct 2025 12:28:27 +0100 Subject: [PATCH 7/7] [core,gateway] improve arm transport --- libfreerdp/core/gateway/arm.c | 113 ++++++++++++++++++++++----------- libfreerdp/crypto/x509_utils.c | 2 +- 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/libfreerdp/core/gateway/arm.c b/libfreerdp/core/gateway/arm.c index d6f607e74..7c4bc5fdf 100644 --- a/libfreerdp/core/gateway/arm.c +++ b/libfreerdp/core/gateway/arm.c @@ -186,8 +186,6 @@ static wStream* arm_build_http_request(rdpArm* arm, const char* method, size_t content_length) { wStream* s = NULL; - HttpRequest* request = NULL; - const char* uri = NULL; WINPR_ASSERT(arm); WINPR_ASSERT(method); @@ -196,16 +194,18 @@ static wStream* arm_build_http_request(rdpArm* arm, const char* method, WINPR_ASSERT(arm->context); WINPR_ASSERT(arm->context->rdp); - uri = http_context_get_uri(arm->http); - request = http_request_new(); + const char* uri = http_context_get_uri(arm->http); + HttpRequest* request = http_request_new(); if (!request) return NULL; + rdpSettings* settings = arm->context->settings; + if (!http_request_set_method(request, method) || !http_request_set_uri(request, uri)) goto out; - if (!freerdp_settings_get_string(arm->context->settings, FreeRDP_GatewayHttpExtAuthBearer)) + if (!freerdp_settings_get_string(settings, FreeRDP_GatewayHttpExtAuthBearer)) { char* token = NULL; @@ -225,8 +225,7 @@ static wStream* arm_build_http_request(rdpArm* arm, const char* method, goto out; } - if (!freerdp_settings_set_string(arm->context->settings, FreeRDP_GatewayHttpExtAuthBearer, - token)) + if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpExtAuthBearer, token)) { free(token); goto out; @@ -236,8 +235,7 @@ static wStream* arm_build_http_request(rdpArm* arm, const char* method, if (!http_request_set_auth_scheme(request, "Bearer") || !http_request_set_auth_param( - request, - freerdp_settings_get_string(arm->context->settings, FreeRDP_GatewayHttpExtAuthBearer))) + request, freerdp_settings_get_string(settings, FreeRDP_GatewayHttpExtAuthBearer))) goto out; if (!http_request_set_transfer_encoding(request, transferEncoding) || @@ -246,6 +244,39 @@ static wStream* arm_build_http_request(rdpArm* arm, const char* method, goto out; s = http_request_write(arm->http, request); + if (!s) + goto out; + + const char* referer = freerdp_settings_get_string(settings, FreeRDP_GatewayHttpReferer); + if (referer && (strlen(referer) > 0)) + { + if (!http_request_append_header(s, "Referer", "%s", referer)) + goto out; + } + + const char* tenantId = freerdp_settings_get_string(settings, FreeRDP_GatewayAvdAadtenantid); + if (!http_request_append_header(s, "x-ms-tenant-id", "%s", tenantId)) + goto out; + + const char* wvd = freerdp_settings_get_string(settings, FreeRDP_GatewayAvdWvdEndpointPool); + if (!wvd) + goto out; + + if (!http_request_append_header(s, "MS-WVD-Activity-Hint", "ms-wvd-hp:%s", wvd)) + goto out; + + const char* armpath = freerdp_settings_get_string(settings, FreeRDP_GatewayAvdArmpath); + if (!armpath) + goto out; + + char* value = crypto_base64url_encode((const BYTE*)armpath, strlen(armpath)); + if (!value) + goto out; + const BOOL rc = http_request_append_header(s, "x-ms-opsarmpath64", "%s", value); + free(value); + + if (!rc) + goto out; out: http_request_free(request); @@ -1046,10 +1077,16 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO BOOL rc = FALSE; + http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response); + const size_t len = http_response_get_body_length(response); const char* msg = (const char*)http_response_get_body(response); - if (strnlen(msg, len + 1) > len) + if (msg && (strnlen(msg, len + 1) > len)) + { + WLog_Print(arm->log, WLOG_ERROR, "Got HTTP Response data, but length is invalid"); + return FALSE; + } WLog_Print(arm->log, WLOG_DEBUG, "Got HTTP Response data: %s", msg); @@ -1062,31 +1099,31 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO return FALSE; } - - WINPR_JSON* gateway_code_obj = WINPR_JSON_GetObjectItemCaseSensitive(json, "Code"); - const char* gw_code_str = WINPR_JSON_GetStringValue(gateway_code_obj); - if (gw_code_str == NULL) - { - WLog_Print(arm->log, WLOG_ERROR, "Response has no \"Code\" property"); - http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response); - goto fail; - } - - if (strcmp(gw_code_str, "E_PROXY_ORCHESTRATION_LB_SESSIONHOST_DEALLOCATED") == 0) - { - *retry = TRUE; - WINPR_JSON* message = WINPR_JSON_GetObjectItemCaseSensitive(json, "Message"); - const char* msgstr = WINPR_JSON_GetStringValue(message); - if (!msgstr) - WLog_WARN(TAG, "Starting your VM. It may take up to 5 minutes"); - else - WLog_WARN(TAG, "%s", msgstr); - freerdp_set_last_error_if_not(arm->context, FREERDP_ERROR_CONNECT_TARGET_BOOTING); - } else { - http_response_log_error_status(WLog_Get(TAG), WLOG_ERROR, response); - goto fail; + WINPR_JSON* gateway_code_obj = WINPR_JSON_GetObjectItemCaseSensitive(json, "Code"); + const char* gw_code_str = WINPR_JSON_GetStringValue(gateway_code_obj); + if (gw_code_str == NULL) + { + WLog_Print(arm->log, WLOG_ERROR, "Response has no \"Code\" property"); + goto fail; + } + + if (strcmp(gw_code_str, "E_PROXY_ORCHESTRATION_LB_SESSIONHOST_DEALLOCATED") == 0) + { + *retry = TRUE; + WINPR_JSON* message = WINPR_JSON_GetObjectItemCaseSensitive(json, "Message"); + const char* msgstr = WINPR_JSON_GetStringValue(message); + if (!msgstr) + WLog_WARN(TAG, "Starting your VM. It may take up to 5 minutes"); + else + WLog_WARN(TAG, "%s", msgstr); + freerdp_set_last_error_if_not(arm->context, FREERDP_ERROR_CONNECT_TARGET_BOOTING); + } + else + { + goto fail; + } } rc = TRUE; @@ -1113,13 +1150,17 @@ static BOOL arm_handle_request(rdpArm* arm, BOOL* retry, DWORD timeout) HttpResponse* response = NULL; long StatusCode = 0; - if (!http_context_set_uri(arm->http, "/api/arm/v2/connections/") || + const char* useragent = + freerdp_settings_get_string(arm->context->settings, FreeRDP_GatewayHttpUserAgent); + const char* msuseragent = + freerdp_settings_get_string(arm->context->settings, FreeRDP_GatewayHttpMsUserAgent); + if (!http_context_set_uri(arm->http, "/api/arm/v2/connections") || !http_context_set_accept(arm->http, "application/json") || !http_context_set_cache_control(arm->http, "no-cache") || !http_context_set_pragma(arm->http, "no-cache") || !http_context_set_connection(arm->http, "Keep-Alive") || - !http_context_set_user_agent(arm->http, FREERDP_USER_AGENT) || - !http_context_set_x_ms_user_agent(arm->http, FREERDP_USER_AGENT) || + !http_context_set_user_agent(arm->http, useragent) || + !http_context_set_x_ms_user_agent(arm->http, msuseragent) || !http_context_set_host(arm->http, freerdp_settings_get_string(arm->context->settings, FreeRDP_GatewayHostname))) goto arm_error; diff --git a/libfreerdp/crypto/x509_utils.c b/libfreerdp/crypto/x509_utils.c index f36d5b02b..a322b67d0 100644 --- a/libfreerdp/crypto/x509_utils.c +++ b/libfreerdp/crypto/x509_utils.c @@ -573,7 +573,7 @@ static int asn1_object_cmp(const ASN1_OBJECT* const* a, const ASN1_OBJECT* const { if (!a || !b) return (a == b) ? 0 : (a ? 1 : -1); - + if (!*a || !*b) return (*a == *b) ? 0 : (*a ? 1 : -1);