diff --git a/CMakeLists.txt b/CMakeLists.txt index a3d02c0bf..e8efbe21e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,13 +633,6 @@ find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DE find_package(cJSON) option(WITH_AAD "Compile with support for Azure AD authentication" ${cJSON_FOUND}) -if (WITH_AAD) - if (NOT cJSON_FOUND) - find_package(PkgConfig REQUIRED) - pkg_check_modules(CJSON REQUIRED libcjson) - endif() - include_directories(${CJSON_INCLUDE_DIRS}) -endif() if (WITH_DSP_FFMPEG OR WITH_VIDEO_FFMPEG OR WITH_FFMPEG) set(FFMPEG_FEATURE_TYPE "REQUIRED" ) diff --git a/client/common/client.c b/client/common/client.c index 67fcceafa..e23c5319a 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -59,20 +59,8 @@ #endif #ifdef WITH_AAD -#include #include - -#if CJSON_VERSION_MAJOR == 1 -#if CJSON_VERSION_MINOR <= 7 -#if CJSON_VERSION_PATCH < 13 -#define USE_CJSON_COMPAT -#endif -#endif -#endif - -#if defined(USE_CJSON_COMPAT) -extern cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length); -#endif +#include #endif #include @@ -1130,9 +1118,8 @@ BOOL client_common_get_access_token(freerdp* instance, const char* request, char long resp_code = 0; BYTE* response = NULL; size_t response_length = 0; - cJSON* json = NULL; - cJSON* access_token_prop = NULL; - const char* access_token_str = NULL; + + wLog* log = WLog_Get(TAG); if (!freerdp_http_request("https://login.microsoftonline.com/common/oauth2/v2.0/token", request, &resp_code, &response, &response_length)) @@ -1144,7 +1131,7 @@ BOOL client_common_get_access_token(freerdp* instance, const char* request, char if (resp_code != HTTP_STATUS_OK) { char buffer[64] = { 0 }; - wLog* log = WLog_Get(TAG); + WLog_Print(log, WLOG_ERROR, "Server unwilling to provide access token; returned status code %s", freerdp_http_status_string_format(resp_code, buffer, sizeof(buffer))); @@ -1153,36 +1140,11 @@ BOOL client_common_get_access_token(freerdp* instance, const char* request, char goto cleanup; } - json = cJSON_ParseWithLength((const char*)response, response_length); - if (!json) - { - char buffer[64] = { 0 }; - WLog_ERR( - TAG, "Failed to parse access token response [got %" PRIuz " bytes, response code %s", - response_length, freerdp_http_status_string_format(resp_code, buffer, sizeof(buffer))); - goto cleanup; - } - - access_token_prop = cJSON_GetObjectItem(json, "access_token"); - if (!access_token_prop) - { - WLog_ERR(TAG, "Response has no \"access_token\" property"); - goto cleanup; - } - - access_token_str = cJSON_GetStringValue(access_token_prop); - if (!access_token_str) - { - WLog_ERR(TAG, "Invalid value for \"access_token\""); - goto cleanup; - } - - *token = _strdup(access_token_str); + *token = freerdp_utils_aad_get_access_token(log, response, response_length); if (*token) ret = TRUE; cleanup: - cJSON_Delete(json); free(response); return ret; #else diff --git a/include/freerdp/utils/aad.h b/include/freerdp/utils/aad.h new file mode 100644 index 000000000..c59e83cb5 --- /dev/null +++ b/include/freerdp/utils/aad.h @@ -0,0 +1,35 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Network Level Authentication (NLA) + * + * Copyright 2023 Armin Novak + * Copyright 2023 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_UTILS_AAD_H +#define FREERDP_UTILS_AAD_H + +#include + +#include +#include + +#ifdef WITH_AAD + +FREERDP_API char* freerdp_utils_aad_get_access_token(wLog* log, const char* data, size_t length); + +#endif + +#endif /* FREERDP_UTILS_AAD_H */ diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index fcadbedf3..74b47ae9c 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -226,8 +226,14 @@ if(FAAC_FOUND) include_directories(${FAAC_INCLUDE_DIRS}) endif() -if(WITH_AAD) - freerdp_library_add_public(${CJSON_LIBRARIES}) +if (WITH_AAD) + if (NOT cJSON_FOUND) + find_package(PkgConfig REQUIRED) + pkg_check_modules(CJSON REQUIRED libcjson) + endif() + include_directories(${CJSON_INCLUDE_DIRS}) + + freerdp_library_add(${CJSON_LIBRARIES}) include_directories(${CJSON_INCLUDE_DIRS}) endif() diff --git a/libfreerdp/core/aad.c b/libfreerdp/core/aad.c index b4d132cb6..e4f4538cd 100644 --- a/libfreerdp/core/aad.c +++ b/libfreerdp/core/aad.c @@ -26,6 +26,7 @@ #include #include "../crypto/privatekey.h" #include +#include #include @@ -830,3 +831,40 @@ BOOL aad_is_supported(void) return FALSE; #endif } + +#ifdef WITH_AAD +char* freerdp_utils_aad_get_access_token(wLog* log, const char* data, size_t length) +{ + char* token = NULL; + cJSON* access_token_prop = NULL; + const char* access_token_str = NULL; + + cJSON* json = cJSON_ParseWithLength(data, length); + if (!json) + { + WLog_Print(log, WLOG_ERROR, "Failed to parse access token response [got %" PRIuz " bytes", + length); + goto cleanup; + } + + access_token_prop = cJSON_GetObjectItem(json, "access_token"); + if (!access_token_prop) + { + WLog_Print(log, WLOG_ERROR, "Response has no \"access_token\" property"); + goto cleanup; + } + + access_token_str = cJSON_GetStringValue(access_token_prop); + if (!access_token_str) + { + WLog_Print(log, WLOG_ERROR, "Invalid value for \"access_token\""); + goto cleanup; + } + + token = _strdup(access_token_str); + +cleanup: + cJSON_Delete(json); + return token; +} +#endif