From 6f3da4edb6a4a1134be5d27a11d128474793f8f2 Mon Sep 17 00:00:00 2001 From: Bartosz Wieczorek Date: Fri, 13 Jun 2025 12:51:58 +0200 Subject: [PATCH] remove codeconv usage --- PAM/ssh/include/rublon/check_application.hpp | 2 +- PAM/ssh/include/rublon/configuration.hpp | 38 ++++++---- PAM/ssh/include/rublon/utils.hpp | 76 ++++++++++++-------- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/PAM/ssh/include/rublon/check_application.hpp b/PAM/ssh/include/rublon/check_application.hpp index 62e4156..63560c7 100644 --- a/PAM/ssh/include/rublon/check_application.hpp +++ b/PAM/ssh/include/rublon/check_application.hpp @@ -182,7 +182,7 @@ class CheckApplication { status.updateAppVersion(RUBLON_VERSION_STRING); status.updateSystemVersion(details::osName(&mr)); status.updateSSHDConfig(); - status.updateRublonConfig(); + // status.updateRublonConfig(); if(status.updated()) { auto & alloc = status.data().GetAllocator(); diff --git a/PAM/ssh/include/rublon/configuration.hpp b/PAM/ssh/include/rublon/configuration.hpp index 4622b9d..7d8ec7c 100644 --- a/PAM/ssh/include/rublon/configuration.hpp +++ b/PAM/ssh/include/rublon/configuration.hpp @@ -33,7 +33,7 @@ class Configuration { std::pmr::string apiServer{memoryResource}; int prompt{}; - bool enablePasswdEmail{}; + bool enablePasswdEmail{}; // obsolete bool logging{}; bool autopushPrompt{}; FailMode failMode{}; @@ -86,6 +86,8 @@ class ConfigurationReader { tl::expected< bool, ConfigurationError > applyTo(Configuration & config) const { using string = std::pmr::string; + auto logRequiredFieldNotAvailable = [](auto fieldname) { log(LogLevel::Error, "%s field is not set", fieldname); }; + // Helper lambdas for conversion auto getStringOpt = [&](const string & key) -> std::optional< std::pmr::string > { auto it = keyValues.find(key); @@ -215,20 +217,26 @@ class ConfigurationReader { // * configuration value is empty -> RequiredValueEmpty // Reading required fields - if(auto val = getStringReq("systemToken"); not val.has_value()) + if(auto val = getStringReq("systemToken"); not val.has_value()) { + logRequiredFieldNotAvailable("systemToken"); return tl::unexpected{val.error()}; - else + } else { config.systemToken = std::move(val.value()); + } - if(auto val = getStringReq("secretKey"); not val.has_value()) + if(auto val = getStringReq("secretKey"); not val.has_value()) { + logRequiredFieldNotAvailable("secretKey"); return tl::unexpected{val.error()}; - else + } else { config.secretKey = std::move(val.value()); + } - if(auto val = getStringReq("rublonApiServer"); not val.has_value()) + if(auto val = getStringReq("rublonApiServer"); not val.has_value()) { + logRequiredFieldNotAvailable("rublonApiServer"); return tl::unexpected{val.error()}; - else + } else { config.apiServer = std::move(val.value()); + } // optional configuration options config.prompt = getInt("prompt").value_or(1); @@ -242,22 +250,22 @@ class ConfigurationReader { config.proxyEnabled = getBool("proxyEnabled").value_or(false); config.proxyType = getStringOpt("proxyType"); config.proxyServer = getStringOpt("proxyServer"); - - + // Apply fallback if no config is set - if (config.proxyEnabled && (!config.proxyType || config.proxyType->empty()) && (!config.proxyServer || config.proxyServer->empty())) { + if(config.proxyEnabled && (!config.proxyType || config.proxyType->empty()) && + (!config.proxyServer || config.proxyServer->empty())) { log(LogLevel::Info, "Proxy is enabled but no configuration for it is provided, trying to read from env"); - if (const char* https_proxy = std::getenv("https_proxy"); https_proxy && *https_proxy) { - if (parseProxyURL(https_proxy)) { + if(const char * https_proxy = std::getenv("https_proxy"); https_proxy && *https_proxy) { + if(parseProxyURL(https_proxy)) { log(LogLevel::Info, "Loaded proxy config from HTTPS_PROXY"); } - } else if (const char* http_proxy = std::getenv("http_proxy"); http_proxy && *http_proxy) { - if (parseProxyURL(http_proxy)) { + } else if(const char * http_proxy = std::getenv("http_proxy"); http_proxy && *http_proxy) { + if(parseProxyURL(http_proxy)) { log(LogLevel::Info, "Loaded proxy config from HTTP_PROXY"); } } } - + if(config.proxyEnabled) { if(not config.proxyType or config.proxyType->empty()) { log(LogLevel::Error, "Proxy is enabled but proxy type is not present or empty"); diff --git a/PAM/ssh/include/rublon/utils.hpp b/PAM/ssh/include/rublon/utils.hpp index 1f36b46..54dce12 100755 --- a/PAM/ssh/include/rublon/utils.hpp +++ b/PAM/ssh/include/rublon/utils.hpp @@ -1,17 +1,20 @@ #pragma once -#include +#include +#include +#include #include +#include +#include + #include #include #include #include -#include #include #include #include -#include #include #include @@ -150,23 +153,33 @@ namespace conv { std::transform(userinput.cbegin(), userinput.cend(), buf.data(), asciitolower); return strcmp(buf.data(), "true") == 0; } - - inline std::optional< std::uint32_t> to_uint32opt(std::string_view userinput) noexcept { - int out; - const std::from_chars_result result = std::from_chars(userinput.data(), userinput.data() + userinput.size(), out); - if(result.ec == std::errc::invalid_argument || result.ec == std::errc::result_out_of_range) { + + inline std::optional< std::uint32_t > to_uint32opt(std::string_view userinput) noexcept { + constexpr auto max = std::numeric_limits< uint32_t >::digits10 + 1; + if(userinput.empty() || userinput.size() >= max) + return std::nullopt; // Avoid large or empty inputs + + char buffer[max]={0}; + std::memcpy(buffer, userinput.data(), userinput.size()); + buffer[userinput.size()] = '\0'; // Ensure null termination + + char * endptr = nullptr; + errno = 0; + + long result = std::strtol(buffer, &endptr, 10); + + if(errno == ERANGE || endptr != buffer + userinput.size() || result < 0 || result > std::numeric_limits::max()) { return std::nullopt; } - return out; + + return static_cast< std::uint32_t >(result); } - + inline tl::expected< std::uint32_t, Error > to_uint32(std::string_view userinput) noexcept { - int out; - const std::from_chars_result result = std::from_chars(userinput.data(), userinput.data() + userinput.size(), out); - if(result.ec == std::errc::invalid_argument || result.ec == std::errc::result_out_of_range) { - return tl::make_unexpected(Error::NotANumber); - } - return out; + auto val = to_uint32opt(userinput); + if(val) + return *val; + return tl::unexpected{Error::NotANumber}; } } // namespace conv @@ -186,33 +199,33 @@ namespace details { static inline std::string_view trim(std::string_view s) { return ltrim(rtrim(s)); } - - template + + template < typename StrT > void trimInPlace(StrT & s) { // Remove leading whitespace size_t start = 0; while(start < s.size() && isspace(static_cast< unsigned char >(s[start]))) ++start; - - // Remove trailing whitespace + + // Remove trailing whitespace size_t end = s.size(); while(end > start && isspace(static_cast< unsigned char >(s[end - 1]))) --end; - + if(start > 0 || end < s.size()) { s = s.substr(start, end - start); } } - + template < typename Headers > inline void headers(std::string_view data, Headers & headers) { memory::Monotonic_4k_Resource stackResource; std::pmr::string tmp{&stackResource}; tmp.reserve(300); - + std::istringstream resp{}; resp.rdbuf()->pubsetbuf(const_cast< char * >(data.data()), data.size()); - + while(std::getline(resp, tmp)) { if(tmp == "\r") continue; @@ -250,9 +263,8 @@ namespace details { std::pmr::string _key{&memoryResource}; std::pmr::string _value{&memoryResource}; line.reserve(100); - - while(std::getline(file, line)) { + while(std::getline(file, line)) { if(!line.length()) continue; @@ -299,19 +311,21 @@ constexpr std::array< Out, sizeof...(Types) > make_array(Types... names) { return {std::forward< Types >(names)...}; } -template std::size_t size_buffer(const T &item) { - using U = std::decay_t; - if constexpr (std::is_same_v) { +template < typename T > +std::size_t size_buffer(const T & item) { + using U = std::decay_t< T >; + if constexpr(std::is_same_v< U, const char * >) { return strlen(item); } else if constexpr(std::is_same_v< U, std::pmr::string > || std::is_same_v< U, std::string >) { return item.size(); } else if constexpr(std::is_integral_v< U > || std::is_floating_point_v< U >) { - return std::numeric_limits::digits; + return std::numeric_limits< U >::digits; } return 0; } -template std::size_t size_buffer(const std::optional &item) { +template < typename T > +std::size_t size_buffer(const std::optional< T > & item) { if(item.has_value()) return size_buffer(*item); return 0;