From 3cb8567f4248ce466b4d786e4936fa050182608a Mon Sep 17 00:00:00 2001 From: Bartosz Wieczorek Date: Fri, 21 Jul 2023 13:23:27 +0200 Subject: [PATCH] Provide better LOG function, refactor cmake --- PAM/ssh/CMakeLists.txt | 2 +- PAM/ssh/include/rublon/CoreHandler.hpp | 40 +++++++------- PAM/ssh/include/rublon/curl.hpp | 35 ++++++------- .../include/rublon/method/method_factory.hpp | 1 - PAM/ssh/include/rublon/pam.hpp | 16 +++--- PAM/ssh/include/rublon/rublon.hpp | 4 +- PAM/ssh/include/rublon/utils.hpp | 52 +++++++++++++++---- PAM/ssh/lib/CMakeLists.txt | 21 +++++++- PAM/ssh/lib/pam.cpp | 17 ++---- 9 files changed, 110 insertions(+), 78 deletions(-) diff --git a/PAM/ssh/CMakeLists.txt b/PAM/ssh/CMakeLists.txt index b18a4cc..4c4578a 100644 --- a/PAM/ssh/CMakeLists.txt +++ b/PAM/ssh/CMakeLists.txt @@ -8,11 +8,11 @@ add_library(rublon-ssh include/rublon/curl.hpp include/rublon/span.hpp include/rublon/sign.hpp + include/rublon/utils.hpp include/rublon/CoreHandler.hpp include/rublon/configuration.hpp ) -#set(CMAKE_SHARED_LINKER_FLAGS "-fpic -static-libstdc++ -fvisibility=hidden -ffunction-sections -fdata-sections -fwhole-program") target_include_directories(rublon-ssh PUBLIC INTERFACE diff --git a/PAM/ssh/include/rublon/CoreHandler.hpp b/PAM/ssh/include/rublon/CoreHandler.hpp index 7c99bf7..071ba77 100644 --- a/PAM/ssh/include/rublon/CoreHandler.hpp +++ b/PAM/ssh/include/rublon/CoreHandler.hpp @@ -27,7 +27,7 @@ template < typename Impl > class CoreHandlerInterface { public: tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const { - rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__); + rublon::log(LogLevel::Debug, "%s", __PRETTY_FUNCTION__); return static_cast< const Impl * >(this)->request(path, body); } }; @@ -42,12 +42,10 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { } void signRequest(std::pmr::monotonic_buffer_resource & mr, Request & request) const { - rublon::debugLog("[TMP]",__PRETTY_FUNCTION__); request.headers["X-Rublon-Signature"] = xRublonSignature(mr, request.body); } bool responseSigned(const Response & response) const { - rublon::debugLog("[TMP]",__PRETTY_FUNCTION__); const auto & xRubResp = response.headers.at("x-rublon-signature"); const auto & sign = signData(response.body, secretKey); return xRubResp == sign.data(); @@ -62,7 +60,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { CoreHandler(const rublon::Configuration & config) : secretKey{config.parameters.secretKey}, url{config.parameters.apiServer} {} tl::expected< rublon::Document, CoreHandlerError > request(std::string_view path, const rublon::Document & body) const { - rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__); + rublon::log(LogLevel::Info, "Sending request to %s", path.data()); std::byte _buffer[16 * 1024]; std::pmr::monotonic_buffer_resource mr{_buffer, sizeof(_buffer)}; @@ -79,32 +77,30 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { request.body = jsonStr.GetString(); - rublon::debugLog("[TMP] request", "sign"); signRequest(mr, request); -// std::pmr::string uri{url + path.data(), &mr}; + std::pmr::string uri{url + path.data(), &mr}; -// rublon::debugLog("[TMP] send", request.body.c_str()); -// auto response = http.request(uri, request); + auto response = http.request(uri, request); -// if(not response.has_value()) { + if(not response.has_value()) { return tl::unexpected{CoreHandlerError::ConnectionError}; -// } -// if(not responseSigned(*response)) { -// return tl::unexpected{CoreHandlerError::BadSigature}; -// } + } + if(not responseSigned(*response)) { + return tl::unexpected{CoreHandlerError::BadSigature}; + } -// rublon::Document resp{&alloc}; -// resp.Parse(response->body.c_str()); + rublon::Document resp{&alloc}; + resp.Parse(response->body.c_str()); -// if(resp.HasParseError() or not resp.HasMember("result")) { -// return tl::unexpected{CoreHandlerError::BrokenData}; -// } -// if(resp["result"].HasMember("exception")) { -// return tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException, resp["result"]["exception"].GetString()}}; -// } + if(resp.HasParseError() or not resp.HasMember("result")) { + return tl::unexpected{CoreHandlerError::BrokenData}; + } + if(resp["result"].HasMember("exception")) { + return tl::unexpected{CoreHandlerError{CoreHandlerError::CoreException, resp["result"]["exception"].GetString()}}; + } -// return resp; + return resp; } }; diff --git a/PAM/ssh/include/rublon/curl.hpp b/PAM/ssh/include/rublon/curl.hpp index 83fafae..a0f25d0 100644 --- a/PAM/ssh/include/rublon/curl.hpp +++ b/PAM/ssh/include/rublon/curl.hpp @@ -15,41 +15,37 @@ namespace rublon { static size_t WriteMemoryCallback(void * contents, size_t size, size_t nmemb, void * userp) { - size_t realsize = size * nmemb; + size_t realsize = size * nmemb; reinterpret_cast< std::string * >(userp)->append(static_cast< const char * >(contents), realsize); return realsize; } -struct Request{ - std::map headers; +struct Request { + std::map< std::string, std::string > headers; std::string body; }; -struct Response{ - std::map headers; +struct Response { + std::map< std::string, std::string > headers; std::string body; }; - class CURL { std::unique_ptr< ::CURL, void (*)(::CURL *) > curl; public: CURL() : curl{std::unique_ptr< ::CURL, void (*)(::CURL *) >(curl_easy_init(), curl_easy_cleanup)} {} - std::optional< Response > request(std::string_view uri, const Request &request) const { - rublon::debugLog("[TMP] request",__PRETTY_FUNCTION__); - + std::optional< Response > request(std::string_view uri, const Request & request) const { std::string response_data; response_data.reserve(1000); - - + Response response; /// TODO this can be done on stack using pmr auto curl_headers = std::unique_ptr< curl_slist, void (*)(curl_slist *) >(nullptr, curl_slist_free_all); std::for_each(request.headers.begin(), request.headers.end(), [&](auto header) { - curl_headers.reset(curl_slist_append(curl_headers.release(),(header.first + ": " + header.second).c_str())); + curl_headers.reset(curl_slist_append(curl_headers.release(), (header.first + ": " + header.second).c_str())); }); curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1); @@ -61,21 +57,20 @@ class CURL { curl_easy_setopt(curl.get(), CURLOPT_HEADER, 1); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_data); - - rublon::debugLog("[TMP] calling curl",__PRETTY_FUNCTION__); - + + rublon::log(LogLevel::Debug, "Request send uri:{%s} body:{%s}", uri.data(), request.body.c_str()); auto res = curl_easy_perform(curl.get()); if(res != CURLE_OK) { // debugLog("No response from Rublon server (perform)", ""); return std::nullopt; } - + long size; curl_easy_getinfo(curl.get(), CURLINFO_HEADER_SIZE, &size); - - ///TODO ogarnąć alokację pamięci - response.headers = details::headers({response_data.data(), static_cast(size)}); - response.body = response_data.substr(size); + + /// TODO ogarnąć alokację pamięci + response.headers = details::headers({response_data.data(), static_cast< std::size_t >(size)}); + response.body = response_data.substr(size); return response; } diff --git a/PAM/ssh/include/rublon/method/method_factory.hpp b/PAM/ssh/include/rublon/method/method_factory.hpp index 2e90e1c..63fdcc8 100644 --- a/PAM/ssh/include/rublon/method/method_factory.hpp +++ b/PAM/ssh/include/rublon/method/method_factory.hpp @@ -35,7 +35,6 @@ class MethodFactory { template < typename Array_t > tl::expected< Method, PamAction > create(const Array_t & methods) const { - rublon::debugLog("[TMP] ",__PRETTY_FUNCTION__); std::pmr::map< int, std::pmr::string > methods_id; pam.print("%s", ""); int i; diff --git a/PAM/ssh/include/rublon/pam.hpp b/PAM/ssh/include/rublon/pam.hpp index 014f663..9bb3394 100644 --- a/PAM/ssh/include/rublon/pam.hpp +++ b/PAM/ssh/include/rublon/pam.hpp @@ -23,22 +23,24 @@ class LinuxPam { public: LinuxPam(pam_handle_t * handler) : pamh{handler} {} - + rublon::NonOwningPtr< const char > ip() const { const void * ip = NULL; pam_get_item(pamh, PAM_RHOST, &ip); - if(ip == NULL) + if(ip == NULL) { + rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM"); ip = ""; - rublon::debugLog(__PRETTY_FUNCTION__, (const char*)ip); - return (const char*)ip; + } + return ( const char * ) ip; } rublon::NonOwningPtr< const char > username() const { const char * user = NULL; pam_get_user(pamh, &user, nullptr); - if(user == NULL) + if(user == NULL) { + rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM"); user = ""; - rublon::debugLog(__PRETTY_FUNCTION__, user); + } return user; } @@ -50,7 +52,7 @@ class LinuxPam { template < typename Fun, typename... Ti > [[nodiscard]] auto scan(Fun && f, const char * fmt, Ti... ti) const noexcept { char * responseBuffer = nullptr; - pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &responseBuffer, fmt, std::forward< Ti... >(ti...)); + pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &responseBuffer, fmt, std::forward< Ti... >(ti...)); if(responseBuffer) { auto ret = f(responseBuffer); free(responseBuffer); diff --git a/PAM/ssh/include/rublon/rublon.hpp b/PAM/ssh/include/rublon/rublon.hpp index 0b7aec4..b4111a2 100644 --- a/PAM/ssh/include/rublon/rublon.hpp +++ b/PAM/ssh/include/rublon/rublon.hpp @@ -62,13 +62,11 @@ class Init : public AuthenticationStep< Init< MethodFactory_t, PamInfo_t > > { Init(pam_handle_t * pamHandler, const rublon::Configuration & config) : _systemToken{config.parameters.systemToken}, _pamInfo{pamHandler}, _methodFactory{_pamInfo} { - rublon::debugLog("[TMP] Init ctor",__PRETTY_FUNCTION__); } /// TODO add core handler interface template < typename Hander_t > tl::expected< Method, PamAction > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const { - rublon::debugLog("[TMP] init handle",__PRETTY_FUNCTION__); char _buffer[1024]; std::pmr::monotonic_buffer_resource mr{_buffer, 1024}; @@ -85,7 +83,7 @@ class Init : public AuthenticationStep< Init< MethodFactory_t, PamInfo_t > > { params.AddMember("os", "Ubuntu 23.04", alloc); /// TODO add version to cmake body.AddMember("params", std::move(params), alloc); - rublon::debugLog("[TMP] calling coreHandler",__PRETTY_FUNCTION__); + auto httpResponse = coreHandler.request(apiPath, body); // if(httpResponse.has_value()) { diff --git a/PAM/ssh/include/rublon/utils.hpp b/PAM/ssh/include/rublon/utils.hpp index be76817..f51b00a 100644 --- a/PAM/ssh/include/rublon/utils.hpp +++ b/PAM/ssh/include/rublon/utils.hpp @@ -1,9 +1,11 @@ #pragma once #include +#include #include #include #include +#include #include #include #include @@ -16,19 +18,49 @@ #include namespace rublon { +enum LogLevel { Debug, Info, Warning, Error }; -inline void debugLog(const char * message1, const char * message2) { - auto file_name = "/tmp/rublon.log"; - auto fp = fopen(file_name, "a"); - fprintf(fp, "[%s] %s %s\n", "cmake version", message1, message2); - fflush(fp); - fclose(fp); - -// openlog("pam_rublon", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); -// syslog(LOG_NOTICE, "[%s] %s %s", "cmake version", message1, message2); -// closelog(); +namespace { +inline auto dateStr() { + std::array< char, 32 > date; + time_t now; + time(&now); + strftime(date.data(), date.size(), "%FT%TZ", gmtime(&now)); + return date; } +const auto LogLevelNames = {"Debug", "Info", "Warning", "Error"}; + +template < typename... Ti > +void log(LogLevel level, const char * fmt, Ti &&... ti) noexcept { + constexpr auto file_name = "/var/log/rublon-ssh.log"; + + if(level < 0) + return; + + auto fp = std::unique_ptr< FILE, int (*)(FILE *) >(fopen(file_name, "a"), fclose); + + if(fp) { + std::array< char, 1000 > line; + + sprintf(line.data(), fmt, std::forward< Ti >(ti)...); + + fprintf(fp.get(), "[%s] %s %s\n", "rublon_ssh_pam", dateStr().data(), line.data()); + } +} +} +// inline void debugLog(const char * message1, const char * message2) { +// auto file_name = "/tmp/rublon.log"; +// auto fp = fopen(file_name, "a"); +// fprintf(fp, "[%s] %s %s\n", "cmake version", message1, message2); +// fflush(fp); +// fclose(fp); + +//// openlog("pam_rublon", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); +//// syslog(LOG_NOTICE, "[%s] %s %s", "cmake version", message1, message2); +//// closelog(); +//} + template < typename T > class NonOwningPtr { T * object; diff --git a/PAM/ssh/lib/CMakeLists.txt b/PAM/ssh/lib/CMakeLists.txt index 98ae930..88d8917 100644 --- a/PAM/ssh/lib/CMakeLists.txt +++ b/PAM/ssh/lib/CMakeLists.txt @@ -3,12 +3,29 @@ add_library(rublon-ssh-pam pam.cpp ) +target_compile_options(rublon-ssh-pam + PUBLIC + -fno-exceptions + -fno-rtti + -fvisibility=hidden + -ffunction-sections + -fdata-sections + -fno-unwind-tables + -fno-asynchronous-unwind-tables +) + target_link_options(rublon-ssh-pam PUBLIC - -fpic -shared + -fpic + -s +# -static-libstdc++ + -Wl,--gc-sections ) target_link_libraries(rublon-ssh-pam PUBLIC - -lcurl -lssl -lcrypto rublon-ssh + rublon-ssh + -lcurl + -lssl + -lcrypto ) diff --git a/PAM/ssh/lib/pam.cpp b/PAM/ssh/lib/pam.cpp index d3569ca..02b323b 100644 --- a/PAM/ssh/lib/pam.cpp +++ b/PAM/ssh/lib/pam.cpp @@ -9,6 +9,8 @@ #include #include +#define DLL_PUBLIC __attribute__ ((visibility ("default"))) + using namespace std; namespace { @@ -22,30 +24,21 @@ Expected< rublon::Confirm > confirm() {} } // namespace -PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char ** argv) { - rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__); - +DLL_PUBLIC int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char ** argv) { return PAM_SUCCESS; } -PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) { - rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__); - +DLL_PUBLIC int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) { return PAM_SUCCESS; } -PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv) { - rublon::debugLog("[TMP]start", __PRETTY_FUNCTION__); +DLL_PUBLIC int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv) { auto rublonConfig = rublon::ConfigurationFactory{}.systemConfig(); - - rublon::debugLog("[TMP]create core handler", ""); rublon::CoreHandler CH{rublonConfig.value()}; - rublon::debugLog("[TMP]start", ""); auto action = rublon::Init{pamh, rublonConfig.value()} .fire(CH) // .and_then([](const auto & method) -> Expected< int > { - rublon::debugLog("[TMP]start", "init lambda"); return tl::unexpected{rublon::PamAction::accept}; });