diff --git a/PAM/ssh/bin/rublon_application.cpp b/PAM/ssh/bin/rublon_application.cpp index ce07310..3912ccb 100644 --- a/PAM/ssh/bin/rublon_application.cpp +++ b/PAM/ssh/bin/rublon_application.cpp @@ -78,7 +78,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char ** argv) { }; { - CheckApplication ca; + CheckApplication ca{session}; auto ret = ca.call(CH, session.config().systemToken).or_else(mapError); if(not ret.has_value()) { log(LogLevel::Error, "Check Application step failed, check configration"); diff --git a/PAM/ssh/include/rublon/check_application.hpp b/PAM/ssh/include/rublon/check_application.hpp index 63560c7..3ec04ef 100644 --- a/PAM/ssh/include/rublon/check_application.hpp +++ b/PAM/ssh/include/rublon/check_application.hpp @@ -1,5 +1,7 @@ #pragma once +#include "rublon/configuration.hpp" +#include "rublon/session.hpp" #include #include #include @@ -11,6 +13,8 @@ #include #include +#include +#include namespace rublon { @@ -127,6 +131,85 @@ class Status { } } + template < typename T > + void updateRublonConfigParameter(std::string_view name, const T & newParam) { + memory::MonotonicStack_1k_Resource memoryResource{}; + RapidJSONPMRAlloc stackAlloc{&memoryResource}; + + std::pmr::string jsonPath{&memoryResource}; + jsonPath += _configBase; + jsonPath += name; + + JSONPointer jsonPointer{jsonPath.c_str(), &stackAlloc}; + auto * param = jsonPointer.Get(_data); + + Document::AllocatorType & alloc = _data.GetAllocator(); + Value newValue; + + if constexpr(std::is_same_v< T, std::pmr::string > || std::is_same_v< T, std::string_view >) { + newValue.SetString(newParam.data(), static_cast< rapidjson::SizeType >(newParam.size()), alloc); + if(!param || !param->IsString() || param->GetString() != newParam) { + markUpdated(); + jsonPointer.Set(_data, newValue); + } + } else if constexpr(std::is_same_v< T, bool >) { + newValue.SetBool(newParam); + if(!param || !param->IsBool() || param->GetBool() != newParam) { + markUpdated(); + jsonPointer.Set(_data, newValue); + } + } else if constexpr(std::is_integral_v< T >) { + newValue.SetInt(static_cast< int >(newParam)); + if(!param || !param->IsInt() || param->GetInt() != static_cast< int >(newParam)) { + markUpdated(); + jsonPointer.Set(_data, newValue); + } + } + } + + // For std::optional + template < typename T > + void updateRublonConfigParameter(std::string_view name, const std::optional< T > & optParam) { + memory::MonotonicStack_1k_Resource memoryResource{}; + RapidJSONPMRAlloc stackAlloc{&memoryResource}; + + std::pmr::string fullPath{&memoryResource}; + fullPath += _configBase; + fullPath += name; + + JSONPointer jsonPointer{fullPath.c_str(), &stackAlloc}; + Value* existing = jsonPointer.Get(_data); + + if (optParam.has_value()) { + // Delegate to regular (non-optional) setter + updateRublonConfigParameter(name, *optParam); + } else { + // Set the entire field to `null` if no value + if (!existing || !existing->IsNull()) { + markUpdated(); + Value nullValue(rapidjson::kNullType); + jsonPointer.Set(_data, nullValue); + } + } + } + + void updateRublonConfig(const Configuration & config) { + updateRublonConfigParameter("prompt", config.prompt); + updateRublonConfigParameter("logging", config.logging); + updateRublonConfigParameter("autopushPrompt", config.autopushPrompt); + updateRublonConfigParameter("failMode", static_cast(config.failMode)); + updateRublonConfigParameter("nonInteractiveMode", config.nonInteractiveMode); + + updateRublonConfigParameter("proxyType", config.proxyType); + updateRublonConfigParameter("proxyServer", config.proxyServer); + updateRublonConfigParameter("proxyUsername", config.proxyUsername); + updateRublonConfigParameter("proxyPass", config.proxyPass); + updateRublonConfigParameter("proxyPort", config.proxyPort); + + updateRublonConfigParameter("proxyAuthRequired", config.proxyAuthRequired); + updateRublonConfigParameter("proxyEnabled", config.proxyEnabled); + } + void markUpdated() { _statusUpdated = true; } @@ -164,6 +247,7 @@ class Status { }; class CheckApplication { + const Session & _sesion; tl::expected< bool, Error > persistStatus(Status & status) const { status.data().RemoveMember("systemToken"); status.save(); @@ -171,6 +255,8 @@ class CheckApplication { } public: + CheckApplication(const Session & session) : _sesion{session} {} + tl::expected< int, Error > call(const CoreHandler_t & coreHandler, std::string_view systemToken) const { memory::MonotonicStack_2k_Resource mr; RapidJSONPMRAlloc alloc{&mr}; @@ -182,7 +268,7 @@ class CheckApplication { status.updateAppVersion(RUBLON_VERSION_STRING); status.updateSystemVersion(details::osName(&mr)); status.updateSSHDConfig(); - // status.updateRublonConfig(); + status.updateRublonConfig(_sesion.config()); if(status.updated()) { auto & alloc = status.data().GetAllocator(); diff --git a/PAM/ssh/lib/pam.cpp b/PAM/ssh/lib/pam.cpp index 1276387..06548c2 100644 --- a/PAM/ssh/lib/pam.cpp +++ b/PAM/ssh/lib/pam.cpp @@ -98,7 +98,7 @@ pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unu }; { - CheckApplication ca; + CheckApplication ca{session}; const auto ret = ca.call(CH, session.config().systemToken).or_else(mapError); if(not ret.has_value()) { log(LogLevel::Error, "Check Application step failed, check configration");