diff --git a/PAM/ssh/CMakeLists.txt b/PAM/ssh/CMakeLists.txt index 26dad44..3f7b726 100755 --- a/PAM/ssh/CMakeLists.txt +++ b/PAM/ssh/CMakeLists.txt @@ -128,7 +128,7 @@ 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/authentication_step_interface.hpp b/PAM/ssh/include/rublon/authentication_step_interface.hpp index 63f7ad3..89d0fa2 100644 --- a/PAM/ssh/include/rublon/authentication_step_interface.hpp +++ b/PAM/ssh/include/rublon/authentication_step_interface.hpp @@ -35,7 +35,7 @@ class AuthenticationStep { auto event = eventListener.listen(); if(event.status == transactionConfirmed ){ log(LogLevel::Debug, " Transaction confirmed"); - return AuthenticationStatus{AuthenticationStatus::Action::Confirmed, std::string{event.accessToken.value().c_str()}}; + return AuthenticationStatus{AuthenticationStatus::Action::Confirmed, event.accessToken.value().c_str()}; } log(LogLevel::Debug, " Transaction denied"); return AuthenticationStatus{AuthenticationStatus::Action::Denied}; diff --git a/PAM/ssh/include/rublon/core_handler.hpp b/PAM/ssh/include/rublon/core_handler.hpp index 1e88c78..46feb55 100755 --- a/PAM/ssh/include/rublon/core_handler.hpp +++ b/PAM/ssh/include/rublon/core_handler.hpp @@ -73,7 +73,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { public: CoreHandler() = delete; - CoreHandler(const Configuration & config) : _config{config}, _ws{std::make_unique(_config.apiServer)}, http{_config} { + CoreHandler(const Configuration & config) : _config{config}, _ws{std::make_unique(_config)}, http{_config} { log(LogLevel::Debug, "Core Handler apiServer: %s", _config.apiServer.c_str()); } CoreHandler(CoreHandler &&) noexcept = default; @@ -132,7 +132,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { 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 + // can happen only during check application step if(auto error = RublonCheckApplicationException::fromString(exceptionString); error.has_value()) return tl::unexpected{Error{error.value()}}; @@ -184,7 +184,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { bool createWSConnection(std::string_view tid) const { if(not _ws){ - _ws.reset(new WebSocket (_config.apiServer)); + _ws.reset(new WebSocket (_config)); } /// TODO connect can be separated from subscribtion on event /// TODO status of attach is not checked diff --git a/PAM/ssh/include/rublon/init.hpp b/PAM/ssh/include/rublon/init.hpp index df8026b..dd524e6 100644 --- a/PAM/ssh/include/rublon/init.hpp +++ b/PAM/ssh/include/rublon/init.hpp @@ -13,8 +13,6 @@ #include -[[deprecated]] extern std::string g_tid; - namespace rublon { template < class MethodSelect_t = MethodSelect > diff --git a/PAM/ssh/include/rublon/pam_action.hpp b/PAM/ssh/include/rublon/pam_action.hpp index cb35c98..44e341f 100644 --- a/PAM/ssh/include/rublon/pam_action.hpp +++ b/PAM/ssh/include/rublon/pam_action.hpp @@ -1,15 +1,18 @@ #pragma once +#include "rublon/static_string.hpp" +#include #include namespace rublon { class AuthenticationStatus { public: + using tokenT = std::optional< StaticString< 64 > >; enum class Action { Denied, Confirmed, Bypass }; - AuthenticationStatus(Action action, std::string authenticationToken = "") - : _action{action}, _authenticationToken{std::move(authenticationToken)} {} + AuthenticationStatus(Action action, const char * token = nullptr) + : _action{action}, _authenticationToken{token == nullptr ? tokenT{std::nullopt} : tokenT{token}} {} constexpr bool userAuthorized() const { return _action == Action::Confirmed; @@ -20,12 +23,12 @@ class AuthenticationStatus { } std::string_view accessToken() const { - return _authenticationToken; + return {_authenticationToken->c_str(), _authenticationToken->size()}; } private: Action _action; - std::string _authenticationToken; /// TODO dynamic mem + tokenT _authenticationToken; /// TODO dynamic mem }; } // namespace rublon diff --git a/PAM/ssh/include/rublon/static_string.hpp b/PAM/ssh/include/rublon/static_string.hpp index 5d0ac45..b78c14e 100644 --- a/PAM/ssh/include/rublon/static_string.hpp +++ b/PAM/ssh/include/rublon/static_string.hpp @@ -31,19 +31,22 @@ template < size_t N > class StaticString : public details::StaticStringBase { public: constexpr StaticString() = default; - constexpr StaticString(const char (&chars)[N]) : m_str(toStdArray(chars)) {} + constexpr StaticString(const char (&chars)[N]) : m_str(toStdArray(chars)), _size{N} {} - constexpr StaticString(std::array< const char, N > chars) : m_str(std::move(chars)) {} + constexpr StaticString(std::array< const char, N > chars) : m_str(std::move(chars)), _size{N} {} constexpr StaticString(const char * str) { - std::strncpy(m_str.data(), str, N); + _size = std::min(strlen(str), N); + std::memcpy(m_str.data(), str, _size); } void operator=(const char * str) { - std::strncpy(m_str.data(), str, N); + _size = std::min(strlen(str), N); + std::memcpy(m_str.data(), str, _size); } - + void operator=(std::string_view str) { - std::strncpy(m_str.data(), str.data(), N); + _size = std::min(str.size(), N); + std::memcpy(m_str.data(), str.data(), _size); } const char * c_str() const noexcept { @@ -67,16 +70,23 @@ class StaticString : public details::StaticStringBase { } std::size_t size() const { - return strlen(m_str.data()); + return _size; } constexpr std::size_t capacity() const noexcept { return N - 1; } - template < std::size_t M > - constexpr StaticString< N + M - 1 > operator+(const StaticString< M > & rhs) const { - return join(resize< N - 1 >(m_str), rhs.m_str); + StaticString< N > & operator+=(const char * rhs) { + auto remaining = capacity() - _size; + auto rhs_len = std::strlen(rhs); + auto copy_len = std::min(rhs_len, remaining); + + std::strncpy(data() + _size, rhs, copy_len); + _size += copy_len; + data()[_size] = '\0'; // null + + return *this; } template < std::size_t M > @@ -88,10 +98,11 @@ class StaticString : public details::StaticStringBase { private: std::array< char, N + 1 > m_str{}; + std::size_t _size; }; -template -bool operator==(const StaticString &lhs, const char* rhs){ +template < size_t N > +bool operator==(const StaticString< N > & lhs, const char * rhs) { return strcmp(lhs.c_str(), rhs) == 0; } diff --git a/PAM/ssh/include/rublon/websockets.hpp b/PAM/ssh/include/rublon/websockets.hpp index 5abc469..1ef4758 100644 --- a/PAM/ssh/include/rublon/websockets.hpp +++ b/PAM/ssh/include/rublon/websockets.hpp @@ -130,19 +130,21 @@ class WebSocket { } bool attachToTransactionConfirmationChannel(std::string_view transaction_id) { - /// TODO change to StaticString and += - std::array< char, 128 > subscribe_message{0}; - std::array< char, 128 > buf{0}; + StaticString< 128 > subscribe_message{}; + unsigned char buf[128 + LWS_PRE] = {}; - sprintf(subscribe_message.data(), R"msg(42["subscribe",{"channel":"transactionConfirmation.%s"}])msg", transaction_id.data()); - memcpy(&buf[LWS_PRE], subscribe_message.data(), strlen(subscribe_message.data())); + subscribe_message += R"msg(42["subscribe",{"channel":"transactionConfirmation.)msg"; + subscribe_message += transaction_id.data(); + subscribe_message += "}]"; - log(LogLevel::Debug, "WS send message: %s", subscribe_message.data()); - int bytes_sent = lws_write(wsi, ( unsigned char * ) &buf[LWS_PRE], strlen(subscribe_message.data()), LWS_WRITE_TEXT); + memcpy(buf + LWS_PRE, subscribe_message.data(), subscribe_message.size()); + + log(LogLevel::Debug, "WS send message: %s", subscribe_message.c_str()); + int bytes_sent = lws_write(wsi, buf + LWS_PRE, subscribe_message.size(), LWS_WRITE_TEXT); log(LogLevel::Debug, "WS send: %d bytes", bytes_sent); - if(bytes_sent < ( int ) strlen(subscribe_message.data())) { + if(bytes_sent < ( int ) subscribe_message.size()) { log(LogLevel::Error, "Failed to send subscribe message"); return false; } @@ -151,7 +153,6 @@ class WebSocket { bool AttachToCore(std::string_view tid) { log(LogLevel::Debug, "connecting to %s", ccinfo.address); - /// needed here only for rublon core api URL, so 1k fine lws_client_connect_via_info(&ccinfo); const int seconds = 10; @@ -209,7 +210,7 @@ class WebSocket { case LWS_CALLBACK_CLIENT_WRITEABLE: { // Perform the Socket.IO 4.x handshake (send `40` message) const std::string_view handshake = "40"; - unsigned char buf[64]; + unsigned char buf[64]={}; memcpy(&buf[LWS_PRE], handshake.data(), handshake.size()); lws_write(wsi, &buf[LWS_PRE], handshake.size(), LWS_WRITE_TEXT); log(LogLevel::Debug, "Sent Socket.IO handshake");