Bwi/v2.3.1 (#18)

* Fix handling of fail mode

* Fix handling proxy configuration

* Minor changes to logging

* Fix compiler warnings
This commit is contained in:
rublon-bwi 2025-07-28 14:51:35 +02:00 committed by GitHub
parent 0934902bba
commit de26451445
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 40 additions and 46 deletions

View File

@ -7,7 +7,7 @@ include(GNUInstallDirs)
set(PROJECT_VERSION_MAJOR 2) set(PROJECT_VERSION_MAJOR 2)
set(PROJECT_VERSION_MINOR 3) set(PROJECT_VERSION_MINOR 3)
set(PROJECT_VERSION_PATCH 0) set(PROJECT_VERSION_PATCH 1)
set(RUBLON_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") set(RUBLON_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <algorithm>
#include <rublon/error.hpp> #include <rublon/error.hpp>
#include <rublon/memory.hpp> #include <rublon/memory.hpp>
#include <rublon/static_string.hpp> #include <rublon/static_string.hpp>
@ -69,6 +70,9 @@ class ConfigurationReader {
auto posEqual = line.find('='); auto posEqual = line.find('=');
std::pmr::string key{line.substr(0, posEqual), &memoryResource}; std::pmr::string key{line.substr(0, posEqual), &memoryResource};
std::pmr::string value{line.substr(posEqual + 1), &memoryResource}; std::pmr::string value{line.substr(posEqual + 1), &memoryResource};
details::trimInPlace(key);
details::trimInPlace(value);
keyValues[std::move(key)] = std::move(value); keyValues[std::move(key)] = std::move(value);
} }
@ -86,6 +90,7 @@ class ConfigurationReader {
if(it == keyValues.end()) { if(it == keyValues.end()) {
return std::nullopt; return std::nullopt;
} }
return string{it->second.data(), it->second.size(), memoryResource}; return string{it->second.data(), it->second.size(), memoryResource};
}; };
@ -120,7 +125,7 @@ class ConfigurationReader {
std::pmr::string val{&memoryResource}; std::pmr::string val{&memoryResource};
val = it->second; val = it->second;
std::transform(val.begin(), val.end(), val.begin(), [](unsigned char c) { return static_cast< char >(std::tolower(c)); }); std::transform(val.begin(), val.end(), val.begin(), [](auto c) { return std::tolower(c); });
if(val == "1" || val == "true" || val == "yes" || val == "on") if(val == "1" || val == "true" || val == "yes" || val == "on")
return true; return true;
@ -134,6 +139,7 @@ class ConfigurationReader {
if(it == keyValues.end()) if(it == keyValues.end())
return std::nullopt; return std::nullopt;
auto val = it->second; auto val = it->second;
std::transform(val.begin(), val.end(), val.begin(), [](auto c) { return std::tolower(c); });
if(val == "bypass") if(val == "bypass")
return FailMode::bypass; return FailMode::bypass;
if(val == "deny") if(val == "deny")
@ -198,6 +204,11 @@ class ConfigurationReader {
return true; return true;
}; };
auto toLowerCaseOpt = [](auto & str) {
if(str)
std::transform(str->cbegin(), str->cend(), str->begin(), [](auto c) { return std::tolower(c); });
};
/// NOTE: /// NOTE:
// getStringOpt can return a valid empty string, for example configuration entry like // getStringOpt can return a valid empty string, for example configuration entry like
// option= // option=
@ -281,15 +292,12 @@ class ConfigurationReader {
} }
} }
auto defaultProxyPort = [&]() -> int { toLowerCaseOpt(config.proxyType);
memory::MonotonicStackResource< 32 > memoryResource; toLowerCaseOpt(config.proxyHost);
if(config.proxyType) { auto defaultProxyPort = [&]() -> int {
std::pmr::string val{*config.proxyType, &memoryResource}; if(config.proxyType.value_or("").find("socks") != std::pmr::string::npos) {
std::transform(val.begin(), val.end(), val.begin(), [](auto c) { return std::tolower(c); }); return 1080;
if(val.find("socks") != std::pmr::string::npos) {
return 1080;
}
} }
return 8080; return 8080;
}; };

View File

@ -44,7 +44,7 @@ class ErrorHandler {
} }
if(error.is< ConnectionError >()) { if(error.is< ConnectionError >()) {
if(config.failMode == FailMode::deny) { if(config.failMode == FailMode::bypass) {
pam.print("Incorrect response from the Rublon API, user bypassed"); pam.print("Incorrect response from the Rublon API, user bypassed");
return AuthenticationStatus::Action::Bypass; return AuthenticationStatus::Action::Bypass;
} else { } else {

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstddef>
#include <rublon/memory.hpp> #include <rublon/memory.hpp>
#include <rublon/static_string.hpp> #include <rublon/static_string.hpp>
#include <rublon/stdlib.hpp> #include <rublon/stdlib.hpp>
@ -7,8 +8,9 @@
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <string> #include <string>
#include <utility> #include <string_view>
#include <tl/expected.hpp> #include <tl/expected.hpp>
#include <utility>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -84,12 +86,18 @@ namespace details {
return logPath(); return logPath();
} }
inline void doLog(LogLevel level, const char * line) noexcept { inline void doLog(LogLevel level, std::string_view line) noexcept {
auto fp = std::unique_ptr< FILE, int (*)(FILE *) >(fopen(initLog(), "a+"), fclose); auto fp = std::unique_ptr< FILE, int (*)(FILE *) >(fopen(initLog(), "a+"), fclose);
if(fp) { if(fp) {
auto newl = line.back() == '\n' ? "" : "\n";
/// TODO add transaction ID /// TODO add transaction ID
fprintf( fprintf(fp.get(),
fp.get(), "%s %s[%s] %s\n", dateStr().c_str(), application == nullptr ? "" : application, LogLevelNames[( int ) level], line); "%s %s[%s] %s%s",
dateStr().c_str(),
application == nullptr ? "" : application,
LogLevelNames[( int ) level],
line.data(),
newl);
if(syncLogFile) if(syncLogFile)
sync(); sync();
} }
@ -111,33 +119,11 @@ void log(LogLevel level, const char * fmt, Ti &&... ti) noexcept {
return; return;
constexpr auto maxEntryLength = 1000; constexpr auto maxEntryLength = 1000;
std::array< char, maxEntryLength > line; std::array< char, maxEntryLength > line;
snprintf(line.data(), maxEntryLength, fmt, std::forward< Ti >(ti)...); auto len = snprintf(line.data(), maxEntryLength, fmt, std::forward< Ti >(ti)...);
details::doLog(level, line.data()); if(len>0)
details::doLog(level, {line.data(), static_cast< std::size_t >(len)});
} }
class PrintUser {
public:
template < typename Printer >
PrintUser(Printer & p) : _impl{std::make_unique< ModelImpl >(p)} {}
private:
struct model {
virtual ~model();
virtual void print(std::string_view line) const = 0;
};
template < typename Printer_T >
struct ModelImpl : public model {
ModelImpl(Printer_T & printer) : _printer{printer} {}
void print(std::string_view line) const override {
_printer.print(line);
}
Printer_T & _printer;
};
std::unique_ptr< model > _impl;
};
namespace conv { namespace conv {
enum class Error { OutOfRange, NotANumber }; enum class Error { OutOfRange, NotANumber };
@ -157,8 +143,8 @@ namespace conv {
constexpr auto max = std::numeric_limits< uint32_t >::digits10 + 1; constexpr auto max = std::numeric_limits< uint32_t >::digits10 + 1;
if(userinput.empty() || userinput.size() >= max) if(userinput.empty() || userinput.size() >= max)
return std::nullopt; // Avoid large or empty inputs return std::nullopt; // Avoid large or empty inputs
char buffer[max]={0}; char buffer[max] = {0};
std::memcpy(buffer, userinput.data(), userinput.size()); std::memcpy(buffer, userinput.data(), userinput.size());
buffer[userinput.size()] = '\0'; // Ensure null termination buffer[userinput.size()] = '\0'; // Ensure null termination
@ -167,7 +153,7 @@ namespace conv {
long result = std::strtol(buffer, &endptr, 10); long result = std::strtol(buffer, &endptr, 10);
if(errno == ERANGE || endptr != buffer + userinput.size() || result < 0 || result > std::numeric_limits<uint32_t>::max()) { if(errno == ERANGE || endptr != buffer + userinput.size() || result < 0 || result > std::numeric_limits< uint32_t >::max()) {
return std::nullopt; return std::nullopt;
} }
@ -203,12 +189,12 @@ namespace details {
void trimInPlace(StrT & s) { void trimInPlace(StrT & s) {
// Remove leading whitespace // Remove leading whitespace
size_t start = 0; size_t start = 0;
while(start < s.size() && isspace(static_cast< unsigned char >(s[start]))) while(start < s.size() && isspace(s[start]))
++start; ++start;
// Remove trailing whitespace // Remove trailing whitespace
size_t end = s.size(); size_t end = s.size();
while(end > start && isspace(static_cast< unsigned char >(s[end - 1]))) while(end > start && isspace(s[end - 1]))
--end; --end;
if(start > 0 || end < s.size()) { if(start > 0 || end < s.size()) {

View File

@ -64,7 +64,7 @@ class WebSocket {
}; };
if(_config.get().logging) { if(_config.get().logging) {
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG | LLL_HEADER, lws_log_emit); lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG, lws_log_emit);
} else { } else {
lws_set_log_level(LLL_ERR | LLL_WARN, lws_log_emit); lws_set_log_level(LLL_ERR | LLL_WARN, lws_log_emit);
} }