diff --git a/CMakeLists.txt b/CMakeLists.txt index ffe7e4d..8757471 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ set(CMAKE_POSITION_INDEPENDENT_CODE YES) add_compile_options(-Wall -Wextra -Wno-format-security) +# add_compile_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer) +# add_link_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer) + add_compile_definitions(RUBLON_VERSION_STRING="${RUBLON_VERSION_STRING}") option(ENABLE_TESTS "Enable tests" OFF) diff --git a/PAM/ssh/CMakeLists.txt b/PAM/ssh/CMakeLists.txt index b1e8931..6aa715e 100755 --- a/PAM/ssh/CMakeLists.txt +++ b/PAM/ssh/CMakeLists.txt @@ -114,11 +114,17 @@ FetchContent_Declare( FetchContent_MakeAvailable(libwebsockets) + +set(RAPIDJSON_BUILD_DOC OFF) +set(RAPIDJSON_BUILD_EXAMPLES OFF) +set(RAPIDJSON_BUILD_TESTS OFF) +set(RAPIDJSON_HAS_STDSTRING OFF) + FetchContent_Declare( RapidJSON URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.zip URL_HASH MD5=ceb1cf16e693a3170c173dc040a9d2bd - PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/patches/rapidjson.patch + # PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/patches/rapidjson.patch ) if(NOT RapidJSON_POPULATED) diff --git a/PAM/ssh/include/rublon/check_application.hpp b/PAM/ssh/include/rublon/check_application.hpp index a5f1439..c038c75 100644 --- a/PAM/ssh/include/rublon/check_application.hpp +++ b/PAM/ssh/include/rublon/check_application.hpp @@ -67,7 +67,7 @@ class Status { } void updateAppVersion(std::string_view newVersion) { - RapidJSONPMRStackAlloc< 128 > stackAlloc; + RapidJSONPMRStackAlloc< 512 > stackAlloc; auto jsonPointer = JSONPointer{_appVersionKey.data(), &stackAlloc}; auto version = jsonPointer.Get(_data); if(not version || version->GetString() != newVersion) { @@ -77,7 +77,7 @@ class Status { } void updateSystemVersion(std::string_view system) { - RapidJSONPMRStackAlloc< 128 > stackAlloc; + RapidJSONPMRStackAlloc< 512 > stackAlloc; auto jsonPointer = JSONPointer{_paramSystemName.data(), &stackAlloc}; auto version = jsonPointer.Get(_data); if(not version || version->GetString() != system) { diff --git a/PAM/ssh/include/rublon/core_handler.hpp b/PAM/ssh/include/rublon/core_handler.hpp index e0a030b..15ee3af 100755 --- a/PAM/ssh/include/rublon/core_handler.hpp +++ b/PAM/ssh/include/rublon/core_handler.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rublon/error.hpp" #include "rublon/static_string.hpp" #include #include @@ -58,10 +59,12 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { bool hasException(const Document & coreResponse) const { using namespace std::string_view_literals; + log(LogLevel::Debug, "TMP Checking error status in core response"); return coreResponse.HasMember("status") and coreResponse["status"].GetString() == "ERROR"sv; } bool isUnHealthy(const Document & coreResponse) const { + log(LogLevel::Debug, "TMP Checking errors in core response"); return coreResponse.HasParseError(); } @@ -102,7 +105,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { tl::expected< Document, Error > resp{&alloc}; resp->Parse(response.body.c_str()); - log(LogLevel::Debug, "Begin, Core Response validation"); + log(LogLevel::Debug, "Starting Core Response validation"); if(isUnHealthy(*resp)) { log(LogLevel::Error, "Rublon Core responded with broken data"); @@ -122,11 +125,13 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { // additional check for mallformed responses (A invalid response, without any x-rublon-signature will stop at this check) return tl::unexpected{CoreHandlerError{CoreHandlerError::BadSigature}}; } - + + log(LogLevel::Debug, "Core Response validated OK"); return resp; } tl::unexpected< Error > handleCoreException(std::string_view exceptionString) const { + log(LogLevel::Debug, "TMP got core exception: %s", exceptionString.data() ); // can happen only dyring check application step if(auto error = RublonCheckApplicationException::fromString(exceptionString); error.has_value()) return tl::unexpected{Error{error.value()}}; @@ -138,7 +143,9 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { // verification error wrong passcode etc. if(auto error = WerificationError::fromString(exceptionString); error.has_value()) return tl::unexpected{Error{error.value()}}; - + + // CoreHandlerError::TransactionAccessTokenExpiredException + // other exceptions, just "throw" // TODO Handle return tl::unexpected{Error{CoreHandlerError{CoreHandlerError::RublonCoreException}}}; diff --git a/PAM/ssh/include/rublon/init.hpp b/PAM/ssh/include/rublon/init.hpp index be29423..b7c769e 100644 --- a/PAM/ssh/include/rublon/init.hpp +++ b/PAM/ssh/include/rublon/init.hpp @@ -1,6 +1,7 @@ #pragma once #include "rublon/memory.hpp" +#include "rublon/utils.hpp" #include #include @@ -23,15 +24,25 @@ class Init : public AuthenticationStep { const char * apiPath = "/api/transaction/init"; tl::expected< MethodSelect_t, Error > createMethod(const Document & coreResponse) const { - memory::MonotonicStackResource< 256 > stackResource; + rublon::log(LogLevel::Debug, "TMP create method"); + memory::MonotonicStackResource< 512 > stackResource; + rublon::log(LogLevel::Debug, "TMP stack resource created"); RapidJSONPMRAlloc alloc{&stackResource}; + rublon::log(LogLevel::Debug, "TMP alloc created"); - const auto & rublonResponse = coreResponse["result"]; - + const auto * rublonMethods = JSONPointer{"/result/methods", &alloc}.Get(coreResponse); + rublon::log(LogLevel::Debug, "TMP json methods pointers created"); const auto * rublonTid = JSONPointer{"/result/tid", &alloc}.Get(coreResponse); + + if(not rublonMethods) + log(LogLevel::Error, "core response has no methods"); + if(not rublonTid) + log(LogLevel::Error, "core response has no transaction ID"); + + rublon::log(LogLevel::Debug, "TMP json pointers created"); + _session.updateTransactionId(rublonTid); - - return MethodSelect_t{_session, rublonResponse["methods"], _session.config().prompt, _session.config().autopushPrompt}; + return MethodSelect_t{_session, *rublonMethods, _session.config().prompt, _session.config().autopushPrompt}; } void addPamInfo(Document & coreRequest, const Pam_t & pam) const { @@ -68,7 +79,7 @@ class Init : public AuthenticationStep { const auto * rublonStatus = JSONPointer{"/result/status", &alloc}.Get(coreResponse); const auto * rublonWebURI = JSONPointer{"/result/webURI", &alloc}.Get(coreResponse); - + if(rublonStatus) { const auto & status = rublonStatus->GetString(); log(LogLevel::Warning, "Got enrolement message with stats %s", status); diff --git a/PAM/ssh/include/rublon/json.hpp b/PAM/ssh/include/rublon/json.hpp index 2a06fa1..d158600 100644 --- a/PAM/ssh/include/rublon/json.hpp +++ b/PAM/ssh/include/rublon/json.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rapidjson/encodings.h" #include #include #include @@ -137,7 +138,6 @@ inline auto begin(const rublon::Value & __ils) noexcept { inline ::rublon::Value::ConstValueIterator end(const rublon::Value & __ils) noexcept { return __ils.End(); } - [[nodiscard]] inline std::size_t size(const rublon::Value & __cont) { return __cont.Size(); } diff --git a/PAM/ssh/include/rublon/method/method_select.hpp b/PAM/ssh/include/rublon/method/method_select.hpp index 4446b4a..37763cd 100644 --- a/PAM/ssh/include/rublon/method/method_select.hpp +++ b/PAM/ssh/include/rublon/method/method_select.hpp @@ -1,6 +1,4 @@ #pragma once -#include "rublon/json.hpp" -#include "rublon/utils.hpp" #include #include #include @@ -8,9 +6,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -135,6 +135,7 @@ class MethodSelect { template < typename Array_t > MethodSelect(Session & session, const Array_t & methodsEnabledInCore, int prompts, bool autopushPrompt) : _session{session}, _prompts{prompts}, _autopushPrompt{autopushPrompt} { + rublon::log(LogLevel::Debug, "Checking what methods from core are supported"); using namespace std::string_view_literals; _methodsAvailable.reserve(std::size(methodsEnabledInCore)); @@ -175,10 +176,11 @@ class MethodSelect { }; auto printAvailableMethods = [&]() -> tl::expected< int, MethodError > { + rublon::log(LogLevel::Debug, "TMP printing available methods"); int i{}; for(const auto & method : _methodsAvailable) { if(method == "totp") { - if(_session.inInteractiveMode()) { + if(not _session.inInteractiveMode()) { logMethodSkippedInteractive(method); continue; } @@ -198,7 +200,7 @@ class MethodSelect { } if(method == "yotp") { - if(_session.inInteractiveMode()) { + if(not _session.inInteractiveMode()) { logMethodSkippedInteractive(method); continue; } @@ -210,7 +212,7 @@ class MethodSelect { } if(method == "sms") { - if(_session.inInteractiveMode()) { + if(not _session.inInteractiveMode()) { logMethodSkippedInteractive(method); continue; } @@ -260,6 +262,7 @@ class MethodSelect { }; const auto createMethod = [&](std::uint32_t methodid) -> tl::expected< PostMethod, MethodError > { + rublon::log(LogLevel::Debug, "Trace Create method %d", methods_id); auto hasMethod = methods_id.find(methodid) != methods_id.end(); if(!hasMethod) { log(LogLevel::Error, "User selected option %d, which is not correct", methodid); @@ -283,7 +286,7 @@ class MethodSelect { log(LogLevel::Debug, "Automatically selected first available non interactive authentication method: %s", methods_names.at(key).c_str()); - + pam.print("Automatically selected first available non interactive authentication method: %s", methods_names.at(key).c_str()); return key; @@ -301,6 +304,7 @@ class MethodSelect { }; auto reducePromptCount = [&](int selected_method) -> tl::expected< uint32_t, MethodError > { + rublon::log(LogLevel::Debug, "Trace User has %d prompts available", prompts); prompts--; return selected_method; }; diff --git a/PAM/ssh/include/rublon/rublon.hpp b/PAM/ssh/include/rublon/rublon.hpp index d30ab1d..1bfcbcb 100755 --- a/PAM/ssh/include/rublon/rublon.hpp +++ b/PAM/ssh/include/rublon/rublon.hpp @@ -21,7 +21,7 @@ class RublonFactory { return tl::unexpected{ConfigurationError{}}; } - return Session{pam, config.value()}; + return Session{pam, config.value(), false}; } }; diff --git a/PAM/ssh/patches/rapidjson.patch b/PAM/ssh/patches/rapidjson.patch index 7a50f4b..e43d863 100644 --- a/PAM/ssh/patches/rapidjson.patch +++ b/PAM/ssh/patches/rapidjson.patch @@ -1,63 +1,51 @@ diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h -index e3e20dfb..ecd454dd 100644 +index e3e20dfb..592c5678 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h -@@ -99,15 +99,13 @@ struct GenericMember { +@@ -97,17 +97,20 @@ struct GenericMember { + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wdeprecated-declarations" template class GenericMemberIterator -- : public std::iterator >::Type> { -+ { - + : public std::iterator >::Type> { +- ++ friend class GenericValue; template friend class GenericMemberIterator; typedef GenericMember PlainType; typedef typename internal::MaybeAddConst::Type ValueType; -- typedef std::iterator BaseType; + typedef std::iterator BaseType; ++#pragma GCC diagnostic pop public: //! Iterator type itself -@@ -116,13 +114,12 @@ public: - typedef GenericMemberIterator ConstIterator; - //! Non-constant iterator type - typedef GenericMemberIterator NonConstIterator; -- -- //! Pointer to (const) GenericMember -- typedef typename BaseType::pointer Pointer; -- //! Reference to (const) GenericMember -- typedef typename BaseType::reference Reference; -- //! Signed integer type (e.g. \c ptrdiff_t) -- typedef typename BaseType::difference_type DifferenceType; -+ -+ typedef ValueType value_type; -+ typedef ValueType * Pointer; -+ typedef ValueType & Reference; -+ typedef std::ptrdiff_t DifferenceType; -+ typedef std::random_access_iterator_tag iterator_category; - - //! Default constructor (singular value) - /*! Creates an iterator pointing to no element. -@@ -1936,7 +1933,9 @@ private: +@@ -1936,7 +1939,10 @@ private: if (count) { GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); SetElementsPointer(e); -- std::memcpy(e, values, count * sizeof(GenericValue)); -+ for(SizeType i=0;i(allocator.Malloc(count * sizeof(Member))); SetMembersPointer(m); -- std::memcpy(m, members, count * sizeof(Member)); -+ for(SizeType i=0;i