diff --git a/PAM/ssh/include/rublon/authentication_step_interface.hpp b/PAM/ssh/include/rublon/authentication_step_interface.hpp index fbc7d97..d33d0a0 100644 --- a/PAM/ssh/include/rublon/authentication_step_interface.hpp +++ b/PAM/ssh/include/rublon/authentication_step_interface.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rublon/pam_action.hpp" #include #include @@ -7,13 +8,38 @@ namespace rublon { template < typename Impl > class AuthenticationStep { + protected: + std::string _systemToken; + std::string _tid; + public: + AuthenticationStep(){} + AuthenticationStep(std::string systemToken, std::string tid) : _systemToken{std::move(systemToken)}, _tid{std::move(tid)} {} + template < typename Handler_t > auto fire(const CoreHandlerInterface< Handler_t > & coreHandler) const { // log step log(Info, "Starting %s step", static_cast< const Impl * >(this)->name); return static_cast< const Impl * >(this)->handle(coreHandler); } + + template < typename HandlerReturn_t > + PamAction coreErrorHandler(const HandlerReturn_t & coreResponse) const { + switch(coreResponse.error().errorClass) { + case CoreHandlerError::ErrorClass::BadSigature: + log(LogLevel::Error, "ErrorClass::BadSigature"); + return PamAction::decline; + case CoreHandlerError::ErrorClass::CoreException: /// TODO exception handling + log(LogLevel::Error, "ErrorClass::CoreException"); + return PamAction::decline; /// TODO accept? + case CoreHandlerError::ErrorClass::ConnectionError: + log(LogLevel::Error, "ErrorClass::ConnectionError"); + return PamAction::decline; /// TODO decline? + case CoreHandlerError::ErrorClass::BrokenData: + log(LogLevel::Error, "ErrorClass::BrokenData"); + return PamAction::decline; + } + } }; } // namespace rublon diff --git a/PAM/ssh/include/rublon/init.hpp b/PAM/ssh/include/rublon/init.hpp index c1401bb..22990cd 100644 --- a/PAM/ssh/include/rublon/init.hpp +++ b/PAM/ssh/include/rublon/init.hpp @@ -15,17 +15,18 @@ class Verify{}; namespace rublon { template < class MethodSelect_t = MethodSelect, typename Pam_t = LinuxPam > class Init : public AuthenticationStep< Init< MethodSelect_t, Pam_t > > { + using base_t = AuthenticationStep< Init< MethodSelect_t, Pam_t > >; + const char * apiPath = "/api/transaction/init"; - const std::string & _systemToken; protected: - const Pam_t & _pamInfo; + Pam_t & _pamInfo; public: const char * name = "Initialization"; - Init(const Pam_t & pamHandler, const rublon::Configuration & config) - : _systemToken{config.parameters.systemToken}, _pamInfo{pamHandler} {} + Init(Pam_t & pamHandler, const rublon::Configuration & config) + : base_t(config.parameters.systemToken, ""), _pamInfo{pamHandler} {} /// TODO add core handler interface template < typename Hander_t > @@ -35,9 +36,9 @@ class Init : public AuthenticationStep< Init< MethodSelect_t, Pam_t > > { RapidJSONPMRAlloc alloc{&mr}; Document body{rapidjson::kObjectType, &alloc}; - - body.AddMember("systemToken", Value{_systemToken.c_str(), alloc}, alloc); - body.AddMember("username", Value{_pamInfo.username().get(), alloc}, alloc); + + body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc); + body.AddMember("username", Value{this->_pamInfo.username().get(), alloc}, alloc); body.AddMember("userEmail", "bwi@rublon.com", alloc); /// TODO proper username Value params{rapidjson::kObjectType}; @@ -53,23 +54,9 @@ class Init : public AuthenticationStep< Init< MethodSelect_t, Pam_t > > { log(LogLevel::Info, "[TMP] has response, processing", __PRETTY_FUNCTION__); const auto & rublonResponse = coreResponse.value()["result"]; std::string tid = rublonResponse["tid"].GetString(); - return MethodSelect_t{_systemToken, tid, rublonResponse["methods"]}; + return MethodSelect_t{this->_systemToken, tid, rublonResponse["methods"]}; } else { - // mostly connectio errors - switch(coreResponse.error().errorClass) { - case CoreHandlerError::ErrorClass::BadSigature: - log(LogLevel::Error, "ErrorClass::BadSigature"); - return tl::unexpected{PamAction::decline}; - case CoreHandlerError::ErrorClass::CoreException: /// TODO exception handling - log(LogLevel::Error, "ErrorClass::CoreException"); - return tl::unexpected{PamAction::decline}; /// TODO accept? - case CoreHandlerError::ErrorClass::ConnectionError: - log(LogLevel::Error, "ErrorClass::ConnectionError"); - return tl::unexpected{PamAction::decline}; /// TODO decline? - case CoreHandlerError::ErrorClass::BrokenData: - log(LogLevel::Error, "ErrorClass::BrokenData"); - return tl::unexpected{PamAction::decline}; - } + return tl::unexpected{this->coreErrorHandler(coreResponse)}; } return tl::unexpected{PamAction::decline}; diff --git a/PAM/ssh/include/rublon/method/OTP.hpp b/PAM/ssh/include/rublon/method/OTP.hpp index aa76811..eb31f10 100644 --- a/PAM/ssh/include/rublon/method/OTP.hpp +++ b/PAM/ssh/include/rublon/method/OTP.hpp @@ -13,16 +13,17 @@ class Confirmation {}; namespace rublon::method { template < typename PamInfo_t = LinuxPam > -class OTP : public rublon::AuthenticationStep< OTP< PamInfo_t > > { - public: +class OTP : public AuthenticationStep< OTP< PamInfo_t > > { + using base_t = AuthenticationStep< OTP< PamInfo_t > >; const char * uri = "/api/transaction/confirmCode"; - const char * name = "One Time Password"; - - std::string _systemToken; - std::string _tid; + + protected: const PamInfo_t & _pamInfo; - - OTP(std::string systemToken, std::string tid, const PamInfo_t & pam) : _systemToken{systemToken}, _tid{tid}, _pamInfo{pam} {} + + public: + const char * name = "One Time Password"; + + OTP(std::string systemToken, std::string tid, const PamInfo_t & pam) : base_t(std::move(systemToken), std::move(tid)), _pamInfo{pam} {} template < typename Hander_t > tl::expected< Confirmation, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const { @@ -37,8 +38,8 @@ class OTP : public rublon::AuthenticationStep< OTP< PamInfo_t > > { RapidJSONPMRAlloc alloc{&mr}; Document body{rapidjson::kObjectType, &alloc}; - body.AddMember("systemToken", Value{_systemToken.c_str(), alloc}, alloc); - body.AddMember("tid", Value{_tid.c_str(), alloc}, alloc); + body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc); + body.AddMember("tid", Value{this->_tid.c_str(), alloc}, alloc); body.AddMember("vericode", Value{passcode.value().c_str(), alloc}, alloc); /// TODO proper username auto coreResponse = coreHandler.request(uri, body); @@ -49,21 +50,7 @@ class OTP : public rublon::AuthenticationStep< OTP< PamInfo_t > > { std::string tid = rublonResponse["tid"].GetString(); return tl::unexpected{PamAction::accept}; } else { - // mostly connectio errors - switch(coreResponse.error().errorClass) { - case CoreHandlerError::ErrorClass::BadSigature: - log(LogLevel::Error, "ErrorClass::BadSigature"); - return tl::unexpected{PamAction::decline}; - case CoreHandlerError::ErrorClass::CoreException: /// TODO exception handling - log(LogLevel::Error, "ErrorClass::CoreException"); - return tl::unexpected{PamAction::decline}; /// TODO accept? - case CoreHandlerError::ErrorClass::ConnectionError: - log(LogLevel::Error, "ErrorClass::ConnectionError"); - return tl::unexpected{PamAction::decline}; /// TODO decline? - case CoreHandlerError::ErrorClass::BrokenData: - log(LogLevel::Error, "ErrorClass::BrokenData"); - return tl::unexpected{PamAction::decline}; - } + return tl::unexpected{this->coreErrorHandler(coreResponse)}; } return tl::unexpected{PamAction::accept}; diff --git a/PAM/ssh/include/rublon/method/method_factory.hpp b/PAM/ssh/include/rublon/method/method_factory.hpp index 810b21f..b061587 100644 --- a/PAM/ssh/include/rublon/method/method_factory.hpp +++ b/PAM/ssh/include/rublon/method/method_factory.hpp @@ -77,26 +77,26 @@ class Method : AuthenticationStep< Method< Pam_t > > { template < typename Pam_t = LinuxPam > class PostMethod : public rublon::AuthenticationStep< PostMethod< Pam_t > > { - public: + using base_t = rublon::AuthenticationStep< PostMethod< Pam_t > >; + const char * uri = "/api/transaction/methodSSH"; - const char * name = "Confirm Method"; - - std::string _systemToken; - std::string _tid; std::string _method; - - PostMethod(std::string systemToken, std::string tid, std::string method) : _systemToken{systemToken}, _tid{tid}, _method{method} {} + + public: + const char * name = "Confirm Method"; + + PostMethod(std::string systemToken, std::string tid, std::string method) + : base_t(std::move(systemToken), std::move(tid)), _method{method} {} template < typename Hander_t > tl::expected< Method<>, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const { char _buffer[1024]; std::pmr::monotonic_buffer_resource mr{_buffer, 1024}; - RapidJSONPMRAlloc alloc{&mr}; Document body{rapidjson::kObjectType, &alloc}; - - body.AddMember("systemToken", Value{_systemToken.c_str(), alloc}, alloc); - body.AddMember("tid", Value{_tid.c_str(), alloc}, alloc); + + body.AddMember("systemToken", Value{this->_systemToken.c_str(), alloc}, alloc); + body.AddMember("tid", Value{this->_tid.c_str(), alloc}, alloc); body.AddMember("method", Value{_method.c_str(), alloc}, alloc); body.AddMember("GDPRAccepted", Value{"true", alloc}, alloc); body.AddMember("tosAccepted", Value{"true", alloc}, alloc); @@ -109,21 +109,7 @@ class PostMethod : public rublon::AuthenticationStep< PostMethod< Pam_t > > { std::string tid = rublonResponse["tid"].GetString(); return tl::unexpected{PamAction::accept}; } else { - // mostly connectio errors - switch(coreResponse.error().errorClass) { - case CoreHandlerError::ErrorClass::BadSigature: - log(LogLevel::Error, "ErrorClass::BadSigature"); - return tl::unexpected{PamAction::decline}; - case CoreHandlerError::ErrorClass::CoreException: /// TODO exception handling - log(LogLevel::Error, "ErrorClass::CoreException"); - return tl::unexpected{PamAction::decline}; /// TODO accept? - case CoreHandlerError::ErrorClass::ConnectionError: - log(LogLevel::Error, "ErrorClass::ConnectionError"); - return tl::unexpected{PamAction::decline}; /// TODO decline? - case CoreHandlerError::ErrorClass::BrokenData: - log(LogLevel::Error, "ErrorClass::BrokenData"); - return tl::unexpected{PamAction::decline}; - } + return tl::unexpected{this->coreErrorHandler(coreResponse)}; } return tl::unexpected{PamAction::accept}; diff --git a/PAM/ssh/tests/init_test.cpp b/PAM/ssh/tests/init_test.cpp index 8685348..a4b7cca 100644 --- a/PAM/ssh/tests/init_test.cpp +++ b/PAM/ssh/tests/init_test.cpp @@ -56,7 +56,6 @@ class CoreHandlerMock : public CoreHandlerInterface< CoreHandlerMock > { class PamInfoMock { public: - PamInfoMock(pam_handle_t *) {} MOCK_METHOD(rublon::NonOwningPtr< const char >, ip, (), (const)); MOCK_METHOD(rublon::NonOwningPtr< const char >, username, (), (const)); }; @@ -73,9 +72,9 @@ class MethodFactoryMock { class InitTestable : public Init< MethodFactoryMock, PamInfoMock > { public: - InitTestable(const rublon::Configuration & conf) : Init{nullptr, conf} {} + InitTestable(PamInfoMock&pam, const rublon::Configuration & conf) : Init{pam, conf} {} PamInfoMock & pam() { - return const_cast(_pamInfo); + return _pamInfo; } }; @@ -86,13 +85,13 @@ class RublonHttpInitTest : public testing::Test { EXPECT_CALL(pam, username()).WillOnce(Return("bwi")); } - RublonHttpInitTest() : coreHandler{}, sut{conf}, pam{sut.pam()}{ + RublonHttpInitTest() : coreHandler{}, pam{}, sut{pam, conf}{ expectDefaultPamInfo(); } CoreHandlerMock coreHandler; - InitTestable sut{conf}; - PamInfoMock & pam; + PamInfoMock pam; + InitTestable sut; // MethodFactoryMock &methodFactoryMock; };