diff --git a/cmd/agent_local/package/windows/Package.wxs b/cmd/agent_local/package/windows/Package.wxs index 376693e9..6d823bea 100644 --- a/cmd/agent_local/package/windows/Package.wxs +++ b/cmd/agent_local/package/windows/Package.wxs @@ -20,7 +20,7 @@ - + @@ -30,15 +30,17 @@ - + + + + - - - + + @@ -112,8 +114,8 @@ - - + + @@ -125,10 +127,8 @@ - - diff --git a/cmd/agent_system/package/windows/config.json b/cmd/agent_system/package/windows/config.json index 34776859..a2ebdb79 100644 --- a/cmd/agent_system/package/windows/config.json +++ b/cmd/agent_system/package/windows/config.json @@ -1,5 +1,5 @@ { "debug": false, - "domains": "C:\\Program Files\\Authentik Security Inc\\sysd\\domains", - "runtime": "C:\\Program Files\\Authentik Security Inc\\sysd\\runtime" + "domains": "C:\\ProgramData\\Authentik Security Inc\\domains", + "runtime": "C:\\ProgramData\\Authentik Security Inc\\runtime" } diff --git a/ee/wcp/CMakeLists.txt b/ee/wcp/CMakeLists.txt index fb564ee8..232cfb49 100644 --- a/ee/wcp/CMakeLists.txt +++ b/ee/wcp/CMakeLists.txt @@ -228,81 +228,17 @@ if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Release") endif() endif() -# --- jwt-cpp and OpenSSL - Begin -find_package(Perl REQUIRED) # Needed to build OpenSSL -set(PERL "C:\\Strawberry\\perl\\bin\\perl.exe") -set(PERL_EXECUTABLE "C:\\Strawberry\\perl\\bin\\perl.exe") -message(INFO " > Perl Path: ${PERL_EXECUTABLE}") -message(INFO " > Perl Version: ${PERL_VERSION_STRING}") - -include(FetchContent) - -FetchContent_Declare(OpenSSL - URL https://github.com/openssl/openssl/releases/download/openssl-3.5.0/openssl-3.5.0.tar.gz - URL_HASH SHA256=344d0a79f1a9b08029b0744e2cc401a43f9c90acd1044d09a530b4885a8e9fc0 - DOWNLOAD_EXTRACT_TIMESTAMP OFF - # OVERRIDE_FIND_PACKAGE -) -set(FETCHCONTENT_QUIET OFF CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(OpenSSL) - -if (NOT EXISTS "${openssl_SOURCE_DIR}/libssl.lib") - execute_process(COMMAND ${PERL_EXECUTABLE} Configure WORKING_DIRECTORY ${openssl_SOURCE_DIR}) - execute_process(COMMAND nmake WORKING_DIRECTORY ${openssl_SOURCE_DIR}) -endif() -if (NOT EXISTS "${openssl_SOURCE_DIR}/libssl.lib") - message(FATAL_ERROR "OpenSSL library files not found in build. OpenSSL build must succeed first.") -endif() - -set(CMAKE_FIND_DEBUG_MODE OFF) - # Always generate debug symbols add_compile_options("$<$>:/Zi>") add_link_options("$<$>:/DEBUG>") add_link_options("$<$>:/OPT:REF>") add_link_options("$<$>:/OPT:ICF>") -# Set path to OpenSSL library directory for search -set(OPENSSL_ROOT_DIR "${openssl_SOURCE_DIR}") - -# Test if the just built OpenSSL package can be found, so that the `jwt-cpp` would also -# find the same package with find_package() call -find_package(OpenSSL REQUIRED) - -# Display the set and detected paths -message(INFO " > OPENSSL_ROOT_DIR: ${OPENSSL_ROOT_DIR}") -message(INFO "") -message(INFO " > OPENSSL_CRYPTO_LIBRARY: ${OPENSSL_CRYPTO_LIBRARY}") -message(INFO " > OPENSSL_CRYPTO_LIBRARIES: ${OPENSSL_CRYPTO_LIBRARIES}") -message(INFO " > OPENSSL_SSL_LIBRARY: ${OPENSSL_SSL_LIBRARY}") -message(INFO " > OPENSSL_SSL_LIBRARIES: ${OPENSSL_SSL_LIBRARIES}") - -# Test if the detected OpenSSL package is indeed the one just built and not from another installation such as Strawberry Perl -cmake_path(IS_PREFIX OPENSSL_ROOT_DIR ${OPENSSL_CRYPTO_LIBRARIES} isprefix) -if (NOT isprefix) - message(FATAL_ERROR "CMake must reference the OpenSSL Crypto library in the project build directory (${OPENSSL_ROOT_DIR}) but it is instead referencing the path (${OPENSSL_CRYPTO_LIBRARIES}).") -endif() -cmake_path(IS_PREFIX OPENSSL_ROOT_DIR ${OPENSSL_SSL_LIBRARIES} isprefix) -if (NOT isprefix) - message(FATAL_ERROR "CMake must reference the OpenSSL SSL library in the project build directory (${OPENSSL_ROOT_DIR}) but it is instead referencing the path (${OPENSSL_SSL_LIBRARIES}).") -endif() - -# If OpenSSL is sorted, fetch and build jwt-cpp that relies on it -FetchContent_Declare(jwtcpp - GIT_REPOSITORY https://github.com/Thalhammer/jwt-cpp.git - GIT_TAG v0.7.1 - DOWNLOAD_EXTRACT_TIMESTAMP OFF -) -set(FETCHCONTENT_QUIET OFF CACHE BOOL "" FORCE) -set(JWT_BUILD_EXAMPLES OFF CACHE BOOL "disable building examples" FORCE) -FetchContent_MakeAvailable(jwtcpp) - -# --- jwt-cpp and OpenSSL - End +include(FetchContent) -FetchContent_Declare( - Corrosion +FetchContent_Declare(Corrosion GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git - GIT_TAG v0.5 # Optionally specify a commit hash, version tag or branch here + GIT_TAG v0.6 ) # Set any global configuration variables such as `Rust_TOOLCHAIN` before this line! FetchContent_MakeAvailable(Corrosion) @@ -337,15 +273,14 @@ endif() FetchContent_Declare(spdlog GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.16.0 + GIT_TAG v1.17.0 ) FetchContent_MakeAvailable(spdlog) set_property(TARGET spdlog PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) FetchContent_Declare(sentry GIT_REPOSITORY https://github.com/getsentry/sentry-native.git - GIT_TAG 0.12.0 - DOWNLOAD_EXTRACT_TIMESTAMP OFF + GIT_TAG 0.12.3 ) set(FETCHCONTENT_QUIET OFF CACHE BOOL "" FORCE) set(SENTRY_BUILD_SHARED_LIBS OFF) @@ -359,6 +294,9 @@ set_property(TARGET sentry PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) # Define CEF-based targets. # +add_subdirectory(ak_common) +set_property(TARGET ak_common PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) + # Include the ak_cred_provider target. # Comes from the libcef_dll/CMakeLists.txt file in the binary distribution # directory. @@ -376,8 +314,7 @@ endif() # Set the project output directory for subprojects, such as `cefexe`, to copy their binaries to set(PROJECT_INSALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/ak_cred_provider/Release") add_subdirectory(cefexe) -# Copy cefexe executable and OpenSSL library file to the common build directory -file(COPY "${OPENSSL_ROOT_DIR}/libcrypto-3-x64.dll" DESTINATION "${PROJECT_INSALL_DIR}") +set_property(TARGET ak_cef PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) # Display configuration settings. PRINT_CEF_CONFIG() diff --git a/ee/wcp/Makefile b/ee/wcp/Makefile index a7f280ab..ed90fedf 100644 --- a/ee/wcp/Makefile +++ b/ee/wcp/Makefile @@ -2,39 +2,36 @@ include ../../common.mk .ONESHELL: -TARGET := wcp +OUT_TARGET := wcp + +TARGETS := ak_cred_provider ak_common cefexe cefsimple CLANG_FORMAT := "C:\Program Files\LLVM\bin\clang-format.exe" +FORMAT_FIND_ARGS := -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' .PHONY: bump bump: - sed -i 's/#define AK_WCP_VERSION ".*"/#define AK_WCP_VERSION ${VERSION}/g' ${PWD}/ak_cred_provider/include/ak_version.h + sed -i 's/#define AK_VERSION ".*"/#define AK_VERSION ${VERSION}/g' ${PWD}/ak_common/include/ak_version.h .PHONY: clean clean: - cd "${TOP}" && rm -rf "bin/${TARGET}" + cd "${TOP}" && rm -rf "bin/${OUT_TARGET}" .PHONY: lint lint: - find "${PWD}/ak_cred_provider" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --dry-run --Werror --verbose -i - find "${PWD}/cefexe" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --dry-run --Werror --verbose -i - find "${PWD}/cefsimple" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --dry-run --Werror --verbose -i + $(foreach target,$(TARGETS),$(shell find "${PWD}/${target}" ${FORMAT_FIND_ARGS} | xargs ${CLANG_FORMAT} --dry-run --Werror --verbose -i)) .PHONY: lint-fix lint-fix: - find "${PWD}/ak_cred_provider" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --verbose -i - find "${PWD}/cefexe" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --verbose -i - find "${PWD}/cefsimple" -iname '*.h' -o -iname '*.cpp' | xargs ${CLANG_FORMAT} --verbose -i + $(foreach target,$(TARGETS),$(shell find "${PWD}/${target}" ${FORMAT_FIND_ARGS} | xargs ${CLANG_FORMAT} --verbose -i)) .PHONY: build build: ${TOP}/hack/windows/setup.sh - mkdir -p ${TOP}/bin/${TARGET} - mkdir -p ${TOP}/cache/${TARGET} - # To avoid the OpenSSL build using linux `link.exe` - mv /usr/bin/link.exe /usr/bin/link_bak || true - powershell.exe -noprofile -executionpolicy bypass -file ./build.ps1 ${PWD} ${TOP} ${TARGET} - cp -r ${TOP}/cache/${TARGET}/ak_cred_provider/Release/* ${TOP}/bin/${TARGET}/ + mkdir -p ${TOP}/bin/${OUT_TARGET} + mkdir -p ${TOP}/cache/${OUT_TARGET} + powershell.exe -noprofile -executionpolicy bypass -file ./build.ps1 ${PWD} ${TOP} ${OUT_TARGET} + cp -r ${TOP}/cache/${OUT_TARGET}/ak_cred_provider/Release/* ${TOP}/bin/${OUT_TARGET}/ ifdef SENTRY_AUTH_TOKEN - @$(call sentry_upload_symbols,"${TOP}/bin/${TARGET}/") + @$(call sentry_upload_symbols,"${TOP}/bin/${OUT_TARGET}/") endif diff --git a/ee/wcp/README.md b/ee/wcp/README.md index 1ac71980..52edcec9 100644 --- a/ee/wcp/README.md +++ b/ee/wcp/README.md @@ -2,52 +2,24 @@ ## Build tools and test environment -Visual Studio 17 2022 - -Strawberry Perl (to build OpenSSL for jwt-cpp) - (`winget install StrawberryPerl.StrawberryPerl`) - -Windows 10 x64 - -Rust - `winget install -e --id Rustlang.Rustup` +- Visual Studio 17 2022 +- Windows 10/11 x64 +- Rust (`winget install -e --id Rustlang.Rustup`) +- Make ### Build steps #### Development ``` -mkdir build -cd build -cmake -G "Visual Studio 17" .. -cmake --build . --config Release +make ee/wcp/build ``` -Alternatively, instead of the last step, open the Visual Studio solution file `cef.sln` inside the *build* directory and build the solution (F7) inside the Visual Studio. - -The credential provider files are generated inside the `build/ak_cred_provider/Release` subdirectory. - -#### Installer package - -**Update:** With the python patch script `addsetup.py` in the `.utils` directory, manually performing this step can be avoided. The following information is provided as an alternate method but should not be necessary anymore. - -Inside the *build* directory, open the Visual Studio solution file `cef.sln`. - -Right click the `cef` solution in the *Solution Explorer* sub-window and click `Add->Existing Project...`. - -Select the Setup project file inside the **build** directory in path `build/Setup/Setup.vdproj`. - -`Do not` select the Setup file inside the project source under the *Setup* subdirectory. - -Build solution (F7) (again), or right-click the `Setup` project in the *Solution Explorer* sub-window and click `Build`. - -The setup package files are available in `build/Release` subdirectory. +The credential provider files are generated inside the `cache/wcp/ak_cred_provider/Release` subdirectory. #### Testing -During development, the registry setup files inside the `ak_cred_provider/Setup` path could be used to register the credential provide inside the `build` directory for testing. - -The setup file/ installer registers the credential provider similarly, so **take note** that either the credential provider inside the build directory or the credential provider installed via the Setup file could be displayed at the logon prompt UI at a time and not both simultaneously. +Use the authentk Agent from https://pkg.goauthentik.io to install the current stable build of the Agent, and enable the credential provider in the setup wizard. Afterwards, copy the files from `cache/wcp/ak_cred_provider/Release` into the `C:\Program Files\Authentik Security Inc.\wcp\` folder on the target machine, overwriting all files. ## Important points diff --git a/ee/wcp/ak_common/CMakeLists.txt b/ee/wcp/ak_common/CMakeLists.txt new file mode 100644 index 00000000..ebf008bc --- /dev/null +++ b/ee/wcp/ak_common/CMakeLists.txt @@ -0,0 +1,27 @@ +project(ak_common) + +set(CMAKE_BUILD_TYPE Release) +set(CMAKE_CXX_STANDARD 20) + +set(SRCS + ak_log.cpp + ak_sentry.cpp + crypt.cc +) + +add_library(${PROJECT_NAME} STATIC + ${SRCS} +) + +# include_directories(${PROJECT_NAME} PUBLIC ..) +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_link_libraries(${PROJECT_NAME} + authentik_sys_bridge + spdlog + sentry +) +set_property(TARGET authentik_sys PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) +set_property(TARGET authentik_sys_bridge PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) diff --git a/ee/wcp/ak_cred_provider/ak_log.cpp b/ee/wcp/ak_common/ak_log.cpp similarity index 70% rename from ee/wcp/ak_cred_provider/ak_log.cpp rename to ee/wcp/ak_common/ak_log.cpp index ad67ed8d..4a23db6f 100644 --- a/ee/wcp/ak_cred_provider/ak_log.cpp +++ b/ee/wcp/ak_common/ak_log.cpp @@ -1,7 +1,5 @@ -#include "pch.h" - -#include "ak_log.h" -#include "ak_version.h" +#include "include/ak_log.h" +#include "include/ak_version.h" #include "spdlog/async.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/win_eventlog_sink.h" @@ -13,7 +11,7 @@ bool g_logSetup; const auto _ak_log_max_size = 1024 * 1024 * 50; const auto _ak_log_max_files = 3; -void SetupLogs(const char* logger_name) { +void ak_setup_logs(const char* logger_name) { const auto logger = spdlog::rotating_logger_mt( logger_name, std::string(AK_PROGRAM_DATA).append("\\logs\\").append(logger_name).append(".log").c_str(), @@ -21,6 +19,11 @@ void SetupLogs(const char* logger_name) { spdlog::set_level(spdlog::level::debug); spdlog::flush_every(std::chrono::seconds(5)); spdlog::set_default_logger(logger); - SPDLOG_INFO("authentik Platform Credential Provider Version {}", AK_WCP_VERSION); + SPDLOG_INFO("authentik Platform {} Version {}", logger_name, AK_VERSION); g_logSetup = true; } + +void ak_teardown_logs() { + if (!g_logSetup) return; + spdlog::shutdown(); +} diff --git a/ee/wcp/ak_cred_provider/ak_sentry.cpp b/ee/wcp/ak_common/ak_sentry.cpp similarity index 89% rename from ee/wcp/ak_cred_provider/ak_sentry.cpp rename to ee/wcp/ak_common/ak_sentry.cpp index b38b154d..7b795173 100644 --- a/ee/wcp/ak_cred_provider/ak_sentry.cpp +++ b/ee/wcp/ak_common/ak_sentry.cpp @@ -1,4 +1,4 @@ -#include "ak_version.h" +#include "include/ak_version.h" #include #define SENTRY_BUILD_STATIC 1 @@ -17,12 +17,12 @@ static void ak_sentry_log_callback(sentry_level_t level, const char* message, va spdlog::get("sentry")->debug(formatted_message); } -void SentrySetup(const char* component) { +void ak_setup_sentry(const char* component) { if (g_sentrySetup) return; spdlog::register_logger(spdlog::default_logger()->clone("sentry")); std::string release = - std::string("ak-platform-wcp-").append(component).append("@").append(AK_WCP_VERSION); + std::string("ak-platform-wcp-").append(component).append("@").append(AK_VERSION); sentry_options_t* options = sentry_options_new(); sentry_options_set_database_path(options, std::string(AK_PROGRAM_DATA).append("\\wcp-sentry\\").c_str()); @@ -38,4 +38,4 @@ void SentrySetup(const char* component) { g_sentrySetup = true; } -void SentryShutdown() { sentry_shutdown(); } +void ak_teardown_sentry() { sentry_shutdown(); } diff --git a/ee/wcp/ak_common/crypt.cc b/ee/wcp/ak_common/crypt.cc new file mode 100644 index 00000000..5b06992c --- /dev/null +++ b/ee/wcp/ak_common/crypt.cc @@ -0,0 +1,105 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (C) Microsoft. All rights reserved. +/* +Abstract: + Sample program for SHA 256 hashing using CNG +*/ + +#include "crypt.h" + +#define WIN32_NO_STATUS +#include +#undef WIN32_NO_STATUS +#include +#include + +#include +#include + +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) + +const std::string strChars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +const size_t nCharsLen = strChars.length(); + +bool GenerateRandomInt(size_t& nRandom, const size_t nBytesCount) +{ + if (!((nBytesCount >= 1) && (nBytesCount <= sizeof(nRandom)))) + { + return false; + } + NTSTATUS status = STATUS_UNSUCCESSFUL; + + // The output seems to write to atleast 4 bytes, so assigning 8 just in case (64-bit machines). + UCHAR bBuffer[sizeof(nRandom)]; + ULONG cbBuffer = sizeof(bBuffer); + + memset(bBuffer, 0, cbBuffer); + + if(!NT_SUCCESS(status = BCryptGenRandom( + /*[in, out] BCRYPT_ALG_HANDLE*/ NULL, + /*[in, out] PUCHAR*/ bBuffer, + /*[in] ULONG*/ (ULONG)nBytesCount, + /*[in] ULONG*/ BCRYPT_USE_SYSTEM_PREFERRED_RNG + )) + ) + { + wprintf(L"**** Error 0x%x returned by BCryptGenRandom\n", status); + nRandom = 0; + return false; + } + nRandom = 0; + size_t nTmp = 0; + for (SIZE_T i = 0; i < cbBuffer; ++i) + { + nTmp = bBuffer[i]; + nRandom += nTmp << (8*i); + } + + return true; +} + +size_t GetRandomInt(const size_t nExclusiveUpperBound) +{ + size_t nBytesCount = 0; + size_t nMaxValue = 255; + for (nBytesCount = 1; nBytesCount < 8; ++nBytesCount) + { + size_t nDiv = (nExclusiveUpperBound / nMaxValue); + if ((nDiv == 0) || ((nDiv == 1) && ((nExclusiveUpperBound % nMaxValue) == 0))) + { + break; + } + nMaxValue = nMaxValue << 8; + nMaxValue = nMaxValue + 255; + } + size_t nRandom = 0; + if (! GenerateRandomInt(nRandom, nBytesCount)) + { + // fallback + srand((unsigned int)time(NULL)); + nRandom = rand(); + } + nRandom = nRandom % nExclusiveUpperBound; + return nRandom; +} + +std::string GetRandomStr(const size_t nLength) +{ + std::string strRet = ""; + for (size_t i = 0; i < nLength; ++i) + { + strRet.append(1, strChars.at(GetRandomInt(nCharsLen))); + } + return strRet; +} + +std::wstring GetRandomWStr(const size_t nLength) +{ + std::string str = GetRandomStr(nLength); + return std::wstring(str.begin(), str.end()); +} diff --git a/ee/wcp/ak_cred_provider/include/ak_log.h b/ee/wcp/ak_common/include/ak_log.h similarity index 53% rename from ee/wcp/ak_cred_provider/include/ak_log.h rename to ee/wcp/ak_common/include/ak_log.h index eceb5ac9..45e08924 100644 --- a/ee/wcp/ak_cred_provider/include/ak_log.h +++ b/ee/wcp/ak_common/include/ak_log.h @@ -4,4 +4,5 @@ #include #include -void SetupLogs(const char* logger_name); +void ak_setup_logs(const char* logger_name); +void ak_teardown_logs(); diff --git a/ee/wcp/ak_cred_provider/include/ak_sentry.h b/ee/wcp/ak_common/include/ak_sentry.h similarity index 71% rename from ee/wcp/ak_cred_provider/include/ak_sentry.h rename to ee/wcp/ak_common/include/ak_sentry.h index 4a68829c..8c5a5942 100644 --- a/ee/wcp/ak_cred_provider/include/ak_sentry.h +++ b/ee/wcp/ak_common/include/ak_sentry.h @@ -2,8 +2,8 @@ #include -void SentrySetup(const char* component); -void SentryShutdown(); +void ak_setup_sentry(const char* component); +void ak_teardown_sentry(); static void ak_sentry_log_callback(sentry_level_t level, const char* message, va_list args, void* userdata); diff --git a/ee/wcp/ak_cred_provider/include/ak_version.h b/ee/wcp/ak_common/include/ak_version.h similarity index 71% rename from ee/wcp/ak_cred_provider/include/ak_version.h rename to ee/wcp/ak_common/include/ak_version.h index 735fd51b..7045367d 100644 --- a/ee/wcp/ak_cred_provider/include/ak_version.h +++ b/ee/wcp/ak_common/include/ak_version.h @@ -1,5 +1,5 @@ #pragma once -#define AK_WCP_VERSION "0.35.6" +#define AK_VERSION "0.35.6" #define AK_PROGRAM_DATA "C:\\ProgramData\\Authentik Security Inc" diff --git a/ee/wcp/cefsimple/crypt.h b/ee/wcp/ak_common/include/crypt.h similarity index 76% rename from ee/wcp/cefsimple/crypt.h rename to ee/wcp/ak_common/include/crypt.h index cfe684cf..cea7e455 100644 --- a/ee/wcp/cefsimple/crypt.h +++ b/ee/wcp/ak_common/include/crypt.h @@ -2,7 +2,6 @@ #include -bool Hash_SHA256(const std::string& strData, std::string& strHash); size_t GetRandomInt(const size_t nExclusiveUpperBound); std::string GetRandomStr(const size_t nLength); std::wstring GetRandomWStr(const size_t nLength); diff --git a/ee/wcp/ak_cred_provider/CMakeLists.txt b/ee/wcp/ak_cred_provider/CMakeLists.txt index 7c010e5c..b2738b39 100644 --- a/ee/wcp/ak_cred_provider/CMakeLists.txt +++ b/ee/wcp/ak_cred_provider/CMakeLists.txt @@ -12,14 +12,12 @@ project( # TODO: Add tests and install targets if needed. -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 20) # Add source to this project's executable. set(SRCS - "ak_sentry.cpp" "ClassFactory.cpp" "Credential.cpp" - "ak_log.cpp" "Dll.cpp" "GUIDs.cpp" "Helpers.cpp" @@ -32,7 +30,7 @@ find_library(CREDUI_LIB_PATH Credui.lib) find_library(SECUR32_LIB_PATH Secur32.lib) find_library(SHLWAPI_LIB_PATH Shlwapi.lib) -add_library (${PROJECT_NAME} SHARED +add_library(${PROJECT_NAME} SHARED ${SRCS} ) @@ -42,24 +40,20 @@ include_directories( ../ ) -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() if (MSVC) - target_compile_definitions(${PROJECT_NAME} PUBLIC UNICODE _UNICODE) - target_sources(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.def + target_compile_definitions(${PROJECT_NAME} PUBLIC UNICODE _UNICODE) + target_sources(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.def ) endif() -target_link_libraries(${PROJECT_NAME} PUBLIC - ${CREDUI_LIB_PATH} - ${SECUR32_LIB_PATH} - ${SHLWAPI_LIB_PATH} +target_link_libraries(${PROJECT_NAME} + ${CREDUI_LIB_PATH} + ${SECUR32_LIB_PATH} + ${SHLWAPI_LIB_PATH} + ak_common cefsimple authentik_sys_bridge - spdlog - sentry ) # TODO: Add tests and install targets if needed. diff --git a/ee/wcp/ak_cred_provider/Credential.cpp b/ee/wcp/ak_cred_provider/Credential.cpp index 57ca63aa..b64ea227 100644 --- a/ee/wcp/ak_cred_provider/Credential.cpp +++ b/ee/wcp/ak_cred_provider/Credential.cpp @@ -12,7 +12,7 @@ #include #define WIN_PASS_LEN 50 -#include "cefsimple/crypt.h" +#include "ak_common/include/crypt.h" extern HINSTANCE g_hinst; #define HINST_THISDLL g_hinst @@ -38,7 +38,7 @@ Credential::Credential() : m_cRef(1) { } Credential::~Credential() { - SPDLOG_DEBUG("~Credential"); + spdlog::debug("~Credential"); if (m_oCefAppData.pCefApp) { SendMessage(m_hWndOwner, WM_NULL, 200, (LPARAM)(NULL)); for (size_t i = 0; i < 100; ++i) { @@ -47,7 +47,7 @@ Credential::~Credential() { } Sleep(100); } - SPDLOG_DEBUG("Shutdown exit"); + spdlog::debug("Shutdown exit"); } m_hWndOwner = NULL; @@ -210,7 +210,7 @@ Credential::Advise(_In_ ICredentialProviderCredentialEvents* pcpce) { std::string str = "Advise:: m_hWndOwner: " + std::to_string((uint64_t)m_hWndOwner) + " "; str = str + "Advise:: ProcessID: " + std::to_string(GetCurrentProcessId()) + ", ThreadID: " + std::to_string(GetCurrentThreadId()); - SPDLOG_DEBUG(str.c_str()); + spdlog::debug(str.c_str()); // Two approaches are tested to subclass the window procedure of the window // returned by OnCreatingWindow() in order to launch the CEF UI in the same // UI thread as that window: @@ -220,7 +220,7 @@ Credential::Advise(_In_ ICredentialProviderCredentialEvents* pcpce) { // thread as the target UI thread. if (m_hWndOwner) { if (hWndProcOrig == NULL) { - SPDLOG_DEBUG("Hook:: SetWindowLongPtr"); + spdlog::debug("Hook:: SetWindowLongPtr"); // Both the following work hWndProcOrig = SetWindowLongPtr(m_hWndOwner, GWLP_WNDPROC, (LONG_PTR)Credential::WndProc); // hWndProcOrig = SetWindowLongPtr(m_hWndOwner, GWLP_WNDPROC, @@ -241,7 +241,7 @@ Credential::Advise(_In_ ICredentialProviderCredentialEvents* pcpce) { DWORD dwThreadID = GetWindowThreadProcessId(m_hWndOwner, &dwProcessID); std::string strHookInfo = "Hook:: Process ID: " + std::to_string(dwProcessID) + ", Thread ID: " + std::to_string(dwThreadID); - SPDLOG_DEBUG(strHookInfo.c_str()); + spdlog::debug(strHookInfo.c_str()); if (dwThreadID != 0) { // hHook = SetWindowsHookEx(WH_CALLWNDPROC, Credential::CallWndProc, // NULL, dwThreadID); @@ -250,14 +250,14 @@ Credential::Advise(_In_ ICredentialProviderCredentialEvents* pcpce) { // dwThreadID); if (! hHook) // { // std::string strHook = "Hook:: Hook failed. Code: " + - // std::to_string(GetLastError()); SPDLOG_DEBUG(strHook.c_str()); + // std::to_string(GetLastError()); spdlog::debug(strHook.c_str()); // } // else // { - // SPDLOG_DEBUG("Hook:: hooked.."); + // spdlog::debug("Hook:: hooked.."); // } } else { - SPDLOG_DEBUG("Hook:: Invalid thread ID"); + spdlog::debug("Hook:: Invalid thread ID"); } } } @@ -276,19 +276,19 @@ LRESULT APIENTRY Credential::WndProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM ", ThreadID: " + std::to_string(GetCurrentThreadId()) + "\n"; strLog += "Code: " + std::to_string(uMsg) + ", wParam: " + std::to_string(wParam) + ", lParam: " + std::to_string(lParam); - SPDLOG_DEBUG(strLog.c_str()); + spdlog::debug(strLog.c_str()); sHookData* pData = (sHookData*)lParam; // if (m_mapThreads.find(pData->UserSid) != m_mapThreads.end()) // { // m_mapThreads[pData->UserSid].join(); //- todo: force quit // } - SPDLOG_DEBUG("UI..."); + spdlog::debug("UI..."); // m_mapThreads[pData->UserSid] = std::thread([&] // {CEFLaunch(pData->hInstance, 0);}); - SPDLOG_DEBUG(std::string("(m_oCefAppData.pCefApp) before: " + - std::to_string((size_t)((m_oCefAppData.pCefApp).get()))) - .c_str()); + spdlog::debug(std::string("(m_oCefAppData.pCefApp) before: " + + std::to_string((size_t)((m_oCefAppData.pCefApp).get()))) + .c_str()); if (!(m_oCefAppData.pCefApp)) { if (m_pProvCallSet) { m_oCefAppData.SetInit(false); @@ -302,19 +302,19 @@ LRESULT APIENTRY Credential::WndProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM L"Error", 0); } } - SPDLOG_DEBUG(std::string("(m_oCefAppData.pCefApp) after: " + - std::to_string((size_t)((m_oCefAppData.pCefApp).get()))) - .c_str()); + spdlog::debug(std::string("(m_oCefAppData.pCefApp) after: " + + std::to_string((size_t)((m_oCefAppData.pCefApp).get()))) + .c_str()); if ((m_oCefAppData.pCefApp)) { - SPDLOG_DEBUG("WndProc:: CEFLaunch"); + spdlog::debug("WndProc:: CEFLaunch"); pData->strUsername = ""; try { CEFLaunch(pData, m_oCefAppData.pCefApp); } catch (const std::exception& e) { SPDLOG_WARN("Failed to CEFLaunch", e.what()); } - SPDLOG_DEBUG(std::string("User logged in: " + pData->strUsername).c_str()); - SPDLOG_DEBUG("WndProc:: CEFLaunched"); + spdlog::debug(std::string("User logged in: " + pData->strUsername).c_str()); + spdlog::debug("WndProc:: CEFLaunched"); } else { ::MessageBox(hWnd, L"Failure: CEF app is not set up. The authentik UI cannot " @@ -322,9 +322,9 @@ LRESULT APIENTRY Credential::WndProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM L"Error", 0); } pData->SetComplete(true); - SPDLOG_DEBUG("UI... end"); + spdlog::debug("UI... end"); } else if (wParam == 200) { - SPDLOG_DEBUG("WndProc:: Shut"); + spdlog::debug("WndProc:: Shut"); if (m_oCefAppData.pCefApp) { if (m_pProvCallShut) { m_pProvCallShut(); @@ -335,7 +335,7 @@ LRESULT APIENTRY Credential::WndProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM L"Error", 0); } } - SPDLOG_DEBUG("WndProc:: Shut exit"); + spdlog::debug("WndProc:: Shut exit"); } } break; } @@ -349,18 +349,18 @@ LRESULT CALLBACK Credential::CallWndProc( // std::to_string(GetCurrentProcessId()) + ", ThreadID: " + // std::to_string(GetCurrentThreadId()) + "\t"; strLog1 += "Code: " + // std::to_string(nCode) + ", wParam: " + std::to_string(wParam) + ", lParam: - // " + std::to_string(lParam); SPDLOG_DEBUG(strLog1.c_str()); + // " + std::to_string(lParam); spdlog::debug(strLog1.c_str()); if (nCode < 0) return CallNextHookEx(Credential::hHook, nCode, wParam, lParam); switch (nCode) { case WM_NULL: { - SPDLOG_DEBUG("WM_NULL"); + spdlog::debug("WM_NULL"); if (InSendMessage()) { std::string strLog = "___ ProcessID: " + std::to_string(GetCurrentProcessId()) + ", ThreadID: " + std::to_string(GetCurrentThreadId()) + "\n"; strLog += "Code: " + std::to_string(nCode) + ", wParam: " + std::to_string(wParam) + ", lParam: " + std::to_string(lParam); - SPDLOG_DEBUG(strLog.c_str()); + spdlog::debug(strLog.c_str()); ReplyMessage(TRUE); } // sHookData* pData = (sHookData*)lParam; @@ -369,15 +369,15 @@ LRESULT CALLBACK Credential::CallWndProc( ", ThreadID: " + std::to_string(GetCurrentThreadId()) + "\n"; strLog += "Code: " + std::to_string(nCode) + ", wParam: " + std::to_string(wParam) + ", lParam: " + std::to_string(lParam); - SPDLOG_DEBUG(strLog.c_str()); + spdlog::debug(strLog.c_str()); // if (m_mapThreads.find(pData->UserSid) != m_mapThreads.end()) // { // m_mapThreads[pData->UserSid].join(); //- todo: force quit // } - // SPDLOG_DEBUG("UI..."); + // spdlog::debug("UI..."); // m_mapThreads[pData->UserSid] = std::thread([&] // {CEFLaunch(pData->hInstance, 0);}); - SPDLOG_DEBUG("UI... end"); + spdlog::debug("UI... end"); } } break; } @@ -388,10 +388,10 @@ LRESULT CALLBACK Credential::CallWndProc( // LogonUI calls this to tell us to release the callback. IFACEMETHODIMP Credential::UnAdvise() { - SPDLOG_DEBUG("UnAdvise"); + spdlog::debug("UnAdvise"); if (hHook) { if (UnhookWindowsHookEx(hHook)) { - SPDLOG_DEBUG("Unhook successful"); + spdlog::debug("Unhook successful"); } } if (m_pCredProvCredentialEvents) { @@ -663,7 +663,7 @@ int FindTarget(const char* procname) { IFACEMETHODIMP Credential::Disconnect() { return S_OK; } IFACEMETHODIMP Credential::Connect(IQueryContinueWithStatus* pqcws) { - SPDLOG_DEBUG("::Connect"); + spdlog::debug("::Connect"); HRESULT hr = S_OK; if (m_pCredProvCredentialEvents) { HWND hwndOwner = nullptr; @@ -676,34 +676,34 @@ IFACEMETHODIMP Credential::Connect(IQueryContinueWithStatus* pqcws) { DWORD dwThreadID = GetWindowThreadProcessId(hwndOwner, &dwProcessID); str += "Submit:: HWND:: Process ID: " + std::to_string(dwProcessID) + ", Thread ID: " + std::to_string(dwThreadID); - SPDLOG_DEBUG(str.c_str()); + spdlog::debug(str.c_str()); // Pop a messagebox indicating the click. // ::MessageBox(hwndOwner, L"Command link clicked", L"Click!", 0); HINSTANCE hInstance = (HINSTANCE)(LONG_PTR)GetWindowLong(hwndOwner, GWLP_HINSTANCE); { std::string strInst = "GetWindowLong:: hInstance: " + std::to_string((uint64_t)hInstance); - SPDLOG_DEBUG(strInst.c_str()); + spdlog::debug(strInst.c_str()); } // HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); { std::string strInst = "GetModuleHandle:: hInstance: " + std::to_string((uint64_t)hInstance); - SPDLOG_DEBUG(strInst.c_str()); + spdlog::debug(strInst.c_str()); } - // SPDLOG_DEBUG(std::hash{}(std::thread::get_id)); + // spdlog::debug(std::hash{}(std::thread::get_id)); std::string strID = "Submit:: ProcessID: " + std::to_string(GetCurrentProcessId()) + ", ThreadID: " + std::to_string(GetCurrentThreadId()); - SPDLOG_DEBUG(strID.c_str()); + spdlog::debug(strID.c_str()); m_oHookData.Update(m_pszUserSid, hInstance); //- todo: Move it to Initialize(...) or // Advise(...)(?) may be std::string strLog = "Sending message... " + std::to_string((uint64_t)(&m_oHookData)); - SPDLOG_DEBUG(strLog.c_str()); + spdlog::debug(strLog.c_str()); { std::string strErr = " LastError: " + std::to_string((uint64_t)(GetLastError())); - SPDLOG_DEBUG(strErr.c_str()); + spdlog::debug(strErr.c_str()); } SetLastError(0); pqcws->SetStatusMessage(L"Please sign in to your authentik account..."); @@ -728,13 +728,13 @@ IFACEMETHODIMP Credential::Connect(IQueryContinueWithStatus* pqcws) { } { std::string strErr = "_LastError: " + std::to_string((uint64_t)(GetLastError())); - SPDLOG_DEBUG(strErr.c_str()); + spdlog::debug(strErr.c_str()); } // SendMessage(hwndOwner, WM_NULL, 100, (LPARAM)(&oData)); // SendNotifyMessage(hwndOwner, WM_NULL, 100, (LPARAM)(&oData)); // PostMessage(hwndOwner, WM_NULL, 100, (LPARAM)(&oData)); std::string strRet = "Message sent. LResult: " + std::to_string((uint64_t)hRet); - SPDLOG_DEBUG(strRet.c_str()); + spdlog::debug(strRet.c_str()); std::wstring strCredUser = L""; if (m_fIsLocalUser) { @@ -773,7 +773,7 @@ IFACEMETHODIMP Credential::Connect(IQueryContinueWithStatus* pqcws) { } else { hr = E_POINTER; } - SPDLOG_DEBUG("Connect end"); + spdlog::debug("Connect end"); // do not return S_OK to avoid displaying the Disconnect button in the // credential provider UI @@ -782,7 +782,7 @@ IFACEMETHODIMP Credential::Connect(IQueryContinueWithStatus* pqcws) { // Called when the user clicks a command link. IFACEMETHODIMP Credential::CommandLinkClicked(DWORD dwFieldID) { - SPDLOG_DEBUG("CommandLinkClicked"); + spdlog::debug("CommandLinkClicked"); HRESULT hr = S_OK; CREDENTIAL_PROVIDER_FIELD_STATE cpfsShow = CPFS_HIDDEN; @@ -798,7 +798,7 @@ IFACEMETHODIMP Credential::CommandLinkClicked(DWORD dwFieldID) { if (m_pCredProvCredentialEvents) { m_pCredProvCredentialEvents->OnCreatingWindow(&hwndOwner); } - SPDLOG_DEBUG("CommandLinkClicked: FI_LAUNCHWINDOW_LINK"); + spdlog::debug("CommandLinkClicked: FI_LAUNCHWINDOW_LINK"); // Pop a messagebox indicating the click. ::MessageBox(hwndOwner, L"Command link clicked", L"Click!", 0); } break; @@ -860,14 +860,17 @@ IFACEMETHODIMP Credential::GetSerialization( PWSTR pwzProtectedPassword; // hr = ProtectIfNecessaryAndCopyPassword(m_rgFieldStrings[FI_PASSWORD], // m_cpus, &pwzProtectedPassword); + spdlog::debug("GetSerialization->Protect"); hr = ProtectIfNecessaryAndCopyPassword(m_strPass.c_str(), m_cpus, &pwzProtectedPassword); m_strPass = GetRandomWStr(WIN_PASS_LEN); // overwrite for safety if (SUCCEEDED(hr)) { PWSTR pszDomain; PWSTR pszUsername; hr = SplitDomainAndUsername(m_pszQualifiedUserName, &pszDomain, &pszUsername); + spdlog::debug("GetSerialization->SplitDomainAndUsername"); if (SUCCEEDED(hr)) { KERB_INTERACTIVE_UNLOCK_LOGON kiul; + spdlog::debug("GetSerialization->KerbInteractiveUnlockLogonInit"); hr = KerbInteractiveUnlockLogonInit(pszDomain, pszUsername, pwzProtectedPassword, m_cpus, &kiul); if (SUCCEEDED(hr)) { @@ -875,10 +878,12 @@ IFACEMETHODIMP Credential::GetSerialization( // scenarios. It contains a KERB_INTERACTIVE_LOGON to hold the // creds plus a LUID that is filled in for us by Winlogon as // necessary. + spdlog::debug("GetSerialization->KerbInteractiveUnlockLogonPack"); hr = KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization); if (SUCCEEDED(hr)) { ULONG ulAuthPackage; + spdlog::debug("GetSerialization->RetrieveNegotiateAuthPackage"); hr = RetrieveNegotiateAuthPackage(&ulAuthPackage); if (SUCCEEDED(hr)) { pcpcs->ulAuthenticationPackage = ulAuthPackage; @@ -970,7 +975,7 @@ static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] = { HRESULT Credential::ReportResult(NTSTATUS ntsStatus, NTSTATUS ntsSubstatus, _Outptr_result_maybenull_ PWSTR* ppwszOptionalStatusText, _Out_ CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon) { - SPDLOG_DEBUG("ReportResult"); + spdlog::debug("ReportResult"); *ppwszOptionalStatusText = nullptr; *pcpsiOptionalStatusIcon = CPSI_NONE; diff --git a/ee/wcp/ak_cred_provider/Dll.cpp b/ee/wcp/ak_cred_provider/Dll.cpp index 22b834b7..d808f4d7 100644 --- a/ee/wcp/ak_cred_provider/Dll.cpp +++ b/ee/wcp/ak_cred_provider/Dll.cpp @@ -4,7 +4,8 @@ #include "Dll.h" -#include "ak_sentry.h" +#include "ak_common/include/ak_sentry.h" +#include "ak_common/include/ak_log.h" #include "include/cef_command_line.h" #include "include/cef_sandbox_win.h" #include "spdlog/spdlog.h" @@ -45,8 +46,8 @@ DllMain(__in HINSTANCE hinstDll, __in DWORD dwReason, __in LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: { SetPaths(); - SetupLogs("ak_cred_provider"); - SentrySetup("ak_cred_provider"); + ak_setup_logs("ak_cred_provider"); + ak_setup_sentry("ak_cred_provider"); SPDLOG_INFO("DllMain::DLL_PROCESS_ATTACH"); DisableThreadLibraryCalls(hinstDll); @@ -60,8 +61,8 @@ DllMain(__in HINSTANCE hinstDll, __in DWORD dwReason, __in LPVOID lpReserved) { break; case DLL_PROCESS_DETACH: SPDLOG_INFO("DllMain::DLL_PROCESS_DETACH"); - SentryShutdown(); - spdlog::shutdown(); + ak_teardown_sentry(); + ak_teardown_logs(); break; } return TRUE; diff --git a/ee/wcp/ak_cred_provider/Helpers.cpp b/ee/wcp/ak_cred_provider/Helpers.cpp index 5c5742a6..2affff1e 100644 --- a/ee/wcp/ak_cred_provider/Helpers.cpp +++ b/ee/wcp/ak_cred_provider/Helpers.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "Helpers.h" +#include +#include // // Copies the field descriptor pointed to by rcpfd into a buffer allocated @@ -595,3 +597,8 @@ SplitDomainAndUsername(_In_ PCWSTR pszQualifiedUserName, } return hr; } + +std::wstring utf8_decode(const std::string& str) { + std::wstring_convert> myconv; + return myconv.from_bytes(str); +} diff --git a/ee/wcp/ak_cred_provider/Provider.cpp b/ee/wcp/ak_cred_provider/Provider.cpp index c378ac7b..7c9d757b 100644 --- a/ee/wcp/ak_cred_provider/Provider.cpp +++ b/ee/wcp/ak_cred_provider/Provider.cpp @@ -1,8 +1,8 @@ #include "pch.h" -#include "ak_log.h" +#include "ak_common/include/ak_log.h" +#include "ak_common/include/ak_version.h" #include "Provider.h" -#include "ak_version.h" #include "authentik_sys_bridge/ffi.h" #include "rust/cxx.h" #include @@ -97,7 +97,7 @@ void Provider::SetCefApp(sHookData* pData) { settings.log_severity = LOGSEVERITY_INFO; std::string strUserAgent = std::string("authentik Platform/WCP/CredProvider@") - .append(AK_WCP_VERSION) + .append(AK_VERSION) .append(" (CEF ") .append(CEF_VERSION) .append(")"); diff --git a/ee/wcp/ak_cred_provider/ak_cred_provider.def b/ee/wcp/ak_cred_provider/ak_cred_provider.def index c64ec94e..296c8bbf 100644 --- a/ee/wcp/ak_cred_provider/ak_cred_provider.def +++ b/ee/wcp/ak_cred_provider/ak_cred_provider.def @@ -9,8 +9,4 @@ EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE CefExecuteProcess - SetupLogs - SentrySetup - SentryShutdown - CEFLaunch ; //- todo: remove diff --git a/ee/wcp/ak_cred_provider/include/Common.h b/ee/wcp/ak_cred_provider/include/Common.h index 3e211f94..943f8fe2 100644 --- a/ee/wcp/ak_cred_provider/include/Common.h +++ b/ee/wcp/ak_cred_provider/include/Common.h @@ -1,7 +1,8 @@ #pragma once #include "pch.h" -#include "ak_log.h" +#include "ak_common/include/ak_log.h" + // The indexes of each of the fields in the credential provider's tiles. enum FIELD_ID { FI_TILEIMAGE = 0, diff --git a/ee/wcp/ak_cred_provider/include/Helpers.h b/ee/wcp/ak_cred_provider/include/Helpers.h index 02cb1c73..fd77611c 100644 --- a/ee/wcp/ak_cred_provider/include/Helpers.h +++ b/ee/wcp/ak_cred_provider/include/Helpers.h @@ -49,4 +49,6 @@ HRESULT DomainUsernameStringAlloc(_In_ PCWSTR pwszDomain, _In_ PCWSTR pwszUserna HRESULT SplitDomainAndUsername(_In_ PCWSTR pszQualifiedUserName, _Outptr_result_nullonfailure_ PWSTR* ppszDomain, - _Outptr_result_nullonfailure_ PWSTR* ppszUsername); \ No newline at end of file + _Outptr_result_nullonfailure_ PWSTR* ppszUsername); + +std::wstring utf8_decode(const std::string& str); diff --git a/ee/wcp/ak_cred_provider/include/framework.h b/ee/wcp/ak_cred_provider/include/framework.h index 2a67836c..ee364f63 100644 --- a/ee/wcp/ak_cred_provider/include/framework.h +++ b/ee/wcp/ak_cred_provider/include/framework.h @@ -19,7 +19,9 @@ // Credential provider #include +#pragma warning(disable : 4005) #include +#pragma warning(default : 4005) #include // std diff --git a/ee/wcp/cefexe/CMakeLists.txt b/ee/wcp/cefexe/CMakeLists.txt index 86569ce1..a861d17f 100644 --- a/ee/wcp/cefexe/CMakeLists.txt +++ b/ee/wcp/cefexe/CMakeLists.txt @@ -27,6 +27,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ..) target_link_libraries(${PROJECT_NAME} # ${LIBCEF_LIB_PATH} #//- todo: revise if really needed + ak_common ak_cred_provider # ${LIBCEF_DLL_WRAPPER_LIB_PATH} #- # ${CEF_STANDARD_LIBS} diff --git a/ee/wcp/cefexe/cefexe.cpp b/ee/wcp/cefexe/cefexe.cpp index 2d612c1a..93930532 100644 --- a/ee/wcp/cefexe/cefexe.cpp +++ b/ee/wcp/cefexe/cefexe.cpp @@ -1,14 +1,10 @@ #include "cefsimple/simple_app.h" #include "include/cef_app.h" -#include "ak_cred_provider/include/ak_log.h" -#include "ak_cred_provider/include/ak_sentry.h" +#include "ak_common/include/ak_log.h" +#include "ak_common/include/ak_sentry.h" #include "spdlog/spdlog.h" #include -// #pragma comment(lib,"libcef.lib") - -// int main(int argc, char* argv[]) -// { int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { @@ -19,24 +15,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd CefMainArgs main_args(hInst); - SetupLogs("cefexe"); - SentrySetup("cefexe"); + ak_setup_logs("cefexe"); + ak_setup_sentry("cefexe"); SPDLOG_DEBUG("wWinMain"); - // printf("> %d\n", argc); - // for (int i = 0; i < argc; ++i) - // { - // const wchar_t str[100] = { i, '\0' }; - // const wchar_t txt[1000] = { *argv[i], '\0'}; - // printf("%s\n", argv[i]); - // const char str1[100] = { i, '\0' }; - // const char txt1[1000] = { *argv[i], '\0' }; - // // SPDLOG_DEBUG(str1); - // // SPDLOG_DEBUG(txt1); - // } - - // Sleep(3000); - int ret = 0; try { SPDLOG_DEBUG("CefExecuteProcess"); @@ -45,7 +27,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd } catch (const std::exception&) { SPDLOG_DEBUG("CefExecuteProcess... catch...!"); } - // spdlog::shutdown(); - SentryShutdown(); + ak_teardown_sentry(); + ak_teardown_logs(); return ret; } diff --git a/ee/wcp/cefsimple/BUILD.bazel b/ee/wcp/cefsimple/BUILD.bazel deleted file mode 100644 index 562352be..00000000 --- a/ee/wcp/cefsimple/BUILD.bazel +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights -# reserved. Use of this source code is governed by a BSD-style license that -# can be found in the LICENSE file. - -PRODUCT_NAME = "cefsimple" -PKG_NAME = "//tests/{}".format(PRODUCT_NAME) - -# Allow access from subpackages only. -package(default_visibility = [ - ":__subpackages__", -]) - -load("//bazel:library_helpers.bzl", "declare_cc_library", "declare_objc_library") -load("@rules_cc//cc:defs.bzl", "cc_library") - -# -# Source file lists. -# - -srcs_browser = [ - "simple_app.cc", - "simple_app.h", - "simple_handler.cc", - "simple_handler.h" -] - -srcs_browser_linux = [ - "cefsimple_linux.cc", - "simple_handler_linux.cc" -] - -srcs_browser_mac = [ - "cefsimple_mac.mm", - "simple_handler_mac.mm" -] - -srcs_browser_win = [ - "cefsimple_win.cc", - "resource.h", - "simple_handler_win.cc" -] - -srcs_renderer_mac = [ - "process_helper_mac.cc" -] - -# -# MacOS targets. -# - -declare_objc_library( - name = "BrowserLibMac", - srcs = srcs_browser + srcs_browser_mac, - target_compatible_with = [ - "@platforms//os:macos", - ], - deps = [ - "//:cef_wrapper", - ], -) - -declare_cc_library( - name = "RendererLibMac", - srcs = srcs_renderer_mac, - target_compatible_with = [ - "@platforms//os:macos", - ], - deps = [ - "//:cef_wrapper", - ], -) - -# -# Windows targets. -# - -# Allow access to resource.h from the declare_exe target. -cc_library( - name = "ResourceH", - hdrs = [ - "resource.h" - ] -) - -# Include files directly in the declare_exe target. This simplifies the build -# configuration and avoids issues with Windows discarding symbols (like WinMain) -# when linking libraries. -filegroup( - name = "SrcsWin", - srcs = srcs_browser + srcs_browser_win, - target_compatible_with = [ - "@platforms//os:windows", - ], -) - -# -# Linux targets. -# - -# Include files directly in the declare_exe target. This simplifies the build -# configuration. -filegroup( - name = "SrcsLinux", - srcs = srcs_browser + srcs_browser_linux, - target_compatible_with = [ - "@platforms//os:linux", - ], -) - -# -# Alias to platform-specific build targets. -# - -alias( - name = PRODUCT_NAME, - actual = select({ - "@platforms//os:linux": "{}/linux:{}".format(PKG_NAME, PRODUCT_NAME), - "@platforms//os:macos": "{}/mac:{}".format(PKG_NAME, PRODUCT_NAME), - "@platforms//os:windows": "{}/win:{}".format(PKG_NAME, PRODUCT_NAME), - }), -) diff --git a/ee/wcp/cefsimple/CMakeLists.txt b/ee/wcp/cefsimple/CMakeLists.txt index 8715a4af..f548fe7f 100644 --- a/ee/wcp/cefsimple/CMakeLists.txt +++ b/ee/wcp/cefsimple/CMakeLists.txt @@ -14,8 +14,6 @@ set(CEFSIMPLE_SRCS simple_app.h simple_handler.cc simple_handler.h - crypt.cc - crypt.h ) set(CEFSIMPLE_SRCS_LINUX cefsimple_linux.cc diff --git a/ee/wcp/cefsimple/cefsimple1.def b/ee/wcp/cefsimple/cefsimple1.def index 1766400f..3932ed8b 100644 --- a/ee/wcp/cefsimple/cefsimple1.def +++ b/ee/wcp/cefsimple/cefsimple1.def @@ -1,10 +1,10 @@ -;cefsimple.def +;cefsimple.def ; cefsimple module-definition file -; LIBRARY cefsimple.dll +; LIBRARY cefsimple.dll ; LIBRARY -LIBRARY cefsimple.dll +LIBRARY cefsimple.dll EXPORTS - CEFLaunch + CEFLaunch CEFTest - + diff --git a/ee/wcp/cefsimple/cefsimple_win.cc b/ee/wcp/cefsimple/cefsimple_win.cc index 54ef1ccd..510ae412 100644 --- a/ee/wcp/cefsimple/cefsimple_win.cc +++ b/ee/wcp/cefsimple/cefsimple_win.cc @@ -9,10 +9,10 @@ // #include "cefsimple/simple_app.h" #include "cefsimple/simple_handler.h" #include "cefsimple/cefsimple_win.h" -#include "ak_cred_provider/include/ak_log.h" -#include "crypt.h" +#include "ak_common/include/ak_log.h" +#include "ak_common/include/ak_sentry.h" +#include "ak_common/include/crypt.h" #include "Credential.h" -#include extern std::string g_strPath; @@ -117,8 +117,9 @@ int CEFLaunch(sHookData* pData, CefRefPtr pCefApp) { Sleep(5); // as precaution to relieve the CPU (though unlikely that its needed) } pHandler = nullptr; // Release for the destructor to be called subsequently - if (pData->strUsername == "") // User clicked the close button or cancel + if (pData->strUsername == "") // User clicked the close button or cancel { + spdlog::debug("Token empty"); pData->SetCancel(true); } // perform (at max) 10 precautionary loops even though 1 `CefDoMessageLoopWork()` diff --git a/ee/wcp/cefsimple/crypt.cc b/ee/wcp/cefsimple/crypt.cc deleted file mode 100644 index b522ae29..00000000 --- a/ee/wcp/cefsimple/crypt.cc +++ /dev/null @@ -1,280 +0,0 @@ -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (C) Microsoft. All rights reserved. -/* -Abstract: - Sample program for SHA 256 hashing using CNG -*/ - -#include "crypt.h" - -#define WIN32_NO_STATUS -#include -#undef WIN32_NO_STATUS -#include -#include - -#include -#include - -#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) -#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) - -const std::string strChars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const size_t nCharsLen = strChars.length(); - -bool Hash_SHA256(const std::string& strData, std::string& strHash) -{ - BCRYPT_ALG_HANDLE hAlg = NULL; - BCRYPT_HASH_HANDLE hHash = NULL; - NTSTATUS status = STATUS_UNSUCCESSFUL; - DWORD cbData = 0, - cbHash = 0, - cbHashObject = 0; - PBYTE pbHashObject = NULL; - PBYTE pbHash = NULL; - - BYTE data[1000]; //- todo: add dynamic allocation to match input data length - ULONG dataSize = (ULONG)(strData.size()); - if (!(dataSize <= sizeof(data))) - { - wprintf(L"**** Error: Insufficient fixed size buffer. Input data length is too large.\n"); - return false; - } - - bool bRet = false; - for (size_t i = 0; i < strData.size(); ++i) - { - data[i] = (BYTE)(strData[i]); - } - - //open an algorithm handle - if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( - &hAlg, - BCRYPT_SHA256_ALGORITHM, - NULL, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - goto Cleanup; - } - - //calculate the size of the buffer to hold the hash object - if(!NT_SUCCESS(status = BCryptGetProperty( - hAlg, - BCRYPT_OBJECT_LENGTH, - (PBYTE)&cbHashObject, - sizeof(DWORD), - &cbData, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); - goto Cleanup; - } - - //allocate the hash object on the heap - pbHashObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHashObject); - if(NULL == pbHashObject) - { - wprintf(L"**** memory allocation failed\n"); - goto Cleanup; - } - - //calculate the length of the hash - if(!NT_SUCCESS(status = BCryptGetProperty( - hAlg, - BCRYPT_HASH_LENGTH, - (PBYTE)&cbHash, - sizeof(DWORD), - &cbData, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); - goto Cleanup; - } - - //allocate the hash buffer on the heap - pbHash = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHash); - if(NULL == pbHash) - { - wprintf(L"**** memory allocation failed\n"); - goto Cleanup; - } - - //create a hash - if(!NT_SUCCESS(status = BCryptCreateHash( - hAlg, - &hHash, - pbHashObject, - cbHashObject, - NULL, - 0, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status); - goto Cleanup; - } - - - //hash some data - if(!NT_SUCCESS(status = BCryptHashData( - hHash, - (PBYTE)data, - dataSize, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status); - goto Cleanup; - } - - //close the hash - if(!NT_SUCCESS(status = BCryptFinishHash( - hHash, - pbHash, - cbHash, - 0))) - { - wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status); - goto Cleanup; - } - - wprintf(L"Success!\n"); - - LPSTR pszString = NULL; - DWORD cchString = 0; - BOOL bEncodingRet = FALSE; - BOOL bAlloc = FALSE; - for (size_t i = 0; i < 2; ++i) - { - if (cchString > 0) - { - pszString = new char[cchString]; - bAlloc = TRUE; - } - bEncodingRet = CryptBinaryToStringA( - /*[in] const BYTE* */ pbHash, - /*[in] DWORD*/ cbHash, - /*[in] DWORD*/ CRYPT_STRING_BASE64URI | CRYPT_STRING_NOCRLF, - /*[out, optional] LPSTR*/ pszString, - /*[in, out] DWORD* */ &cchString - ); - } - strHash = ""; - if (bEncodingRet == TRUE) - { - bRet = true; - for (size_t i = 0; i < cchString; ++i) - { - strHash.append(1, pszString[i]); - } - } - if (bAlloc == TRUE) - { - delete pszString; - } - -Cleanup: - - if(hAlg) - { - BCryptCloseAlgorithmProvider(hAlg,0); - } - - if (hHash) - { - BCryptDestroyHash(hHash); - } - - if(pbHashObject) - { - HeapFree(GetProcessHeap(), 0, pbHashObject); - } - - if(pbHash) - { - HeapFree(GetProcessHeap(), 0, pbHash); - } - - return bRet; -} - -bool GenerateRandomInt(size_t& nRandom, const size_t nBytesCount) -{ - if (!((nBytesCount >= 1) && (nBytesCount <= sizeof(nRandom)))) - { - return false; - } - NTSTATUS status = STATUS_UNSUCCESSFUL; - - // The output seems to write to atleast 4 bytes, so assigning 8 just in case (64-bit machines). - UCHAR bBuffer[sizeof(nRandom)]; - ULONG cbBuffer = sizeof(bBuffer); - - memset(bBuffer, 0, cbBuffer); - - if(!NT_SUCCESS(status = BCryptGenRandom( - /*[in, out] BCRYPT_ALG_HANDLE*/ NULL, - /*[in, out] PUCHAR*/ bBuffer, - /*[in] ULONG*/ (ULONG)nBytesCount, - /*[in] ULONG*/ BCRYPT_USE_SYSTEM_PREFERRED_RNG - )) - ) - { - wprintf(L"**** Error 0x%x returned by BCryptGenRandom\n", status); - nRandom = 0; - return false; - } - nRandom = 0; - size_t nTmp = 0; - for (SIZE_T i = 0; i < cbBuffer; ++i) - { - nTmp = bBuffer[i]; - nRandom += nTmp << (8*i); - } - - return true; -} - -size_t GetRandomInt(const size_t nExclusiveUpperBound) -{ - size_t nBytesCount = 0; - size_t nMaxValue = 255; - for (nBytesCount = 1; nBytesCount < 8; ++nBytesCount) - { - size_t nDiv = (nExclusiveUpperBound / nMaxValue); - if ((nDiv == 0) || ((nDiv == 1) && ((nExclusiveUpperBound % nMaxValue) == 0))) - { - break; - } - nMaxValue = nMaxValue << 8; - nMaxValue = nMaxValue + 255; - } - size_t nRandom = 0; - if (! GenerateRandomInt(nRandom, nBytesCount)) - { - // fallback - srand((unsigned int)time(NULL)); - nRandom = rand(); - } - nRandom = nRandom % nExclusiveUpperBound; - return nRandom; -} - -std::string GetRandomStr(const size_t nLength) -{ - std::string strRet = ""; - for (size_t i = 0; i < nLength; ++i) - { - strRet.append(1, strChars.at(GetRandomInt(nCharsLen))); - } - return strRet; -} - -std::wstring GetRandomWStr(const size_t nLength) -{ - std::string str = GetRandomStr(nLength); - return std::wstring(str.begin(), str.end()); -} diff --git a/ee/wcp/cefsimple/simple_handler.h b/ee/wcp/cefsimple/simple_handler.h index 1c6d889e..bc0f0448 100644 --- a/ee/wcp/cefsimple/simple_handler.h +++ b/ee/wcp/cefsimple/simple_handler.h @@ -5,11 +5,6 @@ #ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_ #define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_ -#pragma warning(push) -#pragma warning(disable : 4005) -#include -#pragma warning(pop) -#include #include "rust/cxx.h" #include "authentik_sys_bridge/ffi.h" #include @@ -24,7 +19,7 @@ #include "include/cef_client.h" #include "include/cef_command_ids.h" -#include "ak_log.h" +#include "ak_common/include/ak_log.h" #include "Credential.h" @@ -74,10 +69,10 @@ class SimpleHandler : public CefClient, CefRefPtr request, CefRefPtr response) override { std::string strURL = "URL: " + request->GetURL().ToString() + " " + request->GetMethod().ToString(); - SPDLOG_DEBUG(strURL.c_str()); + spdlog::debug(strURL.c_str()); std::string str = "OnResourceResponse ProcessID: " + std::to_string(GetCurrentProcessId()) + ", ThreadID: " + std::to_string(GetCurrentThreadId()); - SPDLOG_DEBUG(str.c_str()); + spdlog::debug(str.c_str()); return false; } @@ -86,7 +81,7 @@ class SimpleHandler : public CefClient, CefRefPtr callback) override { const std::string strKey = "goauthentik.io://"; std::string strURL = request->GetURL().ToString(); - SPDLOG_DEBUG(strURL.c_str()); + spdlog::debug(strURL.c_str()); CefString headerKey; headerKey.FromString("X-Authentik-Platform-Auth-DTH"); @@ -96,9 +91,9 @@ class SimpleHandler : public CefClient, request->SetHeaderByName(headerKey, headerValue, true); if (strURL.length() >= strKey.length()) { if (strURL.substr(0, strKey.length()) == strKey) { - SPDLOG_DEBUG("URL inhibited: ", strURL.c_str()); - SPDLOG_DEBUG("OnBeforeResourceLoad ProcessID: ", std::to_string(GetCurrentProcessId()), - ", ThreadID: ", std::to_string(GetCurrentThreadId())); + spdlog::debug("URL inhibited: ", strURL.c_str()); + spdlog::debug("OnBeforeResourceLoad ProcessID: ", std::to_string(GetCurrentProcessId()), + ", ThreadID: ", std::to_string(GetCurrentThreadId())); Hide(); m_pData->UpdateStatus(L"Authenticating, please wait..."); TokenResponse validatedToken; diff --git a/ee/wcp/cefsimple/win/BUILD.bazel b/ee/wcp/cefsimple/win/BUILD.bazel deleted file mode 100644 index 8a2197eb..00000000 --- a/ee/wcp/cefsimple/win/BUILD.bazel +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights -# reserved. Use of this source code is governed by a BSD-style license that -# can be found in the LICENSE file. - -PRODUCT_NAME = "cefsimple" -PKG_NAME = "//tests/{}".format(PRODUCT_NAME) - -# Allow access from the parent package only. -package(default_visibility = [ - "{}:__pkg__".format(PKG_NAME), -]) - -load("//bazel/win:exe_helpers.bzl", "declare_exe") - -# -# Windows executable target. -# - -declare_exe( - name = PRODUCT_NAME, - srcs = [ - "{}:SrcsWin".format(PKG_NAME), - ], - rc_file = "{}.rc".format(PRODUCT_NAME), - manifest_srcs = [ - "compatibility.manifest", - "{}.exe.manifest".format(PRODUCT_NAME), - ], - resources_srcs = [ - "{}.ico".format(PRODUCT_NAME), - "small.ico", - ], - resources_deps = [ - "{}:ResourceH".format(PKG_NAME), - ], - linkopts = [ - "/SUBSYSTEM:WINDOWS", - ], -) diff --git a/ee/wcp/libcef_dll/CMakeLists.txt b/ee/wcp/libcef_dll/CMakeLists.txt index 9575488a..bf8eb32a 100644 --- a/ee/wcp/libcef_dll/CMakeLists.txt +++ b/ee/wcp/libcef_dll/CMakeLists.txt @@ -811,8 +811,6 @@ set(CEFSIMPLE_SRCS ${CEFSIMPLE_PATH}/simple_app.h ${CEFSIMPLE_PATH}/simple_handler.cc ${CEFSIMPLE_PATH}/simple_handler.h - ${CEFSIMPLE_PATH}/crypt.cc - ${CEFSIMPLE_PATH}/crypt.h ) set(CEFSIMPLE_SRCS_LINUX ${CEFSIMPLE_PATH}/cefsimple_linux.cc @@ -901,8 +899,6 @@ set(WCP_PATH "../${WCP}") set(WCP_SRCS "${WCP_PATH}/ClassFactory.cpp" "${WCP_PATH}/Credential.cpp" - "${WCP_PATH}/ak_sentry.cpp" - "${WCP_PATH}/ak_log.cpp" "${WCP_PATH}/Dll.cpp" "${WCP_PATH}/GUIDs.cpp" "${WCP_PATH}/Helpers.cpp" @@ -983,10 +979,8 @@ target_link_libraries(${CEF_TARGET} ${SHLWAPI_LIB_PATH} ${CRYPT32_LIB_PATH} ${NETAPI32_LIB_PATH} - jwt-cpp + ak_common authentik_sys_bridge - spdlog - sentry ) # Copy binary and resource files to the target output directory. diff --git a/pkg/agent_system/config/domain.go b/pkg/agent_system/config/domain.go index 1f803e1e..33a23829 100644 --- a/pkg/agent_system/config/domain.go +++ b/pkg/agent_system/config/domain.go @@ -69,8 +69,7 @@ func (dc DomainConfig) APIClient() (*api.APIClient, error) { apiConfig.UserAgent = fmt.Sprintf("goauthentik.io/platform/%s", meta.FullVersion()) c := api.NewAPIClient(apiConfig) - dc.c = c - return dc.c, nil + return c, nil } func (dc DomainConfig) Test() error {