diff --git a/PAM/ssh/include/rublon/configuration.hpp b/PAM/ssh/include/rublon/configuration.hpp index 30f03be..92fd275 100644 --- a/PAM/ssh/include/rublon/configuration.hpp +++ b/PAM/ssh/include/rublon/configuration.hpp @@ -76,7 +76,7 @@ class ConfigurationReader { auto posEqual = line.find('='); key = line.substr(0, posEqual); value = line.substr(posEqual + 1); - + keyValues[std::move(key)] = std::move(value); } @@ -84,10 +84,10 @@ class ConfigurationReader { } // Load values into Configuration object, with defaults provided - tl::expected< bool, ConfigurationError > applyTo(Configuration & config) { - // Helper lambdas for conversion + tl::expected< bool, ConfigurationError > applyTo(Configuration & config) const { using string = std::pmr::string; + // Helper lambdas for conversion auto getStringOpt = [&](const string & key) -> std::optional< std::pmr::string > { auto it = keyValues.find(key); if(it == keyValues.end()) { @@ -98,8 +98,12 @@ class ConfigurationReader { auto getStringReq = [&](const string & key) -> tl::expected< std::pmr::string, ConfigurationError > { auto val = getStringOpt(key); - if(val.has_value()) + if(val.has_value()) { + if(val->empty()) { + return tl::unexpected{ConfigurationError::ErrorClass::RequiredValueEmpty}; + } return std::move(val.value()); + } return tl::unexpected{ConfigurationError::ErrorClass::RequiredValueNotFound}; }; @@ -145,6 +149,14 @@ class ConfigurationReader { return std::nullopt; }; + /// NOTE: + // getStringOpt can return a valid empty string, for example configuration entry like + // option= + // will return a optional val which contains empty string. + // getStringReq on the other hand, returns error in case when + // * configuration is not found -> RequiredValueNotFound + // * configuration value is empty -> RequiredValueEmpty + // Reading required fields if(auto val = getStringReq("systemToken"); not val.has_value()) return tl::unexpected{val.error()}; @@ -161,7 +173,7 @@ class ConfigurationReader { else config.apiServer = std::move(val.value()); - // optional + // optional configuration options config.prompt = getInt("prompt").value_or(1); config.enablePasswdEmail = getBool("enablePasswdEmail").value_or(true); config.logging = getBool("logging").value_or(true); @@ -174,12 +186,12 @@ class ConfigurationReader { config.proxyType = getStringOpt("proxyType"); config.proxyServer = getStringOpt("proxyServer"); if(config.proxyEnabled) { - if(not config.proxyType) { - log(LogLevel::Error, "Proxy is enabled but proxy type is not set"); + if(not config.proxyType or config.proxyType->empty()) { + log(LogLevel::Error, "Proxy is enabled but proxy type is not present or empty"); return tl::unexpected{ConfigurationError::ErrorClass::BadConfiguration}; } - if(not config.proxyServer) { - log(LogLevel::Error, "Proxy is enabled but proxy server is not set"); + if(not config.proxyServer or config.proxyServer->empty()) { + log(LogLevel::Error, "Proxy is enabled but proxy server is not present or empty"); return tl::unexpected{ConfigurationError::ErrorClass::BadConfiguration}; } } @@ -187,12 +199,14 @@ class ConfigurationReader { config.proxyUsername = getStringOpt("proxyUsername"); config.proxyPass = getStringOpt("proxyPass"); if(config.proxyAuthRequired) { - if(not config.proxyUsername) { - log(LogLevel::Error, "Proxy auth is required but proxy proxy username is not set"); + if(not config.proxyUsername or config.proxyUsername->empty()) { + log(LogLevel::Error, "Proxy auth is required but proxy proxy username is not present or empty"); return tl::unexpected{ConfigurationError::ErrorClass::BadConfiguration}; } if(not config.proxyPass) { - log(LogLevel::Error, "Proxy is enabled but proxy password is not set,"); + log(LogLevel::Error, + "Proxy is enabled but proxy password is not present, " + "if no password is required add an empty entry to configuration file"); return tl::unexpected{ConfigurationError::ErrorClass::BadConfiguration}; } } diff --git a/PAM/ssh/include/rublon/error.hpp b/PAM/ssh/include/rublon/error.hpp index 79eee49..4d9b41a 100755 --- a/PAM/ssh/include/rublon/error.hpp +++ b/PAM/ssh/include/rublon/error.hpp @@ -13,6 +13,7 @@ class ConfigurationError { public: enum class ErrorClass { // RequiredValueNotFound, + RequiredValueEmpty, BadFailMode, BadInput, BadConfiguration, @@ -20,6 +21,7 @@ class ConfigurationError { }; constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "RequiredValueNotFound", + "RequiredValueEmpty", "BadFailMode", "BadInput", "BadConfiguration",